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

View File

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

View File

@ -3,6 +3,7 @@
// by the OpenBeOS license.
//---------------------------------------------------------------------
#include <errno.h>
#include <fcntl.h>
#include <new.h>
#include <stdio.h>
@ -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

View File

@ -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(&notification, B_DEVICE_ADDED,
cause, device) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE_LIST);
fWatchingService->NotifyWatchers(&notification, &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(&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
@ -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(&notification, B_DEVICE_SESSION_ADDED,
cause, session) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE);
fWatchingService->NotifyWatchers(&notification, &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(&notification, B_DEVICE_SESSION_REMOVED,
cause, session) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_DEVICE);
fWatchingService->NotifyWatchers(&notification, &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(&notification, B_DEVICE_PARTITION_ADDED,
cause, partition) == B_OK) {
EventMaskWatcherFilter filter(B_DEVICE_REQUEST_SESSION);
fWatchingService->NotifyWatchers(&notification, &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(&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

View File

@ -6,6 +6,7 @@
#ifndef DISK_DEVICE_LIST_H
#define DISK_DEVICE_LIST_H
#include <DiskDeviceRoster.h>
#include <Messenger.h>
#include <ObjectList.h>
@ -21,20 +22,6 @@ class RPartition;
class RSession;
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 {
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;

View File

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

View File

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

View File

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