Added notification support for the mounting and mount point moving events. Several fixes.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2680 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2003-02-10 00:23:46 +00:00
parent c947b11347
commit 30bb74bbd2
8 changed files with 377 additions and 64 deletions
+94 -22
View File
@@ -7,30 +7,33 @@
#include <RegistrarDefs.h> #include <RegistrarDefs.h>
#include "DiskDeviceManager.h" #include "DiskDeviceManager.h"
#include "Debug.h"
#include "EventMaskWatcher.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"
#include "Debug.h"
enum { enum {
REQUEST_PRIORITY = 0, REQUEST_PRIORITY = 0,
NODE_MONITOR_PRIORITY = 10, NODE_MONITOR_PRIORITY = 10,
WATCHING_REQUEST_PRIORITY = 20,
}; };
// constructor // constructor
DiskDeviceManager::DiskDeviceManager() DiskDeviceManager::DiskDeviceManager()
: BLooper("disk device manager"), : BLooper("disk device manager"),
fDeviceListLock(), fDeviceListLock(),
fWatchingService(),
fVolumeList(BMessenger(this), fDeviceListLock), fVolumeList(BMessenger(this), fDeviceListLock),
fDeviceList(BMessenger(this), fDeviceListLock, fVolumeList), fDeviceList(BMessenger(this), fDeviceListLock, fVolumeList,
&fWatchingService),
fMessageQueue(), fMessageQueue(),
fWorker(-1), fWorker(-1),
fMessageCounter(-1), fMessageCounter(-1),
fTerminating(false) fTerminating(false)
{ {
// set up the device list // set up the device list
fVolumeList.Rescan();
fVolumeList.Dump(); fVolumeList.Dump();
fDeviceList.Rescan(); fDeviceList.Rescan();
fDeviceList.Dump(); fDeviceList.Dump();
@@ -61,10 +64,14 @@ DiskDeviceManager::MessageReceived(BMessage *message)
case B_REG_NEXT_DISK_DEVICE: case B_REG_NEXT_DISK_DEVICE:
case B_REG_GET_DISK_DEVICE: case B_REG_GET_DISK_DEVICE:
case B_REG_UPDATE_DISK_DEVICE: case B_REG_UPDATE_DISK_DEVICE:
DetachCurrentMessage();
if (!_PushMessage(message, REQUEST_PRIORITY))
delete message;
break;
case B_REG_DEVICE_START_WATCHING: case B_REG_DEVICE_START_WATCHING:
case B_REG_DEVICE_STOP_WATCHING: case B_REG_DEVICE_STOP_WATCHING:
DetachCurrentMessage(); DetachCurrentMessage();
if (!_PushMessage(message, REQUEST_PRIORITY)) if (!_PushMessage(message, WATCHING_REQUEST_PRIORITY))
delete message; delete message;
break; break;
case B_NODE_MONITOR: case B_NODE_MONITOR:
@@ -80,13 +87,14 @@ DiskDeviceManager::MessageReceived(BMessage *message)
// _NextDiskDeviceRequest // _NextDiskDeviceRequest
void void
DiskDeviceManager::_NextDiskDeviceRequest(BMessage *message) DiskDeviceManager::_NextDiskDeviceRequest(BMessage *request)
{ {
FUNCTION_START(); FUNCTION_START();
Lock();
status_t error = B_OK; status_t error = B_OK;
int32 cookie = 0; int32 cookie = 0;
BMessage reply(B_REG_RESULT); BMessage reply(B_REG_RESULT);
if (message->FindInt32("cookie", &cookie) == B_OK) { if (request->FindInt32("cookie", &cookie) == B_OK) {
// get next device // get next device
if (RDiskDevice *device = fDeviceList.DeviceWithID(cookie, false)) { if (RDiskDevice *device = fDeviceList.DeviceWithID(cookie, false)) {
// archive device // archive device
@@ -103,23 +111,25 @@ DiskDeviceManager::_NextDiskDeviceRequest(BMessage *message)
SET_ERROR(error, B_BAD_VALUE); SET_ERROR(error, B_BAD_VALUE);
// add result and send reply // add result and send reply
reply.AddInt32("result", error); reply.AddInt32("result", error);
message->SendReply(&reply); request->SendReply(&reply);
Unlock();
} }
// _GetDiskDeviceRequest // _GetDiskDeviceRequest
void void
DiskDeviceManager::_GetDiskDeviceRequest(BMessage *message) DiskDeviceManager::_GetDiskDeviceRequest(BMessage *request)
{ {
Lock();
status_t error = B_ENTRY_NOT_FOUND; status_t error = B_ENTRY_NOT_FOUND;
// get the device // get the device
RDiskDevice *device = NULL; RDiskDevice *device = NULL;
int32 id = 0; int32 id = 0;
if (message->FindInt32("device_id", &id) == B_OK) if (request->FindInt32("device_id", &id) == B_OK)
device = fDeviceList.DeviceWithID(id); device = fDeviceList.DeviceWithID(id);
else if (message->FindInt32("session_id", &id) == B_OK) { else if (request->FindInt32("session_id", &id) == B_OK) {
if (RSession *session = fDeviceList.SessionWithID(id)) if (RSession *session = fDeviceList.SessionWithID(id))
device = session->Device(); device = session->Device();
} else if (message->FindInt32("partition_id", &id) == B_OK) { } else if (request->FindInt32("partition_id", &id) == B_OK) {
if (RPartition *partition = fDeviceList.PartitionWithID(id)) if (RPartition *partition = fDeviceList.PartitionWithID(id))
device = partition->Device(); device = partition->Device();
} else } else
@@ -134,13 +144,15 @@ DiskDeviceManager::_GetDiskDeviceRequest(BMessage *message)
} }
// add result and send reply // add result and send reply
reply.AddInt32("result", error); reply.AddInt32("result", error);
message->SendReply(&reply); request->SendReply(&reply);
Unlock();
} }
// _UpdateDiskDeviceRequest // _UpdateDiskDeviceRequest
void void
DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message) DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *request)
{ {
Lock();
status_t error = B_ENTRY_NOT_FOUND; status_t error = B_ENTRY_NOT_FOUND;
// get the device and check the object is up to date // get the device and check the object is up to date
bool upToDate = false; bool upToDate = false;
@@ -148,20 +160,20 @@ DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message)
int32 id = 0; int32 id = 0;
int32 changeCounter = 0; int32 changeCounter = 0;
uint32 policy = 0; uint32 policy = 0;
if (message->FindInt32("change_counter", &changeCounter) != B_OK if (request->FindInt32("change_counter", &changeCounter) != B_OK
|| message->FindInt32("update_policy", (int32*)&policy) != B_OK) { || request->FindInt32("update_policy", (int32*)&policy) != B_OK) {
// bad request message // bad request request
SET_ERROR(error, B_BAD_VALUE); SET_ERROR(error, B_BAD_VALUE);
} else if (message->FindInt32("device_id", &id) == B_OK) { } else if (request->FindInt32("device_id", &id) == B_OK) {
device = fDeviceList.DeviceWithID(id); device = fDeviceList.DeviceWithID(id);
if (device) if (device)
upToDate = (device->ChangeCounter() == changeCounter); upToDate = (device->ChangeCounter() == changeCounter);
} else if (message->FindInt32("session_id", &id) == B_OK) { } else if (request->FindInt32("session_id", &id) == B_OK) {
if (RSession *session = fDeviceList.SessionWithID(id)) { if (RSession *session = fDeviceList.SessionWithID(id)) {
device = session->Device(); device = session->Device();
upToDate = (session->ChangeCounter() == changeCounter); upToDate = (session->ChangeCounter() == changeCounter);
} }
} else if (message->FindInt32("partition_id", &id) == B_OK) { } else if (request->FindInt32("partition_id", &id) == B_OK) {
if (RPartition *partition = fDeviceList.PartitionWithID(id)) { if (RPartition *partition = fDeviceList.PartitionWithID(id)) {
device = partition->Device(); device = partition->Device();
upToDate = (partition->ChangeCounter() == changeCounter); upToDate = (partition->ChangeCounter() == changeCounter);
@@ -184,9 +196,66 @@ DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message)
if (error == B_OK) if (error == B_OK)
error = reply.AddBool("up_to_date", upToDate); error = reply.AddBool("up_to_date", upToDate);
reply.AddInt32("result", error); reply.AddInt32("result", error);
message->SendReply(&reply); request->SendReply(&reply);
Unlock();
} }
// _StartWatchingRequest
void
DiskDeviceManager::_StartWatchingRequest(BMessage *request)
{
FUNCTION_START();
Lock();
status_t error = B_OK;
// get the parameters
BMessenger target;
uint32 events;
if (error == B_OK
&& (request->FindMessenger("target", &target) != B_OK
|| request->FindInt32("events", (int32*)&events) != B_OK)) {
SET_ERROR(error, B_BAD_VALUE);
}
// add the new watcher
if (error == B_OK) {
Watcher *watcher = new(nothrow) EventMaskWatcher(target, events);
if (watcher) {
if (!fWatchingService.AddWatcher(watcher)) {
SET_ERROR(error, B_NO_MEMORY);
delete watcher;
}
} else
SET_ERROR(error, B_NO_MEMORY);
}
// add result and send reply
BMessage reply(B_REG_RESULT);
reply.AddInt32("result", error);
request->SendReply(&reply);
Unlock();
};
// _StopWatchingRequest
void
DiskDeviceManager::_StopWatchingRequest(BMessage *request)
{
FUNCTION_START();
Lock();
status_t error = B_OK;
// get the parameters
BMessenger target;
if (error == B_OK && request->FindMessenger("target", &target) != B_OK)
error = B_BAD_VALUE;
// remove the watcher
if (error == B_OK) {
if (!fWatchingService.RemoveWatcher(target))
error = B_BAD_VALUE;
}
// add result and send reply
BMessage reply(B_REG_RESULT);
reply.AddInt32("result", error);
request->SendReply(&reply);
Unlock();
};
// _PushMessage // _PushMessage
bool bool
DiskDeviceManager::_PushMessage(BMessage *message, int32 priority) DiskDeviceManager::_PushMessage(BMessage *message, int32 priority)
@@ -233,7 +302,10 @@ DiskDeviceManager::_Worker()
_UpdateDiskDeviceRequest(message); _UpdateDiskDeviceRequest(message);
break; break;
case B_REG_DEVICE_START_WATCHING: case B_REG_DEVICE_START_WATCHING:
_StartWatchingRequest(message);
break;
case B_REG_DEVICE_STOP_WATCHING: case B_REG_DEVICE_STOP_WATCHING:
_StopWatchingRequest(message);
break; break;
case B_NODE_MONITOR: case B_NODE_MONITOR:
{ {
+7 -3
View File
@@ -13,6 +13,7 @@
#include "PriorityMessageQueue.h" #include "PriorityMessageQueue.h"
#include "RDiskDeviceList.h" #include "RDiskDeviceList.h"
#include "RVolumeList.h" #include "RVolumeList.h"
#include "WatchingService.h"
class DiskDeviceManager : public BLooper { class DiskDeviceManager : public BLooper {
public: public:
@@ -23,9 +24,11 @@ public:
private: private:
// requests // requests
void _NextDiskDeviceRequest(BMessage *message); void _NextDiskDeviceRequest(BMessage *request);
void _GetDiskDeviceRequest(BMessage *message); void _GetDiskDeviceRequest(BMessage *request);
void _UpdateDiskDeviceRequest(BMessage *message); void _UpdateDiskDeviceRequest(BMessage *request);
void _StartWatchingRequest(BMessage *request);
void _StopWatchingRequest(BMessage *request);
bool _PushMessage(BMessage *message, int32 priority); bool _PushMessage(BMessage *message, int32 priority);
BMessage *_PopMessage(); BMessage *_PopMessage();
@@ -35,6 +38,7 @@ private:
private: private:
BLocker fDeviceListLock; BLocker fDeviceListLock;
WatchingService fWatchingService;
RVolumeList fVolumeList; RVolumeList fVolumeList;
RDiskDeviceList fDeviceList; RDiskDeviceList fDeviceList;
PriorityMessageQueue fMessageQueue; PriorityMessageQueue fMessageQueue;
+2 -2
View File
@@ -141,10 +141,10 @@ RDiskDevice::RemoveSession(int32 index)
{ {
RSession *session = SessionAt(index); RSession *session = SessionAt(index);
if (session) { if (session) {
session->SetDevice(NULL);
fSessions.RemoveItemAt(index);
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->SessionRemoved(session); deviceList->SessionRemoved(session);
session->SetDevice(NULL);
fSessions.RemoveItemAt(index);
delete session; delete session;
} }
return (session != NULL); return (session != NULL);
+164 -17
View File
@@ -12,6 +12,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <Directory.h> #include <Directory.h>
#include <DiskDeviceRoster.h>
#include <Drivers.h> #include <Drivers.h>
#include <Entry.h> #include <Entry.h>
#include <Locker.h> #include <Locker.h>
@@ -19,24 +20,13 @@
#include "RDiskDeviceList.h" #include "RDiskDeviceList.h"
#include "Debug.h" #include "Debug.h"
#include "EventMaskWatcher.h"
#include "RDiskDevice.h" #include "RDiskDevice.h"
#include "RPartition.h" #include "RPartition.h"
#include "RSession.h" #include "RSession.h"
#include "WatchingService.h"
// compare_ids namespace RDiskDeviceListPredicates {
/*template<typename T>
static
int
compare_ids(const T *object1, const T *object2)
{
int32 id1 = object1->ID();
int32 id2 = object2->ID();
if (id1 < id2)
return -1;
if (id1 > id2)
return 1;
return 0;
}*/
// CompareIDPredicate // CompareIDPredicate
template <typename T> template <typename T>
@@ -71,14 +61,36 @@ private:
const char *fPath; const char *fPath;
}; };
// ComparePartitionPathPredicate
struct ComparePartitionPathPredicate : public UnaryPredicate<RPartition> {
ComparePartitionPathPredicate(const char *path) : fPath(path) {}
virtual int operator()(const RPartition *partition) const
{
char path[B_FILE_NAME_LENGTH];
partition->GetPath(path);
return strcmp(fPath, path);
}
private:
const char *fPath;
};
} // namespace RDiskDeviceListPredicates
using namespace RDiskDeviceListPredicates;
// constructor // constructor
RDiskDeviceList::RDiskDeviceList(BMessenger target, BLocker &lock, RDiskDeviceList::RDiskDeviceList(BMessenger target, BLocker &lock,
RVolumeList &volumeList) RVolumeList &volumeList,
WatchingService *watchingService)
: MessageHandler(), : MessageHandler(),
RVolumeListListener(), RVolumeListListener(),
fLock(lock), fLock(lock),
fTarget(target), fTarget(target),
fVolumeList(volumeList), fVolumeList(volumeList),
fWatchingService(watchingService),
fDevices(20, true), fDevices(20, true),
fSessions(40, false), fSessions(40, false),
fPartitions(80, false) fPartitions(80, false)
@@ -110,6 +122,21 @@ void
RDiskDeviceList::VolumeMounted(const RVolume *volume) RDiskDeviceList::VolumeMounted(const RVolume *volume)
{ {
PRINT(("RDiskDeviceList::VolumeMounted(%ld)\n", volume->ID())); PRINT(("RDiskDeviceList::VolumeMounted(%ld)\n", volume->ID()));
Lock();
// get the partition and set its volume
const char *devicePath = volume->DevicePath();
if (RPartition *partition = PartitionWithPath(devicePath)) {
partition->SetVolume(volume);
// send notifications
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification,
B_DEVICE_PARTITION_MOUNTED, B_DEVICE_CAUSE_UNKNOWN,
partition) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNTING);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
Unlock();
} }
// VolumeUnmounted // VolumeUnmounted
@@ -117,13 +144,46 @@ void
RDiskDeviceList::VolumeUnmounted(const RVolume *volume) RDiskDeviceList::VolumeUnmounted(const RVolume *volume)
{ {
PRINT(("RDiskDeviceList::VolumeUnmounted(%ld)\n", volume->ID())); PRINT(("RDiskDeviceList::VolumeUnmounted(%ld)\n", volume->ID()));
Lock();
// get the partition and set its volume
const char *devicePath = volume->DevicePath();
if (RPartition *partition = PartitionWithPath(devicePath)) {
partition->SetVolume(NULL);
// send notifications
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification,
B_DEVICE_PARTITION_UNMOUNTED, B_DEVICE_CAUSE_UNKNOWN,
partition) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNTING);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
Unlock();
} }
// MountPointMoved // MountPointMoved
void void
RDiskDeviceList::MountPointMoved(const RVolume *volume) RDiskDeviceList::MountPointMoved(const RVolume *volume,
const entry_ref *oldRoot,
const entry_ref *newRoot)
{ {
PRINT(("RDiskDeviceList::MountPointMoved(%ld)\n", volume->ID())); PRINT(("RDiskDeviceList::MountPointMoved(%ld)\n", volume->ID()));
Lock();
// get the partition
const char *devicePath = volume->DevicePath();
if (RPartition *partition = PartitionWithPath(devicePath)) {
// send notifications
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification,
B_DEVICE_MOUNT_POINT_MOVED, B_DEVICE_CAUSE_UNKNOWN,
partition) == B_OK
&& notification.AddRef("old_directory", oldRoot) == B_OK
&& notification.AddRef("new_directory", newRoot) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNT_POINT);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
Unlock();
} }
// AddDevice // AddDevice
@@ -145,9 +205,9 @@ RDiskDeviceList::RemoveDevice(int32 index)
{ {
RDiskDevice *device = DeviceAt(index); RDiskDevice *device = DeviceAt(index);
if (device) { if (device) {
DeviceRemoved(device);
device->SetDeviceList(NULL); device->SetDeviceList(NULL);
fDevices.RemoveItemAt(index); fDevices.RemoveItemAt(index);
DeviceRemoved(device);
delete device; delete device;
} }
return (device != NULL); return (device != NULL);
@@ -206,6 +266,15 @@ RDiskDeviceList::DeviceWithPath(const char *path) const
return const_cast<RDiskDevice*>(device); return const_cast<RDiskDevice*>(device);
} }
// PartitionWithPath
RPartition *
RDiskDeviceList::PartitionWithPath(const char *path) const
{
const RPartition *partition
= fPartitions.FindIf(ComparePartitionPathPredicate(path));
return const_cast<RPartition*>(partition);
}
// Rescan // Rescan
status_t status_t
RDiskDeviceList::Rescan() RDiskDeviceList::Rescan()
@@ -273,6 +342,8 @@ RDiskDeviceList::DeviceRemoved(RDiskDevice *device, uint32 cause)
void void
RDiskDeviceList::SessionAdded(RSession *session, uint32 cause) RDiskDeviceList::SessionAdded(RSession *session, uint32 cause)
{ {
// add the session to our list
fSessions.BinaryInsert(session, CompareIDPredicate<RSession>(session));
// propagate to partitions // propagate to partitions
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++) for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
PartitionAdded(partition, B_DEVICE_CAUSE_PARENT_CHANGED); PartitionAdded(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
@@ -284,6 +355,12 @@ RDiskDeviceList::SessionAdded(RSession *session, uint32 cause)
void void
RDiskDeviceList::SessionRemoved(RSession *session, uint32 cause) RDiskDeviceList::SessionRemoved(RSession *session, uint32 cause)
{ {
// remove the session from our list
bool success = false;
int32 index = fSessions.FindBinaryInsertionIndex(
CompareIDPredicate<RSession>(session), &success);
if (success)
fSessions.RemoveItemAt(index);
// propagate to partitions // propagate to partitions
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++) for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
PartitionRemoved(partition, B_DEVICE_CAUSE_PARENT_CHANGED); PartitionRemoved(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
@@ -295,6 +372,9 @@ RDiskDeviceList::SessionRemoved(RSession *session, uint32 cause)
void void
RDiskDeviceList::PartitionAdded(RPartition *partition, uint32 cause) RDiskDeviceList::PartitionAdded(RPartition *partition, uint32 cause)
{ {
// add the partition to our list
fPartitions.BinaryInsert(partition,
CompareIDPredicate<RPartition>(partition));
// get the corresponding volume, if partition is mounted // get the corresponding volume, if partition is mounted
char path[B_FILE_NAME_LENGTH]; char path[B_FILE_NAME_LENGTH];
partition->GetPath(path); partition->GetPath(path);
@@ -308,6 +388,12 @@ RDiskDeviceList::PartitionAdded(RPartition *partition, uint32 cause)
void void
RDiskDeviceList::PartitionRemoved(RPartition *partition, uint32 cause) RDiskDeviceList::PartitionRemoved(RPartition *partition, uint32 cause)
{ {
// remove the partition from our list
bool success = false;
int32 index = fPartitions.FindBinaryInsertionIndex(
CompareIDPredicate<RPartition>(partition), &success);
if (success)
fPartitions.RemoveItemAt(index);
// notifications // notifications
// ... // ...
} }
@@ -393,3 +479,64 @@ RDiskDeviceList::_ScanDevice(const char *path)
return error; return error;
} }
// _InitNotificationMessage
status_t
RDiskDeviceList::_InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause)
{
status_t error = (message ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
message->what = B_DEVICE_UPDATE;
error = message->AddInt32("event", event);
}
if (error == B_OK)
error = message->AddInt32("cause", cause);
return error;
}
// _InitNotificationMessage
status_t
RDiskDeviceList::_InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause,
const RDiskDevice *device)
{
status_t error = (device ? B_OK : B_BAD_VALUE);
if (error == B_OK)
error = _InitNotificationMessage(message, event, cause);
if (error == B_OK)
error = message->AddInt32("device_id", device->ID());
return error;
}
// _InitNotificationMessage
status_t
RDiskDeviceList::_InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause,
const RSession *session)
{
status_t error = (session ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
error = _InitNotificationMessage(message, event, cause,
session->Device());
}
if (error == B_OK)
error = message->AddInt32("session_id", session->ID());
return error;
}
// _InitNotificationMessage
status_t
RDiskDeviceList::_InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause,
const RPartition *partition)
{
status_t error = (partition ? B_OK : B_BAD_VALUE);
if (error == B_OK) {
error = _InitNotificationMessage(message, event, cause,
partition->Session());
}
if (error == B_OK)
error = message->AddInt32("partition_id", partition->ID());
return error;
}
+18 -2
View File
@@ -19,6 +19,7 @@ class BLocker;
class RDiskDevice; class RDiskDevice;
class RPartition; class RPartition;
class RSession; class RSession;
class WatchingService;
// device list modification causes // device list modification causes
// TODO: to be moved to <DiskDeviceRoster.h> // TODO: to be moved to <DiskDeviceRoster.h>
@@ -36,14 +37,17 @@ enum {
class RDiskDeviceList : public MessageHandler, public RVolumeListListener { class RDiskDeviceList : public MessageHandler, public RVolumeListListener {
public: public:
RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList); RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList,
WatchingService *watchingService);
~RDiskDeviceList(); ~RDiskDeviceList();
virtual void HandleMessage(BMessage *message); virtual void HandleMessage(BMessage *message);
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 *newRoot);
bool AddDevice(RDiskDevice *device); bool AddDevice(RDiskDevice *device);
bool RemoveDevice(int32 index); bool RemoveDevice(int32 index);
@@ -63,6 +67,7 @@ public:
RPartition *PartitionWithID(int32 id) const; RPartition *PartitionWithID(int32 id) const;
RDiskDevice *DeviceWithPath(const char *path) const; RDiskDevice *DeviceWithPath(const char *path) const;
RPartition *PartitionWithPath(const char *path) const;
status_t Rescan(); status_t Rescan();
@@ -88,10 +93,21 @@ private:
status_t _Scan(BDirectory &dir); status_t _Scan(BDirectory &dir);
status_t _ScanDevice(const char *path); status_t _ScanDevice(const char *path);
status_t _InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause);
status_t _InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause, const RDiskDevice *device);
status_t _InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause, const RSession *session);
status_t _InitNotificationMessage(BMessage *message, uint32 event,
uint32 cause,
const RPartition *partition);
private: private:
mutable BLocker &fLock; mutable BLocker &fLock;
BMessenger fTarget; BMessenger fTarget;
RVolumeList &fVolumeList; RVolumeList &fVolumeList;
WatchingService *fWatchingService;
BObjectList<RDiskDevice> fDevices; // sorted by ID BObjectList<RDiskDevice> fDevices; // sorted by ID
BObjectList<RSession> fSessions; // BObjectList<RSession> fSessions; //
BObjectList<RPartition> fPartitions; // BObjectList<RPartition> fPartitions; //
+2 -2
View File
@@ -109,10 +109,10 @@ RSession::RemovePartition(int32 index)
{ {
RPartition *partition = PartitionAt(index); RPartition *partition = PartitionAt(index);
if (partition) { if (partition) {
partition->SetSession(NULL);
fPartitions.RemoveItemAt(index);
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->PartitionRemoved(partition); deviceList->PartitionRemoved(partition);
partition->SetSession(NULL);
fPartitions.RemoveItemAt(index);
delete partition; delete partition;
} }
return (partition != NULL); return (partition != NULL);
+77 -11
View File
@@ -5,14 +5,19 @@
#include <string.h> #include <string.h>
#include <Directory.h>
#include <Entry.h>
#include <Locker.h> #include <Locker.h>
#include <Message.h> #include <Message.h>
#include <NodeMonitor.h> #include <NodeMonitor.h>
#include <Path.h>
#include <Volume.h> #include <Volume.h>
#include "RVolumeList.h" #include "RVolumeList.h"
#include "Debug.h" #include "Debug.h"
namespace RVolumeListPredicates {
// CompareIDPredicate // CompareIDPredicate
struct CompareIDPredicate : public UnaryPredicate<RVolume> { struct CompareIDPredicate : public UnaryPredicate<RVolume> {
CompareIDPredicate(dev_t id) : fID(id) {} CompareIDPredicate(dev_t id) : fID(id) {}
@@ -45,13 +50,18 @@ private:
const char *fPath; const char *fPath;
}; };
} // namespace RVolumeListPredicates
using namespace RVolumeListPredicates;
// RVolume // RVolume
// constructor // constructor
RVolume::RVolume() RVolume::RVolume()
: fID(-1), : fID(-1),
fRootNode(-1) fRootNode(-1),
fRootEntry()
{ {
} }
@@ -60,13 +70,31 @@ status_t
RVolume::SetTo(dev_t id) RVolume::SetTo(dev_t id)
{ {
status_t error = B_OK; status_t error = B_OK;
// get general info
fs_info info; fs_info info;
error = fs_stat_dev(id, &info); error = fs_stat_dev(id, &info);
if (error == B_OK) { if (error == B_OK) {
fID = id; fID = id;
fRootNode = info.root; fRootNode = info.root;
strcpy(fDevicePath, info.device_name); if (info.device_name[0] != '\0')
} else strcpy(fDevicePath, info.device_name);
else // generate a pseudo name -- needed for the list
sprintf(fDevicePath, "%ld", id);
}
// get root dir entry_ref
if (error == B_OK) {
node_ref ref;
GetRootDirNode(&ref);
BDirectory dir;
error = dir.SetTo(&ref);
BEntry entry;
if (error == B_OK)
error = dir.GetEntry(&entry);
if (error == B_OK)
error = entry.GetRef(&fRootEntry);
}
// cleanup on error
if (error != B_OK)
Unset(); Unset();
return error; return error;
} }
@@ -126,7 +154,9 @@ RVolumeListListener::VolumeUnmounted(const RVolume *volume)
// MountPointMoved // MountPointMoved
void void
RVolumeListListener::MountPointMoved(const RVolume *volume) RVolumeListListener::MountPointMoved(const RVolume *volume,
const entry_ref *oldRoot,
const entry_ref *newRoot)
{ {
} }
@@ -194,12 +224,15 @@ RVolumeList::HandleMessage(BMessage *message)
status_t status_t
RVolumeList::Rescan() RVolumeList::Rescan()
{ {
fVolumes.MakeEmpty(); PRINT(("RVolumeList::Rescan()\n"));
for (int32 i = fVolumes.CountItems() - 1; i >= 0; i--)
_RemoveVolumeAt(i);
fRoster.Rewind(); fRoster.Rewind();
BVolume bVolume; BVolume bVolume;
while (fRoster.GetNextVolume(&bVolume) == B_OK) while (fRoster.GetNextVolume(&bVolume) == B_OK)
_AddVolume(bVolume.Device()); _AddVolume(bVolume.Device());
return B_ERROR; PRINT(("RVolumeList::Rescan() done\n"));
return B_OK;
} }
// VolumeForDevicePath // VolumeForDevicePath
@@ -272,6 +305,18 @@ RVolumeList::_AddVolume(dev_t id)
return volume; return volume;
} }
// _RemoveVolumeAt
bool
RVolumeList::_RemoveVolumeAt(int32 index)
{
bool result = false;
if (RVolume *volume = fVolumes.RemoveItemAt(index)) {
volume->StopWatching(fTarget);
delete volume;
}
return result;
}
// _DeviceMounted // _DeviceMounted
void void
RVolumeList::_DeviceMounted(BMessage *message) RVolumeList::_DeviceMounted(BMessage *message)
@@ -307,12 +352,33 @@ RVolumeList::_DeviceUnmounted(BMessage *message)
void void
RVolumeList::_MountPointMoved(BMessage *message) RVolumeList::_MountPointMoved(BMessage *message)
{ {
// Note: The "device" field of the message refers to the device of the
// parent directory. Therefore we need to get an entry_ref, turn it into
// a path and get the device for that path.
// get the message fields
dev_t device; dev_t device;
if (message->FindInt32("device", &device) == B_OK) { ino_t directory;
PRINT(("RVolumeList::_MountPointMoved(%ld)\n", device)); const char *name;
if (RVolume *volume = fVolumes.FindIf(CompareIDPredicate(device))) { if (message->FindInt32("device", &device) == B_OK
if (fListener) && message->FindInt64("to directory", &directory) == B_OK
fListener->MountPointMoved(volume); && message->FindString("name", &name) == B_OK) {
// init an entry_ref
entry_ref ref;
ref.device = device;
ref.directory = directory;
ref.set_name(name);
// get the path and the device for that path
BPath path;
if (path.SetTo(&ref) == B_OK
&& (device = dev_for_path(path.Path())) >= 0) {
PRINT(("RVolumeList::_MountPointMoved(%ld)\n", device));
if (RVolume *volume = fVolumes.FindIf(CompareIDPredicate(device))) {
entry_ref oldRoot;
volume->GetRootDirEntry(&oldRoot);
volume->SetRootDirEntry(&ref);
if (fListener)
fListener->MountPointMoved(volume, &oldRoot, &ref);
}
} }
} }
} }
+13 -5
View File
@@ -6,6 +6,7 @@
#ifndef VOLUME_LIST_H #ifndef VOLUME_LIST_H
#define VOLUME_LIST_H #define VOLUME_LIST_H
#include <Entry.h>
#include <Messenger.h> #include <Messenger.h>
#include <Node.h> #include <Node.h>
#include <ObjectList.h> #include <ObjectList.h>
@@ -26,17 +27,21 @@ public:
dev_t ID() const { return fID; } dev_t ID() const { return fID; }
ino_t RootNode() const { return fRootNode; } ino_t RootNode() const { return fRootNode; }
void GetRootNodeRef(node_ref *ref) const void GetRootDirNode(node_ref *ref) const
{ ref->device = fID; ref->node = fRootNode; } { ref->device = fID; ref->node = fRootNode; }
void GetRootDirEntry(entry_ref *ref) const { *ref = fRootEntry; }
const char *DevicePath() const { return fDevicePath; } const char *DevicePath() const { return fDevicePath; }
void SetRootDirEntry(const entry_ref *ref) { fRootEntry = *ref; }
status_t StartWatching(BMessenger target) const; status_t StartWatching(BMessenger target) const;
status_t StopWatching(BMessenger target) const; status_t StopWatching(BMessenger target) const;
private: private:
dev_t fID; dev_t fID;
ino_t fRootNode; ino_t fRootNode;
char fDevicePath[B_FILE_NAME_LENGTH]; entry_ref fRootEntry;
char fDevicePath[B_FILE_NAME_LENGTH];
}; };
// RVolumeListListener // RVolumeListListener
@@ -47,7 +52,9 @@ public:
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 *newRoot);
}; };
// RVolumeList // RVolumeList
@@ -71,6 +78,7 @@ public:
private: private:
RVolume *_AddVolume(dev_t id); RVolume *_AddVolume(dev_t id);
bool _RemoveVolumeAt(int32 index);
void _DeviceMounted(BMessage *message); void _DeviceMounted(BMessage *message);
void _DeviceUnmounted(BMessage *message); void _DeviceUnmounted(BMessage *message);
void _MountPointMoved(BMessage *message); void _MountPointMoved(BMessage *message);