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:
parent
c947b11347
commit
30bb74bbd2
@ -7,30 +7,33 @@
|
||||
#include <RegistrarDefs.h>
|
||||
|
||||
#include "DiskDeviceManager.h"
|
||||
#include "Debug.h"
|
||||
#include "EventMaskWatcher.h"
|
||||
#include "RDiskDevice.h"
|
||||
#include "RDiskDeviceList.h"
|
||||
#include "RPartition.h"
|
||||
#include "RSession.h"
|
||||
#include "Debug.h"
|
||||
|
||||
enum {
|
||||
REQUEST_PRIORITY = 0,
|
||||
NODE_MONITOR_PRIORITY = 10,
|
||||
WATCHING_REQUEST_PRIORITY = 20,
|
||||
};
|
||||
|
||||
// constructor
|
||||
DiskDeviceManager::DiskDeviceManager()
|
||||
: BLooper("disk device manager"),
|
||||
fDeviceListLock(),
|
||||
fWatchingService(),
|
||||
fVolumeList(BMessenger(this), fDeviceListLock),
|
||||
fDeviceList(BMessenger(this), fDeviceListLock, fVolumeList),
|
||||
fDeviceList(BMessenger(this), fDeviceListLock, fVolumeList,
|
||||
&fWatchingService),
|
||||
fMessageQueue(),
|
||||
fWorker(-1),
|
||||
fMessageCounter(-1),
|
||||
fTerminating(false)
|
||||
{
|
||||
// set up the device list
|
||||
fVolumeList.Rescan();
|
||||
fVolumeList.Dump();
|
||||
fDeviceList.Rescan();
|
||||
fDeviceList.Dump();
|
||||
@ -61,10 +64,14 @@ DiskDeviceManager::MessageReceived(BMessage *message)
|
||||
case B_REG_NEXT_DISK_DEVICE:
|
||||
case B_REG_GET_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_STOP_WATCHING:
|
||||
DetachCurrentMessage();
|
||||
if (!_PushMessage(message, REQUEST_PRIORITY))
|
||||
if (!_PushMessage(message, WATCHING_REQUEST_PRIORITY))
|
||||
delete message;
|
||||
break;
|
||||
case B_NODE_MONITOR:
|
||||
@ -80,13 +87,14 @@ DiskDeviceManager::MessageReceived(BMessage *message)
|
||||
|
||||
// _NextDiskDeviceRequest
|
||||
void
|
||||
DiskDeviceManager::_NextDiskDeviceRequest(BMessage *message)
|
||||
DiskDeviceManager::_NextDiskDeviceRequest(BMessage *request)
|
||||
{
|
||||
FUNCTION_START();
|
||||
Lock();
|
||||
status_t error = B_OK;
|
||||
int32 cookie = 0;
|
||||
BMessage reply(B_REG_RESULT);
|
||||
if (message->FindInt32("cookie", &cookie) == B_OK) {
|
||||
if (request->FindInt32("cookie", &cookie) == B_OK) {
|
||||
// get next device
|
||||
if (RDiskDevice *device = fDeviceList.DeviceWithID(cookie, false)) {
|
||||
// archive device
|
||||
@ -103,23 +111,25 @@ DiskDeviceManager::_NextDiskDeviceRequest(BMessage *message)
|
||||
SET_ERROR(error, B_BAD_VALUE);
|
||||
// add result and send reply
|
||||
reply.AddInt32("result", error);
|
||||
message->SendReply(&reply);
|
||||
request->SendReply(&reply);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// _GetDiskDeviceRequest
|
||||
void
|
||||
DiskDeviceManager::_GetDiskDeviceRequest(BMessage *message)
|
||||
DiskDeviceManager::_GetDiskDeviceRequest(BMessage *request)
|
||||
{
|
||||
Lock();
|
||||
status_t error = B_ENTRY_NOT_FOUND;
|
||||
// get the device
|
||||
RDiskDevice *device = NULL;
|
||||
int32 id = 0;
|
||||
if (message->FindInt32("device_id", &id) == B_OK)
|
||||
if (request->FindInt32("device_id", &id) == B_OK)
|
||||
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))
|
||||
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))
|
||||
device = partition->Device();
|
||||
} else
|
||||
@ -134,13 +144,15 @@ DiskDeviceManager::_GetDiskDeviceRequest(BMessage *message)
|
||||
}
|
||||
// add result and send reply
|
||||
reply.AddInt32("result", error);
|
||||
message->SendReply(&reply);
|
||||
request->SendReply(&reply);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// _UpdateDiskDeviceRequest
|
||||
void
|
||||
DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message)
|
||||
DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *request)
|
||||
{
|
||||
Lock();
|
||||
status_t error = B_ENTRY_NOT_FOUND;
|
||||
// get the device and check the object is up to date
|
||||
bool upToDate = false;
|
||||
@ -148,20 +160,20 @@ DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message)
|
||||
int32 id = 0;
|
||||
int32 changeCounter = 0;
|
||||
uint32 policy = 0;
|
||||
if (message->FindInt32("change_counter", &changeCounter) != B_OK
|
||||
|| message->FindInt32("update_policy", (int32*)&policy) != B_OK) {
|
||||
// bad request message
|
||||
if (request->FindInt32("change_counter", &changeCounter) != B_OK
|
||||
|| request->FindInt32("update_policy", (int32*)&policy) != B_OK) {
|
||||
// bad request request
|
||||
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);
|
||||
if (device)
|
||||
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)) {
|
||||
device = session->Device();
|
||||
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)) {
|
||||
device = partition->Device();
|
||||
upToDate = (partition->ChangeCounter() == changeCounter);
|
||||
@ -184,9 +196,66 @@ DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message)
|
||||
if (error == B_OK)
|
||||
error = reply.AddBool("up_to_date", upToDate);
|
||||
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
|
||||
bool
|
||||
DiskDeviceManager::_PushMessage(BMessage *message, int32 priority)
|
||||
@ -233,7 +302,10 @@ DiskDeviceManager::_Worker()
|
||||
_UpdateDiskDeviceRequest(message);
|
||||
break;
|
||||
case B_REG_DEVICE_START_WATCHING:
|
||||
_StartWatchingRequest(message);
|
||||
break;
|
||||
case B_REG_DEVICE_STOP_WATCHING:
|
||||
_StopWatchingRequest(message);
|
||||
break;
|
||||
case B_NODE_MONITOR:
|
||||
{
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "PriorityMessageQueue.h"
|
||||
#include "RDiskDeviceList.h"
|
||||
#include "RVolumeList.h"
|
||||
#include "WatchingService.h"
|
||||
|
||||
class DiskDeviceManager : public BLooper {
|
||||
public:
|
||||
@ -23,9 +24,11 @@ public:
|
||||
|
||||
private:
|
||||
// requests
|
||||
void _NextDiskDeviceRequest(BMessage *message);
|
||||
void _GetDiskDeviceRequest(BMessage *message);
|
||||
void _UpdateDiskDeviceRequest(BMessage *message);
|
||||
void _NextDiskDeviceRequest(BMessage *request);
|
||||
void _GetDiskDeviceRequest(BMessage *request);
|
||||
void _UpdateDiskDeviceRequest(BMessage *request);
|
||||
void _StartWatchingRequest(BMessage *request);
|
||||
void _StopWatchingRequest(BMessage *request);
|
||||
|
||||
bool _PushMessage(BMessage *message, int32 priority);
|
||||
BMessage *_PopMessage();
|
||||
@ -35,6 +38,7 @@ private:
|
||||
|
||||
private:
|
||||
BLocker fDeviceListLock;
|
||||
WatchingService fWatchingService;
|
||||
RVolumeList fVolumeList;
|
||||
RDiskDeviceList fDeviceList;
|
||||
PriorityMessageQueue fMessageQueue;
|
||||
|
@ -141,10 +141,10 @@ RDiskDevice::RemoveSession(int32 index)
|
||||
{
|
||||
RSession *session = SessionAt(index);
|
||||
if (session) {
|
||||
session->SetDevice(NULL);
|
||||
fSessions.RemoveItemAt(index);
|
||||
if (RDiskDeviceList *deviceList = DeviceList())
|
||||
deviceList->SessionRemoved(session);
|
||||
session->SetDevice(NULL);
|
||||
fSessions.RemoveItemAt(index);
|
||||
delete session;
|
||||
}
|
||||
return (session != NULL);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <Directory.h>
|
||||
#include <DiskDeviceRoster.h>
|
||||
#include <Drivers.h>
|
||||
#include <Entry.h>
|
||||
#include <Locker.h>
|
||||
@ -19,24 +20,13 @@
|
||||
|
||||
#include "RDiskDeviceList.h"
|
||||
#include "Debug.h"
|
||||
#include "EventMaskWatcher.h"
|
||||
#include "RDiskDevice.h"
|
||||
#include "RPartition.h"
|
||||
#include "RSession.h"
|
||||
#include "WatchingService.h"
|
||||
|
||||
// compare_ids
|
||||
/*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;
|
||||
}*/
|
||||
namespace RDiskDeviceListPredicates {
|
||||
|
||||
// CompareIDPredicate
|
||||
template <typename T>
|
||||
@ -71,14 +61,36 @@ private:
|
||||
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
|
||||
RDiskDeviceList::RDiskDeviceList(BMessenger target, BLocker &lock,
|
||||
RVolumeList &volumeList)
|
||||
RVolumeList &volumeList,
|
||||
WatchingService *watchingService)
|
||||
: MessageHandler(),
|
||||
RVolumeListListener(),
|
||||
fLock(lock),
|
||||
fTarget(target),
|
||||
fVolumeList(volumeList),
|
||||
fWatchingService(watchingService),
|
||||
fDevices(20, true),
|
||||
fSessions(40, false),
|
||||
fPartitions(80, false)
|
||||
@ -110,6 +122,21 @@ void
|
||||
RDiskDeviceList::VolumeMounted(const RVolume *volume)
|
||||
{
|
||||
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(¬ification,
|
||||
B_DEVICE_PARTITION_MOUNTED, B_DEVICE_CAUSE_UNKNOWN,
|
||||
partition) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNTING);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// VolumeUnmounted
|
||||
@ -117,13 +144,46 @@ void
|
||||
RDiskDeviceList::VolumeUnmounted(const RVolume *volume)
|
||||
{
|
||||
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(¬ification,
|
||||
B_DEVICE_PARTITION_UNMOUNTED, B_DEVICE_CAUSE_UNKNOWN,
|
||||
partition) == B_OK) {
|
||||
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_MOUNTING);
|
||||
fWatchingService->NotifyWatchers(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// MountPointMoved
|
||||
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()));
|
||||
Lock();
|
||||
// get the partition
|
||||
const char *devicePath = volume->DevicePath();
|
||||
if (RPartition *partition = PartitionWithPath(devicePath)) {
|
||||
// send notifications
|
||||
BMessage notification(B_DEVICE_UPDATE);
|
||||
if (_InitNotificationMessage(¬ification,
|
||||
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(¬ification, &filter);
|
||||
}
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
|
||||
// AddDevice
|
||||
@ -145,9 +205,9 @@ RDiskDeviceList::RemoveDevice(int32 index)
|
||||
{
|
||||
RDiskDevice *device = DeviceAt(index);
|
||||
if (device) {
|
||||
DeviceRemoved(device);
|
||||
device->SetDeviceList(NULL);
|
||||
fDevices.RemoveItemAt(index);
|
||||
DeviceRemoved(device);
|
||||
delete device;
|
||||
}
|
||||
return (device != NULL);
|
||||
@ -206,6 +266,15 @@ RDiskDeviceList::DeviceWithPath(const char *path) const
|
||||
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
|
||||
status_t
|
||||
RDiskDeviceList::Rescan()
|
||||
@ -273,6 +342,8 @@ RDiskDeviceList::DeviceRemoved(RDiskDevice *device, uint32 cause)
|
||||
void
|
||||
RDiskDeviceList::SessionAdded(RSession *session, uint32 cause)
|
||||
{
|
||||
// add the session to our list
|
||||
fSessions.BinaryInsert(session, CompareIDPredicate<RSession>(session));
|
||||
// propagate to partitions
|
||||
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
|
||||
PartitionAdded(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
|
||||
@ -284,6 +355,12 @@ RDiskDeviceList::SessionAdded(RSession *session, uint32 cause)
|
||||
void
|
||||
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
|
||||
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
|
||||
PartitionRemoved(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
|
||||
@ -295,6 +372,9 @@ RDiskDeviceList::SessionRemoved(RSession *session, uint32 cause)
|
||||
void
|
||||
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
|
||||
char path[B_FILE_NAME_LENGTH];
|
||||
partition->GetPath(path);
|
||||
@ -308,6 +388,12 @@ RDiskDeviceList::PartitionAdded(RPartition *partition, uint32 cause)
|
||||
void
|
||||
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
|
||||
// ...
|
||||
}
|
||||
@ -393,3 +479,64 @@ RDiskDeviceList::_ScanDevice(const char *path)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ class BLocker;
|
||||
class RDiskDevice;
|
||||
class RPartition;
|
||||
class RSession;
|
||||
class WatchingService;
|
||||
|
||||
// device list modification causes
|
||||
// TODO: to be moved to <DiskDeviceRoster.h>
|
||||
@ -36,14 +37,17 @@ enum {
|
||||
|
||||
class RDiskDeviceList : public MessageHandler, public RVolumeListListener {
|
||||
public:
|
||||
RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList);
|
||||
RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList,
|
||||
WatchingService *watchingService);
|
||||
~RDiskDeviceList();
|
||||
|
||||
virtual void HandleMessage(BMessage *message);
|
||||
|
||||
virtual void VolumeMounted(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 RemoveDevice(int32 index);
|
||||
@ -63,6 +67,7 @@ public:
|
||||
RPartition *PartitionWithID(int32 id) const;
|
||||
|
||||
RDiskDevice *DeviceWithPath(const char *path) const;
|
||||
RPartition *PartitionWithPath(const char *path) const;
|
||||
|
||||
status_t Rescan();
|
||||
|
||||
@ -88,10 +93,21 @@ private:
|
||||
status_t _Scan(BDirectory &dir);
|
||||
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:
|
||||
mutable BLocker &fLock;
|
||||
BMessenger fTarget;
|
||||
RVolumeList &fVolumeList;
|
||||
WatchingService *fWatchingService;
|
||||
BObjectList<RDiskDevice> fDevices; // sorted by ID
|
||||
BObjectList<RSession> fSessions; //
|
||||
BObjectList<RPartition> fPartitions; //
|
||||
|
@ -109,10 +109,10 @@ RSession::RemovePartition(int32 index)
|
||||
{
|
||||
RPartition *partition = PartitionAt(index);
|
||||
if (partition) {
|
||||
partition->SetSession(NULL);
|
||||
fPartitions.RemoveItemAt(index);
|
||||
if (RDiskDeviceList *deviceList = DeviceList())
|
||||
deviceList->PartitionRemoved(partition);
|
||||
partition->SetSession(NULL);
|
||||
fPartitions.RemoveItemAt(index);
|
||||
delete partition;
|
||||
}
|
||||
return (partition != NULL);
|
||||
|
@ -5,14 +5,19 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <Locker.h>
|
||||
#include <Message.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
#include <Volume.h>
|
||||
|
||||
#include "RVolumeList.h"
|
||||
#include "Debug.h"
|
||||
|
||||
namespace RVolumeListPredicates {
|
||||
|
||||
// CompareIDPredicate
|
||||
struct CompareIDPredicate : public UnaryPredicate<RVolume> {
|
||||
CompareIDPredicate(dev_t id) : fID(id) {}
|
||||
@ -45,13 +50,18 @@ private:
|
||||
const char *fPath;
|
||||
};
|
||||
|
||||
} // namespace RVolumeListPredicates
|
||||
|
||||
using namespace RVolumeListPredicates;
|
||||
|
||||
|
||||
// RVolume
|
||||
|
||||
// constructor
|
||||
RVolume::RVolume()
|
||||
: fID(-1),
|
||||
fRootNode(-1)
|
||||
fRootNode(-1),
|
||||
fRootEntry()
|
||||
{
|
||||
}
|
||||
|
||||
@ -60,13 +70,31 @@ status_t
|
||||
RVolume::SetTo(dev_t id)
|
||||
{
|
||||
status_t error = B_OK;
|
||||
// get general info
|
||||
fs_info info;
|
||||
error = fs_stat_dev(id, &info);
|
||||
if (error == B_OK) {
|
||||
fID = id;
|
||||
fRootNode = info.root;
|
||||
if (info.device_name[0] != '\0')
|
||||
strcpy(fDevicePath, info.device_name);
|
||||
} else
|
||||
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();
|
||||
return error;
|
||||
}
|
||||
@ -126,7 +154,9 @@ RVolumeListListener::VolumeUnmounted(const RVolume *volume)
|
||||
|
||||
// MountPointMoved
|
||||
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
|
||||
RVolumeList::Rescan()
|
||||
{
|
||||
fVolumes.MakeEmpty();
|
||||
PRINT(("RVolumeList::Rescan()\n"));
|
||||
for (int32 i = fVolumes.CountItems() - 1; i >= 0; i--)
|
||||
_RemoveVolumeAt(i);
|
||||
fRoster.Rewind();
|
||||
BVolume bVolume;
|
||||
while (fRoster.GetNextVolume(&bVolume) == B_OK)
|
||||
_AddVolume(bVolume.Device());
|
||||
return B_ERROR;
|
||||
PRINT(("RVolumeList::Rescan() done\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// VolumeForDevicePath
|
||||
@ -272,6 +305,18 @@ RVolumeList::_AddVolume(dev_t id)
|
||||
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
|
||||
void
|
||||
RVolumeList::_DeviceMounted(BMessage *message)
|
||||
@ -307,12 +352,33 @@ RVolumeList::_DeviceUnmounted(BMessage *message)
|
||||
void
|
||||
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;
|
||||
if (message->FindInt32("device", &device) == B_OK) {
|
||||
ino_t directory;
|
||||
const char *name;
|
||||
if (message->FindInt32("device", &device) == B_OK
|
||||
&& message->FindInt64("to directory", &directory) == B_OK
|
||||
&& 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);
|
||||
fListener->MountPointMoved(volume, &oldRoot, &ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#ifndef VOLUME_LIST_H
|
||||
#define VOLUME_LIST_H
|
||||
|
||||
#include <Entry.h>
|
||||
#include <Messenger.h>
|
||||
#include <Node.h>
|
||||
#include <ObjectList.h>
|
||||
@ -26,16 +27,20 @@ public:
|
||||
|
||||
dev_t ID() const { return fID; }
|
||||
ino_t RootNode() const { return fRootNode; }
|
||||
void GetRootNodeRef(node_ref *ref) const
|
||||
void GetRootDirNode(node_ref *ref) const
|
||||
{ ref->device = fID; ref->node = fRootNode; }
|
||||
void GetRootDirEntry(entry_ref *ref) const { *ref = fRootEntry; }
|
||||
const char *DevicePath() const { return fDevicePath; }
|
||||
|
||||
void SetRootDirEntry(const entry_ref *ref) { fRootEntry = *ref; }
|
||||
|
||||
status_t StartWatching(BMessenger target) const;
|
||||
status_t StopWatching(BMessenger target) const;
|
||||
|
||||
private:
|
||||
dev_t fID;
|
||||
ino_t fRootNode;
|
||||
entry_ref fRootEntry;
|
||||
char fDevicePath[B_FILE_NAME_LENGTH];
|
||||
};
|
||||
|
||||
@ -47,7 +52,9 @@ public:
|
||||
|
||||
virtual void VolumeMounted(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
|
||||
@ -71,6 +78,7 @@ public:
|
||||
|
||||
private:
|
||||
RVolume *_AddVolume(dev_t id);
|
||||
bool _RemoveVolumeAt(int32 index);
|
||||
void _DeviceMounted(BMessage *message);
|
||||
void _DeviceUnmounted(BMessage *message);
|
||||
void _MountPointMoved(BMessage *message);
|
||||
|
Loading…
Reference in New Issue
Block a user