The basic functionality is complete now (though untested). The user API requests (save the one concerning watching) are handled. Notification stuff is still missing and proper handling of changes to devices, too.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2661 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2003-02-08 00:48:15 +00:00
parent 11b6269482
commit 3d2f3f00f1
12 changed files with 431 additions and 29 deletions

View File

@ -7,6 +7,11 @@
#include <RegistrarDefs.h>
#include "DiskDeviceManager.h"
#include "RDiskDevice.h"
#include "RDiskDeviceList.h"
#include "RPartition.h"
#include "RSession.h"
#include "Debug.h"
enum {
REQUEST_PRIORITY = 0,
@ -73,6 +78,114 @@ DiskDeviceManager::MessageReceived(BMessage *message)
}
}
// _NextDiskDeviceRequest
void
DiskDeviceManager::_NextDiskDeviceRequest(BMessage *message)
{
status_t error = B_OK;
int32 cookie = 0;
BMessage reply(B_REG_RESULT);
if (message->FindInt32("cookie", &cookie) == B_OK) {
// get next device
if (RDiskDevice *device = fDeviceList.DeviceWithID(cookie, false)) {
// archive device
BMessage deviceArchive;
error = device->Archive(&deviceArchive);
// add archived device and next cookie to reply message
if (error == B_OK)
error = reply.AddMessage("device", &deviceArchive);
if (error == B_OK)
error = reply.AddInt32("cookie", device->ID() + 1);
} else
error = B_ENTRY_NOT_FOUND;
} else
SET_ERROR(error, B_BAD_VALUE);
// add result and send reply
reply.AddInt32("result", error);
message->SendReply(&reply);
}
// _GetDiskDeviceRequest
void
DiskDeviceManager::_GetDiskDeviceRequest(BMessage *message)
{
status_t error = B_ENTRY_NOT_FOUND;
// get the device
RDiskDevice *device = NULL;
int32 id = 0;
if (message->FindInt32("device_id", &id) == B_OK)
device = fDeviceList.DeviceWithID(id);
else if (message->FindInt32("session_id", &id) == B_OK) {
if (RSession *session = fDeviceList.SessionWithID(id))
device = session->Device();
} else if (message->FindInt32("partition_id", &id) == B_OK) {
if (RPartition *partition = fDeviceList.PartitionWithID(id))
device = partition->Device();
} else
error = B_BAD_VALUE;
// archive device and add it to the reply message
BMessage reply(B_REG_RESULT);
if (device) {
BMessage deviceArchive;
error = device->Archive(&deviceArchive);
if (error == B_OK)
error = reply.AddMessage("device", &deviceArchive);
}
// add result and send reply
reply.AddInt32("result", error);
message->SendReply(&reply);
}
// _UpdateDiskDeviceRequest
void
DiskDeviceManager::_UpdateDiskDeviceRequest(BMessage *message)
{
status_t error = B_ENTRY_NOT_FOUND;
// get the device and check the object is up to date
bool upToDate = false;
RDiskDevice *device = NULL;
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
SET_ERROR(error, B_BAD_VALUE);
} else if (message->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) {
if (RSession *session = fDeviceList.SessionWithID(id)) {
device = session->Device();
upToDate = (session->ChangeCounter() == changeCounter);
}
} else if (message->FindInt32("partition_id", &id) == B_OK) {
if (RPartition *partition = fDeviceList.PartitionWithID(id)) {
device = partition->Device();
upToDate = (partition->ChangeCounter() == changeCounter);
}
} else // bad request message
SET_ERROR(error, B_BAD_VALUE);
// archive device and add it to the reply message
BMessage reply(B_REG_RESULT);
if (device) {
if (policy == B_REG_DEVICE_UPDATE_DEVICE_CHANGED)
upToDate = (device->ChangeCounter() == changeCounter);
if (!upToDate && policy != B_REG_DEVICE_UPDATE_CHECK) {
BMessage deviceArchive;
error = device->Archive(&deviceArchive);
if (error == B_OK)
error = reply.AddMessage("device", &deviceArchive);
}
}
// add result and send reply
if (error == B_OK)
error = reply.AddBool("up_to_date", upToDate);
reply.AddInt32("result", error);
message->SendReply(&reply);
}
// _PushMessage
bool
DiskDeviceManager::_PushMessage(BMessage *message, int32 priority)
@ -110,23 +223,20 @@ DiskDeviceManager::_Worker()
// dispatch the message
switch (message->what) {
case B_REG_NEXT_DISK_DEVICE:
_NextDiskDeviceRequest(message);
break;
case B_REG_GET_DISK_DEVICE:
_GetDiskDeviceRequest(message);
break;
case B_REG_UPDATE_DISK_DEVICE:
_UpdateDiskDeviceRequest(message);
break;
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);
}
}
fVolumeList.HandleMessage(message);
break;
}
default:

