From 03fa4a4f9c61172a487019ed84df66b4e5cfeaa7 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sat, 8 Feb 2003 23:34:47 +0000 Subject: [PATCH] Implemented high-level iteration code. Various fixes. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2666 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/storage/DiskDevice.h | 3 + headers/private/storage/DiskDeviceRoster.h | 7 + headers/private/storage/DiskDeviceVisitor.h | 1 + headers/private/storage/Session.h | 2 + src/kits/storage/DiskDevice.cpp | 85 ++++++++- src/kits/storage/DiskDeviceRoster.cpp | 191 +++++++++++++++++++- src/kits/storage/Partition.cpp | 7 +- src/kits/storage/Session.cpp | 35 +++- 8 files changed, 310 insertions(+), 21 deletions(-) diff --git a/headers/private/storage/DiskDevice.h b/headers/private/storage/DiskDevice.h index 6a5866bda6..44a390348f 100644 --- a/headers/private/storage/DiskDevice.h +++ b/headers/private/storage/DiskDevice.h @@ -50,6 +50,9 @@ public: BPartition *VisitEachPartition(BDiskDeviceVisitor *visitor); bool Traverse(BDiskDeviceVisitor *visitor); + BSession *SessionWithID(int32 id); + BPartition *PartitionWithID(int32 id); + private: BDiskDevice(const BDiskDevice &); BDiskDevice &operator=(const BDiskDevice &); diff --git a/headers/private/storage/DiskDeviceRoster.h b/headers/private/storage/DiskDeviceRoster.h index 4fd1507b0b..43640f5fd7 100644 --- a/headers/private/storage/DiskDeviceRoster.h +++ b/headers/private/storage/DiskDeviceRoster.h @@ -55,6 +55,9 @@ public: bool VisitEachDevice(BDiskDeviceVisitor *visitor, BDiskDevice *device = NULL); + bool VisitEachSession(BDiskDeviceVisitor *visitor, + BDiskDevice *device = NULL, + BSession **session = NULL); bool VisitEachPartition(BDiskDeviceVisitor *visitor, BDiskDevice *device = NULL, BPartition **partition = NULL); @@ -81,6 +84,10 @@ public: uint32 eventMask = B_DEVICE_REQUEST_ALL); status_t StopWatching(BMessenger target); +private: + status_t _GetObjectWithID(const char *fieldName, int32 id, + BDiskDevice *device) const; + private: BMessenger fManager; int32 fCookie; diff --git a/headers/private/storage/DiskDeviceVisitor.h b/headers/private/storage/DiskDeviceVisitor.h index 1a38e83254..884f85ac5a 100644 --- a/headers/private/storage/DiskDeviceVisitor.h +++ b/headers/private/storage/DiskDeviceVisitor.h @@ -12,6 +12,7 @@ class BSession; // BDiskDeviceVisitor class BDiskDeviceVisitor { +public: BDiskDeviceVisitor(); virtual ~BDiskDeviceVisitor(); diff --git a/headers/private/storage/Session.h b/headers/private/storage/Session.h index 085a4d5a06..79f59b4b99 100644 --- a/headers/private/storage/Session.h +++ b/headers/private/storage/Session.h @@ -43,6 +43,8 @@ public: BPartition *VisitEachPartition(BDiskDeviceVisitor *visitor); + BPartition *PartitionWithID(int32 id); + status_t GetPartitioningParameters(const char *partitioningSystem, BString *parameters, BPoint dialogCenter = BPoint(-1, -1), diff --git a/src/kits/storage/DiskDevice.cpp b/src/kits/storage/DiskDevice.cpp index b0a12d9f04..2f5bb25997 100644 --- a/src/kits/storage/DiskDevice.cpp +++ b/src/kits/storage/DiskDevice.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -295,7 +296,13 @@ BDiskDevice::Update() BSession * BDiskDevice::VisitEachSession(BDiskDeviceVisitor *visitor) { - return NULL; // not implemented + if (visitor) { + for (int32 i = 0; BSession *session = SessionAt(i); i++) { + if (visitor->Visit(session)) + return session; + } + } + return NULL; } // VisitEachPartition @@ -312,7 +319,13 @@ BDiskDevice::VisitEachSession(BDiskDeviceVisitor *visitor) BPartition * BDiskDevice::VisitEachPartition(BDiskDeviceVisitor *visitor) { - return NULL; // not implemented + if (visitor) { + for (int32 i = 0; BSession *session = SessionAt(i); i++) { + if (BPartition *partition = session->VisitEachPartition(visitor)) + return partition; + } + } + return NULL; } // Traverse @@ -330,7 +343,46 @@ BDiskDevice::VisitEachPartition(BDiskDeviceVisitor *visitor) bool BDiskDevice::Traverse(BDiskDeviceVisitor *visitor) { - return false; // not implemented + if (visitor) { + // visit the device itself + if (visitor->Visit(this)) + return true; + for (int32 i = 0; BSession *session = SessionAt(i); i++) { + // visit the session + if (visitor->Visit(session)) + return true; + // visit all partitions on the session + if (session->VisitEachPartition(visitor)) + return true; + } + } + return false; +} + +// SessionWithID +/*! \brief Returns the session on the device, that has a certain ID. + \param id The ID of the session to be returned. + \return The session with ID \a id, or \c NULL, if a session with that + ID does not exist on this device. +*/ +BSession * +BDiskDevice::SessionWithID(int32 id) +{ + IDFinderVisitor visitor(id); + return VisitEachSession(&visitor); +} + +// PartitionWithID +/*! \brief Returns the partition on the device, that has a certain ID. + \param id The ID of the partition to be returned. + \return The partition with ID \a id, or \c NULL, if a partition with that + ID does not exist on this device. +*/ +BPartition * +BDiskDevice::PartitionWithID(int32 id) +{ + IDFinderVisitor visitor(id); + return VisitEachPartition(&visitor); } // copy constructor @@ -356,7 +408,7 @@ find_string(BMessage *message, const char *name, char *buffer) { const char *str; status_t error = message->FindString(name, &str); - if (error != B_OK) + if (error == B_OK) strcpy(buffer, str); return error; } @@ -365,6 +417,8 @@ find_string(BMessage *message, const char *name, char *buffer) status_t BDiskDevice::_Unarchive(BMessage *archive) { +//printf("BDiskDevice::_Unarchive()\n"); +//archive->PrintToStream(); Unset(); status_t error = (archive ? B_OK : B_BAD_VALUE); if (error == B_OK) { @@ -373,33 +427,46 @@ BDiskDevice::_Unarchive(BMessage *archive) error = archive->FindInt32("id", &fUniqueID); if (error == B_OK) error = archive->FindInt32("change_counter", &fChangeCounter); +//printf(" check: %s\n", strerror(error)); // geometry if (error == B_OK) error = archive->FindInt64("size", &fSize); +//printf(" check: %s\n", strerror(error)); if (error == B_OK) error = archive->FindInt32("block_size", &fBlockSize); +//printf(" check: %s\n", strerror(error)); if (error == B_OK) error = archive->FindInt8("type", (int8*)&fType); +//printf(" check: %s\n", strerror(error)); if (error == B_OK) error = archive->FindBool("removable", &fRemovable); +//printf(" check: %s\n", strerror(error)); if (error == B_OK) - error = archive->FindBool("read_only", fReadOnly); + error = archive->FindBool("read_only", &fReadOnly); // if (error == B_OK) // error = archive->FindBool("write_once", fGeometry.write_once); // other data +//printf(" check: %s\n", strerror(error)); if (error == B_OK) error = find_string(archive, "path", fPath); +//printf(" check: %s\n", strerror(error)); if (error == B_OK) error = archive->FindInt32("media_status", &fMediaStatus); +//printf(" check: %s\n", strerror(error)); // sessions type_code fieldType; int32 count = 0; - if (error == B_OK) - error = archive->GetInfo("sessions", &fieldType, &count); + if (error == B_OK) { + if (archive->GetInfo("sessions", &fieldType, &count) != B_OK) + count = 0; + } +//printf(" check: %s\n", strerror(error)); for (int32 i = 0; error == B_OK && i < count; i++) { +//printf(" check1: %s\n", strerror(error)); // get the archived session BMessage sessionArchive; error = archive->FindMessage("sessions", i, &sessionArchive); +//printf(" check1.1: %s\n", strerror(error)); // allocate a session object BSession *session = NULL; if (error == B_OK) { @@ -407,12 +474,15 @@ BDiskDevice::_Unarchive(BMessage *archive) if (!session) error = B_NO_MEMORY; } +//printf(" check1.1: %s\n", strerror(error)); // unarchive the session if (error == B_OK) error = session->_Unarchive(&sessionArchive); +//printf(" check1.1: %s\n", strerror(error)); // add the session if (error == B_OK && !_AddSession(session)) error = B_NO_MEMORY; +//printf(" check1.1: %s\n", strerror(error)); // cleanup on error if (error != B_OK && session) delete session; @@ -421,6 +491,7 @@ BDiskDevice::_Unarchive(BMessage *archive) // cleanup on error if (error != B_OK) Unset(); +//printf("BDiskDevice::_Unarchive() done: %s\n", strerror(error)); return error; } diff --git a/src/kits/storage/DiskDeviceRoster.cpp b/src/kits/storage/DiskDeviceRoster.cpp index 348c0d1311..d7c6a17b26 100644 --- a/src/kits/storage/DiskDeviceRoster.cpp +++ b/src/kits/storage/DiskDeviceRoster.cpp @@ -7,9 +7,11 @@ #include #include +#include #include #include #include +#include #include /*! \class BDiskDeviceRoster @@ -29,7 +31,7 @@ BDiskDeviceRoster::BDiskDeviceRoster() { BMessage request(B_REG_GET_DISK_DEVICE_MESSENGER); BMessage reply; - if (_send_to_roster_(&request, &reply, false) == B_OK + if (BRoster::Private().SendTo(&request, &reply, false) == B_OK && reply.what == B_REG_SUCCESS) { reply.FindMessenger("messenger", &fManager); } @@ -55,6 +57,7 @@ BDiskDeviceRoster::~BDiskDeviceRoster() status_t BDiskDeviceRoster::GetNextDevice(BDiskDevice *device) { +//printf("BDiskDeviceRoster::GetNextDevice()\n"); status_t error = (device ? B_OK : B_BAD_VALUE); // compose request message BMessage request(B_REG_NEXT_DISK_DEVICE); @@ -66,21 +69,28 @@ BDiskDeviceRoster::GetNextDevice(BDiskDevice *device) error = fManager.SendMessage(&request, &reply); // analyze reply if (error == B_OK) { +//reply.PrintToStream(); // result status_t result = B_OK; error = reply.FindInt32("result", &result); +//printf(" check: %s\n", strerror(error)); if (error == B_OK) error = result; +//printf(" check: %s\n", strerror(error)); // cookie if (error == B_OK) error = reply.FindInt32("cookie", &fCookie); +//printf(" check: %s\n", strerror(error)); // device BMessage archive; if (error == B_OK) error = reply.FindMessage("device", &archive); +//printf(" check: %s\n", strerror(error)); if (error == B_OK) error = device->_Unarchive(&archive); +//printf(" check: %s\n", strerror(error)); } +//printf("BDiskDeviceRoster::GetNextDevice() done: %s\n", strerror(error)); return error; } @@ -112,7 +122,58 @@ bool BDiskDeviceRoster::VisitEachDevice(BDiskDeviceVisitor *visitor, BDiskDevice *device) { - return false; // not implemented + bool terminatedEarly = false; + if (visitor) { + int32 oldCookie = fCookie; + fCookie = 0; + BDiskDevice deviceOnStack; + BDiskDevice *useDevice = (device ? device : &deviceOnStack); + while (!terminatedEarly && GetNextDevice(useDevice) == B_OK) + terminatedEarly = visitor->Visit(useDevice); + fCookie = oldCookie; + if (!terminatedEarly) + useDevice->Unset(); + } + return terminatedEarly; +} + +// VisitEachSession +/*! \brief Iterates through the all devices' sessions. + + The supplied visitor's Visit(BSession*) is invoked for each session. + If Visit() returns \c true, the iteration is terminated and this method + returns \c true. If supplied, \a device is set to the concerned device + and in \a session the pointer to the session object is returned. + + \param visitor The visitor. + \param device Pointer to a pre-allocated BDiskDevice to be initialized + to the device at which the iteration was terminated. + May be \c NULL. + \param session Pointer to a pre-allocated BSession pointer to be set + to the session at which the iteration was terminated. + May be \c NULL. + \return \c true, if the iteration was terminated, \c false otherwise. +*/ +bool +BDiskDeviceRoster::VisitEachSession(BDiskDeviceVisitor *visitor, + BDiskDevice *device, BSession **session) +{ + bool terminatedEarly = false; + if (visitor) { + int32 oldCookie = fCookie; + fCookie = 0; + BDiskDevice deviceOnStack; + BDiskDevice *useDevice = (device ? device : &deviceOnStack); + BSession *foundSession = NULL; + while (!foundSession && GetNextDevice(useDevice) == B_OK) + foundSession = useDevice->VisitEachSession(visitor); + fCookie = oldCookie; + if (!terminatedEarly) + useDevice->Unset(); + else if (device && session) + *session = foundSession; + } + return terminatedEarly; } // VisitEachPartition @@ -137,7 +198,22 @@ BDiskDeviceRoster::VisitEachPartition(BDiskDeviceVisitor *visitor, BDiskDevice *device, BPartition **partition) { - return false; // not implemented + bool terminatedEarly = false; + if (visitor) { + int32 oldCookie = fCookie; + fCookie = 0; + BDiskDevice deviceOnStack; + BDiskDevice *useDevice = (device ? device : &deviceOnStack); + BPartition *foundPartition = NULL; + while (!foundPartition && GetNextDevice(useDevice) == B_OK) + foundPartition = useDevice->VisitEachPartition(visitor); + fCookie = oldCookie; + if (!terminatedEarly) + useDevice->Unset(); + else if (device && partition) + *partition = foundPartition; + } + return terminatedEarly; } // Traverse @@ -155,7 +231,16 @@ BDiskDeviceRoster::VisitEachPartition(BDiskDeviceVisitor *visitor, bool BDiskDeviceRoster::Traverse(BDiskDeviceVisitor *visitor) { - return false; // not implemented + bool terminatedEarly = false; + if (visitor) { + int32 oldCookie = fCookie; + fCookie = 0; + BDiskDevice device; + while (!terminatedEarly && GetNextDevice(&device) == B_OK) + terminatedEarly = device.Traverse(visitor); + fCookie = oldCookie; + } + return terminatedEarly; } // VisitEachMountedPartition @@ -181,7 +266,17 @@ BDiskDeviceRoster::VisitEachMountedPartition(BDiskDeviceVisitor *visitor, BDiskDevice *device, BPartition **partition) { - return false; // not implemented + bool terminatedEarly = false; + if (visitor) { + struct MountedPartitionFilter : public PartitionFilter { + virtual bool Filter(BPartition *partition) + { return partition->IsMounted(); } + } filter; + PartitionFilterVisitor filterVisitor(visitor, &filter); + terminatedEarly + = VisitEachPartition(&filterVisitor, device, partition); + } + return terminatedEarly; } // VisitEachMountablePartition @@ -207,7 +302,17 @@ BDiskDeviceRoster::VisitEachMountablePartition(BDiskDeviceVisitor *visitor, BDiskDevice *device, BPartition **partition) { - return false; // not implemented + bool terminatedEarly = false; + if (visitor) { + struct MountablePartitionFilter : public PartitionFilter { + virtual bool Filter(BPartition *partition) + { return partition->ContainsFileSystem(); } + } filter; + PartitionFilterVisitor filterVisitor(visitor, &filter); + terminatedEarly + = VisitEachPartition(&filterVisitor, device, partition); + } + return terminatedEarly; } // VisitEachInitializablePartition @@ -233,7 +338,17 @@ BDiskDeviceRoster::VisitEachInitializablePartition(BDiskDeviceVisitor *visitor, BDiskDevice *device, BPartition **partition) { - return false; // not implemented + bool terminatedEarly = false; + if (visitor) { + struct InitializablePartitionFilter : public PartitionFilter { + virtual bool Filter(BPartition *partition) + { return !partition->IsHidden(); } + } filter; + PartitionFilterVisitor filterVisitor(visitor, &filter); + terminatedEarly + = VisitEachPartition(&filterVisitor, device, partition); + } + return terminatedEarly; } // GetDeviceWithID @@ -252,7 +367,7 @@ BDiskDeviceRoster::VisitEachInitializablePartition(BDiskDeviceVisitor *visitor, status_t BDiskDeviceRoster::GetDeviceWithID(int32 id, BDiskDevice *device) const { - return B_ERROR; // not implemented + return _GetObjectWithID("device_id", id, device); } // GetSessionWithID @@ -276,7 +391,12 @@ status_t BDiskDeviceRoster::GetSessionWithID(int32 id, BDiskDevice *device, BSession **session) const { - return B_ERROR; // not implemented + status_t error = (device && session ? B_OK : B_BAD_VALUE); + if (error == B_OK) + error = _GetObjectWithID("session_id", id, device); + if (error == B_OK) + *session = device->SessionWithID(id); + return error; } // GetPartitionWithID @@ -300,6 +420,12 @@ status_t BDiskDeviceRoster::GetPartitionWithID(int32 id, BDiskDevice *device, BPartition **partition) const { + status_t error = (device && partition ? B_OK : B_BAD_VALUE); + if (error == B_OK) + error = _GetObjectWithID("partition_id", id, device); + if (error == B_OK) + *partition = device->PartitionWithID(id); + return error; } // StartWatching @@ -337,3 +463,50 @@ BDiskDeviceRoster::StopWatching(BMessenger target) return B_ERROR; // not implemented } +// _GetObjectWithID +/*! \brief Returns a BDiskDevice for a given device, session or partition ID. + + The supplied \a device is initialized to the device the object identified + by \a id belongs to. + + \param fieldName "device_id", "sesison_id" or "partition_id" according to + the type of object the device shall be retrieved for. + \param id The ID of the device, session or partition to be retrieved. + \param device Pointer to a pre-allocated BDiskDevice to be initialized + to the device to be retrieved. + \return + - \c B_OK: Everything went fine. + - \c B_ENTRY_NOT_FOUND: A device, session or partition respectively with + ID \a id could not be found. + - other error codes +*/ +status_t +BDiskDeviceRoster::_GetObjectWithID(const char *fieldName, int32 id, + BDiskDevice *device) const +{ + status_t error = (device ? B_OK : B_BAD_VALUE); + // compose request message + BMessage request(B_REG_GET_DISK_DEVICE); + if (error == B_OK) + error = request.AddInt32(fieldName, id); + // send request + BMessage reply; + if (error == B_OK) + error = fManager.SendMessage(&request, &reply); + // analyze reply + if (error == B_OK) { + // result + status_t result = B_OK; + error = reply.FindInt32("result", &result); + if (error == B_OK) + error = result; + // device + BMessage archive; + if (error == B_OK) + error = reply.FindMessage("device", &archive); + if (error == B_OK) + error = device->_Unarchive(&archive); + } + return error; +} + diff --git a/src/kits/storage/Partition.cpp b/src/kits/storage/Partition.cpp index 13fee7a157..c2454726a7 100644 --- a/src/kits/storage/Partition.cpp +++ b/src/kits/storage/Partition.cpp @@ -531,7 +531,7 @@ find_string(BMessage *message, const char *name, char *buffer) { const char *str; status_t error = message->FindString(name, &str); - if (error != B_OK) + if (error == B_OK) strcpy(buffer, str); return error; } @@ -540,6 +540,7 @@ find_string(BMessage *message, const char *name, char *buffer) status_t BPartition::_Unarchive(BMessage *archive) { +//printf("BPartition::_Unarchive()\n"); _Unset(); status_t error = (archive ? B_OK : B_BAD_VALUE); if (error == B_OK) { @@ -550,11 +551,13 @@ BPartition::_Unarchive(BMessage *archive) error = archive->FindInt32("change_counter", &fChangeCounter); if (error == B_OK) error = archive->FindInt32("index", &fIndex); +//printf(" check: %s\n", strerror(error)); // fInfo.info.* if (error == B_OK) error = archive->FindInt64("offset", &fInfo.info.offset); if (error == B_OK) error = archive->FindInt64("size", &fInfo.info.size); +//printf(" check: %s\n", strerror(error)); // fInfo.* if (error == B_OK) error = archive->FindInt32("flags", (int32*)&fInfo.flags); @@ -576,6 +579,7 @@ BPartition::_Unarchive(BMessage *archive) error = archive->FindInt32("fs_flags", (int32*)&fInfo.file_system_flags); } +//printf(" check: %s\n", strerror(error)); // dev_t, if mounted if (error == B_OK) { if (archive->FindInt32("volume_id", &fVolumeID) != B_OK) @@ -585,6 +589,7 @@ BPartition::_Unarchive(BMessage *archive) // cleanup on error if (error != B_OK) _Unset(); +//printf("BPartition::_Unarchive() done: %s\n", strerror(error)); return error; } diff --git a/src/kits/storage/Session.cpp b/src/kits/storage/Session.cpp index 451608b07c..ce889976f3 100644 --- a/src/kits/storage/Session.cpp +++ b/src/kits/storage/Session.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -60,7 +61,7 @@ BSession::Offset() const off_t BSession::Size() const { - return fInfo.offset; + return fInfo.size; } // BlockSize @@ -200,7 +201,26 @@ BSession::UniqueID() const BPartition * BSession::VisitEachPartition(BDiskDeviceVisitor *visitor) { - return NULL; // not implemented + if (visitor) { + for (int32 i = 0; BPartition *partition = PartitionAt(i); i++) { + if (visitor->Visit(partition)) + return partition; + } + } + return NULL; +} + +// PartitionWithID +/*! \brief Returns the partition on the session, that has a certain ID. + \param id The ID of the partition to be returned. + \return The partition with ID \a id, or \c NULL, if a partition with that + ID does not exist on this session. +*/ +BPartition * +BSession::PartitionWithID(int32 id) +{ + IDFinderVisitor visitor(id); + return VisitEachPartition(&visitor); } // GetPartitioningParameters @@ -356,6 +376,7 @@ BSession::_Unset() status_t BSession::_Unarchive(BMessage *archive) { +//printf("BSession::_Unarchive()\n"); _Unset(); status_t error = (archive ? B_OK : B_BAD_VALUE); if (error == B_OK) { @@ -366,6 +387,7 @@ BSession::_Unarchive(BMessage *archive) error = archive->FindInt32("change_counter", &fChangeCounter); if (error == B_OK) error = archive->FindInt32("index", &fIndex); +//printf(" check: %s\n", strerror(error)); // fInfo.* if (error == B_OK) error = archive->FindInt64("offset", &fInfo.offset); @@ -373,14 +395,18 @@ BSession::_Unarchive(BMessage *archive) error = archive->FindInt64("size", &fInfo.size); if (error == B_OK) error = archive->FindInt32("flags", (int32*)&fInfo.flags); +//printf(" check: %s\n", strerror(error)); // other data if (error == B_OK) error = archive->FindString("partitioning", &fPartitioningSystem); +//printf(" check: %s\n", strerror(error)); // partitions type_code fieldType; int32 count = 0; - if (error == B_OK) - error = archive->GetInfo("partitions", &fieldType, &count); + if (error == B_OK) { + if (archive->GetInfo("partitions", &fieldType, &count) != B_OK) + count = 0; + } for (int32 i = 0; error == B_OK && i < count; i++) { // get the archived partitions BMessage partitionArchive; @@ -406,6 +432,7 @@ BSession::_Unarchive(BMessage *archive) // cleanup on error if (error != B_OK) _Unset(); +//printf("BSession::_Unarchive() done: %s\n", strerror(error)); return error; }