Completed support for updates and notifications.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2712 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2003-02-14 23:15:20 +00:00
parent bd68efa667
commit 483bea6e79
7 changed files with 161 additions and 36 deletions
+2 -1
View File
@@ -17,11 +17,12 @@ public:
bool Lock() { fLocked++; return true; } bool Lock() { fLocked++; return true; }
void Unlock() { if (fLocked > 0) fLocked--; } void Unlock() { if (fLocked > 0) fLocked--; }
bool IsLocked() const { return (fLocked > 0); }
bool Increment() bool Increment()
{ {
bool changed = false; bool changed = false;
if (fLocked && !fChanged) { if (IsLocked() && !fChanged) {
fCount++; fCount++;
changed = fChanged = true; changed = fChanged = true;
} }
+23 -8
View File
@@ -3,6 +3,7 @@
// by the OpenBeOS license. // by the OpenBeOS license.
//--------------------------------------------------------------------- //---------------------------------------------------------------------
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <new.h> #include <new.h>
#include <stdio.h> #include <stdio.h>
@@ -96,6 +97,7 @@ status_t
RDiskDevice::MediaChanged() RDiskDevice::MediaChanged()
{ {
PRINT(("RDiskDevice::MediaChanged()\n")); PRINT(("RDiskDevice::MediaChanged()\n"));
Changed();
status_t error = B_OK; status_t error = B_OK;
// get the new media status // get the new media status
status_t mediaStatus; status_t mediaStatus;
@@ -110,7 +112,7 @@ PRINT(("RDiskDevice::MediaChanged()\n"));
case B_DEV_DOOR_OPEN: case B_DEV_DOOR_OPEN:
break; break;
case B_DEV_MEDIA_CHANGED: 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. // we rescan the sessions anyway.
fMediaStatus = B_OK; fMediaStatus = B_OK;
break; break;
@@ -119,10 +121,15 @@ PRINT(("RDiskDevice::MediaChanged()\n"));
break; break;
} }
} }
// get the device geometry
if (ioctl(fFD, B_GET_GEOMETRY, &fGeometry) != 0)
error = errno;
// rescan sessions // rescan sessions
error = _RescanSessions(B_DEVICE_CAUSE_PARENT_CHANGED); if (error == B_OK)
// TODO: send notification error = _RescanSessions(B_DEVICE_CAUSE_PARENT_CHANGED);
// ... // notification
if (fDeviceList)
fDeviceList->MediaChanged(this, B_DEVICE_CAUSE_MEDIA_CHANGED);
return error; return error;
} }
@@ -131,6 +138,7 @@ status_t
RDiskDevice::SessionLayoutChanged() RDiskDevice::SessionLayoutChanged()
{ {
PRINT(("RDiskDevice::SessionLayoutChanged()\n")); PRINT(("RDiskDevice::SessionLayoutChanged()\n"));
Changed();
status_t error = B_OK; status_t error = B_OK;
error = _RescanSessions(B_DEVICE_CAUSE_UNKNOWN); error = _RescanSessions(B_DEVICE_CAUSE_UNKNOWN);
return error; return error;
@@ -169,6 +177,7 @@ RDiskDevice::AddSession(RSession *session, uint32 cause)
success = fSessions.AddItem(session); success = fSessions.AddItem(session);
if (success) { if (success) {
session->SetDevice(this); session->SetDevice(this);
Changed();
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->SessionAdded(session, cause); deviceList->SessionAdded(session, cause);
} }
@@ -182,6 +191,7 @@ RDiskDevice::RemoveSession(int32 index, uint32 cause)
{ {
RSession *session = SessionAt(index); RSession *session = SessionAt(index);
if (session) { if (session) {
Changed();
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->SessionRemoved(session, cause); deviceList->SessionRemoved(session, cause);
session->SetDevice(NULL); session->SetDevice(NULL);
@@ -208,6 +218,7 @@ RDiskDevice::RemoveSession(RSession *session, uint32 cause)
status_t status_t
RDiskDevice::Update() RDiskDevice::Update()
{ {
RChangeCounter::Locker lock(fChangeCounter);
status_t error = B_OK; status_t error = B_OK;
status_t mediaStatus = B_OK; status_t mediaStatus = B_OK;
if (ioctl(fFD, B_GET_MEDIA_STATUS, &mediaStatus) == 0) { if (ioctl(fFD, B_GET_MEDIA_STATUS, &mediaStatus) == 0) {
@@ -233,8 +244,10 @@ RDiskDevice::Update()
// remove disappeared sessions // remove disappeared sessions
for (int32 k = CountSessions() - 1; k >= i; k--) for (int32 k = CountSessions() - 1; k >= i; k--)
RemoveSession(k, B_DEVICE_CAUSE_UNKNOWN); RemoveSession(k, B_DEVICE_CAUSE_UNKNOWN);
} else } else {
error = status; // ignore errors -- we can't help it
// error = status;
}
break; break;
} }
// check the session // check the session
@@ -323,8 +336,10 @@ RDiskDevice::_RescanSessions(uint32 cause)
// get the session info // get the session info
status_t status = get_nth_session_info(fFD, i, &sessionInfo); status_t status = get_nth_session_info(fFD, i, &sessionInfo);
if (status != B_OK) { if (status != B_OK) {
if (status != B_ENTRY_NOT_FOUND) if (status != B_ENTRY_NOT_FOUND) {
error = status; // ignore errors -- we can't help it
// error = status;
}
break; break;
} }
// create and add a RSession // create and add a RSession
+76 -6
View File
@@ -374,7 +374,12 @@ RDiskDeviceList::DeviceAdded(RDiskDevice *device, uint32 cause)
for (int32 i = 0; RSession *session = device->SessionAt(i); i++) for (int32 i = 0; RSession *session = device->SessionAt(i); i++)
SessionAdded(session, B_DEVICE_CAUSE_PARENT_CHANGED); SessionAdded(session, B_DEVICE_CAUSE_PARENT_CHANGED);
// notifications // notifications
// ... BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification, B_DEVICE_ADDED,
cause, device) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE_LIST);
fWatchingService->NotifyWatchers(&notification, &filter);
}
} }
// DeviceRemoved // DeviceRemoved
@@ -385,7 +390,25 @@ RDiskDeviceList::DeviceRemoved(RDiskDevice *device, uint32 cause)
for (int32 i = 0; RSession *session = device->SessionAt(i); i++) for (int32 i = 0; RSession *session = device->SessionAt(i); i++)
SessionRemoved(session, B_DEVICE_CAUSE_PARENT_CHANGED); SessionRemoved(session, B_DEVICE_CAUSE_PARENT_CHANGED);
// notifications // notifications
// ... BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification, B_DEVICE_REMOVED,
cause, device) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE_LIST);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
// MediaChanged
void
RDiskDeviceList::MediaChanged(RDiskDevice *device, uint32 cause)
{
// notifications
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification, B_DEVICE_MEDIA_CHANGED,
cause, device) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE);
fWatchingService->NotifyWatchers(&notification, &filter);
}
} }
// SessionAdded // SessionAdded
@@ -398,7 +421,15 @@ RDiskDeviceList::SessionAdded(RSession *session, uint32 cause)
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++) for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
PartitionAdded(partition, B_DEVICE_CAUSE_PARENT_CHANGED); PartitionAdded(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
// notifications // notifications
// ... // TODO: bundle multiple session added events per device
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification, B_DEVICE_SESSION_ADDED,
cause, session) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
} }
// SessionRemoved // SessionRemoved
@@ -415,7 +446,15 @@ RDiskDeviceList::SessionRemoved(RSession *session, uint32 cause)
for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++) for (int32 i = 0; RPartition *partition = session->PartitionAt(i); i++)
PartitionRemoved(partition, B_DEVICE_CAUSE_PARENT_CHANGED); PartitionRemoved(partition, B_DEVICE_CAUSE_PARENT_CHANGED);
// notifications // notifications
// ... // TODO: bundle multiple session removed events per device
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification, B_DEVICE_SESSION_REMOVED,
cause, session) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
} }
// PartitionAdded // PartitionAdded
@@ -431,7 +470,15 @@ RDiskDeviceList::PartitionAdded(RPartition *partition, uint32 cause)
if (const RVolume *volume = fVolumeList.VolumeForDevicePath(path)) if (const RVolume *volume = fVolumeList.VolumeForDevicePath(path))
partition->SetVolume(volume); partition->SetVolume(volume);
// notifications // notifications
// ... // TODO: bundle multiple partition added events per session
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification, B_DEVICE_PARTITION_ADDED,
cause, partition) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_SESSION);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
} }
// PartitionRemoved // PartitionRemoved
@@ -445,7 +492,30 @@ RDiskDeviceList::PartitionRemoved(RPartition *partition, uint32 cause)
if (success) if (success)
fPartitions.RemoveItemAt(index); fPartitions.RemoveItemAt(index);
// notifications // notifications
// ... // TODO: bundle multiple partition removed events per session
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification, B_DEVICE_PARTITION_REMOVED,
cause, partition) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_SESSION);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
}
// PartitionChanged
void
RDiskDeviceList::PartitionChanged(RPartition *partition, uint32 cause)
{
// notifications
if (cause != B_DEVICE_CAUSE_PARENT_CHANGED) {
BMessage notification(B_DEVICE_UPDATE);
if (_InitNotificationMessage(&notification, B_DEVICE_PARTITION_CHANGED,
cause, partition) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_PARTITION);
fWatchingService->NotifyWatchers(&notification, &filter);
}
}
} }
// Dump // Dump
+6 -14
View File
@@ -6,6 +6,7 @@
#ifndef DISK_DEVICE_LIST_H #ifndef DISK_DEVICE_LIST_H
#define DISK_DEVICE_LIST_H #define DISK_DEVICE_LIST_H
#include <DiskDeviceRoster.h>
#include <Messenger.h> #include <Messenger.h>
#include <ObjectList.h> #include <ObjectList.h>
@@ -21,20 +22,6 @@ class RPartition;
class RSession; class RSession;
class WatchingService; class WatchingService;
// 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 { class RDiskDeviceList : public MessageHandler, public RVolumeListListener {
public: public:
RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList, RDiskDeviceList(BMessenger target, BLocker &lock, RVolumeList &volumeList,
@@ -82,6 +69,8 @@ public:
uint32 cause = B_DEVICE_CAUSE_UNKNOWN); uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void DeviceRemoved(RDiskDevice *device, void DeviceRemoved(RDiskDevice *device,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN); uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void MediaChanged(RDiskDevice *device,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void SessionAdded(RSession *session, void SessionAdded(RSession *session,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN); uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void SessionRemoved(RSession *session, void SessionRemoved(RSession *session,
@@ -90,6 +79,9 @@ public:
uint32 cause = B_DEVICE_CAUSE_UNKNOWN); uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void PartitionRemoved(RPartition *partition, void PartitionRemoved(RPartition *partition,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN); uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void PartitionChanged(RPartition *partition,
uint32 cause = B_DEVICE_CAUSE_UNKNOWN);
void Dump() const; void Dump() const;
+33 -2
View File
@@ -41,6 +41,18 @@ RPartition::Unset()
fID = -1; 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 // DeviceList
RDiskDeviceList * RDiskDeviceList *
RPartition::DeviceList() const RPartition::DeviceList() const
@@ -88,9 +100,28 @@ RPartition::GetPath(char *path) const
status_t status_t
RPartition::Update(const extended_partition_info *partitionInfo) RPartition::Update(const extended_partition_info *partitionInfo)
{ {
RChangeCounter::Locker lock(fChangeCounter);
status_t error = B_OK; status_t error = B_OK;
// TODO: Check the partition info for changes! // check the partition info for changes
fInfo = *partitionInfo; // 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; return error;
} }
+2
View File
@@ -31,6 +31,8 @@ public:
RDiskDevice *Device() const; RDiskDevice *Device() const;
RSession *Session() const { return fSession; } RSession *Session() const { return fSession; }
status_t PartitionChanged();
int32 ID() const { return fID; } int32 ID() const { return fID; }
int32 ChangeCounter() const { return fChangeCounter.Count(); } int32 ChangeCounter() const { return fChangeCounter.Count(); }
void Changed(); void Changed();
+19 -5
View File
@@ -64,6 +64,7 @@ status_t
RSession::PartitionLayoutChanged() RSession::PartitionLayoutChanged()
{ {
PRINT(("RSession::PartitionLayoutChanged()\n")); PRINT(("RSession::PartitionLayoutChanged()\n"));
Changed();
status_t error = (fDevice ? B_OK : B_ERROR); status_t error = (fDevice ? B_OK : B_ERROR);
if (error == B_OK) if (error == B_OK)
error = _RescanPartitions(fDevice->FD(), B_DEVICE_CAUSE_UNKNOWN); error = _RescanPartitions(fDevice->FD(), B_DEVICE_CAUSE_UNKNOWN);
@@ -113,6 +114,8 @@ RSession::AddPartition(RPartition *partition, uint32 cause)
success = fPartitions.AddItem(partition); success = fPartitions.AddItem(partition);
if (success) { if (success) {
partition->SetSession(this); partition->SetSession(this);
Changed();
// trigger notifications
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->PartitionAdded(partition, cause); deviceList->PartitionAdded(partition, cause);
} }
@@ -126,6 +129,7 @@ RSession::RemovePartition(int32 index, uint32 cause)
{ {
RPartition *partition = PartitionAt(index); RPartition *partition = PartitionAt(index);
if (partition) { if (partition) {
Changed();
if (RDiskDeviceList *deviceList = DeviceList()) if (RDiskDeviceList *deviceList = DeviceList())
deviceList->PartitionRemoved(partition, cause); deviceList->PartitionRemoved(partition, cause);
partition->SetSession(NULL); partition->SetSession(NULL);
@@ -152,8 +156,14 @@ RSession::RemovePartition(RPartition *partition, uint32 cause)
status_t status_t
RSession::Update(const session_info *sessionInfo) RSession::Update(const session_info *sessionInfo)
{ {
RChangeCounter::Locker lock(fChangeCounter);
status_t error = (fDevice ? B_OK : B_ERROR); 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; fInfo = *sessionInfo;
int fd = (fDevice ? fDevice->FD() : -1); int fd = (fDevice ? fDevice->FD() : -1);
// check the partitions // check the partitions
@@ -175,8 +185,10 @@ RSession::Update(const session_info *sessionInfo)
// remove disappeared partitions // remove disappeared partitions
for (int32 k = CountPartitions() - 1; k >= i; k--) for (int32 k = CountPartitions() - 1; k >= i; k--)
RemovePartition(k, B_DEVICE_CAUSE_UNKNOWN); RemovePartition(k, B_DEVICE_CAUSE_UNKNOWN);
} else } else {
error = status; // ignore errors -- we can't help it
// error = status;
}
break; break;
} }
// check the partition // check the partition
@@ -269,8 +281,10 @@ RSession::_RescanPartitions(int fd, uint32 cause)
status_t status = get_nth_partition_info(fd, fInfo.index, i, status_t status = get_nth_partition_info(fd, fInfo.index, i,
&partitionInfo, (i == 0 ? fPartitioningSystem : NULL)); &partitionInfo, (i == 0 ? fPartitioningSystem : NULL));
if (status != B_OK) { if (status != B_OK) {
if (status != B_ENTRY_NOT_FOUND) if (status != B_ENTRY_NOT_FOUND) {
error = status; // ignore errors -- we can't help it
// error = status;
}
break; break;
} }
// create and add a RPartition // create and add a RPartition