* 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:
Ingo Weinhold 2003-02-06 23:39:54 +00:00
parent e81c38c154
commit 26dd5fd531
6 changed files with 295 additions and 79 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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; //

View File

@ -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;
}
}
}

View File

@ -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