* RVolumeList:
- Added locking, listener support. - Changed message handling from BHandler to MessageHandler interface. - Fixed bugs. * RDiskDeviceList: - Locking uses an external lock now (the same one as the volume list) - Prepared for message handling (MessageHandler). * DiskDeviceManager: - Added priority message queue and message handler thread -- should be more or less complete now. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2644 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
e81c38c154
commit
26dd5fd531
@ -3,28 +3,49 @@
|
||||
// by the OpenBeOS license.
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
#include <NodeMonitor.h>
|
||||
#include <RegistrarDefs.h>
|
||||
|
||||
#include "DiskDeviceManager.h"
|
||||
|
||||
enum {
|
||||
REQUEST_PRIORITY = 0,
|
||||
NODE_MONITOR_PRIORITY = 10,
|
||||
};
|
||||
|
||||
// constructor
|
||||
DiskDeviceManager::DiskDeviceManager()
|
||||
: BLooper("disk device manager"),
|
||||
fDeviceList(),
|
||||
fVolumeList()
|
||||
fDeviceListLock(),
|
||||
fVolumeList(BMessenger(this), fDeviceListLock),
|
||||
fDeviceList(BMessenger(this), fDeviceListLock, fVolumeList),
|
||||
fMessageQueue(),
|
||||
fWorker(-1),
|
||||
fMessageCounter(-1),
|
||||
fTerminating(false)
|
||||
{
|
||||
AddHandler(&fVolumeList);
|
||||
// set up the device list
|
||||
fVolumeList.Rescan();
|
||||
fVolumeList.Dump();
|
||||
fDeviceList.Rescan();
|
||||
fDeviceList.Dump();
|
||||
// start the worker thread
|
||||
fMessageCounter = create_sem(0, "disk device manager msgcounter");
|
||||
if (fMessageCounter >= 0) {
|
||||
fWorker = spawn_thread(_WorkerEntry, "disk device manager worker",
|
||||
B_NORMAL_PRIORITY, this);
|
||||
if (fWorker >= 0)
|
||||
resume_thread(fWorker);
|
||||
}
|
||||
}
|
||||
|
||||
// destructor
|
||||
DiskDeviceManager::~DiskDeviceManager()
|
||||
{
|
||||
Lock();
|
||||
RemoveHandler(&fVolumeList);
|
||||
Unlock();
|
||||
fTerminating = true;
|
||||
delete_sem(fMessageCounter);
|
||||
int32 dummy;
|
||||
wait_for_thread(fWorker, &dummy);
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
@ -37,6 +58,14 @@ DiskDeviceManager::MessageReceived(BMessage *message)
|
||||
case B_REG_UPDATE_DISK_DEVICE:
|
||||
case B_REG_DEVICE_START_WATCHING:
|
||||
case B_REG_DEVICE_STOP_WATCHING:
|
||||
DetachCurrentMessage();
|
||||
if (!_PushMessage(message, REQUEST_PRIORITY))
|
||||
delete message;
|
||||
break;
|
||||
case B_NODE_MONITOR:
|
||||
DetachCurrentMessage();
|
||||
if (!_PushMessage(message, NODE_MONITOR_PRIORITY))
|
||||
delete message;
|
||||
break;
|
||||
default:
|
||||
BLooper::MessageReceived(message);
|
||||
@ -44,3 +73,69 @@ DiskDeviceManager::MessageReceived(BMessage *message)
|
||||
}
|
||||
}
|
||||
|
||||
// _PushMessage
|
||||
bool
|
||||
DiskDeviceManager::_PushMessage(BMessage *message, int32 priority)
|
||||
{
|
||||
bool result = fMessageQueue.PushMessage(message, priority);
|
||||
if (result)
|
||||
release_sem(fMessageCounter);
|
||||
return result;
|
||||
}
|
||||
|
||||
// _PopMessage
|
||||
BMessage *
|
||||
DiskDeviceManager::_PopMessage()
|
||||
{
|
||||
BMessage *result = NULL;
|
||||
status_t error = acquire_sem(fMessageCounter);
|
||||
if (error == B_OK)
|
||||
result = fMessageQueue.PopMessage();
|
||||
return result;
|
||||
}
|
||||
|
||||
// _WorkerEntry
|
||||
int32
|
||||
DiskDeviceManager::_WorkerEntry(void *parameters)
|
||||
{
|
||||
return static_cast<DiskDeviceManager*>(parameters)->_Worker();
|
||||
}
|
||||
|
||||
// _Worker
|
||||
int32
|
||||
DiskDeviceManager::_Worker()
|
||||
{
|
||||
while (!fTerminating) {
|
||||
if (BMessage *message = _PopMessage()) {
|
||||
// dispatch the message
|
||||
switch (message->what) {
|
||||
case B_REG_NEXT_DISK_DEVICE:
|
||||
case B_REG_GET_DISK_DEVICE:
|
||||
case B_REG_UPDATE_DISK_DEVICE:
|
||||
case B_REG_DEVICE_START_WATCHING:
|
||||
case B_REG_DEVICE_STOP_WATCHING:
|
||||
fDeviceList.HandleMessage(message);
|
||||
break;
|
||||
case B_NODE_MONITOR:
|
||||
{
|
||||
int32 opcode = 0;
|
||||
if (message->FindInt32("opcode", &opcode) == B_OK) {
|
||||
if (opcode == B_DEVICE_MOUNTED
|
||||
|| opcode == B_DEVICE_UNMOUNTED) {
|
||||
fVolumeList.HandleMessage(message);
|
||||
} else {
|
||||
fDeviceList.HandleMessage(message);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// error
|
||||
break;
|
||||
}
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,11 @@
|
||||
#ifndef DISK_DEVICE_MANAGER_H
|
||||
#define DISK_DEVICE_MANAGER_H
|
||||
|
||||
#include <Locker.h>
|
||||
#include <Looper.h>
|
||||
#include <OS.h>
|
||||
|
||||
#include "PriorityMessageQueue.h"
|
||||
#include "RDiskDeviceList.h"
|
||||
#include "RVolumeList.h"
|
||||
|
||||
@ -19,8 +22,20 @@ public:
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
|
||||
private:
|
||||
RDiskDeviceList fDeviceList;
|
||||
RVolumeList fVolumeList;
|
||||
bool _PushMessage(BMessage *message, int32 priority);
|
||||
BMessage *_PopMessage();
|
||||
|
||||
static int32 _WorkerEntry(void *parameters);
|
||||
int32 _Worker();
|
||||
|
||||
private:
|
||||
BLocker fDeviceListLock;
|
||||
RVolumeList fVolumeList;
|
||||
RDiskDeviceList fDeviceList;
|
||||
PriorityMessageQueue fMessageQueue;
|
||||
thread_id fWorker;
|
||||
sem_id fMessageCounter;
|
||||
bool fTerminating;
|
||||
};
|
||||
|
||||
#endif // DISK_DEVICE_MANAGER_H
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <Directory.h>
|
||||
#include <Drivers.h>
|
||||
#include <Entry.h>
|
||||
//#include <ObjectLocker.h>
|
||||
#include <Locker.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include "RDiskDeviceList.h"
|
||||
@ -72,12 +72,18 @@ private:
|
||||
};
|
||||
|
||||
// constructor
|
||||
RDiskDeviceList::RDiskDeviceList()
|
||||
: fLock(),
|
||||
RDiskDeviceList::RDiskDeviceList(BMessenger target, BLocker &lock,
|
||||
RVolumeList &volumeList)
|
||||
: MessageHandler(),
|
||||
RVolumeListListener(),
|
||||
fLock(lock),
|
||||
fTarget(target),
|
||||
fVolumeList(volumeList),
|
||||
fDevices(20, true),
|
||||
fSessions(40, false),
|
||||
fPartitions(80, false)
|
||||
{
|
||||
fVolumeList.SetListener(this);
|
||||
}
|
||||
|
||||
// destructor
|
||||
@ -85,6 +91,34 @@ RDiskDeviceList::~RDiskDeviceList()
|
||||
{
|
||||
}
|
||||
|
||||
// HandleMessage
|
||||
void
|
||||
RDiskDeviceList::HandleMessage(BMessage *message)
|
||||
{
|
||||
if (Lock()) {
|
||||
switch (message->what) {
|
||||
default:
|
||||
MessageHandler::HandleMessage(message);
|
||||
break;
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// VolumeMounted
|
||||
void
|
||||
RDiskDeviceList::VolumeMounted(const RVolume *volume)
|
||||
{
|
||||
PRINT(("RDiskDeviceList::VolumeMounted(%ld)\n", volume->ID()));
|
||||
}
|
||||
|
||||
// VolumeUnmounted
|
||||
void
|
||||
RDiskDeviceList::VolumeUnmounted(const RVolume *volume)
|
||||
{
|
||||
PRINT(("RDiskDeviceList::VolumeUnmounted(%ld)\n", volume->ID()));
|
||||
}
|
||||
|
||||
// AddDevice
|
||||
bool
|
||||
RDiskDeviceList::AddDevice(RDiskDevice *device)
|
||||
|
@ -6,21 +6,30 @@
|
||||
#ifndef DISK_DEVICE_LIST_H
|
||||
#define DISK_DEVICE_LIST_H
|
||||
|
||||
#include <Locker.h>
|
||||
#include <Messenger.h>
|
||||
#include <ObjectList.h>
|
||||
|
||||
#include "MessageHandler.h"
|
||||
#include "RVolumeList.h"
|
||||
|
||||
class BDirectory;
|
||||
class BEntry;
|
||||
class BLocker;
|
||||
|
||||
class RDiskDevice;
|
||||
class RPartition;
|
||||
class RSession;
|
||||
|
||||
class RDiskDeviceList {
|
||||
class RDiskDeviceList : public MessageHandler, public RVolumeListListener {
|
||||
public:
|
||||
RDiskDeviceList();
|
||||
RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList);
|
||||
~RDiskDeviceList();
|
||||
|
||||
virtual void HandleMessage(BMessage *message);
|
||||
|
||||
void RDiskDeviceList::VolumeMounted(const RVolume *volume);
|
||||
void RDiskDeviceList::VolumeUnmounted(const RVolume *volume);
|
||||
|
||||
bool AddDevice(RDiskDevice *device);
|
||||
bool RemoveDevice(int32 index);
|
||||
bool RemoveDevice(RDiskDevice *device);
|
||||
@ -59,7 +68,9 @@ private:
|
||||
status_t _ScanDevice(const char *path);
|
||||
|
||||
private:
|
||||
BLocker fLock;
|
||||
mutable BLocker &fLock;
|
||||
BMessenger fTarget;
|
||||
RVolumeList &fVolumeList;
|
||||
BObjectList<RDiskDevice> fDevices; // sorted by ID
|
||||
BObjectList<RSession> fSessions; //
|
||||
BObjectList<RPartition> fPartitions; //
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <Locker.h>
|
||||
#include <Message.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Volume.h>
|
||||
@ -79,66 +80,84 @@ RVolume::Unset()
|
||||
}
|
||||
|
||||
|
||||
// RVolumeListListener
|
||||
|
||||
// constructor
|
||||
RVolumeListListener::RVolumeListListener()
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
RVolumeListListener::~RVolumeListListener()
|
||||
{
|
||||
}
|
||||
|
||||
// VolumeMounted
|
||||
void
|
||||
RVolumeListListener::VolumeMounted(const RVolume *volume)
|
||||
{
|
||||
}
|
||||
|
||||
// VolumeUnmounted
|
||||
void
|
||||
RVolumeListListener::VolumeUnmounted(const RVolume *volume)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// RVolumeList
|
||||
|
||||
// constructor
|
||||
RVolumeList::RVolumeList()
|
||||
: BHandler(),
|
||||
RVolumeList::RVolumeList(BMessenger target, BLocker &lock)
|
||||
: MessageHandler(),
|
||||
fLock(lock),
|
||||
fTarget(target),
|
||||
fVolumes(20, true),
|
||||
fRoster()
|
||||
fRoster(),
|
||||
fListener(NULL)
|
||||
{
|
||||
// TODO: Remove work-around. At this time R5 libbe's watching functions don't
|
||||
// work for us. We have an own implementation in `NodeMonitoring.cpp'.
|
||||
// fRoster.StartWatching(BMessenger(this));
|
||||
watch_node(NULL, B_WATCH_MOUNT, fTarget);
|
||||
Rescan();
|
||||
}
|
||||
|
||||
// destructor
|
||||
RVolumeList::~RVolumeList()
|
||||
{
|
||||
}
|
||||
|
||||
// MessageReceived
|
||||
void
|
||||
RVolumeList::MessageReceived(BMessage *message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case B_NODE_MONITOR:
|
||||
{
|
||||
int32 opcode = 0;
|
||||
if (message->FindInt32("opcode", &opcode) == B_OK) {
|
||||
switch (opcode) {
|
||||
case B_DEVICE_MOUNTED:
|
||||
_DeviceMounted(message);
|
||||
break;
|
||||
case B_DEVICE_UNMOUNTED:
|
||||
_DeviceUnmounted(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
BHandler::MessageReceived(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// SetNextHandler
|
||||
void
|
||||
RVolumeList::SetNextHandler(BHandler *handler)
|
||||
{
|
||||
// stop watching volumes, if removed from looper
|
||||
if (!handler) {
|
||||
// TODO: Remove work-around. At this time R5 libbe's watching functions don't
|
||||
// work for us. We have an own implementation in `NodeMonitoring.cpp'.
|
||||
// fRoster.StopWatching();
|
||||
stop_watching(BMessenger(this));
|
||||
}
|
||||
BHandler::SetNextHandler(handler);
|
||||
// start watching volumes and rescan list, if added to looper
|
||||
if (handler) {
|
||||
// TODO: Remove work-around. At this time R5 libbe's watching functions don't
|
||||
// work for us. We have an own implementation in `NodeMonitoring.cpp'.
|
||||
// fRoster.StartWatching(BMessenger(this));
|
||||
watch_node(NULL, B_WATCH_MOUNT, BMessenger(this));
|
||||
Rescan();
|
||||
stop_watching(fTarget);
|
||||
}
|
||||
|
||||
// HandleMessage
|
||||
void
|
||||
RVolumeList::HandleMessage(BMessage *message)
|
||||
{
|
||||
if (Lock()) {
|
||||
switch (message->what) {
|
||||
case B_NODE_MONITOR:
|
||||
{
|
||||
int32 opcode = 0;
|
||||
if (message->FindInt32("opcode", &opcode) == B_OK) {
|
||||
switch (opcode) {
|
||||
case B_DEVICE_MOUNTED:
|
||||
_DeviceMounted(message);
|
||||
break;
|
||||
case B_DEVICE_UNMOUNTED:
|
||||
_DeviceUnmounted(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MessageHandler::HandleMessage(message);
|
||||
break;
|
||||
}
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,23 +177,37 @@ RVolumeList::Rescan()
|
||||
const RVolume *
|
||||
RVolumeList::VolumeForDevicePath(const char *devicePath) const
|
||||
{
|
||||
// TODO: ...
|
||||
return NULL;
|
||||
const RVolume *volume = NULL;
|
||||
if (devicePath && fLock.Lock()) {
|
||||
bool found = false;
|
||||
int32 index = fVolumes.FindBinaryInsertionIndex(
|
||||
CompareDevicePathPredicate(devicePath), &found);
|
||||
if (found)
|
||||
volume = fVolumes.ItemAt(index);
|
||||
fLock.Unlock();
|
||||
}
|
||||
return volume;
|
||||
}
|
||||
|
||||
// Lock
|
||||
bool
|
||||
RVolumeList::Lock()
|
||||
{
|
||||
// TODO: ...
|
||||
return false;
|
||||
return fLock.Lock();
|
||||
}
|
||||
|
||||
// Unlock
|
||||
void
|
||||
RVolumeList::Unlock()
|
||||
{
|
||||
// TODO: ...
|
||||
fLock.Unlock();
|
||||
}
|
||||
|
||||
// SetListener
|
||||
void
|
||||
RVolumeList::SetListener(RVolumeListListener *listener)
|
||||
{
|
||||
fListener = listener;
|
||||
}
|
||||
|
||||
// Dump
|
||||
@ -189,21 +222,24 @@ RVolumeList::Dump() const
|
||||
}
|
||||
|
||||
// _AddVolume
|
||||
void
|
||||
RVolume *
|
||||
RVolumeList::_AddVolume(dev_t id)
|
||||
{
|
||||
if (RVolume *volume = new RVolume) {
|
||||
RVolume *volume = new RVolume;
|
||||
if (volume) {
|
||||
status_t error = volume->SetTo(id);
|
||||
if (error == B_OK) {
|
||||
fVolumes.BinaryInsert(volume,
|
||||
CompareDevicePathPredicate(volume->DevicePath()));
|
||||
} else {
|
||||
delete volume;
|
||||
volume = NULL;
|
||||
PRINT(("RVolumeList::_AddVolume(): initializing RVolume failed: "
|
||||
"%s\n", strerror(error)));
|
||||
}
|
||||
} else
|
||||
PRINT(("RVolumeList::_AddVolume(): no memory!\n"));
|
||||
return volume;
|
||||
}
|
||||
|
||||
// _DeviceMounted
|
||||
@ -213,7 +249,10 @@ RVolumeList::_DeviceMounted(BMessage *message)
|
||||
dev_t device;
|
||||
if (message->FindInt32("new device", &device) == B_OK) {
|
||||
PRINT(("RVolumeList::_DeviceMounted(%ld)\n", device));
|
||||
_AddVolume(device);
|
||||
if (RVolume *volume = _AddVolume(device)) {
|
||||
if (fListener)
|
||||
fListener->VolumeMounted(volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,8 +263,12 @@ RVolumeList::_DeviceUnmounted(BMessage *message)
|
||||
dev_t device;
|
||||
if (message->FindInt32("device", &device) == B_OK) {
|
||||
PRINT(("RVolumeList::_DeviceUnmounted(%ld)\n", device));
|
||||
if (RVolume *volume = fVolumes.FindIf(CompareIDPredicate(volume)))
|
||||
fVolumes.RemoveItem(volume);
|
||||
if (RVolume *volume = fVolumes.FindIf(CompareIDPredicate(device))) {
|
||||
fVolumes.RemoveItem(volume, false);
|
||||
if (fListener)
|
||||
fListener->VolumeUnmounted(volume);
|
||||
delete volume;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,11 +6,15 @@
|
||||
#ifndef VOLUME_LIST_H
|
||||
#define VOLUME_LIST_H
|
||||
|
||||
#include <Handler.h>
|
||||
#include <Messenger.h>
|
||||
#include <Node.h>
|
||||
#include <ObjectList.h>
|
||||
#include <VolumeRoster.h>
|
||||
|
||||
#include "MessageHandler.h"
|
||||
|
||||
class BLocker;
|
||||
|
||||
// RVolume
|
||||
class RVolume {
|
||||
public:
|
||||
@ -32,14 +36,23 @@ private:
|
||||
char fDevicePath[B_FILE_NAME_LENGTH];
|
||||
};
|
||||
|
||||
// RVolumeList
|
||||
class RVolumeList : public BHandler {
|
||||
// RVolumeListListener
|
||||
class RVolumeListListener {
|
||||
public:
|
||||
RVolumeList();
|
||||
RVolumeListListener();
|
||||
virtual ~RVolumeListListener();
|
||||
|
||||
virtual void VolumeMounted(const RVolume *volume);
|
||||
virtual void VolumeUnmounted(const RVolume *volume);
|
||||
};
|
||||
|
||||
// RVolumeList
|
||||
class RVolumeList : public MessageHandler {
|
||||
public:
|
||||
RVolumeList(BMessenger target, BLocker &lock);
|
||||
virtual ~RVolumeList();
|
||||
|
||||
virtual void MessageReceived(BMessage *message);
|
||||
virtual void SetNextHandler(BHandler *handler);
|
||||
virtual void HandleMessage(BMessage *message);
|
||||
|
||||
status_t Rescan();
|
||||
|
||||
@ -48,16 +61,21 @@ public:
|
||||
bool Lock();
|
||||
void Unlock();
|
||||
|
||||
void SetListener(RVolumeListListener *listener);
|
||||
|
||||
void Dump() const;
|
||||
|
||||
private:
|
||||
void _AddVolume(dev_t id);
|
||||
RVolume *_AddVolume(dev_t id);
|
||||
void _DeviceMounted(BMessage *message);
|
||||
void _DeviceUnmounted(BMessage *message);
|
||||
|
||||
private:
|
||||
mutable BLocker &fLock;
|
||||
BMessenger fTarget;
|
||||
BObjectList<RVolume> fVolumes;
|
||||
BVolumeRoster fRoster;
|
||||
RVolumeListListener *fListener;
|
||||
};
|
||||
|
||||
#endif // VOLUME_LIST_H
|
||||
|
Loading…
Reference in New Issue
Block a user