Patch by Alex Wilson (minor changes by myself) related to the new archiving

features:
* Some cosmetic adjustments of the API, like using references instead of
  pointers, argument order, method names, etc.
* Added convenience template methods for archiving and unarchiving to BArchiver
  and BUnarchiver.
* BUnarchiver (respectively the private BUnarchiveManager) explicitly deals with
  object ownership, now. This is necessary since an error while unarchiving
  could leave an already unarchived object without owning object, which would
  result in it being leaked. The BUnarchiver::{Get,Find}Object() methods do now
  have an optional parameter to specify whether object ownership shall be
  transferred.
* Fixed incorrect header guard in headers/private/binary_compatibility/Global.h.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37538 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2010-07-16 16:49:42 +00:00
parent 6a78d35e85
commit b137ab3eb3
8 changed files with 421 additions and 190 deletions

View File

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

View File

@ -7,11 +7,13 @@
#include <image.h>
#include <Message.h>
#include <SupportDefs.h>
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<class T>
inline status_t GetObject(int32 token, T*& object);
status_t FindArchivable(const char* name,
BArchivable** archivable);
template<class T>
status_t GetObject(int32 token, ownership_policy owning,
T*& object);
status_t FindArchivable(const char* name, int32 index,
BArchivable** archivable);
template<class T>
inline status_t FindObject(const char* name, T*& object);
status_t EnsureUnarchived(const char* name,
template<class T>
inline status_t FindObject(const char* name,
ownership_policy owning,
T*& object);
template<class T>
inline status_t FindObject(const char* name,
int32 index, T*& object);
template<class T>
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<class T>
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<BArchivable>(const char* name, int32 index,
ownership_policy owning, BArchivable*& archivable);
template<class T>
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<T*>(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<BArchivable>(int32 token,
ownership_policy owning, BArchivable*& object);
template<class T>
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<T*>(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<class T>
status_t
BUnarchiver::GetObject(int32 token, T*& object)
{
return GetObject<T>(token, B_ASSUME_OWNERSHIP, object);
}
template<class T>
status_t
BUnarchiver::FindObject(const char* name, ownership_policy owning, T*& object)
{
return FindObject(name, 0, owning, object);
}
template<class T>
status_t
BUnarchiver::FindObject(const char* name, T*& object)
{
return FindObject<T>(name, 0, B_ASSUME_OWNERSHIP, object);
}
template<class T>
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<BArchivable>(BMessage* from,
BArchivable*& object);
template<class T>
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<T*>(interim);
if (object == NULL) {
delete interim;
return B_BAD_TYPE;
}
return B_OK;
}
#endif // _ARCHIVABLE_H

View File

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

View File

@ -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 <binary_compatibility/Global.h>
@ -20,4 +20,4 @@ struct perform_data_all_archived {
status_t return_value;
};
#endif /* _BINARY_COMPATIBILITY_INTERFACE_H_ */
#endif /* _BINARY_COMPATIBILITY_SUPPORT_H_ */

View File

@ -7,6 +7,7 @@
#include <Layout.h>
#include <syslog.h>
#include <new>
#include <Message.h>
@ -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<BLayoutItem*>(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;
}

View File

@ -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<BArchivable>(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<BArchivable>(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<BArchivable>(BMessage* from,
BArchivable*& object)
{
BUnarchiver unarchiver(BUnarchiver::PrepareArchive(from));
object = instantiate_object(from);
return unarchiver.Finish();
}
BMessage*
BUnarchiver::PrepareArchive(BMessage*& archive)
{

View File

@ -6,18 +6,16 @@
* Alex Wilson (yourpalal2@gmail.com)
*/
#include "ArchivingManagers.h"
#include <syslog.h>
#include <typeinfo>
#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<BUnarchiveManager*>(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<BMessage*, const BArchivable*> 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;
}

View File

@ -15,12 +15,13 @@
#include <Archivable.h>
#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;
};