From: <vo...@us...> - 2008-04-16 16:34:37
|
Revision: 709 http://opde.svn.sourceforge.net/opde/?rev=709&view=rev Author: volca Date: 2008-04-16 09:34:37 -0700 (Wed, 16 Apr 2008) Log Message: ----------- Property service adopted to use PropertyStorage as a data storage backend class. Modified Paths: -------------- trunk/src/bindings/PropertyServiceBinder.cpp trunk/src/services/property/PropertyCommon.h trunk/src/services/property/PropertyGroup.cpp trunk/src/services/property/PropertyGroup.h trunk/src/services/property/PropertyService.cpp trunk/src/services/property/PropertyService.h Modified: trunk/src/bindings/PropertyServiceBinder.cpp =================================================================== --- trunk/src/bindings/PropertyServiceBinder.cpp 2008-04-16 16:31:39 UTC (rev 708) +++ trunk/src/bindings/PropertyServiceBinder.cpp 2008-04-16 16:34:37 UTC (rev 709) @@ -134,7 +134,7 @@ { value = PyObjectToDVariant(Object); o->mInstance->set(obj_id, propName, propField, value); - + // TODO: should indicate by Py_True/Py_False here result = Py_None; Py_INCREF(result); return result; @@ -156,10 +156,18 @@ const char* propName; const char* propField; - if (PyArg_ParseTuple(args, "iss", &obj_id, &propName, &propField)) - return DVariantToPyObject(o->mInstance->get(obj_id, propName, propField)); - else - { + if (PyArg_ParseTuple(args, "iss", &obj_id, &propName, &propField)) { + DVariant ret; + + if (o->mInstance->get(obj_id, propName, propField, ret)) { + return DVariantToPyObject(ret); + } else { + PyObject* result = Py_None; + Py_INCREF(result); + return result; + } + + } else { // Invalid parameters PyErr_SetString(PyExc_TypeError, "Expected an integer and two strings!"); return NULL; Modified: trunk/src/services/property/PropertyCommon.h =================================================================== --- trunk/src/services/property/PropertyCommon.h 2008-04-16 16:31:39 UTC (rev 708) +++ trunk/src/services/property/PropertyCommon.h 2008-04-16 16:34:37 UTC (rev 709) @@ -50,6 +50,11 @@ * @param data The Data instance to copy the data from */ PropertyData(int id, DTypePtr data, bool useCache = false) : mID(id), DType(*data, useCache) { }; + /** PropertyData cloning constructor + * @param id The object ID + * @param data The Data instance to copy the data from */ + PropertyData(int id, PropertyData data, bool useCache = false) : mID(id), DType(data, useCache) { }; + /** Destructor */ ~PropertyData() { }; @@ -87,7 +92,6 @@ /// An ID of the object that changed int objectID; }; - } #endif Modified: trunk/src/services/property/PropertyGroup.cpp =================================================================== --- trunk/src/services/property/PropertyGroup.cpp 2008-04-16 16:31:39 UTC (rev 708) +++ trunk/src/services/property/PropertyGroup.cpp 2008-04-16 16:34:37 UTC (rev 709) @@ -27,12 +27,17 @@ namespace Opde { // -------------------------------------------------------------------------- - PropertyGroup::PropertyGroup(const std::string& name, const std::string& chunk_name, DTypeDefPtr type, uint ver_maj, uint ver_min, string inheritorName) : + // PropertyGroup::PropertyGroup(PropertyService* owner, const std::string& name, const std::string& chunk_name, const std::string& ptype, DTypeDefPtr type, string inheritorName) : + PropertyGroup::PropertyGroup(PropertyService* owner, const std::string& name, const std::string& chunk_name, + PropertyStorage* storage, std::string inheritorName, bool deleteStorageOnDestroy) : + mOwner(owner), mName(name), mChunkName(chunk_name), - mType(type), - mVerMaj(ver_maj), - mVerMin(ver_min) { + mVerMaj(1), + mVerMin(1), + mUseDataCache(false), + mPropertyStorage(NULL), + mDeletePropStorageOnDestroy(deleteStorageOnDestroy) { // Find the inheritor by the name, and assign too InheritServicePtr inhs = ServiceManager::getSingleton().getService("InheritService").as<InheritService>(); @@ -42,6 +47,9 @@ Inheritor::ListenerPtr cil = new ClassCallback<InheritValueChangeMsg, PropertyGroup>(this, &PropertyGroup::onInheritChange); mInheritorListenerID = mInheritor->registerListener(cil); + + // create the property storage for this PropertyGroup + mPropertyStorage = storage; } // -------------------------------------------------------------------------- @@ -50,19 +58,29 @@ if (! mInheritor.isNull()) mInheritor->unregisterListener(mInheritorListenerID); + + if (mDeletePropStorageOnDestroy) + delete mPropertyStorage; } - + // -------------------------------------------------------------------------- - PropertyDataPtr PropertyGroup::getData(int obj_id) { - PropertyStore::const_iterator it = mPropertyStore.find(_getEffectiveObject(obj_id)); - - if (it != mPropertyStore.end()) - return it->second; - else - LOG_ERROR("PropertyGroup::getData : Property for object ID %d was not found in group %s", obj_id, mName.c_str()); - return NULL; + void PropertyGroup::setPropertyStorage(PropertyStorage* newStorage, bool deleteOnDestroy) { + // see if we had any data in the current + if (!mPropertyStorage->isEmpty()) { + LOG_ERROR("Property storage replacement for %s: Previous property storage had some data. This could mean something bad could happen...", mName.c_str()); + } + + + if (mDeletePropStorageOnDestroy) { + if (mPropertyStorage != newStorage) + delete mPropertyStorage; + } + + + mPropertyStorage = newStorage; + mDeletePropStorageOnDestroy = deleteOnDestroy; } - + // -------------------------------------------------------------------------- void PropertyGroup::load(FileGroupPtr db) { // Open the chunk specified by "P$" + mChunkName @@ -85,18 +103,13 @@ while (!fprop->eof()) { // load the id fprop->readElem(&id, sizeof(uint32_t)); - // Load the size - fprop->readElem(&size, sizeof(uint32_t)); - - if (id == 0) - LOG_ERROR("PropertyGroup: P$%s : Obj ID == 0", mChunkName.c_str()); - - LOG_VERBOSE("PropertyGroup: P$%s : Loading property %s for obj %d (Sizes: real %d, type %d)", mChunkName.c_str(), mName.c_str(), id, size, mType->size()); - // create the property - PropertyDataPtr prop = new PropertyData(id, mType, fprop, size, mUseDataCache); - - if (!_addProperty(prop)) - LOG_ERROR("PropertyGroup: P$%s : Cannot add property for obj %d (already there)", mChunkName.c_str(), id); + + // Use property storage to load the property + if (mPropertyStorage->readFromFile(fprop, id)) { + _addProperty(id); + } else { + LOG_ERROR("There was an error loading property %s for object %d. Property was not loaded", mName.c_str(), id); + } } } @@ -117,15 +130,11 @@ // Can't calculate the count of the properties, as they can have any size // load. Each record has: OID, size (32 bit uint's) - int id; - uint32_t size; + IntIteratorPtr idit = mPropertyStorage->getAllStoredObjects(); - PropertyStore::const_iterator it = mPropertyStore.begin(); + while (!idit->end()) { + int id = idit->next(); - for (; it != mPropertyStore.end() ; ++it) { - - id = it->second->id(); - // Determine if the prop should be included, based on it's mask uint objmask = 0; @@ -138,16 +147,8 @@ if (!(saveMask & objmask)) continue; - size= it->second->size(); - // load the id - fprop->writeElem(&id, sizeof(uint32_t)); - // Load the size - fprop->writeElem(&size, sizeof(uint32_t)); - - LOG_DEBUG("PropertyGroup: P$%s : Writing property %s for obj %d", mChunkName.c_str(), mName.c_str(), id, size, mType->size()); - - it->second->serialize(fprop); - + if (!mPropertyStorage->writeToFile(fprop, id)) + LOG_ERROR("There was an error writing property %s for object %d. Property was not loaded", mName.c_str(), id); } } @@ -160,70 +161,71 @@ broadcastMessage(msg); - mPropertyStore.clear(); + mPropertyStorage->clear(); mInheritor->clear(); } // -------------------------------------------------------------------------- bool PropertyGroup::createProperty(int obj_id) { - PropertyDataPtr propd = new PropertyData(obj_id, mType, mUseDataCache); - - return _addProperty(propd); + if (mPropertyStorage->createProp(obj_id)) { + _addProperty(obj_id); + + return true; + } + + return false; } // -------------------------------------------------------------------------- - bool PropertyGroup::createProperty(int obj_id, DTypePtr data) { - // simply compare the type pointers... - if (data->type() != mType) - OPDE_EXCEPT("Incompatible types when creating property data", "PropertyGroup::createProperty"); - - PropertyDataPtr propd = new PropertyData(obj_id, data, mUseDataCache); - - return _addProperty(propd); - } - - // -------------------------------------------------------------------------- bool PropertyGroup::removeProperty(int obj_id) { - size_t erased = mPropertyStore.erase(obj_id); - - if (erased) { + if (mPropertyStorage->destroyProp(obj_id)) { mInheritor->setImplements(obj_id, false); - + return true; - } else { - return false; } + + return false; + } // -------------------------------------------------------------------------- bool PropertyGroup::cloneProperty(int obj_id, int src_id) { - PropertyDataPtr pd = getData(src_id); - - if (!pd.isNull()) { - // TODO: clone the data! - // FIX: Implement this method - OPDE_EXCEPT("Property cloning is not yet implemented!", "PropertyGroup::cloneProperty"); - /*PropertyDataPtr propd = new PropertyData(obj_id, *pd); - - return _addProperty(propd);*/ + bool had = false; + + if (mPropertyStorage->hasProp(obj_id)) { + // delete first + mPropertyStorage->destroyProp(obj_id); + had = true; } - return false; - } - - - // -------------------------------------------------------------------------- - bool PropertyGroup::_addProperty(PropertyDataPtr propd) { - pair<PropertyStore::iterator, bool> res = mPropertyStore.insert(make_pair(propd->id(), propd)); - - if (res.second) { - mInheritor->setImplements(propd->id(), true); - + + + if (mPropertyStorage->cloneProp(src_id, obj_id)) { + // went ok, the target now includes the property didn't previously + if (!had) + _addProperty(obj_id); + return true; } else { return false; } } + + // -------------------------------------------------------------------------- + bool PropertyGroup::set(int id, const std::string& field, const DVariant& value) { + return mPropertyStorage->setPropField(id, field, value); + } + // -------------------------------------------------------------------------- + bool PropertyGroup::get(int id, const std::string& field, DVariant& target) { + int effID = _getEffectiveObject(id); + return mPropertyStorage->getPropField(effID, field, target); + } + + // -------------------------------------------------------------------------- + void PropertyGroup::_addProperty(int objID) { + mInheritor->setImplements(objID, true); + } + // -------------------------------------------------------------------------- void PropertyGroup::onInheritChange(const InheritValueChangeMsg& msg) { // Consult the inheritor value change, and build a property change message Modified: trunk/src/services/property/PropertyGroup.h =================================================================== --- trunk/src/services/property/PropertyGroup.h 2008-04-16 16:31:39 UTC (rev 708) +++ trunk/src/services/property/PropertyGroup.h 2008-04-16 16:34:37 UTC (rev 709) @@ -32,9 +32,12 @@ #include "OpdeException.h" #include "logger.h" #include "InheritService.h" +#include "PropertyStorage.h" namespace Opde { - + // forward decl. + class PropertyService; + /** @brief Property group - a group of properties of the same kind (name, type). * Property group holds all the properties of the same kind for all the objects. */ @@ -43,14 +46,28 @@ /** PropertyGroup Constructor * @param name The property name * @param chunk_name The name of the chunk (without the P$) - * @param type The type definition for the property data + * @param storage The property storage created to hold the data + * @param deleteStorageOnDestroy delete the property storage on destroy of this prop. group? * @param ver_maj The major version of the chunk that stores this property * @param ver_min The minor version of the chunk that stores this property */ - PropertyGroup(const std::string& name, const std::string& chunk_name, DTypeDefPtr type, uint ver_maj, uint ver_min, std::string inheritorName); + PropertyGroup(PropertyService* owner, const std::string& name, const std::string& chunk_name, PropertyStorage* storage, std::string inheritorName, bool deleteStorageOnDestroy); + /** Setter for the property chunk version */ + inline void setChunkVersions(uint verMaj, uint verMin) { + mVerMaj = verMaj; + mVerMin = verMin; + }; + /** Destructor */ virtual ~PropertyGroup(); + + /** Property storage setter + * @param propStorage The new storage for properties + * @warning This should not be used when the property group holds some data + */ + virtual void setPropertyStorage(PropertyStorage* newStorage, bool deleteOnDestroy = false); + /// Name getter. Returns the name of property this group manages const std::string& getName() { return mName; }; @@ -76,12 +93,7 @@ * @note Will return false if the object only inherits the property, but does not own it (use has for that) */ bool owns(int obj_id) const { - PropertyStore::const_iterator it = mPropertyStore.find(obj_id); - - if (it != mPropertyStore.end()) - return true; - else - return false; + return mPropertyStorage->hasProp(obj_id); } /** Loads properties from a file group @@ -106,14 +118,6 @@ * @note Notifies inheritor about the change */ bool createProperty(int obj_id); - /** Creates a property for given object ID, using specified values for the property fields - * @param obj_id The id of the object to create the property for - * @param data The property data to use () - * @return true if the property was created, false if the object ID already holds the given property - * @note Broadcasts a PROP_ADDED on success - * @note Notifies inheritor about the change */ - bool createProperty(int obj_id, DTypePtr data); - /** Creates a property for given object ID * @param obj_id The id of the object to create the property for * @return true if the property was removed, false if the object ID didn't hold the property @@ -121,7 +125,7 @@ * @note Notifies inheritor about the change */ bool removeProperty(int obj_id); - /** Creates a new property by cloning a given property on object ID + /** Creates a new property, or replaces all the values on the current, by cloning a given property on object ID * @param obj_id Target object ID (id to create) * @param src_id The id of the object to clone property from */ bool cloneProperty(int obj_id, int src_id); @@ -134,42 +138,23 @@ * @return true if the change was sucessful * @see owns * @note Will log error when object id does not own the property to be changed */ - bool set(int id, std::string field, const DVariant& value) { - PropertyStore::const_iterator it = mPropertyStore.find(id); + bool set(int id, const std::string& field, const DVariant& value); - if (it != mPropertyStore.end()) { - it->second->set(field, value); - return true; - } - - LOG_ERROR("PropertyGroup::set : Property for object ID %d was not found in group %s", id, mName.c_str()); - return false; - } - /** Direct data getter * @param id object id * @param field the field name - * @return The value from the field indicated, or empty DVariant if the object id does not own the property + * @param target The target value holder to be filled from the field indicated, or untouched if field invalid * @see owns - * @note Will silently fail when id is non-valid. Check error log for this happening + * @return false if field name was invalid, true if value was set in target */ - DVariant get(int id, std::string field) { - PropertyStore::const_iterator it = mPropertyStore.find(_getEffectiveObject(id)); - - if (it != mPropertyStore.end()) { - return it->second->get(field); - } - - LOG_ERROR("PropertyGroup::get : Property for object ID %d was not found in group %s", id, mName.c_str()); - return DVariant(); - } + bool get(int id, const std::string& field, DVariant& target); /** Notification that an object was destroyed. @see PropertyService::objectDestroyed */ void objectDestroyed(int id); - /** Sets the property group to cache data (caches fields so no direct to/from data will be used on loading) * @param cache if true, writes will set a the value in a cache as well, and reads will search cache first + * @todo Reflect this into property storage */ void setCacheData(bool cache) { mUseDataCache = cache; }; @@ -177,18 +162,11 @@ bool getCacheData() { return mUseDataCache; }; protected: - /** Property data getter. Internal use only. - * @param obj_id Object ID of the property to fetch - * @note call dataChangeFinished(obj_id), otherwise listeners will not receive broadcasts about the data modification - * @return PropertyDataPtr, which will be null if the property was not found + /** Does the internal handling related to the creation of a property for object + * @param objID The object id to which a property was added */ - PropertyDataPtr getData(int obj_id); + void _addProperty(int objID); - /** Inserts the property into the group, notifies inheritors and broadcasts the change - * @param propd The property to add - */ - bool _addProperty(PropertyDataPtr propd); - /// The listener to the inheritance messages void onInheritChange(const InheritValueChangeMsg& msg); @@ -201,12 +179,6 @@ return mInheritor->getEffectiveID(obj_id); } - /// Stores objectID -> Property - typedef std::map< int, PropertyDataPtr > PropertyStore; - - /// Property store instance - PropertyStore mPropertyStore; - /// The name of the property std::string mName; @@ -218,9 +190,6 @@ /// chunk version - minor uint mVerMin; - /// Type definition for the property data - DTypeDefPtr mType; - /// Inheritor used to determine property inheritance InheritorPtr mInheritor; @@ -229,6 +198,15 @@ /// If true, data caching will be used bool mUseDataCache; + + /// Property storage used to store data for the property + PropertyStorage* mPropertyStorage; + + /// True if the property storage should be deleted upon property group destruction + bool mDeletePropStorageOnDestroy; + + /// Owner service + PropertyService* mOwner; }; /// Shared pointer to property group Modified: trunk/src/services/property/PropertyService.cpp =================================================================== --- trunk/src/services/property/PropertyService.cpp 2008-04-16 16:31:39 UTC (rev 708) +++ trunk/src/services/property/PropertyService.cpp 2008-04-16 16:34:37 UTC (rev 709) @@ -62,6 +62,8 @@ PropertyService::PropertyService(ServiceManager *manager, const std::string& name) : Service(manager, name) { // Ensure listeners are created mServiceManager->createByMask(SERVICE_PROPERTY_LISTENER); + + // Create the standard property storage factories... } // -------------------------------------------------------------------------- @@ -78,9 +80,58 @@ } // -------------------------------------------------------------------------- - PropertyGroupPtr PropertyService::createPropertyGroup(const std::string& name, const std::string& chunk_name, DTypeDefPtr type, uint ver_maj, uint ver_min, string inheritorName) { - PropertyGroupPtr nr = new PropertyGroup(name, chunk_name, type, ver_maj, ver_min, inheritorName); + PropertyGroupPtr PropertyService::createStructuredPropertyGroup(const std::string& name, const std::string& chunk_name, const DTypeDefPtr& type, std::string inheritorName) { + // create a property holder + PropertyStorage* storage; + + try { + storage = new StructuredPropertyStorage(type, false); + } catch (...) { + OPDE_EXCEPT("Failed to create property storage for " + name, "PropertyService::createPropertyGroup"); + } + + // create the propert group + PropertyGroupPtr nr; + try { + nr = new PropertyGroup(this, name, chunk_name, storage, inheritorName, true); + } catch (...) { + delete storage; + + OPDE_EXCEPT("Failed to create property group for " + name, "PropertyService::createPropertyGroup"); + } + + std::pair<PropertyGroupMap::iterator, bool> res = mPropertyGroupMap.insert(make_pair(name, nr)); + if (!res.second) + OPDE_EXCEPT("Failed to insert new instance of PropertyGroup, name already allocated : " + name, + "PropertyService::createPropertyGroup"); + + LOG_INFO("PropertyService::createPropertyGroup: Created a property group %s (With chunk name %s)", name.c_str(), chunk_name.c_str()); + + return nr; + } + + // -------------------------------------------------------------------------- + PropertyGroupPtr PropertyService::createStringPropertyGroup(const std::string& name, const std::string& chunk_name, std::string inheritorName) { + // create a property holder + PropertyStorage* storage; + + try { + storage = new StringPropertyStorage(); + } catch (...) { + OPDE_EXCEPT("Failed to create property storage for " + name, "PropertyService::createPropertyGroup"); + } + + // create the propert group + PropertyGroupPtr nr; + try { + nr = new PropertyGroup(this, name, chunk_name, storage, inheritorName, true); + } catch (...) { + delete storage; + + OPDE_EXCEPT("Failed to create property group for " + name, "PropertyService::createPropertyGroup"); + } + std::pair<PropertyGroupMap::iterator, bool> res = mPropertyGroupMap.insert(make_pair(name, nr)); if (!res.second) @@ -99,15 +150,14 @@ for (; it != mPropertyGroupMap.end(); ++it) { try { - LOG_DEBUG("PropertyService: Loading property group %s", it->first.c_str()); + LOG_INFO("PropertyService: Loading property group %s", it->first.c_str()); it->second->load(db); } catch (BasicException &e) { LOG_FATAL("PropertyService: Caught a fatal exception while loading PropertyGroup %s : %s", it->first.c_str(), e.getDetails().c_str() ); } } - } - + // -------------------------------------------------------------------------- void PropertyService::save(FileGroupPtr db, uint saveMask) { // We just give the db to all registered groups @@ -166,28 +216,26 @@ } // -------------------------------------------------------------------------- - void PropertyService::set(int obj_id, const std::string& propName, const std::string& propField, const DVariant& value) { + bool PropertyService::set(int obj_id, const std::string& propName, const std::string& propField, const DVariant& value) { PropertyGroupPtr prop = getPropertyGroup(propName); if (!prop.isNull()) { - prop->set(obj_id, propField, value); - return; + return prop->set(obj_id, propField, value); } LOG_ERROR("Invalid or undefined property name '%s' on call to PropertyService::set", propName.c_str()); + return false; } // -------------------------------------------------------------------------- - DVariant PropertyService::get(int obj_id, const std::string& propName, const std::string& propField) { - PropertyGroupPtr prop = getPropertyGroup(propName); + bool PropertyService::get(int obj_id, const std::string& propName, const std::string& propField, DVariant& target) { + PropertyGroupPtr prop = getPropertyGroup(propName); if (!prop.isNull()) { - return prop->get(obj_id, propField); + return prop->get(obj_id, propField, target); } - LOG_ERROR("Invalid or undefined property name '%s' on call to PropertyService::get. Returning invalid Variant", propName.c_str()); - - return DVariant(); + return false; } // -------------------------------------------------------------------------- Modified: trunk/src/services/property/PropertyService.h =================================================================== --- trunk/src/services/property/PropertyService.h 2008-04-16 16:31:39 UTC (rev 708) +++ trunk/src/services/property/PropertyService.h 2008-04-16 16:34:37 UTC (rev 709) @@ -39,11 +39,20 @@ PropertyService(ServiceManager *manager, const std::string& name); virtual ~PropertyService(); - /** Creates a property group - a family of properties of the same type. + /** Creates a structured property group - property holder using a structure definition in DTypeDef * @see PropertyGroup::PropertyGroup */ - PropertyGroupPtr createPropertyGroup(const std::string& name, const std::string& chunk_name, DTypeDefPtr type, uint ver_maj, uint ver_min, std::string inheritorName); + PropertyGroupPtr createStructuredPropertyGroup(const std::string& name, const std::string& chunk_name, const DTypeDefPtr& type, std::string inheritorName); + + /** Creates a string holding property group - property holder containing a variable length string + * @see PropertyGroup::PropertyGroup + */ + PropertyGroupPtr createStringPropertyGroup(const std::string& name, const std::string& chunk_name, std::string inheritorName); + /** Creates a string type property group - a family of properties containing a single, variable length string + * @see PropertyGroup::PropertyGroup + */ + /** Retrieves the property group given it's name, or NULL if not found * @param name The name of the property to retrieve the group for * @return PropertyGroupPtr of the PropertyGroup named name if found, isNull()==true otherwise */ @@ -70,14 +79,14 @@ * @param propField The field path to set * @param value The new value */ - void set(int obj_id, const std::string& propName, const std::string& propField, const DVariant& value); + bool set(int obj_id, const std::string& propName, const std::string& propField, const DVariant& value); /** Property getter. Gets a value of a property field * @param obj_id The object id * @param propName The name of the property group * @param propField The field path to get */ - DVariant get(int obj_id, const std::string& propName, const std::string& propField); + bool get(int obj_id, const std::string& propName, const std::string& propField, DVariant& target); /** A notification that object was destroyed (removes all properties of the obj. ID) * @param id The object id that was removed This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |