Implemented rescanning the device list. A few things, e.g. notifications and change counter updates, are still missing. Added a periodical rescan event.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2694 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2003-02-11 23:37:48 +00:00
parent b393d4420b
commit 2d2601d03c
11 changed files with 440 additions and 118 deletions
+29 -1
View File
@@ -9,20 +9,29 @@
#include "DiskDeviceManager.h" #include "DiskDeviceManager.h"
#include "Debug.h" #include "Debug.h"
#include "EventMaskWatcher.h" #include "EventMaskWatcher.h"
#include "EventQueue.h"
#include "MessageEvent.h"
#include "RDiskDevice.h" #include "RDiskDevice.h"
#include "RDiskDeviceList.h" #include "RDiskDeviceList.h"
#include "RPartition.h" #include "RPartition.h"
#include "RSession.h" #include "RSession.h"
// priorities of the different message kinds
enum { enum {
REQUEST_PRIORITY = 0, REQUEST_PRIORITY = 0,
RESCAN_PRIORITY = 5,
NODE_MONITOR_PRIORITY = 10, NODE_MONITOR_PRIORITY = 10,
WATCHING_REQUEST_PRIORITY = 20, WATCHING_REQUEST_PRIORITY = 20,
}; };
// time interval between device rescans
static const bigtime_t kRescanEventInterval = 5000000;
// constructor // constructor
DiskDeviceManager::DiskDeviceManager() DiskDeviceManager::DiskDeviceManager(EventQueue *eventQueue)
: BLooper("disk device manager"), : BLooper("disk device manager"),
fEventQueue(eventQueue),
fRescanEvent(NULL),
fDeviceListLock(), fDeviceListLock(),
fWatchingService(), fWatchingService(),
fVolumeList(BMessenger(this), fDeviceListLock), fVolumeList(BMessenger(this), fDeviceListLock),
@@ -45,11 +54,19 @@ DiskDeviceManager::DiskDeviceManager()
if (fWorker >= 0) if (fWorker >= 0)
resume_thread(fWorker); resume_thread(fWorker);
} }
// set up the rescan event
fRescanEvent = new MessageEvent(system_time() + kRescanEventInterval,
this, B_REG_ROSTER_DEVICE_RESCAN);
fRescanEvent->SetAutoDelete(false);
fEventQueue->AddEvent(fRescanEvent);
} }
// destructor // destructor
DiskDeviceManager::~DiskDeviceManager() DiskDeviceManager::~DiskDeviceManager()
{ {
// remove the rescan event from the event queue
fEventQueue->RemoveEvent(fRescanEvent);
// terminate the worker thread
fTerminating = true; fTerminating = true;
delete_sem(fMessageCounter); delete_sem(fMessageCounter);
int32 dummy; int32 dummy;
@@ -74,6 +91,11 @@ DiskDeviceManager::MessageReceived(BMessage *message)
if (!_PushMessage(message, WATCHING_REQUEST_PRIORITY)) if (!_PushMessage(message, WATCHING_REQUEST_PRIORITY))
delete message; delete message;
break; break;
case B_REG_ROSTER_DEVICE_RESCAN:
DetachCurrentMessage();
if (!_PushMessage(message, RESCAN_PRIORITY))
delete message;
break;
case B_NODE_MONITOR: case B_NODE_MONITOR:
DetachCurrentMessage(); DetachCurrentMessage();
if (!_PushMessage(message, NODE_MONITOR_PRIORITY)) if (!_PushMessage(message, NODE_MONITOR_PRIORITY))
@@ -307,6 +329,12 @@ DiskDeviceManager::_Worker()
case B_REG_DEVICE_STOP_WATCHING: case B_REG_DEVICE_STOP_WATCHING:
_StopWatchingRequest(message); _StopWatchingRequest(message);
break; break;
case B_REG_ROSTER_DEVICE_RESCAN:
fDeviceList.Rescan();
fRescanEvent->SetTime(system_time()
+ kRescanEventInterval);
fEventQueue->AddEvent(fRescanEvent);
break;
case B_NODE_MONITOR: case B_NODE_MONITOR:
{ {
fVolumeList.HandleMessage(message); fVolumeList.HandleMessage(message);
+9 -1
View File
@@ -15,9 +15,12 @@
#include "RVolumeList.h" #include "RVolumeList.h"
#include "WatchingService.h" #include "WatchingService.h"
class EventQueue;
class MessageEvent;
class DiskDeviceManager : public BLooper { class DiskDeviceManager : public BLooper {
public: public:
DiskDeviceManager(); DiskDeviceManager(EventQueue *eventQueue);
virtual ~DiskDeviceManager(); virtual ~DiskDeviceManager();
virtual void MessageReceived(BMessage *message); virtual void MessageReceived(BMessage *message);
@@ -37,6 +40,11 @@ private:
int32 _Worker(); int32 _Worker();
private: private:
class RescanEvent;
private:
EventQueue *fEventQueue;
MessageEvent *fRescanEvent;
BLocker fDeviceListLock; BLocker fDeviceListLock;
WatchingService fWatchingService; WatchingService fWatchingService;
RVolumeList fVolumeList; RVolumeList fVolumeList;
+148 -33
View File
@@ -22,7 +22,7 @@ RDiskDevice::RDiskDevice()
: fSessions(10, true), : fSessions(10, true),
fDeviceList(NULL), fDeviceList(NULL),
fID(-1), fID(-1),
fChangeCounter(0), fChangeCounter(),
fTouched(false), fTouched(false),
fPath(), fPath(),
fFD(-1), fFD(-1),
@@ -45,7 +45,7 @@ PRINT(("RDiskDevice::SetTo()\n"));
Unset(); Unset();
status_t error = B_OK; status_t error = B_OK;
fID = _NextID(); fID = _NextID();
fChangeCounter = 0; fChangeCounter.Reset();
fTouched = true; fTouched = true;
fPath.SetTo(path); fPath.SetTo(path);
fFD = fd; fFD = fd;
@@ -68,28 +68,8 @@ PRINT(("RDiskDevice::SetTo()\n"));
error = fMediaStatus; error = fMediaStatus;
break; break;
} }
// scan the device for sessions, if we have a media // scan the device for sessions
if (fMediaStatus == B_OK) { error = _RescanSessions(B_DEVICE_CAUSE_UNKNOWN);
session_info sessionInfo;
for (int32 i = 0; ; i++) {
// get the session info
status_t status = get_nth_session_info(fFD, i, &sessionInfo);
if (status != B_OK) {
if (status != B_ENTRY_NOT_FOUND)
error = status;
break;
}
// create and add a RSession
if (RSession *session = new(nothrow) RSession) {
error = session->SetTo(fFD, &sessionInfo);
if (error == B_OK)
AddSession(session);
else
delete session;
} else
error = B_NO_MEMORY;
}
}
// cleanup on error // cleanup on error
if (error != B_OK) if (error != B_OK)
Unset(); Unset();
@@ -102,7 +82,7 @@ void
RDiskDevice::Unset() RDiskDevice::Unset()
{ {
for (int32 i = CountSessions() - 1; i >= 0; i--) for (int32 i = CountSessions() - 1; i >= 0; i--)
RemoveSession(i); RemoveSession(i, B_DEVICE_CAUSE_UNKNOWN);
fID = -1; fID = -1;
fPath.SetTo(""); fPath.SetTo("");
if (fFD >= 0) { if (fFD >= 0) {
@@ -111,6 +91,51 @@ RDiskDevice::Unset()
} }
} }
// MediaChanged
status_t
RDiskDevice::MediaChanged()
{
PRINT(("RDiskDevice::MediaChanged()\n"));
status_t error = B_OK;
// get the new media status
status_t mediaStatus;
if (ioctl(fFD, B_GET_MEDIA_STATUS, &mediaStatus) == 0) {
fMediaStatus = mediaStatus;
// analyze the media status
switch (fMediaStatus) {
case B_NO_ERROR:
case B_DEV_NO_MEDIA:
case B_DEV_NOT_READY:
case B_DEV_MEDIA_CHANGE_REQUESTED:
case B_DEV_DOOR_OPEN:
break;
case B_DEV_MEDIA_CHANGED:
// Ignore changes between the our ioctl() and the one before;
// we rescan the sessions anyway.
fMediaStatus = B_OK;
break;
default:
error = fMediaStatus;
break;
}
}
// rescan sessions
error = _RescanSessions(B_DEVICE_CAUSE_PARENT_CHANGED);
// TODO: send notification
// ...
return error;
}
// SessionLayoutChanged
status_t
RDiskDevice::SessionLayoutChanged()
{
PRINT(("RDiskDevice::SessionLayoutChanged()\n"));
status_t error = B_OK;
error = _RescanSessions(B_DEVICE_CAUSE_UNKNOWN);
return error;
}
// Size // Size
off_t off_t
RDiskDevice::Size() const RDiskDevice::Size() const
@@ -119,9 +144,25 @@ RDiskDevice::Size() const
* fGeometry.cylinder_count * fGeometry.head_count; * fGeometry.cylinder_count * fGeometry.head_count;
} }
// AddSession
status_t
RDiskDevice::AddSession(const session_info *sessionInfo, uint32 cause)
{
status_t error = B_OK;
if (RSession *session = new(nothrow) RSession) {
error = session->SetTo(fFD, sessionInfo);
if (error == B_OK)
AddSession(session, cause);
else
delete session;
} else
error = B_NO_MEMORY;
return error;
}
// AddSession // AddSession
bool bool
RDiskDevice::AddSession(RSession *session) RDiskDevice::AddSession(RSession *session, uint32 cause)
{ {
bool success = false; bool success = false;
if (session) { if (session) {
@@ -129,7 +170,7 @@ RDiskDevice::AddSession(RSession *session)
if (success) { if (success) {
session->SetDevice(this); session->SetDevice(this);
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->SessionAdded(session); deviceList->SessionAdded(session, cause);
} }
} }
return success; return success;
@@ -137,12 +178,12 @@ RDiskDevice::AddSession(RSession *session)
// RemoveSession // RemoveSession
bool bool
RDiskDevice::RemoveSession(int32 index) RDiskDevice::RemoveSession(int32 index, uint32 cause)
{ {
RSession *session = SessionAt(index); RSession *session = SessionAt(index);
if (session) { if (session) {
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->SessionRemoved(session); deviceList->SessionRemoved(session, cause);
session->SetDevice(NULL); session->SetDevice(NULL);
fSessions.RemoveItemAt(index); fSessions.RemoveItemAt(index);
delete session; delete session;
@@ -152,13 +193,13 @@ RDiskDevice::RemoveSession(int32 index)
// RemoveSession // RemoveSession
bool bool
RDiskDevice::RemoveSession(RSession *session) RDiskDevice::RemoveSession(RSession *session, uint32 cause)
{ {
bool success = false; bool success = false;
if (session) { if (session) {
int32 index = fSessions.IndexOf(session); int32 index = fSessions.IndexOf(session);
if (index >= 0) if (index >= 0)
success = RemoveSession(index); success = RemoveSession(index, cause);
} }
return success; return success;
} }
@@ -167,7 +208,55 @@ RDiskDevice::RemoveSession(RSession *session)
status_t status_t
RDiskDevice::Update() RDiskDevice::Update()
{ {
return B_ERROR; status_t error = B_OK;
status_t mediaStatus = B_OK;
if (ioctl(fFD, B_GET_MEDIA_STATUS, &mediaStatus) == 0) {
if (mediaStatus == B_DEV_MEDIA_CHANGED
|| (mediaStatus == B_NO_ERROR) != (fMediaStatus == B_NO_ERROR)) {
// The media status is B_DEV_MEDIA_CHANGED or it changed from
// B_NO_ERROR to some error code or the other way around.
error = MediaChanged();
} else {
// TODO: notifications?
fMediaStatus = mediaStatus;
// The media has not been changed. If this is a read-only device,
// then we are safe, since nothing can have changed. Otherwise
// we check the sessions.
if (!IsReadOnly() && fMediaStatus == B_OK) {
session_info sessionInfo;
for (int32 i = 0; error == B_OK; i++) {
// get the session info
status_t status = get_nth_session_info(fFD, i,
&sessionInfo);
if (status != B_OK) {
if (status == B_ENTRY_NOT_FOUND) {
// remove disappeared sessions
for (int32 k = CountSessions() - 1; k >= i; k--)
RemoveSession(k, B_DEVICE_CAUSE_UNKNOWN);
} else
error = status;
break;
}
// check the session
if (RSession *session = SessionAt(i)) {
if (session->Offset() == sessionInfo.offset
&& session->Size() == sessionInfo.size) {
session->Update(&sessionInfo);
} else {
// session layout changed
error = SessionLayoutChanged();
break;
}
} else {
// session added
error = AddSession(&sessionInfo,
B_DEVICE_CAUSE_UNKNOWN);
}
}
}
}
}
return error;
} }
// Archive // Archive
@@ -179,7 +268,7 @@ RDiskDevice::Archive(BMessage *archive) const
if (error == B_OK) if (error == B_OK)
error = archive->AddInt32("id", fID); error = archive->AddInt32("id", fID);
if (error == B_OK) if (error == B_OK)
error = archive->AddInt32("change_counter", fChangeCounter); error = archive->AddInt32("change_counter", ChangeCounter());
// geometry // geometry
if (error == B_OK) if (error == B_OK)
error = archive->AddInt64("size", Size()); error = archive->AddInt64("size", Size());
@@ -219,6 +308,32 @@ RDiskDevice::Dump() const
session->Dump(); session->Dump();
} }
// _RescanSessions
status_t
RDiskDevice::_RescanSessions(uint32 cause)
{
status_t error = B_OK;
// remove the current sessions
for (int32 i = CountSessions() - 1; i >= 0; i--)
RemoveSession(i, cause);
// scan the device for sessions, if we have a media
if (fMediaStatus == B_OK) {
session_info sessionInfo;
for (int32 i = 0; error == B_OK; i++) {
// get the session info
status_t status = get_nth_session_info(fFD, i, &sessionInfo);
if (status != B_OK) {
if (status != B_ENTRY_NOT_FOUND)
error = status;
break;
}
// create and add a RSession
error = AddSession(&sessionInfo, cause);
}
}
RETURN_ERROR(error);
}
// _NextID // _NextID
int32 int32
RDiskDevice::_NextID() RDiskDevice::_NextID()
+22 -5
View File
@@ -10,6 +10,10 @@
#include <ObjectList.h> #include <ObjectList.h>
#include <String.h> #include <String.h>
#include "RChangeCounter.h"
struct session_info;
class RDiskDeviceList; class RDiskDeviceList;
class RPartition; class RPartition;
class RSession; class RSession;
@@ -27,20 +31,31 @@ public:
{ fDeviceList = deviceList ;} { fDeviceList = deviceList ;}
RDiskDeviceList *DeviceList() const { return fDeviceList; } RDiskDeviceList *DeviceList() const { return fDeviceList; }
status_t MediaChanged();
status_t SessionLayoutChanged();
int32 ID() const { return fID; } int32 ID() const { return fID; }
int32 ChangeCounter() const { return fChangeCounter; } int32 ChangeCounter() const { return fChangeCounter.Count(); }
void Changed() { fChangeCounter.Increment(); }
void SetTouched(bool touched) { fTouched = touched; } void SetTouched(bool touched) { fTouched = touched; }
bool Touched() const { return fTouched; } bool Touched() const { return fTouched; }
int FD() const { return fFD; }
off_t Size() const; off_t Size() const;
int32 BlockSize() const { return fGeometry.bytes_per_sector; } int32 BlockSize() const { return fGeometry.bytes_per_sector; }
bool IsReadOnly() { return fGeometry.read_only; }
const char *Path() const { return fPath.String(); } const char *Path() const { return fPath.String(); }
bool AddSession(RSession *session); status_t AddSession(const session_info *sessionInfo,
bool RemoveSession(int32 index); uint32 cause/* = B_DEVICE_CAUSE_UNKNOWN*/);
bool RemoveSession(RSession *session); bool AddSession(RSession *session,
uint32 cause/* = B_DEVICE_CAUSE_UNKNOWN*/);
bool RemoveSession(int32 index,
uint32 cause/* = B_DEVICE_CAUSE_UNKNOWN*/);
bool RemoveSession(RSession *session,
uint32 cause/* = B_DEVICE_CAUSE_UNKNOWN*/);
int32 CountSessions() const { return fSessions.CountItems(); } int32 CountSessions() const { return fSessions.CountItems(); }
RSession *SessionAt(int32 index) const { return fSessions.ItemAt(index); } RSession *SessionAt(int32 index) const { return fSessions.ItemAt(index); }
int32 IndexOfSession(const RSession *session) const int32 IndexOfSession(const RSession *session) const
@@ -53,13 +68,15 @@ public:
void Dump() const; void Dump() const;
private: private:
status_t _RescanSessions(uint32 cause);
static int32 _NextID(); static int32 _NextID();
private: private:
BObjectList<RSession> fSessions; BObjectList<RSession> fSessions;
RDiskDeviceList *fDeviceList; RDiskDeviceList *fDeviceList;
int32 fID; int32 fID;
int32 fChangeCounter; RChangeCounter fChangeCounter;
bool fTouched; bool fTouched;
BString fPath; BString fPath;
int fFD; int fFD;
+55 -35
View File
@@ -186,6 +186,52 @@ RDiskDeviceList::MountPointMoved(const RVolume *volume,
Unlock(); Unlock();
} }
// DeviceAppeared
void
RDiskDeviceList::DeviceAppeared(const char *devicePath)
{
status_t error = (devicePath ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
int fd = open(devicePath, O_RDONLY);
if (fd >= 0) {
bool closeFile = true;
device_geometry geometry;
status_t mediaStatus = B_OK;
partition_info partitionInfo;
if (ioctl(fd, B_GET_MEDIA_STATUS, &mediaStatus) == 0
&& ioctl(fd, B_GET_GEOMETRY, &geometry) == 0
&& ioctl(fd, B_GET_PARTITION_INFO, &partitionInfo) < 0) {
PRINT(("RDiskDeviceList::DeviceAppeared(`%s')\n", devicePath));
RDiskDevice *device = new(nothrow) RDiskDevice;
if (device) {
error = device->SetTo(devicePath, fd, &geometry,
mediaStatus);
if (error == B_OK) {
closeFile = false;
device->SetTouched(true);
AddDevice(device);
} else
delete device;
} else
error = B_NO_MEMORY;
}
if (closeFile)
close(fd);
}
}
}
// DeviceDisappeared
void
RDiskDeviceList::DeviceDisappeared(const char *devicePath)
{
PRINT(("RDiskDeviceList::DeviceDisappeared(`%s')\n", devicePath));
if (devicePath) {
if (RDiskDevice *device = DeviceWithPath(devicePath))
RemoveDevice(device);
}
}
// AddDevice // AddDevice
bool bool
RDiskDeviceList::AddDevice(RDiskDevice *device) RDiskDeviceList::AddDevice(RDiskDevice *device)
@@ -280,6 +326,9 @@ status_t
RDiskDeviceList::Rescan() RDiskDeviceList::Rescan()
{ {
FUNCTION_START(); FUNCTION_START();
// TODO: This method should be reworked, as soon as we react on events only
// and don't need to poll anymore. This method will then do an initial
// scan only.
status_t error = B_OK; status_t error = B_OK;
if (Lock()) { if (Lock()) {
// marked all devices untouched // marked all devices untouched
@@ -292,8 +341,9 @@ FUNCTION_START();
} }
// remove all untouched devices // remove all untouched devices
for (int32 i = CountDevices() - 1; i >= 0; i--) { for (int32 i = CountDevices() - 1; i >= 0; i--) {
if (!DeviceAt(i)->Touched()) RDiskDevice *device = DeviceAt(i);
RemoveDevice(i); if (!device->Touched())
DeviceDisappeared(device->Path());
} }
Unlock(); Unlock();
} else } else
@@ -410,17 +460,11 @@ RDiskDeviceList::Dump() const
status_t status_t
RDiskDeviceList::_Scan(BDirectory &dir) RDiskDeviceList::_Scan(BDirectory &dir)
{ {
//BEntry dirEntry;
//BPath dirPath;
//dir.GetEntry(&dirEntry);
//dirEntry.GetPath(&dirPath);
//PRINT(("RDiskDeviceList::_Scan(`%s')\n", dirPath.Path()));
status_t error = B_OK; status_t error = B_OK;
BEntry entry; BEntry entry;
while (dir.GetNextEntry(&entry) == B_OK) { while (dir.GetNextEntry(&entry) == B_OK) {
struct stat st; struct stat st;
if (entry.GetStat(&st) == B_OK) { if (entry.GetStat(&st) == B_OK) {
//PRINT(("st.st_mode: 0x%x\n", st.st_mode & S_IFMT));
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
BDirectory subdir; BDirectory subdir;
if (subdir.SetTo(&entry) == B_OK) if (subdir.SetTo(&entry) == B_OK)
@@ -444,37 +488,13 @@ RDiskDeviceList::_ScanDevice(const char *path)
// search the list for a device with that path // search the list for a device with that path
if (RDiskDevice *device = DeviceWithPath(path)) { if (RDiskDevice *device = DeviceWithPath(path)) {
// found: just update it // found: just update it
device->SetTouched(true);
error = device->Update(); error = device->Update();
} else { } else {
// not found: check whether it is really a disk device and add it to // not found: check whether it is really a disk device and add it to
// the list // the list
int fd = open(path, O_RDONLY); // The event hook does the work anyway:
if (fd >= 0) { DeviceAppeared(path);
bool closeFile = true;
device_geometry geometry;
status_t mediaStatus = B_OK;
partition_info partitionInfo;
if (ioctl(fd, B_GET_MEDIA_STATUS, &mediaStatus) == 0
&& ioctl(fd, B_GET_GEOMETRY, &geometry) == 0
&& ioctl(fd, B_GET_PARTITION_INFO, &partitionInfo) < 0) {
// int32 blockSize = geometry.bytes_per_sector;
// off_t deviceSize = (off_t)blockSize
// * geometry.sectors_per_track * geometry.cylinder_count
// * geometry.head_count;
RDiskDevice *device = new(nothrow) RDiskDevice;
if (device) {
error = device->SetTo(path, fd, &geometry, mediaStatus);
if (error == B_OK) {
closeFile = false;
AddDevice(device);
} else
delete device;
} else
error = B_NO_MEMORY;
}
if (closeFile)
close(fd);
}
} }
return error; return error;
} }
+4
View File
@@ -43,11 +43,14 @@ public:
virtual void HandleMessage(BMessage *message); virtual void HandleMessage(BMessage *message);
// external event hooks
virtual void VolumeMounted(const RVolume *volume); virtual void VolumeMounted(const RVolume *volume);
virtual void VolumeUnmounted(const RVolume *volume); virtual void VolumeUnmounted(const RVolume *volume);
virtual void MountPointMoved(const RVolume *volume, virtual void MountPointMoved(const RVolume *volume,
const entry_ref *oldRoot, const entry_ref *oldRoot,
const entry_ref *newRoot); const entry_ref *newRoot);
virtual void DeviceAppeared(const char *devicePath);
virtual void DeviceDisappeared(const char *devicePath);
bool AddDevice(RDiskDevice *device); bool AddDevice(RDiskDevice *device);
bool RemoveDevice(int32 index); bool RemoveDevice(int32 index);
@@ -74,6 +77,7 @@ public:
bool Lock(); bool Lock();
void Unlock(); void Unlock();
// internal event hooks
void DeviceAdded(RDiskDevice *device, void DeviceAdded(RDiskDevice *device,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN); uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void DeviceRemoved(RDiskDevice *device, void DeviceRemoved(RDiskDevice *device,
+21 -3
View File
@@ -12,7 +12,7 @@
RPartition::RPartition() RPartition::RPartition()
: fSession(NULL), : fSession(NULL),
fID(-1), fID(-1),
fChangeCounter(0), fChangeCounter(),
fVolume(NULL) fVolume(NULL)
{ {
} }
@@ -29,7 +29,7 @@ RPartition::SetTo(int fd, const extended_partition_info *partitionInfo)
Unset(); Unset();
status_t error = B_OK; status_t error = B_OK;
fID = _NextID(); fID = _NextID();
fChangeCounter = 0; fChangeCounter.Reset();
fInfo = *partitionInfo; fInfo = *partitionInfo;
return error; return error;
} }
@@ -55,6 +55,14 @@ RPartition::Device() const
return (fSession ? fSession->Device() : NULL); return (fSession ? fSession->Device() : NULL);
} }
// Changed
void
RPartition::Changed()
{
if (fChangeCounter.Increment() && fSession)
fSession->Changed();
}
// Index // Index
int32 int32
RPartition::Index() const RPartition::Index() const
@@ -76,6 +84,16 @@ RPartition::GetPath(char *path) const
} }
} }
// Update
status_t
RPartition::Update(const extended_partition_info *partitionInfo)
{
status_t error = B_OK;
// TODO: Check the partition info for changes!
fInfo = *partitionInfo;
return error;
}
// Archive // Archive
status_t status_t
RPartition::Archive(BMessage *archive) const RPartition::Archive(BMessage *archive) const
@@ -85,7 +103,7 @@ RPartition::Archive(BMessage *archive) const
if (error == B_OK) if (error == B_OK)
error = archive->AddInt32("id", fID); error = archive->AddInt32("id", fID);
if (error == B_OK) if (error == B_OK)
error = archive->AddInt32("change_counter", fChangeCounter); error = archive->AddInt32("change_counter", ChangeCounter());
if (error == B_OK) if (error == B_OK)
error = archive->AddInt32("index", Index()); error = archive->AddInt32("index", Index());
// fInfo.info.* // fInfo.info.*
+9 -2
View File
@@ -9,6 +9,8 @@
#include <disk_scanner.h> #include <disk_scanner.h>
#include <SupportDefs.h> #include <SupportDefs.h>
#include "RChangeCounter.h"
class BMessage; class BMessage;
class RDiskDevice; class RDiskDevice;
@@ -30,18 +32,23 @@ public:
RSession *Session() const { return fSession; } RSession *Session() const { return fSession; }
int32 ID() const { return fID; } int32 ID() const { return fID; }
int32 ChangeCounter() const { return fChangeCounter; } int32 ChangeCounter() const { return fChangeCounter.Count(); }
void Changed();
int32 Index() const; int32 Index() const;
const extended_partition_info *Info() const { return &fInfo; } const extended_partition_info *Info() const { return &fInfo; }
void GetPath(char *path) const; void GetPath(char *path) const;
off_t Offset() const { return fInfo.info.offset; }
off_t Size() const { return fInfo.info.size; }
void SetVolume(const RVolume *volume) { fVolume = volume; } void SetVolume(const RVolume *volume) { fVolume = volume; }
const RVolume *Volume() const { return fVolume; } const RVolume *Volume() const { return fVolume; }
status_t Archive(BMessage *archive) const; status_t Archive(BMessage *archive) const;
status_t Update(const extended_partition_info *partitionInfo);
void Dump() const; void Dump() const;
private: private:
@@ -50,7 +57,7 @@ private:
private: private:
RSession *fSession; RSession *fSession;
int32 fID; int32 fID;
int32 fChangeCounter; RChangeCounter fChangeCounter;
extended_partition_info fInfo; extended_partition_info fInfo;
const RVolume *fVolume; const RVolume *fVolume;
+122 -31
View File
@@ -17,7 +17,7 @@ RSession::RSession()
: fPartitions(10, true), : fPartitions(10, true),
fDevice(NULL), fDevice(NULL),
fID(-1), fID(-1),
fChangeCounter(0) fChangeCounter()
{ {
} }
@@ -33,29 +33,10 @@ RSession::SetTo(int fd, const session_info *sessionInfo)
Unset(); Unset();
status_t error = B_OK; status_t error = B_OK;
fID = _NextID(); fID = _NextID();
fChangeCounter = 0; fChangeCounter.Reset();
fInfo = *sessionInfo; fInfo = *sessionInfo;
// iterate through the partitions // scan for partitions
for (int32 i = 0; ; i++) { error = _RescanPartitions(fd, B_DEVICE_CAUSE_UNKNOWN);
// get the partition info
extended_partition_info partitionInfo;
status_t status = get_nth_partition_info(fd, sessionInfo->index, i,
&partitionInfo, (i == 0 ? fPartitioningSystem : NULL));
if (status != B_OK) {
if (status != B_ENTRY_NOT_FOUND)
error = status;
break;
}
// create and add a RPartition
if (RPartition *partition = new(nothrow) RPartition) {
error = partition->SetTo(fd, &partitionInfo);
if (error == B_OK)
AddPartition(partition);
else
delete partition;
} else
error = B_NO_MEMORY;
}
// cleanup on error // cleanup on error
if (error != B_OK) if (error != B_OK)
Unset(); Unset();
@@ -67,7 +48,7 @@ void
RSession::Unset() RSession::Unset()
{ {
for (int32 i = CountPartitions() - 1; i >= 0; i--) for (int32 i = CountPartitions() - 1; i >= 0; i--)
RemovePartition(i); RemovePartition(i, B_DEVICE_CAUSE_UNKNOWN);
fID = -1; fID = -1;
} }
@@ -78,6 +59,25 @@ RSession::DeviceList() const
return (fDevice ? fDevice->DeviceList() : NULL); return (fDevice ? fDevice->DeviceList() : NULL);
} }
// PartitionLayoutChanged
status_t
RSession::PartitionLayoutChanged()
{
PRINT(("RSession::PartitionLayoutChanged()\n"));
status_t error = (fDevice ? B_OK : B_ERROR);
if (error == B_OK)
error = _RescanPartitions(fDevice->FD(), B_DEVICE_CAUSE_UNKNOWN);
return error;
}
// Changed
void
RSession::Changed()
{
if (fChangeCounter.Increment() && fDevice)
fDevice->Changed();
}
// Index // Index
int32 int32
RSession::Index() const RSession::Index() const
@@ -87,9 +87,26 @@ RSession::Index() const
return -1; return -1;
} }
// AddPartition
status_t
RSession::AddPartition(int fd, const extended_partition_info *partitionInfo,
uint32 cause)
{
status_t error = B_OK;
if (RPartition *partition = new(nothrow) RPartition) {
error = partition->SetTo(fd, partitionInfo);
if (error == B_OK)
AddPartition(partition, cause);
else
delete partition;
} else
error = B_NO_MEMORY;
return error;
}
// AddPartition // AddPartition
bool bool
RSession::AddPartition(RPartition *partition) RSession::AddPartition(RPartition *partition, uint32 cause)
{ {
bool success = false; bool success = false;
if (partition) { if (partition) {
@@ -97,7 +114,7 @@ RSession::AddPartition(RPartition *partition)
if (success) { if (success) {
partition->SetSession(this); partition->SetSession(this);
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->PartitionAdded(partition); deviceList->PartitionAdded(partition, cause);
} }
} }
return success; return success;
@@ -105,12 +122,12 @@ RSession::AddPartition(RPartition *partition)
// RemovePartition // RemovePartition
bool bool
RSession::RemovePartition(int32 index) RSession::RemovePartition(int32 index, uint32 cause)
{ {
RPartition *partition = PartitionAt(index); RPartition *partition = PartitionAt(index);
if (partition) { if (partition) {
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->PartitionRemoved(partition); deviceList->PartitionRemoved(partition, cause);
partition->SetSession(NULL); partition->SetSession(NULL);
fPartitions.RemoveItemAt(index); fPartitions.RemoveItemAt(index);
delete partition; delete partition;
@@ -120,17 +137,66 @@ RSession::RemovePartition(int32 index)
// RemovePartition // RemovePartition
bool bool
RSession::RemovePartition(RPartition *partition) RSession::RemovePartition(RPartition *partition, uint32 cause)
{ {
bool success = false; bool success = false;
if (partition) { if (partition) {
int32 index = fPartitions.IndexOf(partition); int32 index = fPartitions.IndexOf(partition);
if (index >= 0) if (index >= 0)
success = RemovePartition(index); success = RemovePartition(index, cause);
} }
return success; return success;
} }
// Update
status_t
RSession::Update(const session_info *sessionInfo)
{
status_t error = (fDevice ? B_OK : B_ERROR);
// TODO: Check the session info for changes!
fInfo = *sessionInfo;
int fd = (fDevice ? fDevice->FD() : -1);
// check the partitions
for (int32 i = 0; error == B_OK; i++) {
// get the partition info
extended_partition_info partitionInfo;
char partitioningSystem[B_FILE_NAME_LENGTH];
status_t status = get_nth_partition_info(fd, sessionInfo->index, i,
&partitionInfo, (i == 0 ? partitioningSystem : NULL));
// check the partitioning system
if ((status == B_OK || status == B_ENTRY_NOT_FOUND) && i == 0
&& strcmp(partitioningSystem, fPartitioningSystem)) {
// partitioning system has changed
error = PartitionLayoutChanged();
break;
}
if (status != B_OK) {
if (status == B_ENTRY_NOT_FOUND) {
// remove disappeared partitions
for (int32 k = CountPartitions() - 1; k >= i; k--)
RemovePartition(k, B_DEVICE_CAUSE_UNKNOWN);
} else
error = status;
break;
}
// check the partition
if (RPartition *partition = PartitionAt(i)) {
if (partition->Offset() == partitionInfo.info.offset
&& partition->Size() == partitionInfo.info.size) {
partition->Update(&partitionInfo);
} else {
// partition layout changed
error = PartitionLayoutChanged();
break;
}
} else {
// partition added
error = AddPartition(fd, &partitionInfo, B_DEVICE_CAUSE_UNKNOWN);
}
}
return error;
}
// Archive // Archive
status_t status_t
RSession::Archive(BMessage *archive) const RSession::Archive(BMessage *archive) const
@@ -140,7 +206,7 @@ RSession::Archive(BMessage *archive) const
if (error == B_OK) if (error == B_OK)
error = archive->AddInt32("id", fID); error = archive->AddInt32("id", fID);
if (error == B_OK) if (error == B_OK)
error = archive->AddInt32("change_counter", fChangeCounter); error = archive->AddInt32("change_counter", ChangeCounter());
if (error == B_OK) if (error == B_OK)
error = archive->AddInt32("index", Index()); error = archive->AddInt32("index", Index());
// fInfo.* // fInfo.*
@@ -188,6 +254,31 @@ RSession::Dump() const
partition->Dump(); partition->Dump();
} }
// _RescanPartitions
status_t
RSession::_RescanPartitions(int fd, uint32 cause)
{
status_t error = B_OK;
// remove the current partitions
for (int32 i = CountPartitions() - 1; i >= 0; i--)
RemovePartition(i, cause);
// scan for partitions
for (int32 i = 0; error == B_OK; i++) {
// get the partition info
extended_partition_info partitionInfo;
status_t status = get_nth_partition_info(fd, fInfo.index, i,
&partitionInfo, (i == 0 ? fPartitioningSystem : NULL));
if (status != B_OK) {
if (status != B_ENTRY_NOT_FOUND)
error = status;
break;
}
// create and add a RPartition
error = AddPartition(fd, &partitionInfo, cause);
}
return error;
}
// _NextID // _NextID
int32 int32
RSession::_NextID() RSession::_NextID()
+18 -5
View File
@@ -9,6 +9,8 @@
#include <disk_scanner.h> #include <disk_scanner.h>
#include <ObjectList.h> #include <ObjectList.h>
#include "RChangeCounter.h"
class RDiskDevice; class RDiskDevice;
class RDiskDeviceList; class RDiskDeviceList;
class RPartition; class RPartition;
@@ -25,14 +27,19 @@ public:
RDiskDeviceList *DeviceList() const; RDiskDeviceList *DeviceList() const;
RDiskDevice *Device() const { return fDevice; } RDiskDevice *Device() const { return fDevice; }
status_t PartitionLayoutChanged();
int32 ID() const { return fID; } int32 ID() const { return fID; }
int32 ChangeCounter() const { return fChangeCounter; } int32 ChangeCounter() const { return fChangeCounter.Count(); }
void Changed();
int32 Index() const; int32 Index() const;
bool AddPartition(RPartition *partition); status_t AddPartition(int fd, const extended_partition_info *partitionInfo,
bool RemovePartition(int32 index); uint32 cause);
bool RemovePartition(RPartition *partition); bool AddPartition(RPartition *partition, uint32 cause);
bool RemovePartition(int32 index, uint32 cause);
bool RemovePartition(RPartition *partition, uint32 cause);
int32 CountPartitions() const { return fPartitions.CountItems(); } int32 CountPartitions() const { return fPartitions.CountItems(); }
RPartition *PartitionAt(int32 index) const RPartition *PartitionAt(int32 index) const
{ return fPartitions.ItemAt(index); } { return fPartitions.ItemAt(index); }
@@ -40,19 +47,25 @@ public:
{ return fPartitions.IndexOf(partition); } { return fPartitions.IndexOf(partition); }
const session_info *Info() const { return &fInfo; } const session_info *Info() const { return &fInfo; }
off_t Offset() const { return fInfo.offset; }
off_t Size() const { return fInfo.size; }
status_t Update(const session_info *sessionInfo);
status_t Archive(BMessage *archive) const; status_t Archive(BMessage *archive) const;
void Dump() const; void Dump() const;
private: private:
status_t _RescanPartitions(int fd, uint32 cause);
static int32 _NextID(); static int32 _NextID();
private: private:
BObjectList<RPartition> fPartitions; BObjectList<RPartition> fPartitions;
RDiskDevice *fDevice; RDiskDevice *fDevice;
int32 fID; int32 fID;
int32 fChangeCounter; RChangeCounter fChangeCounter;
session_info fInfo; session_info fInfo;
char fPartitioningSystem[B_FILE_NAME_LENGTH]; char fPartitioningSystem[B_FILE_NAME_LENGTH];
+3 -2
View File
@@ -218,6 +218,8 @@ void
Registrar::ReadyToRun() Registrar::ReadyToRun()
{ {
FUNCTION_START(); FUNCTION_START();
// create event queue
fEventQueue = new EventQueue(kEventQueueName);
// create roster // create roster
fRoster = new TRoster; fRoster = new TRoster;
fRoster->Init(); fRoster->Init();
@@ -228,10 +230,9 @@ Registrar::ReadyToRun()
fMIMEManager = new MIMEManager; fMIMEManager = new MIMEManager;
fMIMEManager->Run(); fMIMEManager->Run();
// create disk device manager // create disk device manager
fDiskDeviceManager = new DiskDeviceManager; fDiskDeviceManager = new DiskDeviceManager(fEventQueue);
fDiskDeviceManager->Run(); fDiskDeviceManager->Run();
// create message runner manager // create message runner manager
fEventQueue = new EventQueue(kEventQueueName);
fMessageRunnerManager = new MessageRunnerManager(fEventQueue); fMessageRunnerManager = new MessageRunnerManager(fEventQueue);
// init the global be_roster // init the global be_roster
BRoster::Private().SetTo(be_app_messenger, BMessenger(NULL, fMIMEManager)); BRoster::Private().SetTo(be_app_messenger, BMessenger(NULL, fMIMEManager));