From: <vo...@us...> - 2008-09-24 17:29:28
|
Revision: 848 http://opde.svn.sourceforge.net/opde/?rev=848&view=rev Author: volca Date: 2008-09-24 17:29:13 +0000 (Wed, 24 Sep 2008) Log Message: ----------- use DataStorage for links as well Modified Paths: -------------- trunk/src/services/link/LinkCommon.h trunk/src/services/link/LinkService.cpp trunk/src/services/link/LinkService.h trunk/src/services/link/Relation.cpp trunk/src/services/link/Relation.h Modified: trunk/src/services/link/LinkCommon.h =================================================================== --- trunk/src/services/link/LinkCommon.h 2008-09-24 17:27:20 UTC (rev 847) +++ trunk/src/services/link/LinkCommon.h 2008-09-24 17:29:13 UTC (rev 848) @@ -78,51 +78,14 @@ inline int flavor() { return mFlavor; }; }; - /** Link data container. Holds link ID and it's data as a char array. - * @deprecated This construct should be removed the same way the property data struct will be. Any link access should be handled by a properly made DataStorage descendant - */ - class LinkData : public DType { - friend class Relation; - - protected: - link_id_t mID; - - public: - /// Constructor - Creates empty data defined by default values in type - LinkData(link_id_t id, const DTypeDefPtr& type, bool useCache = false) : DType(type, useCache), mID(id) { }; - - /// Constructor - Loads data from FilePtr - LinkData(link_id_t id, const DTypeDefPtr& type, FilePtr file, int _size, bool useCache = false) : DType(type,file,_size, useCache), mID(id) { }; - - /// Constructor - copies the data from another DType instance - LinkData(link_id_t id, const DType& type, bool useCache = false) : DType(type, useCache), mID(id) {}; - - /// Constructor - copies the data from DTypePtr instance - LinkData(link_id_t id, const DTypePtr& type, bool useCache = false) : DType(*type, useCache), mID(id) {}; - - /// Destructor - Deletes the data - ~LinkData() { }; - - /// ID getter. @return The id of the link this data belong to - inline link_id_t id() { return mID; }; - }; - /// Shared pointer to Link typedef shared_ptr< Link > LinkPtr; - /// Shared pointer to Link Data - typedef shared_ptr< LinkData > LinkDataPtr; - /// Supportive Link comparison operator for sets and maps inline bool operator<(const LinkPtr& a, const LinkPtr& b) { return a->id() < b->id(); } - /// Supportive LinkData comparison operator for sets and maps - inline bool operator<(const LinkDataPtr& a, const LinkDataPtr& b) { - return a->id() < b->id(); - } - /// Class representing a link query result. typedef ConstIterator< LinkPtr > LinkQueryResult; Modified: trunk/src/services/link/LinkService.cpp =================================================================== --- trunk/src/services/link/LinkService.cpp 2008-09-24 17:27:20 UTC (rev 847) +++ trunk/src/services/link/LinkService.cpp 2008-09-24 17:29:13 UTC (rev 848) @@ -216,14 +216,14 @@ } //------------------------------------------------------ - RelationPtr LinkService::createRelation(const std::string& name, const DTypeDefPtr& type, bool hidden) { + RelationPtr LinkService::createRelation(const std::string& name, const DataStoragePtr& stor, bool hidden) { if (name.substr(0,1) == "~") OPDE_EXCEPT("Name conflict: Relation can't use ~ character as the first one, it's reserved for inverse relations. Conflicting name: " + name, "LinkService::createRelation"); std::string inverse = "~" + name; - RelationPtr nr = new Relation(name, type, false, hidden); - RelationPtr nrinv = new Relation(inverse, type, true, hidden); + RelationPtr nr = new Relation(name, stor, false, hidden); + RelationPtr nrinv = new Relation(inverse, stor, true, hidden); // Assign inverse relations... nr->setInverseRelation(nrinv.ptr()); @@ -233,7 +233,7 @@ std::pair<RelationNameMap::iterator, bool> res = mRelationNameMap.insert(make_pair(name, nr)); if (!res.second) - OPDE_EXCEPT("Failed to insert new instance of Relation", "LinkService::createRelation"); + OPDE_EXCEPT("Failed to insert new instance of Relation named " + name, "LinkService::createRelation"); // Inverse relation now res = mRelationNameMap.insert(make_pair(inverse, nrinv)); Modified: trunk/src/services/link/LinkService.h =================================================================== --- trunk/src/services/link/LinkService.h 2008-09-24 17:27:20 UTC (rev 847) +++ trunk/src/services/link/LinkService.h 2008-09-24 17:29:13 UTC (rev 848) @@ -64,7 +64,7 @@ * @param name The relation name * @param type The type defining the data format for link data * @param hidden The hidden relations (true) will not show up on public link list places */ - RelationPtr createRelation(const std::string& name, const DTypeDefPtr& type, bool hidden); + RelationPtr createRelation(const std::string& name, const DataStoragePtr& stor, bool hidden); /** Get relation given it's name * @param name The relation's name Modified: trunk/src/services/link/Relation.cpp =================================================================== --- trunk/src/services/link/Relation.cpp 2008-09-24 17:27:20 UTC (rev 847) +++ trunk/src/services/link/Relation.cpp 2008-09-24 17:29:13 UTC (rev 848) @@ -75,14 +75,13 @@ /*-----------------------------------------------------*/ /*----------------------- Relation --------------------*/ /*-----------------------------------------------------*/ - Relation::Relation(const std::string& name, const DTypeDefPtr& type, bool isInverse, bool hidden) : + Relation::Relation(const std::string& name, const DataStoragePtr& stor, bool isInverse, bool hidden) : mID(-1), mName(name), - mType(type), + mStorage(stor), mHidden(hidden), mLinkMap(), mSrcDstLinkMap(), - mLinkDataMap(), mInverse(NULL), mIsInverse(isInverse) { @@ -91,10 +90,10 @@ mMaxID[i] = 0; } - if (mType.isNull()) + if (stor.isNull()) mFakeSize = 0; else - mFakeSize = mType->size(); + mFakeSize = mStorage->getDataSize(); // Some default version values mLCVMaj = 2; @@ -134,7 +133,7 @@ try { fldata = db->getFile(ldchn); } catch (BasicException& e) { - if (mType.isNull()) { + if (mStorage.isNull()) { LOG_INFO("Relation::load : Link data chunk %s not found (It's ok since data type not registered either)", ldchn.c_str()); } else { LOG_FATAL("Relation::load : Could not find the Link data chunk %s with : %s", ldchn.c_str(), e.getDetails().c_str()); @@ -143,7 +142,11 @@ } // now load the data - size_t link_count = flink->size() / LinkStructSize; + size_t link_count = 0; + + if (!mStorage.isNull()) + link_count = flink->size() / sizeof(LinkStruct); + size_t link_data_count = 0; // if the chunk LD exists, and contains at least the data size, load the data size, and set to load data as well @@ -154,28 +157,28 @@ if (fldata->size() > sizeof(uint32_t)) { fldata->readElem(&dsize, sizeof(uint32_t)); - if (mType.isNull()) + if (mStorage.isNull()) LOG_FATAL("Relation (%s): Data exist, but dyntype not set", mName.c_str()); // Maybe I just should stop with exception else { load_data = true; // check for data len - if (dsize != mType->size()) { + if (dsize != mStorage->getDataSize()) { // This just happens. Some links have the size totally different the real // Only if we have the fake size wrong as well if (dsize != mFakeSize) - LOG_FATAL("Relation (%s): Data sizes differ : Type: %d, Fake %d, Chunk: %d", mName.c_str(), mType->size(), mFakeSize, dsize); + LOG_FATAL("Relation (%s): Data sizes differ : Type: %d, Fake %d, Chunk: %d", mName.c_str(), mStorage->getDataSize(), mFakeSize, dsize); // we respect our data size - dsize = mType->size(); + dsize = mStorage->getDataSize(); } // as the last thing, count the data entries link_data_count = (fldata->size() - sizeof(uint32_t)) / dsize; } } else { - if (!mType.isNull()) + if (!mStorage.isNull()) LOG_FATAL("Relation (%s): Link data not present in file, but type defined", mName.c_str()); } @@ -186,23 +189,14 @@ // The count of data and links should be the same // assert(link_count == link_data_count); - for (unsigned int idx = 0; idx < link_count; idx++) { + for (unsigned int idx = 0; idx < link_count; ++idx) { // Will get deleted automatically once the LinkPtr is released... - // link->mData = new char[dsize]; - // Link ID goes first, then the data link_id_t id; fldata->readElem(&id, 4); + mStorage->readFromFile(fldata, id, false); // false - links don't store len - LinkDataPtr ldta = new LinkData(id, mType, fldata, dsize, mUseDataCache); - LOG_VERBOSE("Relation (%s): Loaded link data for link id %d", mName.c_str(), id); - - // Link data are inserted silently - _assignLinkData(id, ldta); - - // And to the inverse relation as well - mInverse->_assignLinkData(id, ldta); } } @@ -259,8 +253,8 @@ uint32_t dtsz = 0; - if (!mType.isNull()) { - dtsz = mType->size(); + if (!mStorage.isNull()) { + dtsz = mStorage->getDataSize(); assert(dtsz > 0); } @@ -294,25 +288,24 @@ LOG_DEBUG("Relation (%s): Link concreteness of link %d was out of requested : %d", mName.c_str(), link->mID, conc); } } + + // if data are used, store + if (!mStorage.isNull()) { + IntIteratorPtr idit = mStorage->getAllStoredObjects(); - // just write the links as they go, and write the data in parallel - LinkDataMap::const_iterator dit = mLinkDataMap.begin(); + while (!idit->end()) { + int32_t id = idit->next(); - // Write the link data if exists - if (!mType.isNull()) { // write the data into the data chunk - for (; dit != mLinkDataMap.end(); ++dit) { - LinkDataPtr ldt = dit->second; - // Test against the link write mask - int conc = LINK_ID_CONCRETE(ldt->mID); + int conc = LINK_ID_CONCRETE(id); if (saveMask & (1 << conc)) { // mask says save! // TODO: What exactly is the rule that one should follow selecting what to write into GAM/MIS? // I mean: there is MP link from 1 to some -X in GAM file. Hmmmm. (I guess this does not matter for in-game) - - fldt->writeElem(&ldt->mID, sizeof(link_id_t)); - - ldt->serialize(fldt); + fldt->writeElem(&id, sizeof(link_id_t)); + + if (!mStorage->writeToFile(fldt, id, false)) + LOG_ERROR("There was an error writing link data %s for object %d. Property was not loaded", mName.c_str(), id); } } } @@ -346,8 +339,10 @@ broadcastMessage(m); mLinkMap.clear(); - mLinkDataMap.clear(); mSrcDstLinkMap.clear(); + + if (!mStorage.isNull()) + mStorage->clear(); // clear maximal link id's @@ -371,13 +366,8 @@ LinkPtr newl = new Link(id, from, to, mID); - LinkDataPtr newd = new LinkData(id, mType, mUseDataCache); + mStorage->create(id); - // assign link data in advance, as it would fail on _addLink otherwise - _assignLinkData(id, newd); - - mInverse->_assignLinkData(id, newd); - // Last, insert the link to the database and notify _addLink(newl); @@ -389,40 +379,6 @@ } // -------------------------------------------------------------------------- - link_id_t Relation::create(int from, int to, const DTypePtr& data) { - // Request an id. First let's see what concreteness we have - unsigned int cidx = 0; - - // simply compare the type pointers... - if (data->type() != mType) - OPDE_EXCEPT("Incompatible types when creating link data", "Relation::create"); - - if (from >= 0 || to >= 0) - cidx = 1; - - link_id_t id = getFreeLinkID(cidx); - - LinkPtr newl = new Link(id, from, to, mID); - - LinkDataPtr newd = new LinkData(id, data, mUseDataCache); - - // assign link data in advance, as it would fail on _addLink otherwise - _assignLinkData(id, newd); - - mInverse->_assignLinkData(id, newd); - - // Last, insert the link to the database and notify - _addLink(newl); - - LinkPtr ilink = createInverseLink(newl); - - mInverse->_addLink(ilink); - - - return id; - } - - // -------------------------------------------------------------------------- void Relation::remove(link_id_t id) { // A waste I smell here. Maybe there will be a difference in Broadcasts later _removeLink(id); @@ -431,12 +387,8 @@ } // -------------------------------------------------------------------------- - void Relation::setLinkField(link_id_t id, const std::string& field, const DVariant& value) { - LinkDataMap::iterator it = mLinkDataMap.find(id); - - if (it != mLinkDataMap.end()) { - mType->set(it->second->mData, field, value); - + bool Relation::setLinkField(link_id_t id, const std::string& field, const DVariant& value) { + if (mStorage->setField(id, field, value)) { LinkChangeMsg m; m.change = LNK_CHANGED; @@ -444,17 +396,20 @@ // Inform the listeners about the change of data broadcastMessage(m); + + return true; } else { LOG_ERROR("Relation::setLinkField : Link %d was not found in relation %d", id, mID); + return false; } } // -------------------------------------------------------------------------- DVariant Relation::getLinkField(link_id_t id, const std::string& field) { - LinkDataMap::const_iterator it = mLinkDataMap.find(id); - - if (it != mLinkDataMap.end()) { - return mType->get(it->second->mData, field); + DVariant value; + + if (mStorage->getField(id, field, value)) { + return value; } else { LOG_ERROR("Relation::getLinkField : Link %d was not found in relation %d", id, mID); return DVariant(); @@ -462,40 +417,6 @@ } // -------------------------------------------------------------------------- - void Relation::setLinkData(link_id_t id, char* data) { - LinkDataMap::iterator it = mLinkDataMap.find(id); - - if (it != mLinkDataMap.end()) { - // swap the data - char* odl = it->second->mData; - it->second->mData = data; - delete odl; - - LinkChangeMsg m; - - m.change = LNK_CHANGED; - m.linkID = id; - - // Inform the listeners about the change of data - broadcastMessage(m); - } else { - LOG_ERROR("Relation::setLinkData : Link data %d was not found in relation %d", id, mID); - } - } - - // -------------------------------------------------------------------------- - LinkDataPtr Relation::getLinkData(link_id_t id) { - LinkDataMap::iterator it = mLinkDataMap.find(id); - - if (it != mLinkDataMap.end()) { - return it->second; - } else { - LOG_ERROR("Relation::getLinkData : Link data %d was not found in relation %d", id, mID); - return NULL; - } - } - - // -------------------------------------------------------------------------- LinkQueryResultPtr Relation::getAllLinks(int src, int dst) const { // based on case of the query, return result assert(src != 0); // Source can't be zero @@ -573,9 +494,7 @@ LOG_ERROR("Relation: Found link with conflicting ID in relation %d (%s): ID: %d (stored %d) - link already existed", mID, mName.c_str(), link->mID, ires.first->second->mID ); } else { // Verify link data exist - LinkDataMap::iterator dit = mLinkDataMap.find(link->mID); - - if (dit == mLinkDataMap.end() && !mType.isNull()) + if (!mStorage.isNull() && !mStorage->has(link->mID)) OPDE_EXCEPT("Relation (" + mName + "): Link Data not defined prior to link insertion", "Relation::_addLink"); // for link id " + link->mID // Update the free link info @@ -653,30 +572,13 @@ // last, erase the link mLinkMap.erase(it); - _removeLinkData(id); + mStorage->destroy(id); } else { LOG_ERROR("Relation %d: Link requested for removal was not found :ID: %d", mID, id); } } // -------------------------------------------------------------------------- - void Relation::_assignLinkData(link_id_t id, const LinkDataPtr& data) { - std::pair<LinkDataMap::iterator, bool> ires = mLinkDataMap.insert(make_pair(id, data)); - - if (!ires.second) { - // data already present - ires.first->second = data; - } - - // Done. - } - - // -------------------------------------------------------------------------- - void Relation::_removeLinkData(link_id_t id) { - mLinkDataMap.erase(id); - } - - // -------------------------------------------------------------------------- link_id_t Relation::getFreeLinkID(uint cidx) { link_id_t id = LINK_MAKE_ID(mID, cidx, mMaxID[cidx] + 1); allocateLinkID(id); Modified: trunk/src/services/link/Relation.h =================================================================== --- trunk/src/services/link/Relation.h 2008-09-24 17:27:20 UTC (rev 847) +++ trunk/src/services/link/Relation.h 2008-09-24 17:29:13 UTC (rev 848) @@ -27,7 +27,8 @@ #include <string> #include "NonCopyable.h" -#include "DTypeDef.h" +#include "DTypeDef.h" +#include "DataStorage.h" #include "LinkCommon.h" #include "FileGroup.h" #include "MessageSource.h" @@ -37,7 +38,7 @@ */ class OPDELIB_EXPORT Relation : public NonCopyable, public MessageSource<LinkChangeMsg> { public: - Relation(const std::string& name, const DTypeDefPtr& type, bool isInverse, bool hidden = false); + Relation(const std::string& name, const DataStoragePtr& stor, bool isInverse, bool hidden = false); virtual ~Relation(); /** Loads the relation data from the given FileGroup */ @@ -46,10 +47,8 @@ /** Saves the relation data to the fiven file group * @todo Save Mask implementation */ void save(const FileGroupPtr& db, uint saveMask); - - /// @returns the Data Type describing the link data - DTypeDefPtr getDataType() { return mType; }; - + + /// Sets the versions of the chunks this relation uses for storage void setChunkVersions(uint lmajor, uint lminor, uint dmajor, uint dminor) { mLCVMaj = lmajor; mLCVMin = lminor; @@ -96,44 +95,21 @@ */ link_id_t create(int from, int to); - /** Creates a new link, returning it's ID - * @see createLink(int, int) - * @note this version does create the link including the data, so a time and plenty of broadcasts is saved. - * @note to create and fill the data, use DTypeDef::create to obtain a valid buffer to fill, then use DTypeDef::set to fill the fields. Once ready, supply the final buffer to the createLink - */ - link_id_t create(int from, int to, const DTypePtr& data); - - /** getter for the DTypeDef this relation uses. - * @note The returned object is better be tested by doing DTypeDefPtr::isNull() to determine if the object is usable. Relations with no data will just return null DTypeDefPtr */ - inline DTypeDefPtr getTypeDef() { return mType; }; - /** Sets the link data field * @param id The link id * @param field The name of the field the modification is requested on * @param DVariant The new value of the field - * @todo If DTypeDef will implement indexing, create a version with index int as a first parameter + * @return true if successful, false otherwise */ - void setLinkField(link_id_t id, const std::string& field, const DVariant& value); + bool setLinkField(link_id_t id, const std::string& field, const DVariant& value); /** Gets the link data field value * @param id The link id - * @param field The name of the field the modification is requested on + * @param field The name of the field the modification is requested on */ DVariant getLinkField(link_id_t id, const std::string& field); - /** Swaps the link data for new data. Deletes the old data - For more massive data overwriting. - * @param id The link id - * @param data The new data pointer - * @note deallocates the original data. All the references to the original data are then invalid and potentially harmful - */ - void setLinkData(link_id_t id, char* data); - /** Returns link data for the given link ID - * @param id The link id - */ - LinkDataPtr getLinkData(link_id_t id); - // ----------------- Link query methods -------------------- /** Gets all links that come from source to destination * @param src Source object ID @@ -192,17 +168,6 @@ */ link_id_t getFreeLinkID(uint cidx); - /** Assigns the link data to a link ID - * @param id Link id to assign the data to - * @param data The link data to be assigned - */ - void _assignLinkData(link_id_t id, const LinkDataPtr& data); - - /** Removes link data for a link ID - * @param id the ID of the link for which data should be removed - */ - void _removeLinkData(link_id_t id); - /** Allocates the link ID, meaning it wont be given as free now. * @param id The link that was allocated * @note This now only increments the maximal index for the concreteness of the link if it is bigger than that @@ -227,9 +192,6 @@ /// Map of links. Indexed by whole link id, contains the link class (LinkPtr) typedef std::map< link_id_t, LinkPtr > LinkMap; - /// Map of link data. Indexed by whole link id, contains the link data (LinkDataPtr) - typedef std::map< link_id_t, LinkDataPtr > LinkDataMap; - /// Map of all links that have an object ID in either target or source typedef std::multimap< int, LinkPtr > ObjectIDToLinks; @@ -247,19 +209,16 @@ /// Name of this relation std::string mName; + + /// Data storage for the link data + DataStoragePtr mStorage; - /// Typedef pointer used by this relation (or null if no data are used) - DTypeDefPtr mType; - /// Hidden relations are those which should not be mentioned by editor as a normal links (metaproperty and such) bool mHidden; /// The map of ID->LinkPtr (Stores link info per link ID) LinkMap mLinkMap; - /// The map of ID->LinkDataPtr (Stores link data per link ID) - LinkDataMap mLinkDataMap; - /// fake size. This size is written as the data size into the LD$ chunks uint32_t mFakeSize; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |