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:
parent
bd68efa667
commit
483bea6e79
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue