From 3e377cc75a948efdf03cb1bd49aeb2c9de209c5c Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Tue, 4 Feb 2003 23:56:38 +0000 Subject: [PATCH] Added RVolumeList, which maintains an up-to-date list of mounted volumes. Will be used as helper for RDiskDeviceList. Not complete yet. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2634 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/registrar/DiskDeviceManager.cpp | 8 +- src/servers/registrar/DiskDeviceManager.h | 2 + src/servers/registrar/RVolumeList.cpp | 231 ++++++++++++++++++++ src/servers/registrar/RVolumeList.h | 63 ++++++ 4 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 src/servers/registrar/RVolumeList.cpp create mode 100644 src/servers/registrar/RVolumeList.h diff --git a/src/servers/registrar/DiskDeviceManager.cpp b/src/servers/registrar/DiskDeviceManager.cpp index e5c0afd942..76667d0845 100644 --- a/src/servers/registrar/DiskDeviceManager.cpp +++ b/src/servers/registrar/DiskDeviceManager.cpp @@ -10,8 +10,11 @@ // constructor DiskDeviceManager::DiskDeviceManager() : BLooper("disk device manager"), - fDeviceList() + fDeviceList(), + fVolumeList() { + AddHandler(&fVolumeList); + fVolumeList.Dump(); fDeviceList.Rescan(); fDeviceList.Dump(); } @@ -19,6 +22,9 @@ DiskDeviceManager::DiskDeviceManager() // destructor DiskDeviceManager::~DiskDeviceManager() { + Lock(); + RemoveHandler(&fVolumeList); + Unlock(); } // MessageReceived diff --git a/src/servers/registrar/DiskDeviceManager.h b/src/servers/registrar/DiskDeviceManager.h index 2c8b59d1a1..1d6c98ffda 100644 --- a/src/servers/registrar/DiskDeviceManager.h +++ b/src/servers/registrar/DiskDeviceManager.h @@ -9,6 +9,7 @@ #include #include "RDiskDeviceList.h" +#include "RVolumeList.h" class DiskDeviceManager : public BLooper { public: @@ -19,6 +20,7 @@ public: private: RDiskDeviceList fDeviceList; + RVolumeList fVolumeList; }; #endif // DISK_DEVICE_MANAGER_H diff --git a/src/servers/registrar/RVolumeList.cpp b/src/servers/registrar/RVolumeList.cpp new file mode 100644 index 0000000000..c636db1de4 --- /dev/null +++ b/src/servers/registrar/RVolumeList.cpp @@ -0,0 +1,231 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- + +#include + +#include +#include +#include + +#include "RVolumeList.h" +#include "Debug.h" + +// CompareIDPredicate +struct CompareIDPredicate : public UnaryPredicate { + CompareIDPredicate(dev_t id) : fID(id) {} + CompareIDPredicate(const RVolume *volume) : fID(volume->ID()) {} + + virtual int operator()(const RVolume *volume) const + { + dev_t id = volume->ID(); + if (fID < id) + return -1; + if (fID > id) + return 1; + return 0; + } + +private: + dev_t fID; +}; + +// CompareDevicePathPredicate +struct CompareDevicePathPredicate : public UnaryPredicate { + CompareDevicePathPredicate(const char *path) : fPath(path) {} + + virtual int operator()(const RVolume *volume) const + { + return strcmp(fPath, volume->DevicePath()); + } + +private: + const char *fPath; +}; + + +// RVolume + +// constructor +RVolume::RVolume() + : fID(-1), + fRootNode(-1) +{ +} + +// SetTo +status_t +RVolume::SetTo(dev_t id) +{ + status_t error = B_OK; + fs_info info; + error = fs_stat_dev(id, &info); + if (error == B_OK) { + fID = id; + fRootNode = info.root; + strcpy(fDevicePath, info.device_name); + } else + Unset(); + return error; +} + +// Unset +void +RVolume::Unset() +{ + fID = -1; + fRootNode = -1; +} + + +// RVolumeList + +// constructor +RVolumeList::RVolumeList() + : BHandler(), + fVolumes(20, true), + fRoster() +{ +} + +// 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(); + } +} + +// Rescan +status_t +RVolumeList::Rescan() +{ + fVolumes.MakeEmpty(); + fRoster.Rewind(); + BVolume bVolume; + while (fRoster.GetNextVolume(&bVolume) == B_OK) + _AddVolume(bVolume.Device()); + return B_ERROR; +} + +// VolumeForDevicePath +const RVolume * +RVolumeList::VolumeForDevicePath(const char *devicePath) const +{ +// TODO: ... + return NULL; +} + +// Lock +bool +RVolumeList::Lock() +{ +// TODO: ... + return false; +} + +// Unlock +void +RVolumeList::Unlock() +{ +// TODO: ... +} + +// Dump +void +RVolumeList::Dump() const +{ + for (int32 i = 0; RVolume *volume = fVolumes.ItemAt(i); i++) { + printf("volume %ld:\n", volume->ID()); + printf(" root node: %lld", volume->RootNode()); + printf(" device: `%s'\n", volume->DevicePath()); + } +} + +// _AddVolume +void +RVolumeList::_AddVolume(dev_t id) +{ + if (RVolume *volume = new RVolume) { + status_t error = volume->SetTo(id); + if (error == B_OK) { + fVolumes.BinaryInsert(volume, + CompareDevicePathPredicate(volume->DevicePath())); + } else { + delete volume; + PRINT(("RVolumeList::_AddVolume(): initializing RVolume failed: " + "%s\n", strerror(error))); + } + } else + PRINT(("RVolumeList::_AddVolume(): no memory!\n")); +} + +// _DeviceMounted +void +RVolumeList::_DeviceMounted(BMessage *message) +{ + dev_t device; + if (message->FindInt32("new device", &device) == B_OK) { + PRINT(("RVolumeList::_DeviceMounted(%ld)\n", device)); + _AddVolume(device); + } +} + +// _DeviceUnmounted +void +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); + } +} + diff --git a/src/servers/registrar/RVolumeList.h b/src/servers/registrar/RVolumeList.h new file mode 100644 index 0000000000..acf4bd4602 --- /dev/null +++ b/src/servers/registrar/RVolumeList.h @@ -0,0 +1,63 @@ +//---------------------------------------------------------------------- +// This software is part of the OpenBeOS distribution and is covered +// by the OpenBeOS license. +//--------------------------------------------------------------------- + +#ifndef VOLUME_LIST_H +#define VOLUME_LIST_H + +#include +#include +#include +#include + +// RVolume +class RVolume { +public: + RVolume(); + ~RVolume() {} + + status_t SetTo(dev_t id); + void Unset(); + + dev_t ID() const { return fID; } + ino_t RootNode() const { return fRootNode; } + void GetRootNodeRef(node_ref *ref) const + { ref->device = fID; ref->node = fRootNode; } + const char *DevicePath() const { return fDevicePath; } + +private: + dev_t fID; + ino_t fRootNode; + char fDevicePath[B_FILE_NAME_LENGTH]; +}; + +// RVolumeList +class RVolumeList : public BHandler { +public: + RVolumeList(); + virtual ~RVolumeList(); + + virtual void MessageReceived(BMessage *message); + virtual void SetNextHandler(BHandler *handler); + + status_t Rescan(); + + const RVolume *VolumeForDevicePath(const char *devicePath) const; + + bool Lock(); + void Unlock(); + + void Dump() const; + +private: + void _AddVolume(dev_t id); + void _DeviceMounted(BMessage *message); + void _DeviceUnmounted(BMessage *message); + +private: + BObjectList fVolumes; + BVolumeRoster fRoster; +}; + +#endif // VOLUME_LIST_H