* Implemented a basic notification mechanism. Right now, only media changes and

device additions/removals can be monitored.
* Minor cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29582 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-03-18 08:55:49 +00:00
parent d95f6cac87
commit 3f78b216ad
6 changed files with 136 additions and 60 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2007, Haiku, Inc. All rights reserved.
* Copyright 2004-2009, Haiku, Inc. All rights reserved.
* Copyright 2003-2004, Ingo Weinhold, [email protected]. All rights reserved.
*
* Distributed under the terms of the MIT License.
@@ -10,6 +10,7 @@
#include <disk_device_manager.h>
#include <Locker.h>
#include <Notifications.h>
namespace BPrivate {
@@ -40,6 +41,9 @@ public:
// Disk Device / Partition Management
DefaultUserNotificationService& Notifications();
void Notify(const KMessage& event, uint32 eventMask);
// manager must be locked
KDiskDevice *FindDevice(const char *path);
KDiskDevice *FindDevice(partition_id id, bool deviceOnly = true);
@@ -104,6 +108,7 @@ private:
struct PartitionSet;
class DiskSystemWatcher;
class DeviceWatcher;
class DiskNotifications;
static status_t _CheckMediaStatusDaemon(void* self);
status_t _CheckMediaStatus();
@@ -126,6 +131,8 @@ private:
status_t _AddRemoveMonitoring(const char *path, bool add);
void _NotifyDeviceEvent(KDiskDevice* device, int32 event, uint32 mask);
BLocker fLock;
DeviceMap *fDevices;
PartitionMap *fPartitions;
@@ -135,6 +142,7 @@ private:
volatile bool fTerminating;
DiskSystemWatcher *fDiskSystemWatcher;
DeviceWatcher *fDeviceWatcher;
DiskNotifications* fNotifications;
static KDiskDeviceManager *sDefaultManager;
};
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2008, Haiku Inc.
* Copyright 2003-2009, Haiku Inc.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -90,6 +90,10 @@ status_t _user_delete_child_partition(partition_id partitionID,
int32* changeCounter, partition_id childID,
int32 childChangeCounter);
// change notification
status_t _user_start_watching_disks(uint32 eventMask, port_id port, int32 token);
status_t _user_stop_watching_disks(port_id port, int32 token);
#ifdef __cplusplus
}
#endif
+5 -10
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008, Haiku Inc. All rights reserved.
* Copyright 2004-2009, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _SYSTEM_SYSCALLS_H
@@ -512,15 +512,10 @@ extern status_t _kern_delete_child_partition(partition_id partitionID,
int32* changeCounter, partition_id childID,
int32 childChangeCounter);
#if 0
// watching
status_t start_disk_device_watching(port_id, int32 token, uint32 flags);
status_t start_disk_device_job_watching(disk_job_id job, port_id, int32 token,
uint32 flags);
status_t stop_disk_device_watching(port_id, int32 token);
#endif // 0
// disk change notification
extern status_t _kern_start_watching_disks(uint32 eventMask, port_id port,
int32 token);
extern status_t _kern_stop_watching_disks(port_id port, int32 token);
// The end mark for gensyscallinfos.
@@ -22,6 +22,8 @@
#include <Path.h>
#include <Volume.h>
#include <MessengerPrivate.h>
#include <syscalls.h>
#include <ddm_userland_interface_defs.h>
@@ -511,8 +513,14 @@ BDiskDeviceRoster::GetFileDeviceForPath(const char* filename,
status_t
BDiskDeviceRoster::StartWatching(BMessenger target, uint32 eventMask)
{
// not implemented
return B_ERROR;
if (eventMask == 0)
return B_BAD_VALUE;
BMessenger::Private messengerPrivate(target);
port_id port = messengerPrivate.Port();
int32 token = messengerPrivate.Token();
return _kern_start_watching_disks(eventMask, port, token);
}
@@ -525,8 +533,11 @@ BDiskDeviceRoster::StartWatching(BMessenger target, uint32 eventMask)
status_t
BDiskDeviceRoster::StopWatching(BMessenger target)
{
// not implemented
return B_ERROR;
BMessenger::Private messengerPrivate(target);
port_id port = messengerPrivate.Port();
int32 token = messengerPrivate.Token();
return _kern_stop_watching_disks(port, token);
}
#if 0
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008, Haiku, Inc. All rights reserved.
* Copyright 2004-2009, Haiku, Inc. All rights reserved.
* Copyright 2003-2004, Ingo Weinhold, bonefish@cs.tu-berlin.de. All rights reserved.
*
* Distributed under the terms of the MIT License.
@@ -20,6 +20,7 @@
#include <VectorMap.h>
#include <VectorSet.h>
#include <DiskDeviceRoster.h>
#include <KernelExport.h>
#include <NodeMonitor.h>
@@ -183,19 +184,42 @@ private:
};
class KDiskDeviceManager::DiskNotifications
: public DefaultUserNotificationService {
public:
DiskNotifications()
: DefaultUserNotificationService("disk devices")
{
}
virtual ~DiskNotifications()
{
}
protected:
status_t _ToFlags(const KMessage& eventSpecifier, uint32& flags)
{
flags = eventSpecifier.GetInt32("flags", 0);
return B_OK;
}
};
// #pragma mark -
KDiskDeviceManager::KDiskDeviceManager()
: fLock("disk device manager"),
fDevices(new(nothrow) DeviceMap),
fPartitions(new(nothrow) PartitionMap),
fDiskSystems(new(nothrow) DiskSystemMap),
fObsoletePartitions(new(nothrow) PartitionSet),
fMediaChecker(-1),
fTerminating(false),
fDiskSystemWatcher(NULL),
fDeviceWatcher(new(nothrow) DeviceWatcher(this))
:
fLock("disk device manager"),
fDevices(new(nothrow) DeviceMap),
fPartitions(new(nothrow) PartitionMap),
fDiskSystems(new(nothrow) DiskSystemMap),
fObsoletePartitions(new(nothrow) PartitionSet),
fMediaChecker(-1),
fTerminating(false),
fDiskSystemWatcher(NULL),
fDeviceWatcher(new(nothrow) DeviceWatcher(this)),
fNotifications(new(nothrow) DiskNotifications)
{
if (InitCheck() != B_OK)
return;
@@ -267,7 +291,8 @@ KDiskDeviceManager::~KDiskDeviceManager()
status_t
KDiskDeviceManager::InitCheck() const
{
if (!fPartitions || !fDevices || !fDiskSystems || !fObsoletePartitions)
if (fPartitions == NULL || fDevices == NULL || fDiskSystems == NULL
|| fObsoletePartitions == NULL || fNotifications == NULL)
return B_NO_MEMORY;
return fLock.Sem() >= 0 ? B_OK : fLock.Sem();
@@ -323,6 +348,20 @@ KDiskDeviceManager::Unlock()
}
DefaultUserNotificationService&
KDiskDeviceManager::Notifications()
{
return *fNotifications;
}
void
KDiskDeviceManager::Notify(const KMessage& event, uint32 eventMask)
{
fNotifications->Notify(event, eventMask);
}
KDiskDevice*
KDiskDeviceManager::FindDevice(const char* path)
{
@@ -637,6 +676,9 @@ KDiskDeviceManager::CreateDevice(const char* path, bool* newlyCreated)
_ScanPartition(device, false);
device->UnmarkBusy(true);
_NotifyDeviceEvent(device, B_DEVICE_ADDED,
B_DEVICE_REQUEST_DEVICE_LIST);
if (newlyCreated)
*newlyCreated = true;
@@ -709,6 +751,9 @@ KDiskDeviceManager::CreateFileDevice(const char* filePath, bool* newlyCreated)
_ScanPartition(device, false);
device->UnmarkBusy(true);
_NotifyDeviceEvent(device, B_DEVICE_ADDED,
B_DEVICE_REQUEST_DEVICE_LIST);
if (newlyCreated)
*newlyCreated = true;
@@ -765,6 +810,7 @@ KDiskDeviceManager::NextDevice(int32* cookie)
{
if (!cookie)
return NULL;
DeviceMap::Iterator it = fDevices->FindClose(*cookie, false);
if (it != fDevices->End()) {
KDiskDevice* device = it->Value();
@@ -787,7 +833,7 @@ KDiskDeviceManager::PartitionRemoved(KPartition* partition)
{
if (partition && partition->PrepareForRemoval()
&& fPartitions->Remove(partition->ID())) {
// If adding the partition to the obsolete list fails (due to lack
// TODO: If adding the partition to the obsolete list fails (due to lack
// of memory), we can't do anything about it. We will leak memory then.
fObsoletePartitions->Insert(partition);
partition->MarkObsolete();
@@ -1091,8 +1137,14 @@ KDiskDeviceManager::_AddDevice(KDiskDevice* device)
bool
KDiskDeviceManager::_RemoveDevice(KDiskDevice* device)
{
return (device && fDevices->Remove(device->ID())
&& PartitionRemoved(device));
if (device != NULL && fDevices->Remove(device->ID())
&& PartitionRemoved(device)) {
_NotifyDeviceEvent(device, B_DEVICE_REMOVED,
B_DEVICE_REQUEST_DEVICE_LIST);
return true;
}
return false;
}
@@ -1433,6 +1485,8 @@ KDiskDeviceManager::_CheckMediaStatus()
dprintf("Media changed from %s\n", device->Path());
device->UpdateGeometry();
_ScanPartition(device, false);
_NotifyDeviceEvent(device, B_DEVICE_MEDIA_CHANGED,
B_DEVICE_REQUEST_DEVICE);
} else if (!device->HasMedia() && hadMedia) {
dprintf("Media removed from %s\n", device->Path());
}
@@ -1452,3 +1506,19 @@ KDiskDeviceManager::_CheckMediaStatusDaemon(void* self)
{
return ((KDiskDeviceManager*)self)->_CheckMediaStatus();
}
void
KDiskDeviceManager::_NotifyDeviceEvent(KDiskDevice* device, int32 event,
uint32 mask)
{
char messageBuffer[512];
KMessage message;
message.SetTo(messageBuffer, sizeof(messageBuffer), B_DEVICE_UPDATE);
message.AddInt32("event", event);
message.AddInt32("id", device->ID());
message.AddString("device", device->Path());
fNotifications->Notify(message, mask);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2008, Haiku, Inc. All Rights Reserved.
* Copyright 2003-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -40,7 +40,6 @@ using namespace BPrivate::DiskDevice;
// TODO: Add user address checks and check return values of user_memcpy()!
// ddm_strlcpy
/*! \brief Wrapper around user_strlcpy() that returns a status_t
indicating appropriate success or failure.
@@ -61,7 +60,6 @@ ddm_strlcpy(char *to, const char *from, size_t size,
}
// copy_from_user_value
template<typename Type>
static inline status_t
copy_from_user_value(Type& value, const Type* userValue)
@@ -76,7 +74,6 @@ copy_from_user_value(Type& value, const Type* userValue)
}
// copy_to_user_value
template<typename Type>
static inline status_t
copy_to_user_value(Type* userValue, const Type& value)
@@ -91,7 +88,6 @@ copy_to_user_value(Type* userValue, const Type& value)
}
// UserStringParameter
template<bool kAllowsNull>
struct UserStringParameter {
char* value;
@@ -144,7 +140,6 @@ struct UserStringParameter {
};
// UserMemoryParameter
template<typename Type, bool kAllowsNull>
struct UserMemoryParameter {
Type* value;
@@ -190,7 +185,6 @@ struct UserMemoryParameter {
#if 0
// move_descendants
static void
move_descendants(KPartition *partition, off_t moveBy)
{
@@ -203,7 +197,6 @@ move_descendants(KPartition *partition, off_t moveBy)
}
// move_descendants_contents
static status_t
move_descendants_contents(KPartition *partition)
{
@@ -228,7 +221,6 @@ move_descendants_contents(KPartition *partition)
#endif // 0
// _user_get_next_disk_device_id
partition_id
_user_get_next_disk_device_id(int32 *_cookie, size_t *neededSize)
{
@@ -262,7 +254,6 @@ _user_get_next_disk_device_id(int32 *_cookie, size_t *neededSize)
}
// _user_find_disk_device
partition_id
_user_find_disk_device(const char *_filename, size_t *neededSize)
{
@@ -293,7 +284,6 @@ _user_find_disk_device(const char *_filename, size_t *neededSize)
}
// _user_find_partition
partition_id
_user_find_partition(const char *_filename, size_t *neededSize)
{
@@ -362,7 +352,6 @@ _user_find_file_disk_device(const char *_filename, size_t *neededSize)
}
// _user_get_disk_device_data
/*! \brief Writes data describing the disk device identified by ID and all
its partitions into the supplied buffer.
@@ -454,7 +443,6 @@ _user_get_disk_device_data(partition_id id, bool deviceOnly,
}
// _user_register_file_device
partition_id
_user_register_file_device(const char *_filename)
{
@@ -475,7 +463,6 @@ _user_register_file_device(const char *_filename)
}
// _user_unregister_file_device
status_t
_user_unregister_file_device(partition_id deviceID, const char *_filename)
{
@@ -520,7 +507,6 @@ _user_get_file_disk_device_path(partition_id id, char* buffer,
}
// _user_get_disk_system_info
status_t
_user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info)
{
@@ -539,7 +525,6 @@ _user_get_disk_system_info(disk_system_id id, user_disk_system_info *_info)
}
// _user_get_next_disk_system_info
status_t
_user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info)
{
@@ -562,7 +547,6 @@ _user_get_next_disk_system_info(int32 *_cookie, user_disk_system_info *_info)
}
// _user_find_disk_system
status_t
_user_find_disk_system(const char *_name, user_disk_system_info *_info)
{
@@ -585,7 +569,6 @@ _user_find_disk_system(const char *_name, user_disk_system_info *_info)
}
// _user_defragment_partition
status_t
_user_defragment_partition(partition_id partitionID, int32* _changeCounter)
{
@@ -640,7 +623,6 @@ _user_defragment_partition(partition_id partitionID, int32* _changeCounter)
}
// _user_repair_partition
status_t
_user_repair_partition(partition_id partitionID, int32* _changeCounter,
bool checkOnly)
@@ -696,7 +678,6 @@ _user_repair_partition(partition_id partitionID, int32* _changeCounter,
}
// _user_resize_partition
status_t
_user_resize_partition(partition_id partitionID, int32* _changeCounter,
partition_id childID, int32* _childChangeCounter, off_t size,
@@ -792,7 +773,6 @@ _user_resize_partition(partition_id partitionID, int32* _changeCounter,
}
// _user_move_partition
status_t
_user_move_partition(partition_id partitionID, int32* changeCounter,
partition_id childID, int32* childChangeCounter, off_t newOffset,
@@ -834,7 +814,6 @@ return B_BAD_VALUE;
}
// _user_set_partition_name
status_t
_user_set_partition_name(partition_id partitionID, int32* _changeCounter,
partition_id childID, int32* _childChangeCounter, const char* _name)
@@ -915,7 +894,6 @@ _user_set_partition_name(partition_id partitionID, int32* _changeCounter,
}
// _user_set_partition_content_name
status_t
_user_set_partition_content_name(partition_id partitionID,
int32* _changeCounter, const char* _name)
@@ -975,7 +953,6 @@ _user_set_partition_content_name(partition_id partitionID,
}
// _user_set_partition_type
status_t
_user_set_partition_type(partition_id partitionID, int32* _changeCounter,
partition_id childID, int32* _childChangeCounter, const char* _type)
@@ -1056,7 +1033,6 @@ _user_set_partition_type(partition_id partitionID, int32* _changeCounter,
}
// _user_set_partition_parameters
status_t
_user_set_partition_parameters(partition_id partitionID, int32* _changeCounter,
partition_id childID, int32* _childChangeCounter, const char* _parameters,
@@ -1139,7 +1115,6 @@ _user_set_partition_parameters(partition_id partitionID, int32* _changeCounter,
}
// _user_set_partition_content_parameters
status_t
_user_set_partition_content_parameters(partition_id partitionID,
int32* _changeCounter, const char* _parameters, size_t parametersSize)
@@ -1201,7 +1176,6 @@ _user_set_partition_content_parameters(partition_id partitionID,
}
// _user_initialize_partition
status_t
_user_initialize_partition(partition_id partitionID, int32* _changeCounter,
const char* _diskSystemName, const char* _name, const char* _parameters,
@@ -1276,7 +1250,6 @@ _user_initialize_partition(partition_id partitionID, int32* _changeCounter,
}
// _user_uninitialize_partition
status_t
_user_uninitialize_partition(partition_id partitionID, int32* _changeCounter)
{
@@ -1328,7 +1301,6 @@ _user_uninitialize_partition(partition_id partitionID, int32* _changeCounter)
}
// _user_create_child_partition
status_t
_user_create_child_partition(partition_id partitionID, int32* _changeCounter,
off_t offset, off_t size, const char* _type, const char* _name,
@@ -1404,7 +1376,6 @@ _user_create_child_partition(partition_id partitionID, int32* _changeCounter,
}
// _user_delete_child_partition
status_t
_user_delete_child_partition(partition_id partitionID, int32* _changeCounter,
partition_id childID, int32 childChangeCounter)
@@ -1473,3 +1444,20 @@ _user_delete_child_partition(partition_id partitionID, int32* _changeCounter,
return B_OK;
}
status_t
_user_start_watching_disks(uint32 eventMask, port_id port, int32 token)
{
KDiskDeviceManager* manager = KDiskDeviceManager::Default();
return manager->Notifications().UpdateUserListener(eventMask, port, token);
}
status_t
_user_stop_watching_disks(port_id port, int32 token)
{
KDiskDeviceManager* manager = KDiskDeviceManager::Default();
return manager->Notifications().RemoveUserListeners(port, token);
}