View File

@ -22,6 +22,11 @@ public:
virtual void MessageReceived(BMessage *message);
private:
// requests
void _NextDiskDeviceRequest(BMessage *message);
void _GetDiskDeviceRequest(BMessage *message);
void _UpdateDiskDeviceRequest(BMessage *message);
bool _PushMessage(BMessage *message, int32 priority);
BMessage *_PopMessage();

View File

@ -110,6 +110,14 @@ RDiskDevice::Unset()
}
}
// Size
off_t
RDiskDevice::Size() const
{
return (off_t)fGeometry.bytes_per_sector * fGeometry.sectors_per_track
* fGeometry.cylinder_count * fGeometry.head_count;
}
// AddSession
bool
RDiskDevice::AddSession(RSession *session)
@ -161,6 +169,46 @@ RDiskDevice::Update()
return B_ERROR;
}
// Archive
status_t
RDiskDevice::Archive(BMessage *archive) const
{
status_t error = (archive ? B_OK : B_BAD_VALUE);
// ID and change counter
if (error == B_OK)
error = archive->AddInt32("id", fID);
if (error == B_OK)
error = archive->AddInt32("change_counter", fChangeCounter);
// geometry
if (error == B_OK)
error = archive->AddInt64("size", Size());
if (error == B_OK)
error = archive->AddInt32("block_size", BlockSize());
if (error == B_OK)
error = archive->AddInt8("type", (int8)fGeometry.device_type);
if (error == B_OK)
error = archive->AddBool("removable", fGeometry.removable);
if (error == B_OK)
error = archive->AddBool("read_only", fGeometry.read_only);
if (error == B_OK)
error = archive->AddBool("write_once", fGeometry.write_once);
// other data
if (error == B_OK)
error = archive->AddString("path", fPath.String());
if (error == B_OK)
error = archive->AddInt32("media_status", fMediaStatus);
// sessions
for (int32 i = 0; const RSession *session = SessionAt(i); i++) {
BMessage sessionArchive;
error = session->Archive(&sessionArchive);
if (error == B_OK)
error = archive->AddMessage("sessions", &sessionArchive);
if (error != B_OK)
break;
}
return error;
}
// Dump
void
RDiskDevice::Dump() const

View File

@ -33,6 +33,9 @@ public:
void SetTouched(bool touched) { fTouched = touched; }
bool Touched() const { return fTouched; }
off_t Size() const;
int32 BlockSize() const { return fGeometry.bytes_per_sector; }
const char *Path() const { return fPath.String(); }
bool AddSession(RSession *session);
@ -40,9 +43,13 @@ public:
bool RemoveSession(RSession *session);
int32 CountSessions() const { return fSessions.CountItems(); }
RSession *SessionAt(int32 index) const { return fSessions.ItemAt(index); }
int32 IndexOfSession(const RSession *session) const
{ return fSessions.IndexOf(session); }
status_t Update();
status_t Archive(BMessage *archive) const;
void Dump() const;
private:

View File

