diff --git a/headers/os/interface/Layout.h b/headers/os/interface/Layout.h index 2a59ab7110..dc488cdfbe 100644 --- a/headers/os/interface/Layout.h +++ b/headers/os/interface/Layout.h @@ -54,11 +54,11 @@ public: virtual status_t Archive(BMessage* into, bool deep = true) const; virtual status_t AllUnarchived(const BMessage* from); - virtual status_t ArchiveLayoutData(BMessage* into, - const BLayoutItem* of) const; - virtual status_t RestoreItemAndData(const BMessage* from, - BLayoutItem* item); + virtual status_t ItemArchived(BMessage* into, BLayoutItem* item, + int32 index) const; + virtual status_t ItemUnarchived(const BMessage* from, + BLayoutItem* item, int32 index); protected: // TODO: Since memory allocations can fail, we should return a bool and // undo the addition, if false. diff --git a/headers/os/support/Archivable.h b/headers/os/support/Archivable.h index 6424240b8d..6f15977375 100644 --- a/headers/os/support/Archivable.h +++ b/headers/os/support/Archivable.h @@ -7,11 +7,13 @@ #include +#include #include class BMessage; + namespace BPrivate { namespace Archiving { class BArchiveManager; @@ -38,9 +40,12 @@ public: virtual status_t AllArchived(BMessage* archive) const; private: + friend class BUnarchiveManager; + virtual void _ReservedArchivable3(); - uint32 _reserved[2]; + int32 fArchivingToken; + uint32 _reserved; }; @@ -52,11 +57,13 @@ public: status_t AddArchivable(const char* name, BArchivable* archivable, bool deep = true); + inline status_t GetTokenForArchivable(BArchivable* archivable, + int32& _token); status_t GetTokenForArchivable(BArchivable* archivable, - int32& _token, bool deep = true); + bool deep, int32& _token); bool IsArchived(BArchivable* archivable); - status_t Finish(); + status_t Finish(status_t err = B_OK); BMessage* ArchiveMessage() const; private: @@ -71,37 +78,64 @@ private: BArchiveManager* fManager; BMessage* fArchive; bool fFinished; + uint32 _reserved[2]; }; class BUnarchiver { public: + enum ownership_policy { + B_ASSUME_OWNERSHIP, + B_DONT_ASSUME_OWNERSHIP + }; + BUnarchiver(const BMessage* archive); ~BUnarchiver(); - status_t GetArchivable(int32 token, - BArchivable** archivable); + template + inline status_t GetObject(int32 token, T*& object); - status_t FindArchivable(const char* name, - BArchivable** archivable); + template + status_t GetObject(int32 token, ownership_policy owning, + T*& object); - status_t FindArchivable(const char* name, int32 index, - BArchivable** archivable); + template + inline status_t FindObject(const char* name, T*& object); - status_t EnsureUnarchived(const char* name, + template + inline status_t FindObject(const char* name, + ownership_policy owning, + T*& object); + + template + inline status_t FindObject(const char* name, + int32 index, T*& object); + + template + status_t FindObject(const char* name, int32 index, + ownership_policy owning, T*& object); + + inline status_t EnsureUnarchived(const char* name, int32 index = 0); - status_t EnsureUnarchived(int32 token); + inline status_t EnsureUnarchived(int32 token); bool IsInstantiated(int32 token); bool IsInstantiated(const char* name, int32 index = 0); - status_t Finish(); + status_t Finish(status_t err = B_OK); const BMessage* ArchiveMessage() const; + void AssumeOwnership(BArchivable* archivable); + void RelinquishOwnership(BArchivable* archivable); + static bool IsArchiveManaged(BMessage* archive); static BMessage* PrepareArchive(BMessage*& archive); + template + static status_t InstantiateObject(BMessage* archive, + T*& object); + private: friend class BArchivable; @@ -110,11 +144,12 @@ private: void RegisterArchivable(BArchivable* archivable); - void _CallDebuggerIfManagerNull(); + inline void _CallDebuggerIfManagerNull(); BUnarchiveManager* fManager; const BMessage* fArchive; bool fFinished; + uint32 _reserved[2]; }; @@ -131,4 +166,144 @@ instantiation_func find_instantiation_func(const char* className, instantiation_func find_instantiation_func(const char* className); instantiation_func find_instantiation_func(BMessage* archive); + +status_t +BArchiver::GetTokenForArchivable(BArchivable* archivable, int32& _token) +{ + return GetTokenForArchivable(archivable, true, _token); +} + + +template<> +status_t BUnarchiver::FindObject(const char* name, int32 index, + ownership_policy owning, BArchivable*& archivable); + + +template +status_t +BUnarchiver::FindObject(const char* name, int32 index, + ownership_policy owning, T*& object) +{ + object = NULL; + + BArchivable* interim; + status_t err = FindObject(name, index, owning, interim); + + if (err == B_OK && interim) { + object = dynamic_cast(interim); + if (!object) { + err = B_BAD_TYPE; + // we will not be deleting this item, but it must be deleted + if (owning == B_ASSUME_OWNERSHIP) + RelinquishOwnership(interim); + } + } + return err; +} + + +template<> +status_t +BUnarchiver::GetObject(int32 token, + ownership_policy owning, BArchivable*& object); + + +template +status_t +BUnarchiver::GetObject(int32 token, ownership_policy owning, T*& object) +{ + object = NULL; + + BArchivable* interim; + status_t err = GetObject(token, owning, interim); + + if (err == B_OK && interim) { + object = dynamic_cast(interim); + if (!object) { + err = B_BAD_TYPE; + // we will not be deleting this item, but it must be deleted + if (owning == B_ASSUME_OWNERSHIP) + RelinquishOwnership(interim); + } + } + return err; +} + + +template +status_t +BUnarchiver::GetObject(int32 token, T*& object) +{ + return GetObject(token, B_ASSUME_OWNERSHIP, object); +} + + +template +status_t +BUnarchiver::FindObject(const char* name, ownership_policy owning, T*& object) +{ + return FindObject(name, 0, owning, object); +} + + +template +status_t +BUnarchiver::FindObject(const char* name, T*& object) +{ + return FindObject(name, 0, B_ASSUME_OWNERSHIP, object); +} + + +template +status_t +BUnarchiver::FindObject(const char* name, + int32 index, T*& object) +{ + return FindObject(name, index, B_ASSUME_OWNERSHIP, object); +} + + +status_t +BUnarchiver::EnsureUnarchived(int32 token) +{ + BArchivable* dummy; + return GetObject(token, B_DONT_ASSUME_OWNERSHIP, dummy); +} + + +status_t +BUnarchiver::EnsureUnarchived(const char* name, int32 index) +{ + BArchivable* dummy; + return FindObject(name, index, B_DONT_ASSUME_OWNERSHIP, dummy); +} + + +template<> +status_t +BUnarchiver::InstantiateObject(BMessage* from, + BArchivable*& object); + + +template +status_t +BUnarchiver::InstantiateObject(BMessage* archive, T*& object) +{ + object = NULL; + + BArchivable* interim; + status_t err = InstantiateObject(archive, interim); + if (err != B_OK || interim == NULL) + return err; + + object = dynamic_cast(interim); + if (object == NULL) { + delete interim; + return B_BAD_TYPE; + } + + return B_OK; +} + + #endif // _ARCHIVABLE_H diff --git a/headers/private/binary_compatibility/Global.h b/headers/private/binary_compatibility/Global.h index b2897035e1..f8811573fa 100644 --- a/headers/private/binary_compatibility/Global.h +++ b/headers/private/binary_compatibility/Global.h @@ -4,7 +4,7 @@ * Distributed under the terms of the MIT License. */ #ifndef _BINARY_COMPATIBILITY_GLOBAL_H_ -#define _BINARY_COMPATIBILITY__GLOBAL_H_ +#define _BINARY_COMPATIBILITY_GLOBAL_H_ // method codes @@ -24,7 +24,6 @@ enum { PERFORM_CODE_GET_TOOL_TIP_AT = 1009, // support kit - PERFORM_CODE_ALL_ARCHIVED = 1010, PERFORM_CODE_ALL_UNARCHIVED = 1011 }; diff --git a/headers/private/binary_compatibility/Support.h b/headers/private/binary_compatibility/Support.h index 5d8ae0a176..f33f39be60 100644 --- a/headers/private/binary_compatibility/Support.h +++ b/headers/private/binary_compatibility/Support.h @@ -2,8 +2,8 @@ * Copyright 2010, Haiku, Inc. * Distributed under the terms of the MIT License. */ -#ifndef _BINARY_COMPATIBILITY_SUPPORT_H -#define _BINARY_COMPATIBILITY_SUPPORT_H +#ifndef _BINARY_COMPATIBILITY_SUPPORT_H_ +#define _BINARY_COMPATIBILITY_SUPPORT_H_ #include @@ -20,4 +20,4 @@ struct perform_data_all_archived { status_t return_value; }; -#endif /* _BINARY_COMPATIBILITY_INTERFACE_H_ */ +#endif /* _BINARY_COMPATIBILITY_SUPPORT_H_ */ diff --git a/src/kits/interface/Layout.cpp b/src/kits/interface/Layout.cpp index 3fae634b6d..d165c81e97 100644 --- a/src/kits/interface/Layout.cpp +++ b/src/kits/interface/Layout.cpp @@ -7,6 +7,7 @@ #include +#include #include #include @@ -19,11 +20,9 @@ using std::nothrow; namespace { const char* kLayoutItemField = "BLayout:_items"; - const char* kLayoutDataField = "BLayout:_data"; } -// constructor BLayout::BLayout() : fView(NULL), @@ -211,77 +210,64 @@ BLayout::Archive(BMessage* into, bool deep) const BArchiver archiver(into); status_t err = BArchivable::Archive(into, deep); - if (err != B_OK) - return err; - if (deep) { int32 count = CountItems(); - for (int32 i = 0; i < count; i++) { - err = archiver.AddArchivable(kLayoutItemField, ItemAt(i), deep); + for (int32 i = 0; i < count && err == B_OK; i++) { + BLayoutItem* item = ItemAt(i); + err = archiver.AddArchivable(kLayoutItemField, item, deep); if (err == B_OK) { - BMessage data; - err = ArchiveLayoutData(&data, ItemAt(i)); - if (err == B_OK) - err = into->AddMessage(kLayoutDataField, &data); + err = ItemArchived(into, item, i); + if (err != B_OK) + syslog(LOG_ERR, "ItemArchived() failed at index: %d.", i); } - - if (err != B_OK) - return err; } } - return archiver.Finish(); + return archiver.Finish(err); } status_t BLayout::AllUnarchived(const BMessage* from) { - status_t err = BArchivable::AllUnarchived(from); BUnarchiver unarchiver(from); + status_t err = BArchivable::AllUnarchived(from); if (err != B_OK) return err; - for (int32 i = 0; ; i++) { - BArchivable* retriever; - err = unarchiver.FindArchivable(kLayoutItemField, i, &retriever); + int32 itemCount; + unarchiver.ArchiveMessage()->GetInfo(kLayoutItemField, NULL, &itemCount); + for (int32 i = 0; i < itemCount && err == B_OK; i++) { + BLayoutItem* item; + err = unarchiver.FindObject(kLayoutItemField, i, item); - if (err == B_BAD_INDEX) - break; - - if (err == B_OK) { - BMessage layoutData; - err = from->FindMessage(kLayoutDataField, i, &layoutData); - - if (err == B_OK) { - BLayoutItem* item = dynamic_cast(retriever); - err = RestoreItemAndData(&layoutData, item); - } + if (err == B_OK && item) { + if (fItems.AddItem(item)) { + ItemAdded(item); + item->SetLayout(this); + err = ItemUnarchived(from, item, i); + } else + err = B_NO_MEMORY; } - - if (err != B_OK) - return err; } - return B_OK; + return err; } status_t -BLayout::ArchiveLayoutData(BMessage* into, const BLayoutItem* of) const +BLayout::ItemArchived(BMessage* into, BLayoutItem* of, int32 index) const { return B_OK; } status_t -BLayout::RestoreItemAndData(const BMessage* from, BLayoutItem* item) +BLayout::ItemUnarchived(const BMessage* from, BLayoutItem* item, int32 index) { - if (item && AddItem(item)) - return B_OK; - return B_ERROR; + return B_OK; } diff --git a/src/kits/support/Archivable.cpp b/src/kits/support/Archivable.cpp index 8a8c76cdcd..13c7102b4b 100644 --- a/src/kits/support/Archivable.cpp +++ b/src/kits/support/Archivable.cpp @@ -210,11 +210,15 @@ check_signature(const char* signature, image_info& info) BArchivable::BArchivable() + : + fArchivingToken(NULL_TOKEN) { } BArchivable::BArchivable(BMessage* from) + : + fArchivingToken(NULL_TOKEN) { if (BUnarchiver::IsArchiveManaged(from)) { BUnarchiver::PrepareArchive(from); @@ -313,7 +317,7 @@ BArchiver::BArchiver(BMessage* archive) BArchiver::~BArchiver() { if (!fFinished) - fManager->ArchiverLeaving(this); + fManager->ArchiverLeaving(this, B_OK); } @@ -321,7 +325,7 @@ status_t BArchiver::AddArchivable(const char* name, BArchivable* archivable, bool deep) { int32 token; - status_t err = GetTokenForArchivable(archivable, token, deep); + status_t err = GetTokenForArchivable(archivable, deep, token); if (err != B_OK) return err; @@ -332,17 +336,9 @@ BArchiver::AddArchivable(const char* name, BArchivable* archivable, bool deep) status_t BArchiver::GetTokenForArchivable(BArchivable* archivable, - int32& _token, bool deep) + bool deep, int32& _token) { - status_t err = B_OK; - - if (!IsArchived(archivable)) - err = fManager->ArchiveObject(archivable, deep); - - if (err == B_OK) - return fManager->GetTokenForArchivable(archivable, _token); - - return err; + return fManager->ArchiveObject(archivable, deep, _token); } @@ -354,13 +350,14 @@ BArchiver::IsArchived(BArchivable* archivable) status_t -BArchiver::Finish() +BArchiver::Finish(status_t err) { if (fFinished) debugger("Finish() called multiple times on same BArchiver."); fFinished = true; - return fManager->ArchiverLeaving(this); + + return fManager->ArchiverLeaving(this, err); } @@ -393,56 +390,32 @@ BUnarchiver::BUnarchiver(const BMessage* archive) BUnarchiver::~BUnarchiver() { if (!fFinished && fManager) - fManager->UnarchiverLeaving(this); + fManager->UnarchiverLeaving(this, B_OK); } +template<> status_t -BUnarchiver::GetArchivable(int32 token, BArchivable** archivable) +BUnarchiver::GetObject(int32 token, + ownership_policy owning, BArchivable*& object) { _CallDebuggerIfManagerNull(); - - if (archivable == NULL) - return B_BAD_VALUE; - - return fManager->ArchivableForToken(archivable, token); + return fManager->GetArchivableForToken(token, owning, object); } +template<> status_t -BUnarchiver::FindArchivable(const char* name, BArchivable** archivable) +BUnarchiver::FindObject(const char* name, + int32 index, ownership_policy owning, BArchivable*& archivable) { - return FindArchivable(name, 0, archivable); -} - - -status_t -BUnarchiver::FindArchivable(const char* name, - int32 index, BArchivable** archivable) -{ - + archivable = NULL; int32 token; status_t err = fArchive->FindInt32(name, index, &token); if (err != B_OK) return err; - return GetArchivable(token, archivable); -} - - -status_t -BUnarchiver::EnsureUnarchived(const char* name, int32 index) -{ - BArchivable* dummy; - return FindArchivable(name, index, &dummy); -} - - -status_t -BUnarchiver::EnsureUnarchived(int32 token) -{ - BArchivable* dummy; - return GetArchivable(token, &dummy); + return GetObject(token, owning, archivable); } @@ -452,6 +425,7 @@ BUnarchiver::IsInstantiated(int32 token) return fManager->IsInstantiated(token); } + bool BUnarchiver::IsInstantiated(const char* field, int32 index) { @@ -461,14 +435,18 @@ BUnarchiver::IsInstantiated(const char* field, int32 index) return false; } + status_t -BUnarchiver::Finish() +BUnarchiver::Finish(status_t err) { if (fFinished) debugger("Finish() called multiple times on same BArchiver."); fFinished = true; - return fManager->UnarchiverLeaving(this); + if (fManager) + return fManager->UnarchiverLeaving(this, err); + else + return B_OK; } @@ -479,6 +457,22 @@ BUnarchiver::ArchiveMessage() const } +void +BUnarchiver::AssumeOwnership(BArchivable* archivable) +{ + _CallDebuggerIfManagerNull(); + fManager->AssumeOwnership(archivable); +} + + +void +BUnarchiver::RelinquishOwnership(BArchivable* archivable) +{ + _CallDebuggerIfManagerNull(); + fManager->RelinquishOwnership(archivable); +} + + bool BUnarchiver::IsArchiveManaged(BMessage* archive) { @@ -487,14 +481,25 @@ BUnarchiver::IsArchiveManaged(BMessage* archive) return true; // managed top level archives return here - int32 dummy; - if (archive->FindInt32(kArchiveCountField, &dummy) == B_OK) + bool dummy; + if (archive->FindBool(kManagedField, &dummy) == B_OK) return true; return false; } +template<> +status_t +BUnarchiver::InstantiateObject(BMessage* from, + BArchivable*& object) +{ + BUnarchiver unarchiver(BUnarchiver::PrepareArchive(from)); + object = instantiate_object(from); + return unarchiver.Finish(); +} + + BMessage* BUnarchiver::PrepareArchive(BMessage*& archive) { diff --git a/src/kits/support/ArchivingManagers.cpp b/src/kits/support/ArchivingManagers.cpp index 819825ce4d..8eda3a3596 100644 --- a/src/kits/support/ArchivingManagers.cpp +++ b/src/kits/support/ArchivingManagers.cpp @@ -6,18 +6,16 @@ * Alex Wilson (yourpalal2@gmail.com) */ +#include "ArchivingManagers.h" #include #include -#include "ArchivingManagers.h" - namespace BPrivate { namespace Archiving { - const char* kArchiveCountField = "_managed_archive_count"; const char* kArchivableField = "_managed_archivable"; - const char* kTokenField = "_managed_token"; + const char* kManagedField = "_managed_archive"; } } @@ -50,7 +48,7 @@ BManagerBase::UnarchiveManager(const BMessage* archive) if (manager->fType == UNARCHIVE_MANAGER) return static_cast(manager); - debugger("More calls to BUnarchiver::PrepareMessage()" + debugger("More calls to BUnarchiver::PrepareArchive()" " than BUnarchivers created."); return NULL; @@ -84,14 +82,15 @@ BArchiveManager::BArchiveManager(const BArchiver* creator) : BManagerBase(creator->ArchiveMessage(), BManagerBase::ARCHIVE_MANAGER), fTokenMap(), - fCreator(creator) + fCreator(creator), + fError(B_OK) { } BArchiveManager::~BArchiveManager() { - fTopLevelArchive->AddInt32(kArchiveCountField, fTokenMap.size()); + fTopLevelArchive->AddBool(kManagedField, true); } @@ -99,7 +98,7 @@ status_t BArchiveManager::GetTokenForArchivable(BArchivable* archivable, int32& _token) { if (!archivable) { - _token = -42; + _token = NULL_TOKEN; return B_OK; } @@ -114,25 +113,32 @@ BArchiveManager::GetTokenForArchivable(BArchivable* archivable, int32& _token) status_t -BArchiveManager::ArchiveObject(BArchivable* archivable, bool deep) +BArchiveManager::ArchiveObject(BArchivable* archivable, + bool deep, int32& _token) { - if (IsArchived(archivable)){ - debugger("BArchivable requested to be archived" - " was previously archived."); + if (!archivable) { + _token = NULL_TOKEN; + return B_OK; } ArchiveInfo& info = fTokenMap[archivable]; - info.archive = new BMessage(); - info.token = fTokenMap.size() - 1; + status_t err = B_OK; - MarkArchive(info.archive); - status_t err = archivable->Archive(info.archive, deep); + if (!info.archive) { + info.archive = new BMessage(); + info.token = fTokenMap.size() - 1; + + MarkArchive(info.archive); + err = archivable->Archive(info.archive, deep); + } if (err != B_OK) { fTokenMap.erase(archivable); // info.archive gets deleted here - } + _token = NULL_TOKEN; + } else + _token = info.token; return err; } @@ -149,9 +155,12 @@ BArchiveManager::IsArchived(BArchivable* archivable) status_t -BArchiveManager::ArchiverLeaving(const BArchiver* archiver) +BArchiveManager::ArchiverLeaving(const BArchiver* archiver, status_t err) { - if (archiver == fCreator) { + if (fError == B_OK) + fError = err; + + if (archiver == fCreator && fError == B_OK) { // first, we must sort the objects into the order they were archived in typedef std::pair ArchivePair; ArchivePair pairs[fTokenMap.size()]; @@ -167,29 +176,28 @@ BArchiveManager::ArchiverLeaving(const BArchiver* archiver) info.archive = NULL; } - status_t err = B_ERROR; int32 count = fTokenMap.size(); for (int32 i = 0; i < count; i++) { const ArchivePair& pair = pairs[i]; - err = pair.second->AllArchived(pair.first); + fError = pair.second->AllArchived(pair.first); - if (err == B_OK && i > 0) { - err = fTopLevelArchive->AddMessage(kArchivableField, + if (fError == B_OK && i > 0) { + fError = fTopLevelArchive->AddMessage(kArchivableField, pair.first); } - if (err != B_OK) { + if (fError != B_OK) { syslog(LOG_ERR, "AllArchived failed for object of type %s.", typeid(*pairs[i].second).name()); break; } } - - delete this; - return err; } - return B_OK; + if (archiver == fCreator) + delete this; + + return fError; } @@ -211,7 +219,8 @@ struct BUnarchiveManager::ArchiveInfo { ArchiveInfo() : archivable(NULL), - archive() + archive(), + adopted(false) { } @@ -223,6 +232,7 @@ struct BUnarchiveManager::ArchiveInfo { BArchivable* archivable; BMessage archive; + bool adopted; }; @@ -235,9 +245,12 @@ BUnarchiveManager::BUnarchiveManager(BMessage* archive) fObjects(NULL), fObjectCount(0), fTokenInProgress(0), - fRefCount(0) + fRefCount(0), + fError(B_OK) { - archive->FindInt32(kArchiveCountField, &fObjectCount); + archive->GetInfo(kArchivableField, NULL, &fObjectCount); + fObjectCount++; + // root object needs a spot too fObjects = new ArchiveInfo[fObjectCount]; // fObjects[0] is a placeholder for the object that started @@ -260,28 +273,37 @@ BUnarchiveManager::~BUnarchiveManager() status_t -BUnarchiveManager::ArchivableForToken(BArchivable** _archivable, int32 token) +BUnarchiveManager::GetArchivableForToken(int32 token, + BUnarchiver::ownership_policy owning, BArchivable*& _archivable) { - if (!_archivable || token > fObjectCount) + if (token >= fObjectCount) return B_BAD_VALUE; if (token < 0) { - *_archivable = NULL; + _archivable = NULL; return B_OK; } status_t err = B_OK; - if (!fObjects[token].archivable) { - if (fRefCount > 0) - err = _InstantiateObjectForToken(token); - else { + ArchiveInfo& info = fObjects[token]; + if (!info.archivable) { + if (fRefCount > 0) { + fTokenInProgress = token; + if(!instantiate_object(&info.archive)) + err = B_ERROR; + } else { syslog(LOG_ERR, "Object requested from AllUnarchived()" " was not previously instantiated"); err = B_ERROR; } } - *_archivable = fObjects[token].archivable; + if (!info.adopted && owning == BUnarchiver::B_ASSUME_OWNERSHIP) + info.adopted = true; + else if (info.adopted && owning == BUnarchiver::B_ASSUME_OWNERSHIP) + debugger("Cannot assume ownership of an object that is already owned"); + + _archivable = info.archivable; return err; } @@ -302,37 +324,84 @@ BUnarchiveManager::RegisterArchivable(BArchivable* archivable) debugger("Cannot register NULL pointer"); fObjects[fTokenInProgress].archivable = archivable; + archivable->fArchivingToken = fTokenInProgress; } status_t -BUnarchiveManager::UnarchiverLeaving(const BUnarchiver* unarchiver) +BUnarchiveManager::UnarchiverLeaving(const BUnarchiver* unarchiver, + status_t err) { - if (--fRefCount == 0) { - fRefCount = -1; - // make sure we de not end up here again! + if (--fRefCount >= 0 && fError == B_OK) + fError = err; + if (fRefCount != 0) + return fError; + + if (fError == B_OK) { BArchivable* archivable = fObjects[0].archivable; - status_t err = archivable->AllUnarchived(fTopLevelArchive); - - for (int32 i = 1; i < fObjectCount; i++) { - if (err != B_OK) - break; + if (archivable) { + fError = archivable->AllUnarchived(fTopLevelArchive); + archivable->fArchivingToken = NULL_TOKEN; + } + for (int32 i = 1; i < fObjectCount && fError == B_OK; i++) { archivable = fObjects[i].archivable; - err = archivable->AllUnarchived(&fObjects[i].archive); + if (archivable) { + fError = archivable->AllUnarchived(&fObjects[i].archive); + archivable->fArchivingToken = NULL_TOKEN; + } } - - if (err != B_OK) { - syslog(LOG_ERR, "AllUnarchived failed for object of type %s.", - typeid(*archivable).name()); + if (fError != B_OK) { + syslog(LOG_ERR, "Error in AllUnarchived" + " method of object of type %s", typeid(*archivable).name()); } - - delete this; - return err; } - return B_OK; + if (fError != B_OK) { + syslog(LOG_ERR, "An error occured during unarchival, cleaning up."); + for (int32 i = 1; i < fObjectCount; i++) { + if (!fObjects[i].adopted) + delete fObjects[i].archivable; + } + } + + delete this; + return fError; +} + + +void +BUnarchiveManager::RelinquishOwnership(BArchivable* archivable) +{ + int32 token = NULL_TOKEN; + if (archivable) + token = archivable->fArchivingToken; + + if (token < 0 || token >= fObjectCount + || fObjects[token].archivable != archivable) + return; + + fObjects[token].adopted = false; +} + + +void +BUnarchiveManager::AssumeOwnership(BArchivable* archivable) +{ + int32 token = NULL_TOKEN; + if (archivable) + token = archivable->fArchivingToken; + + if (token < 0 || token >= fObjectCount + || fObjects[token].archivable != archivable) + return; + + if (!fObjects[token].adopted) + fObjects[token].adopted = true; + else { + debugger("Cannot assume ownership of an object that is already owned"); + } } @@ -342,14 +411,3 @@ BUnarchiveManager::Acquire() if (fRefCount >= 0) fRefCount++; } - - -status_t -BUnarchiveManager::_InstantiateObjectForToken(int32 token) -{ - fTokenInProgress = token; - if(!instantiate_object(&fObjects[token].archive)) - return B_ERROR; - return B_OK; -} - diff --git a/src/kits/support/ArchivingManagers.h b/src/kits/support/ArchivingManagers.h index abea19f6b3..7137e771ce 100644 --- a/src/kits/support/ArchivingManagers.h +++ b/src/kits/support/ArchivingManagers.h @@ -15,12 +15,13 @@ #include +#define NULL_TOKEN -42 + + namespace BPrivate { namespace Archiving { -extern const char* kArchiveCountField; -extern const char* kArchivableField; -extern const char* kTokenField; +extern const char* kManagedField; class BManagerBase { @@ -101,11 +102,13 @@ public: int32& _token); status_t ArchiveObject(BArchivable* archivable, - bool deep); + bool deep, int32& _token); bool IsArchived(BArchivable* archivable); - status_t ArchiverLeaving(const BArchiver* archiver); + status_t ArchiverLeaving(const BArchiver* archiver, + status_t err); + void Acquire(); void RegisterArchivable( const BArchivable* archivable); @@ -118,6 +121,7 @@ private: TokenMap fTokenMap; const BArchiver* fCreator; + status_t fError; }; @@ -127,20 +131,23 @@ class BUnarchiveManager: public BManagerBase { public: BUnarchiveManager(BMessage* topLevelArchive); - status_t ArchivableForToken(BArchivable** archivable, - int32 token); + status_t GetArchivableForToken(int32 token, + BUnarchiver::ownership_policy owning, + BArchivable*& _archivable); bool IsInstantiated(int32 token); void RegisterArchivable(BArchivable* archivable); - status_t UnarchiverLeaving(const BUnarchiver* archiver); + status_t UnarchiverLeaving(const BUnarchiver* archiver, + status_t err); void Acquire(); + void RelinquishOwnership(BArchivable* archivable); + void AssumeOwnership(BArchivable* archivable); private: ~BUnarchiveManager(); status_t _ExtractArchiveAt(int32 index); - status_t _InstantiateObjectForToken(int32 token); struct ArchiveInfo; @@ -148,6 +155,7 @@ private: int32 fObjectCount; int32 fTokenInProgress; int32 fRefCount; + status_t fError; };