From 483bea6e79f60fb2113d7942969e34daa902f71d Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Fri, 14 Feb 2003 23:15:20 +0000 Subject: [PATCH] Completed support for updates and notifications. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2712 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/registrar/RChangeCounter.h | 3 +- src/servers/registrar/RDiskDevice.cpp | 31 ++++++--- src/servers/registrar/RDiskDeviceList.cpp | 82 +++++++++++++++++++++-- src/servers/registrar/RDiskDeviceList.h | 20 ++---- src/servers/registrar/RPartition.cpp | 35 +++++++++- src/servers/registrar/RPartition.h | 2 + src/servers/registrar/RSession.cpp | 24 +++++-- 7 files changed, 161 insertions(+), 36 deletions(-) diff --git a/src/servers/registrar/RChangeCounter.h b/src/servers/registrar/RChangeCounter.h index c7ba20ed77..3ec763e414 100644 --- a/src/servers/registrar/RChangeCounter.h +++ b/src/servers/registrar/RChangeCounter.h @@ -17,11 +17,12 @@ public: bool Lock() { fLocked++; return true; } void Unlock() { if (fLocked > 0) fLocked--; } + bool IsLocked() const { return (fLocked > 0); } bool Increment() { bool changed = false; - if (fLocked && !fChanged) { + if (IsLocked() && !fChanged) { fCount++; changed = fChanged = true; } diff --git a/src/servers/registrar/RDiskDevice.cpp b/src/servers/registrar/RDiskDevice.cpp index f640a376fe..83a616fc0f 100644 --- a/src/servers/registrar/RDiskDevice.cpp +++ b/src/servers/registrar/RDiskDevice.cpp @@ -3,6 +3,7 @@ // by the OpenBeOS license. //--------------------------------------------------------------------- +#include #include #include #include @@ -96,6 +97,7 @@ status_t RDiskDevice::MediaChanged() { PRINT(("RDiskDevice::MediaChanged()\n")); + Changed(); status_t error = B_OK; // get the new media status status_t mediaStatus; @@ -110,7 +112,7 @@ PRINT(("RDiskDevice::MediaChanged()\n")); case B_DEV_DOOR_OPEN: break; case B_DEV_MEDIA_CHANGED: - // Ignore changes between the our ioctl() and the one before; + // Ignore changes between the ioctl() and the one before; // we rescan the sessions anyway. fMediaStatus = B_OK; break; @@ -119,10 +121,15 @@ PRINT(("RDiskDevice::MediaChanged()\n")); break; } } + // get the device geometry + if (ioctl(fFD, B_GET_GEOMETRY, &fGeometry) != 0) + error = errno; // rescan sessions - error = _RescanSessions(B_DEVICE_CAUSE_PARENT_CHANGED); - // TODO: send notification - // ... + if (error == B_OK) + error = _RescanSessions(B_DEVICE_CAUSE_PARENT_CHANGED); + // notification + if (fDeviceList) + fDeviceList->MediaChanged(this, B_DEVICE_CAUSE_MEDIA_CHANGED); return error; } @@ -131,6 +138,7 @@ status_t RDiskDevice::SessionLayoutChanged() { PRINT(("RDiskDevice::SessionLayoutChanged()\n")); + Changed(); status_t error = B_OK; error = _RescanSessions(B_DEVICE_CAUSE_UNKNOWN); return error; @@ -169,6 +177,7 @@ RDiskDevice::AddSession(RSession *session, uint32 cause) success = fSessions.AddItem(session); if (success) { session->SetDevice(this); + Changed(); if (RDiskDeviceList *deviceList = DeviceList()) deviceList->SessionAdded(session, cause); } @@ -182,6 +191,7 @@ RDiskDevice::RemoveSession(int32 index, uint32 cause) { RSession *session = SessionAt(index); if (session) { + Changed(); if (RDiskDeviceList *deviceList = DeviceList()) deviceList->SessionRemoved(session, cause); session->SetDevice(NULL); @@ -208,6 +218,7 @@ RDiskDevice::RemoveSession(RSession *session, uint32 cause) status_t RDiskDevice::Update() { + RChangeCounter::Locker lock(fChangeCounter); status_t error = B_OK; status_t mediaStatus = B_OK; if (ioctl(fFD, B_GET_MEDIA_STATUS, &mediaStatus) == 0) { @@ -233,8 +244,10 @@ RDiskDevice::Update() // remove disappeared sessions for (int32 k = CountSessions() - 1; k >= i; k--) RemoveSession(k, B_DEVICE_CAUSE_UNKNOWN); - } else - error = status; + } else { + // ignore errors -- we can't help it +// error = status; + } break; } // check the session @@ -323,8 +336,10 @@ RDiskDevice::_RescanSessions(uint32 cause) // get the session info status_t status = get_nth_session_info(fFD, i, &sessionInfo); if (status != B_OK) { - if (status != B_ENTRY_NOT_FOUND) - error = status; + if (status != B_ENTRY_NOT_FOUND) { + // ignore errors -- we can't help it +// error = status; + } break; } // create and add a RSession diff --git a/src/servers/registrar/RDiskDeviceList.cpp b/src/servers/registrar/RDiskDeviceList.cpp index 5e98ac6821..e8a71c234a 100644 --- a/src/servers/registrar/RDiskDeviceList.cpp +++ b/src/servers/registrar/RDiskDeviceList.cpp @@ -374,7 +374,12 @@ RDiskDeviceList::DeviceAdded(RDiskDevice *device, uint32 cause) for (int32 i = 0; RSession *session = device->SessionAt(i); i++) SessionAdded(session, B_DEVICE_CAUSE_PARENT_CHANGED); // notifications - // ... + BMessage notification(B_DEVICE_UPDATE); + if (_InitNotificationMessage(¬ification, B_DEVICE_ADDED, + cause, device) == B_OK) { + EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE_LIST); + fWatchingService->NotifyWatchers(¬ification, &filter); + } } // DeviceRemoved @@ -385,7 +390,25 @@ RDiskDeviceList::DeviceRemoved(RDiskDevice *device, uint32 cause) for (int32 i = 0; RSession *session = device->SessionAt(i); i++) SessionRemoved(session, B_DEVICE_CAUSE_PARENT_CHANGED); // notifications - // ... + BMessage notification(B_DEVICE_UPDATE); + if (_InitNotificationMessage(¬ification, B_DEVICE_REMOVED, + cause, device) == B_OK) { + EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE_LIST); + fWatchingService->NotifyWatchers(¬ification, &filter); + } +} + +// MediaChanged +void +RDiskDeviceList::MediaChanged(RDiskDevice *device, uint32 cause) +{ + // notifications + BMessage notification(B_DEVICE_UPDATE); + if (_InitNotificationMessage(¬ification, B_DEVICE_MEDIA_CHANGED, + cause, device) == B_OK) { + EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE); + fWatchingService->NotifyWatchers(¬ification, &filter); + } } // SessionAdded @@ -398,7 +421,15 @@ RDiskDeviceList::SessionAdded(RSession *session, uint32 cause) for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++) PartitionAdded(partition, B_DEVICE_CAUSE_PARENT_CHANGED); // notifications - // ... +// TODO: bundle multiple session added events per device + if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) { + BMessage notification(B_DEVICE_UPDATE); + if (_InitNotificationMessage(¬ification, B_DEVICE_SESSION_ADDED, + cause, session) == B_OK) { + EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE); + fWatchingService->NotifyWatchers(¬ification, &filter); + } + } } // SessionRemoved @@ -415,7 +446,15 @@ RDiskDeviceList::SessionRemoved(RSession *session, uint32 cause) for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++) PartitionRemoved(partition, B_DEVICE_CAUSE_PARENT_CHANGED); // notifications - // ... +// TODO: bundle multiple session removed events per device + if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) { + BMessage notification(B_DEVICE_UPDATE); + if (_InitNotificationMessage(¬ification, B_DEVICE_SESSION_REMOVED, + cause, session) == B_OK) { + EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE); + fWatchingService->NotifyWatchers(¬ification, &filter); + } + } } // PartitionAdded @@ -431,7 +470,15 @@ RDiskDeviceList::PartitionAdded(RPartition *partition, uint32 cause) if (const RVolume *volume = fVolumeList.VolumeForDevicePath(path)) partition->SetVolume(volume); // notifications - // ... +// TODO: bundle multiple partition added events per session + if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) { + BMessage notification(B_DEVICE_UPDATE); + if (_InitNotificationMessage(¬ification, B_DEVICE_PARTITION_ADDED, + cause, partition) == B_OK) { + EventMaskWatcherFilter filter(B_DEVICE_REQUEST_SESSION); + fWatchingService->NotifyWatchers(¬ification, &filter); + } + } } // PartitionRemoved @@ -445,7 +492,30 @@ RDiskDeviceList::PartitionRemoved(RPartition *partition, uint32 cause) if (success) fPartitions.RemoveItemAt(index); // notifications - // ... +// TODO: bundle multiple partition removed events per session + if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) { + BMessage notification(B_DEVICE_UPDATE); + if (_InitNotificationMessage(¬ification, B_DEVICE_PARTITION_REMOVED, + cause, partition) == B_OK) { + EventMaskWatcherFilter filter(B_DEVICE_REQUEST_SESSION); + fWatchingService->NotifyWatchers(¬ification, &filter); + } + } +} + +// PartitionChanged +void +RDiskDeviceList::PartitionChanged(RPartition *partition, uint32 cause) +{ + // notifications + if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) { + BMessage notification(B_DEVICE_UPDATE); + if (_InitNotificationMessage(¬ification, B_DEVICE_PARTITION_CHANGED, + cause, partition) == B_OK) { + EventMaskWatcherFilter filter(B_DEVICE_REQUEST_PARTITION); + fWatchingService->NotifyWatchers(¬ification, &filter); + } + } } // Dump diff --git a/src/servers/registrar/RDiskDeviceList.h b/src/servers/registrar/RDiskDeviceList.h index 1bf982f69b..adae1c24c1 100644 --- a/src/servers/registrar/RDiskDeviceList.h +++ b/src/servers/registrar/RDiskDeviceList.h @@ -6,6 +6,7 @@ #ifndef DISK_DEVICE_LIST_H #define DISK_DEVICE_LIST_H +#include #include #include @@ -21,20 +22,6 @@ class RPartition; class RSession; class WatchingService; -// device list modification causes -// TODO: to be moved to -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, @@ -82,6 +69,8 @@ public: uint32 cause = B_DEVICE_CAUSE_UNKNOWN); void DeviceRemoved(RDiskDevice *device, uint32 cause = B_DEVICE_CAUSE_UNKNOWN); + void MediaChanged(RDiskDevice *device, + uint32 cause = B_DEVICE_CAUSE_UNKNOWN); void SessionAdded(RSession *session, uint32 cause = B_DEVICE_CAUSE_UNKNOWN); void SessionRemoved(RSession *session, @@ -90,6 +79,9 @@ public: uint32 cause = B_DEVICE_CAUSE_UNKNOWN); void PartitionRemoved(RPartition *partition, uint32 cause = B_DEVICE_CAUSE_UNKNOWN); + void PartitionChanged(RPartition *partition, + uint32 cause = B_DEVICE_CAUSE_UNKNOWN); + void Dump() const; diff --git a/src/servers/registrar/RPartition.cpp b/src/servers/registrar/RPartition.cpp index d77c64a7be..dad0e19b23 100644 --- a/src/servers/registrar/RPartition.cpp +++ b/src/servers/registrar/RPartition.cpp @@ -41,6 +41,18 @@ RPartition::Unset() fID = -1; } +// PartitionChanged +status_t +RPartition::PartitionChanged() +{ + Changed(); + status_t error = B_OK; + // notification + if (RDiskDeviceList *deviceList = DeviceList()) + deviceList->PartitionChanged(this, B_DEVICE_CAUSE_UNKNOWN); + return error; +} + // DeviceList RDiskDeviceList * RPartition::DeviceList() const @@ -88,9 +100,28 @@ RPartition::GetPath(char *path) const status_t RPartition::Update(const extended_partition_info *partitionInfo) { + RChangeCounter::Locker lock(fChangeCounter); status_t error = B_OK; - // TODO: Check the partition info for changes! - fInfo = *partitionInfo; + // check the partition info for changes + // Currently there is very little that can have changed. offset and size + // must not be changed, logical_block_size and device are ignored anyway + // and session and partition index don't change. + // So only the fields in extended_partition_info - partition_info remain. + if (partitionInfo->flags != fInfo.flags + || strcmp(partitionInfo->partition_name, fInfo.partition_name) + || strcmp(partitionInfo->partition_type, fInfo.partition_type) + || strcmp(partitionInfo->file_system_short_name, + fInfo.file_system_short_name) + || strcmp(partitionInfo->file_system_short_name, + fInfo.file_system_short_name) + || strcmp(partitionInfo->file_system_long_name, + fInfo.file_system_long_name) + || strcmp(partitionInfo->volume_name, fInfo.volume_name) + || partitionInfo->partition_code != fInfo.partition_code + || partitionInfo->file_system_flags != fInfo.file_system_flags) { + fInfo = *partitionInfo; + PartitionChanged(); + } return error; } diff --git a/src/servers/registrar/RPartition.h b/src/servers/registrar/RPartition.h index 71e7b48398..fc72d5540f 100644 --- a/src/servers/registrar/RPartition.h +++ b/src/servers/registrar/RPartition.h @@ -31,6 +31,8 @@ public: RDiskDevice *Device() const; RSession *Session() const { return fSession; } + status_t PartitionChanged(); + int32 ID() const { return fID; } int32 ChangeCounter() const { return fChangeCounter.Count(); } void Changed(); diff --git a/src/servers/registrar/RSession.cpp b/src/servers/registrar/RSession.cpp index 16cdf949f1..e0b4f7fa31 100644 --- a/src/servers/registrar/RSession.cpp +++ b/src/servers/registrar/RSession.cpp @@ -64,6 +64,7 @@ status_t RSession::PartitionLayoutChanged() { PRINT(("RSession::PartitionLayoutChanged()\n")); + Changed(); status_t error = (fDevice ? B_OK : B_ERROR); if (error == B_OK) error = _RescanPartitions(fDevice->FD(), B_DEVICE_CAUSE_UNKNOWN); @@ -113,6 +114,8 @@ RSession::AddPartition(RPartition *partition, uint32 cause) success = fPartitions.AddItem(partition); if (success) { partition->SetSession(this); + Changed(); + // trigger notifications if (RDiskDeviceList *deviceList = DeviceList()) deviceList->PartitionAdded(partition, cause); } @@ -126,6 +129,7 @@ RSession::RemovePartition(int32 index, uint32 cause) { RPartition *partition = PartitionAt(index); if (partition) { + Changed(); if (RDiskDeviceList *deviceList = DeviceList()) deviceList->PartitionRemoved(partition, cause); partition->SetSession(NULL); @@ -152,8 +156,14 @@ RSession::RemovePartition(RPartition *partition, uint32 cause) status_t RSession::Update(const session_info *sessionInfo) { + RChangeCounter::Locker lock(fChangeCounter); status_t error = (fDevice ? B_OK : B_ERROR); - // TODO: Check the session info for changes! + // check the session info for changes + // Currently there is very little that can have changed. offset and size + // must not be changed, logical_block_size is ignored anyway and index + // doesn't change. So only flags remains, but that indicates only, if the + // session is virtual or a data/audio partition. So we don't do anything + // for now. fInfo = *sessionInfo; int fd = (fDevice ? fDevice->FD() : -1); // check the partitions @@ -175,8 +185,10 @@ RSession::Update(const session_info *sessionInfo) // remove disappeared partitions for (int32 k = CountPartitions() - 1; k >= i; k--) RemovePartition(k, B_DEVICE_CAUSE_UNKNOWN); - } else - error = status; + } else { + // ignore errors -- we can't help it +// error = status; + } break; } // check the partition @@ -269,8 +281,10 @@ RSession::_RescanPartitions(int fd, uint32 cause) status_t status = get_nth_partition_info(fd, fInfo.index, i, &partitionInfo, (i == 0 ? fPartitioningSystem : NULL)); if (status != B_OK) { - if (status != B_ENTRY_NOT_FOUND) - error = status; + if (status != B_ENTRY_NOT_FOUND) { + // ignore errors -- we can't help it +// error = status; + } break; } // create and add a RPartition