@ -119,6 +119,13 @@ RDiskDeviceList::VolumeUnmounted(const RVolume *volume)
PRINT(("RDiskDeviceList::VolumeUnmounted(%ld)\n", volume->ID()));
}
// MountPointMoved
void
RDiskDeviceList::MountPointMoved(const RVolume *volume)
{
PRINT(("RDiskDeviceList::MountPointMoved(%ld)\n", volume->ID()));
}
// AddDevice
bool
RDiskDeviceList::AddDevice(RDiskDevice *device)
@ -162,12 +169,12 @@ RDiskDeviceList::RemoveDevice(RDiskDevice *device)
// DeviceWithID
RDiskDevice *
RDiskDeviceList::DeviceWithID(int32 id) const
RDiskDeviceList::DeviceWithID(int32 id, bool exact) const
{
bool inList = false;
int32 index = fDevices.FindBinaryInsertionIndex(
CompareIDPredicate<RDiskDevice>(id), &inList);
return (inList ? DeviceAt(index) : NULL);
return (inList || !exact ? DeviceAt(index) : NULL);
}
// SessionWithID
@ -242,38 +249,67 @@ RDiskDeviceList::Unlock()
// DeviceAdded
void
RDiskDeviceList::DeviceAdded(RDiskDevice *device)
RDiskDeviceList::DeviceAdded(RDiskDevice *device, uint32 cause)
{
// propagate to sessions
for (int32 i = 0; RSession *session = device->SessionAt(i); i++)
SessionAdded(session, B_DEVICE_CAUSE_PARENT_CHANGED);
// notifications
// ...
}
// DeviceRemoved
void
RDiskDeviceList::DeviceRemoved(RDiskDevice *device)
RDiskDeviceList::DeviceRemoved(RDiskDevice *device, uint32 cause)
{
// propagate to sessions
for (int32 i = 0; RSession *session = device->SessionAt(i); i++)
SessionRemoved(session, B_DEVICE_CAUSE_PARENT_CHANGED);
// notifications
// ...
}
// SessionAdded
void
RDiskDeviceList::SessionAdded(RSession *session)
RDiskDeviceList::SessionAdded(RSession *session, uint32 cause)
{
// propagate to partitions
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
PartitionAdded(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
// notifications
// ...
}
// SessionRemoved
void
RDiskDeviceList::SessionRemoved(RSession *session)
RDiskDeviceList::SessionRemoved(RSession *session, uint32 cause)
{
// propagate to partitions
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
PartitionRemoved(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
// notifications
// ...
}
// PartitionAdded
void
RDiskDeviceList::PartitionAdded(RPartition *partition)
RDiskDeviceList::PartitionAdded(RPartition *partition, uint32 cause)
{
// get the corresponding volume, if partition is mounted
char path[B_FILE_NAME_LENGTH];
partition->GetPath(path);
if (const RVolume *volume = fVolumeList.VolumeForDevicePath(path))
partition->SetVolume(volume);
// notifications
// ...
}
// PartitionRemoved
void
RDiskDeviceList::PartitionRemoved(RPartition *partition)
RDiskDeviceList::PartitionRemoved(RPartition *partition, uint32 cause)
{
// notifications
// ...
}
// Dump

View File

@ -20,6 +20,20 @@ class RDiskDevice;
class RPartition;
class RSession;
// device list modification causes
// TODO: to be moved to <DiskDeviceRoster.h>
enum {
// helpful causes
B_DEVICE_CAUSE_MEDIA_CHANGED,
B_DEVICE_CAUSE_FORMATTED,
B_DEVICE_CAUSE_PARTITIONED,
B_DEVICE_CAUSE_INITIALIZED,
// unknown cause
B_DEVICE_CAUSE_UNKNOWN,
// for internal use only (e.g.: partition added, because device added)
B_DEVICE_CAUSE_PARENT_CHANGED,
};
class RDiskDeviceList : public MessageHandler, public RVolumeListListener {
public:
RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList);
@ -27,8 +41,9 @@ public:
virtual void HandleMessage(BMessage *message);
void RDiskDeviceList::VolumeMounted(const RVolume *volume);
void RDiskDeviceList::VolumeUnmounted(const RVolume *volume);
virtual void VolumeMounted(const RVolume *volume);
virtual void VolumeUnmounted(const RVolume *volume);
virtual void MountPointMoved(const RVolume *volume);
bool AddDevice(RDiskDevice *device);
bool RemoveDevice(int32 index);
@ -43,7 +58,7 @@ public:
RPartition *PartitionAt(int32 index) const
{ return fPartitions.ItemAt(index); }
RDiskDevice *DeviceWithID(int32 id) const;
RDiskDevice *DeviceWithID(int32 id, bool exact = true) const;
RSession *SessionWithID(int32 id) const;
RPartition *PartitionWithID(int32 id) const;
@ -54,12 +69,18 @@ public:
bool Lock();
void Unlock();
void DeviceAdded(RDiskDevice *device);
void DeviceRemoved(RDiskDevice *device);
void SessionAdded(RSession *session);
void SessionRemoved(RSession *session);
void PartitionAdded(RPartition *partition);
void PartitionRemoved(RPartition *partition);
void DeviceAdded(RDiskDevice *device,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void DeviceRemoved(RDiskDevice *device,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void SessionAdded(RSession *session,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void SessionRemoved(RSession *session,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void PartitionAdded(RPartition *partition,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void PartitionRemoved(RPartition *partition,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void Dump() const;

View File

@ -12,7 +12,8 @@
RPartition::RPartition()
: fSession(NULL),
fID(-1),
fChangeCounter(0)
fChangeCounter(0),
fVolume(NULL)
{
}
@ -54,6 +55,69 @@ RPartition::Device() const
return (fSession ? fSession->Device() : NULL);
}
// Index
int32
RPartition::Index() const
{
if (fSession)
return fSession->IndexOfPartition(this);
return -1;
}
// GetPath
void
RPartition::GetPath(char *path) const
{
RDiskDevice *device = Device();
if (path && device) {
strcpy(path, device->Path());
if (char *lastSlash = strrchr(path, '/'))
sprintf(lastSlash + 1, "%ld_%ld", Session()->Index(), Index());
}
}
// Archive
status_t
RPartition::Archive(BMessage *archive) const
{
status_t error = (archive ? B_OK : B_BAD_VALUE);
// ID, change counter and index
if (error == B_OK)
error = archive->AddInt32("id", fID);
if (error == B_OK)
error = archive->AddInt32("change_counter", fChangeCounter);
if (error == B_OK)
error = archive->AddInt32("index", Index());
// fInfo.info.*
if (error == B_OK)
error = archive->AddInt64("offset", fInfo.info.offset);
if (error == B_OK)
error = archive->AddInt64("size", fInfo.info.size);
// fInfo.*
if (error == B_OK)
error = archive->AddInt32("flags", (int32)fInfo.flags);
if (error == B_OK)
error = archive->AddString("name", fInfo.partition_name);
if (error == B_OK)
error = archive->AddString("type", fInfo.partition_type);
if (error == B_OK) {
error = archive->AddString("fs_short_name",
fInfo.file_system_short_name);
}
if (error == B_OK) {
error = archive->AddString("fs_long_name",
fInfo.file_system_long_name);
}
if (error == B_OK)
error = archive->AddString("volume_name", fInfo.volume_name);
if (error == B_OK)
error = archive->AddInt32("fs_flags", (int32)fInfo.file_system_flags);
// dev_t, if mounted
if (error == B_OK && fVolume)
error = archive->AddInt32("volume_id", fVolume->ID());
return error;
}
// print_partition_info
static
void
@ -72,7 +136,7 @@ print_partition_info(const char *prefix, const extended_partition_info &info)
printf("%sFS short name: `%s'\n", prefix, info.file_system_short_name);
printf("%sFS long name: `%s'\n", prefix, info.file_system_long_name);
printf("%svolume name: `%s'\n", prefix, info.volume_name);
printf("%smounted at: `%s'\n", prefix, info.mounted_at);
// printf("%smounted at: `%s'\n", prefix, info.mounted_at);
printf("%sFS flags: 0x%lx\n", prefix, info.file_system_flags);
}

View File

@ -9,9 +9,12 @@
#include <disk_scanner.h>
#include <SupportDefs.h>
class BMessage;
class RDiskDevice;
class RDiskDeviceList;
class RSession;
class RVolume;
class RPartition {
public:
@ -29,7 +32,15 @@ public:
int32 ID() const { return fID; }
int32 ChangeCounter() const { return fChangeCounter; }
int32 Index() const;
const extended_partition_info *Info() const { return &fInfo; }
void GetPath(char *path) const;
void SetVolume(const RVolume *volume) { fVolume = volume; }
const RVolume *Volume() const { return fVolume; }
status_t Archive(BMessage *archive) const;
void Dump() const;
@ -41,6 +52,7 @@ private:
int32 fID;
int32 fChangeCounter;
extended_partition_info fInfo;
const RVolume *fVolume;
static vint32 fNextID;
};

View File

@ -78,6 +78,15 @@ RSession::DeviceList() const
return (fDevice ? fDevice->DeviceList() : NULL);
}
// Index
int32
RSession::Index() const
{
if (fDevice)
return fDevice->IndexOfSession(this);
return -1;
}
// AddPartition
bool
RSession::AddPartition(RPartition *partition)
@ -134,6 +143,40 @@ print_session_info(const char *prefix, const session_info &info)
printf("%sflags: %lx\n", prefix, info.flags);
}
// Archive
status_t
RSession::Archive(BMessage *archive) const
{
status_t error = (archive ? B_OK : B_BAD_VALUE);
// ID, change counter and index
if (error == B_OK)
error = archive->AddInt32("id", fID);
if (error == B_OK)
error = archive->AddInt32("change_counter", fChangeCounter);
if (error == B_OK)
error = archive->AddInt32("index", Index());
// fInfo.*
if (error == B_OK)
error = archive->AddInt64("offset", fInfo.offset);
if (error == B_OK)
error = archive->AddInt64("size", fInfo.size);
if (error == B_OK)
error = archive->AddInt32("flags", (int32)fInfo.flags);
// other data
if (error == B_OK)
error = archive->AddString("partitioning", fPartitioningSystem);
// partitions
for (int32 i = 0; const RPartition *partition = PartitionAt(i); i++) {
BMessage partitionArchive;
error = partition->Archive(&partitionArchive);
if (error == B_OK)
error = archive->AddMessage("partitions", &partitionArchive);
if (error != B_OK)
break;
}
return error;
}
// Dump
void
RSession::Dump() const

View File

@ -28,15 +28,21 @@ public:
int32 ID() const { return fID; }
int32 ChangeCounter() const { return fChangeCounter; }
int32 Index() const;
bool AddPartition(RPartition *partition);
bool RemovePartition(int32 index);
bool RemovePartition(RPartition *partition);
int32 CountPartitions() const { return fPartitions.CountItems(); }
RPartition *PartitionAt(int32 index) const
{ return fPartitions.ItemAt(index); }
int32 IndexOfPartition(const RPartition *partition) const
{ return fPartitions.IndexOf(partition); }
const session_info *Info() const { return &fInfo; }
status_t Archive(BMessage *archive) const;
void Dump() const;
private:

View File

@ -79,6 +79,26 @@ RVolume::Unset()
fRootNode = -1;
}
// StartWatching
status_t
RVolume::StartWatching(BMessenger target) const
{
node_ref ref;
ref.device = fID;
ref.node = fRootNode;
return watch_node(&ref, B_WATCH_NAME, target);
}
// StopWatching
status_t
RVolume::StopWatching(BMessenger target) const
{
node_ref ref;
ref.device = fID;
ref.node = fRootNode;
return watch_node(&ref, B_STOP_WATCHING, target);
}
// RVolumeListListener
@ -104,6 +124,12 @@ RVolumeListListener::VolumeUnmounted(const RVolume *volume)
{
}
// MountPointMoved
void
RVolumeListListener::MountPointMoved(const RVolume *volume)
{
}
// RVolumeList
@ -149,6 +175,9 @@ RVolumeList::HandleMessage(BMessage *message)
case B_DEVICE_UNMOUNTED:
_DeviceUnmounted(message);
break;
case B_ENTRY_MOVED:
_MountPointMoved(message);
break;
}
}
break;
@ -231,6 +260,7 @@ RVolumeList::_AddVolume(dev_t id)
if (error == B_OK) {
fVolumes.BinaryInsert(volume,
CompareDevicePathPredicate(volume->DevicePath()));
volume->StartWatching(fTarget);
} else {
delete volume;
volume = NULL;
@ -264,6 +294,7 @@ RVolumeList::_DeviceUnmounted(BMessage *message)
if (message->FindInt32("device", &device) == B_OK) {
PRINT(("RVolumeList::_DeviceUnmounted(%ld)\n", device));
if (RVolume *volume = fVolumes.FindIf(CompareIDPredicate(device))) {
volume->StopWatching(fTarget);
fVolumes.RemoveItem(volume, false);
if (fListener)
fListener->VolumeUnmounted(volume);
@ -272,3 +303,17 @@ RVolumeList::_DeviceUnmounted(BMessage *message)
}
}
// _MountPointMoved
void
RVolumeList::_MountPointMoved(BMessage *message)
{
dev_t device;
if (message->FindInt32("device", &device) == B_OK) {
PRINT(("RVolumeList::_MountPointMoved(%ld)\n", device));
if (RVolume *volume = fVolumes.FindIf(CompareIDPredicate(device))) {
if (fListener)
fListener->MountPointMoved(volume);
}
}
}

View File

@ -30,6 +30,9 @@ public:
{ ref->device = fID; ref->node = fRootNode; }
const char *DevicePath() const { return fDevicePath; }
status_t StartWatching(BMessenger target) const;
status_t StopWatching(BMessenger target) const;
private:
dev_t fID;
ino_t fRootNode;
@ -44,6 +47,7 @@ public:
virtual void VolumeMounted(const RVolume *volume);
virtual void VolumeUnmounted(const RVolume *volume);
virtual void MountPointMoved(const RVolume *volume);
};
// RVolumeList
@ -69,6 +73,7 @@ private:
RVolume *_AddVolume(dev_t id);
void _DeviceMounted(BMessage *message);
void _DeviceUnmounted(BMessage *message);
void _MountPointMoved(BMessage *message);
private:
mutable BLocker &fLock;