///////////////////////////////////////////////////////////////// // WARNING : this is a generated file, don't change it ! ///////////////////////////////////////////////////////////////// #ifndef #define #include "nel/misc/types_nl.h" #include <memory> #include "nel/misc/hierarchical_timer.h" #include "nel/misc/string_conversion.h" #include "nel/net/message.h" #include "nel/net/module.h" #include "nel/net/module_builder_parts.h" #include "nel/net/module_message.h" #include "nel/net/module_gateway.h" #include "game_share/callback_adaptor.h" #include "nel/misc/string_common.h" #include "server_share/mysql_wrapper.h" #include "game_share/synchronised_message.h" #endif namespace { class ; class Ptr; } #include ".h" namespace { } #include "" #include <> #include "" <?php require_once(''); ?> ///////////////////////////////////////////////////////////////// // WARNING : this is a generated file, don't change it ! ///////////////////////////////////////////////////////////////// class Skel { public: /// the interceptor type typedef NLNET::CInterceptorForwarder < Skel> TInterceptor; protected: Skel() { // do early run time check for message table getMessageHandlers(); } virtual ~Skel() { } void init(NLNET::IModule *module) { _Interceptor.init(this, module); } public: // unused interceptors std::string fwdBuildModuleManifest() const { return std::string(); } void fwdOnModuleUp(NLNET::IModuleProxy *moduleProxy) {} void fwdOnModuleDown(NLNET::IModuleProxy *moduleProxy) {} void fwdOnModuleSecurityChange(NLNET::IModuleProxy *moduleProxy) {} // process module message interceptor bool fwdOnProcessModuleMessage(NLNET::IModuleProxy *sender, const NLNET::CMessage &message); private: typedef void (Skel::*TMessageHandler)(NLNET::IModuleProxy *sender, const NLNET::CMessage &message); typedef std::map<std::string, TMessageHandler> TMessageHandlerMap; const TMessageHandlerMap &getMessageHandlers() const; void _skel(NLNET::IModuleProxy *sender, const NLNET::CMessage &__message); void _skel(NLNET::IModuleProxy *sender, const NLNET::CMessage &__message); // declare one interceptor member of the skeleton TInterceptor _Interceptor; // declare the interceptor forwarder as friend of this class friend class NLNET::CInterceptorForwarder < Skel>; public: ///////////////////////////////////////////////////////////////// // WARNING : this is a generated file, don't change it ! ///////////////////////////////////////////////////////////////// virtual void (NLNET::IModuleProxy *sender) =0; virtual (NLNET::IModuleProxy *sender) =0; }; ///////////////////////////////////////////////////////////////// // WARNING : this is a generated file, don't change it ! ///////////////////////////////////////////////////////////////// class Proxy { /// Smart pointer on the module proxy NLNET::TModuleProxyPtr _ModuleProxy; // Pointer on the local module that implement the interface (if the proxy is for a local module) NLNET::TModulePtr _LocalModule; // Direct pointer on the server implementation interface for collocated module Skel *_LocalModuleSkel; public: Proxy(NLNET::IModuleProxy *proxy) { nlassert(proxy->getModuleClassName() == ); _ModuleProxy = proxy; // initialize collocated servant interface if (proxy->getModuleDistance() == 0) { _LocalModule = proxy->getLocalModule(); nlassert(_LocalModule != NULL); Skel::TInterceptor *interceptor = NULL; interceptor = static_cast < NLNET::CModuleBase* >(_LocalModule.getPtr())->getInterceptor(interceptor); nlassert(interceptor != NULL); _LocalModuleSkel = interceptor->getParent(); nlassert(_LocalModuleSkel != NULL); } else _LocalModuleSkel = 0; } virtual ~Proxy() { } NLNET::IModuleProxy *getModuleProxy() { return _ModuleProxy; } void (NLNET::IModule *sender); (NLNET::IModule *sender); // This is the broadcast version of the method. template < class ProxyIterator > static void broadcast_(ProxyIterator first, ProxyIterator last, NLNET::IModule *sender) { NLNET::CMessage message; // create the message to send to multiple dest buildMessageFor_(message , ); for (; first != last; ++first) { NLNET::IModuleProxy *proxy = *first; proxy->sendModuleMessage(sender, message); } } // Message serializer. Return the message received in reference for easier integration static const NLNET::CMessage &buildMessageFor_(NLNET::CMessage &__message); }; ///////////////////////////////////////////////////////////////// // WARNING : this is a generated file, don't change it ! ///////////////////////////////////////////////////////////////// const ::TMessageHandlerMap &::getMessageHandlers() const { static TMessageHandlerMap handlers; static bool init = false; if (!init) { std::pair < TMessageHandlerMap::iterator, bool > res; res = handlers.insert(std::make_pair(std::string(""), &::_skel)); // if this assert, you have a doubly message name in your interface definition ! nlassert(res.second); init = true; } return handlers; } bool Skel::fwdOnProcessModuleMessage(NLNET::IModuleProxy *sender, const NLNET::CMessage &message) { const TMessageHandlerMap &mh = getMessageHandlers(); TMessageHandlerMap::const_iterator it(mh.find(message.getName())); if (it == mh.end()) { return false; } TMessageHandler cmd = it->second; (this->*cmd)(sender, message); return true; } void ::_skel(NLNET::IModuleProxy *sender, const NLNET::CMessage &__message) { H_AUTO(__); ; (sender, ); } void ::_skel(NLNET::IModuleProxy *sender, const NLNET::CMessage &__message) { H_AUTO(__); ; __ret = (sender, ); // encode the return message NLNET::CMessage __retMsg; __retMsg.setType("R_", NLNET::CMessage::Response); nlWrite(__retMsg, serial, __ret); // and send back the response sender->sendModuleMessage(static_cast<NLNET::IModule*>(_Interceptor.getRegistrar()), __retMsg); } void ::(NLNET::IModule *sender) { if (_LocalModuleSkel && _LocalModule->isImmediateDispatchingSupported()) { // immediate local synchronous dispatching _LocalModuleSkel->(_ModuleProxy->getModuleGateway()->getPluggedModuleProxy(sender), ); } else { // send the message for remote dispatching and execution or local queing NLNET::CMessage __message; buildMessageFor_(__message, ); _ModuleProxy->sendModuleMessage(sender, __message); } } ::(NLNET::IModule *sender) { if (_LocalModuleSkel && _LocalModule->isImmediateDispatchingSupported()) { // immediate local synchronous dispatching return _LocalModuleSkel->(_ModuleProxy->getModuleGateway()->getPluggedModuleProxy(sender), ); } else { // send the message for remote dispatching and execution NLNET::CMessage __message; buildMessageFor_(__message, ); NLNET::CMessage __retMsg; sender->invokeModuleOperation(_ModuleProxy, __message, __retMsg); // check the return message type if (__retMsg.getName() != "R_") throw NLNET::IModule::EInvokeBadReturn(); __ret; nlRead(__retMsg, serial, __ret); return __ret; } } // Message serializer. Return the message received in reference for easier integration const NLNET::CMessage &::buildMessageFor_(NLNET::CMessage &__message) { __message.setType("", NLNET::CMessage::Request); return __message; } // // , const std::vector<> &, const &, nlWrite(, serial, const_cast < & > ()); nlWrite(, serial, ); nlWrite(, serialCont, ); nlRead(, serial, ); nlRead(, serialCont, ); <?php ///////////////////////////////////////////////////////////////// // WARNING : this is a generated file, don't change it ! ///////////////////////////////////////////////////////////////// $arrayCounter = 0; $__EnumValues[$arrayCounter++] = ""; $__EnumValues[$arrayCounter] = "invalid"; $__InvalidValue = $arrayCounter; class _ { var $Value; function _() { global $__InvalidValue; $this->Value = $__InvalidValue; } function toString() { global $__EnumValues; return $__EnumValues[$this->Value]; } function fromString($strValue) { global $__EnumValues; foreach ($__EnumValues as $k => $v) { if ($strValue === $v) { $this->Value = $k; return; } } $this->Value = $__InvalidValue; } function toInt() { return $this->Value; } function fromInt($intValue) { global $__InvalidValue; global $__EnumValues; if (array_key_exists($intValue, $__EnumValues)) $this->Value = $intValue; else $this->Value = $__InvalidValue; } } ?> typedef NLMISC::CEnumBitset < Enum, uint32, Enum::invalid_val, ',', NLMISC::TContainedEnum < Enum, uint32 >, Enum::TValues > ; ERROR : You can't set a base value AND a value for the first item on enum definition struct { enum TValues { = = , /// the highest valid value in the enum last_enum_item = , /// a value equal to the last enum item +1 end_of_enum, invalid_val, /// Number of enumerated values nb_enum_items = }; /// Index table to convert enum value to linear index table const std::map<TValues, uint32> &getIndexTable() const { static std::map<TValues, uint32> indexTable; static bool init = false; if (!init) { // fill the index table indexTable.insert(std::make_pair(, )); init = true; } return indexTable; } static const NLMISC::CStringConversion<TValues> &getConversionTable() { NL_BEGIN_STRING_CONVERSION_TABLE(TValues) NL_STRING_CONVERSION_TABLE_ENTRY() NL_STRING_CONVERSION_TABLE_ENTRY(invalid_val) }; static NLMISC::CStringConversion<TValues> conversionTable(TValues_nl_string_conversion_table, sizeof(TValues_nl_string_conversion_table) / sizeof(TValues_nl_string_conversion_table[0]), invalid_val); return conversionTable; } TValues _Value; public: () : _Value(invalid_val) { } (TValues value) : _Value(value) { } (const std::string &str) { _Value = getConversionTable().fromString(str); } void serial(NLMISC::IStream &s) { s.serialEnum(_Value); } bool operator == (const &other) const { return _Value == other._Value; } bool operator != (const &other) const { return ! (_Value == other._Value); } bool operator < (const &other) const { return _Value < other._Value; } bool operator <= (const &other) const { return _Value <= other._Value; } bool operator > (const &other) const { return !(_Value <= other._Value); } bool operator >= (const &other) const { return !(_Value < other._Value); } const std::string &toString() const { return getConversionTable().toString(_Value); } static const std::string &toString(TValues value) { return getConversionTable().toString(value); } TValues getValue() const { return _Value; } // return true if the actual value of the enum is valid, otherwise false bool isValid() { if (_Value == invalid_val) return false; // not invalid, check other enum value return getConversionTable().isValid(_Value); } uint32 asIndex() { std::map<TValues, uint32>::const_iterator it(getIndexTable().find(_Value)); nlassert(it != getIndexTable().end()); return it->second; } }; // _; // const &get() const { return _; } &get() { return _; } void set(const &value) { if (_ != value) { if (getPersistentState() != NOPE::os_transient) setPersistentState(NOPE::os_dirty); Ptr parent = ::loadFromCache(_); if (parent && getPersistentState() != NOPE::os_transient ) parent->removeChild(this); _ = value; Ptr parent = ::loadFromCache(_); if (parent && getPersistentState() != NOPE::os_transient) parent->insertChild(this); } } get() const { return _; } void set( value) { if (_ != value) { if (getPersistentState() != NOPE::os_transient) setPersistentState(NOPE::os_dirty); _ = value; } } /** Return a const reference to the vector of child. * If you want to modify the element inside, you need to * use on of the two following methods who return non const pointer * on contained elements. */ const std::vector<Ptr> &get() const; /** Return the ith element of the child vector * index must be valid (ie less than size of the vector) */ Ptr &getByIndex(uint32 index) const; /** Return the identified element by looking in the vector * If no element match the id, NULL pointer is returned */ Ptr &getById(uint32 id) const; /** Return a const reference to the map of child. * If you want to modify the element inside, you need to * use on of the two following method who return non const pointer * on contained elements. */ const std::map<uint32, Ptr> &get() const; /** Return the identified element by looking in the map * If no element match the id, NULL pointer is returned */ Ptr &getById(uint32 id) const; ERROR : Invalide container, child must be either map or vector for child in class /** Return the one child object (or null if not) */ Ptr get(); qs += " , "; qs += " , "; qs += " , "; qs += "'"+_.toString()+"'"; qs += "'"+MSW::encodeDate(_)+"'"; qs += "'"+MSW::escapeString(_.toString(), connection)+"'"; qs += "'"+MSW::escapeString(NLMISC::toString(_), connection)+"'"; qs += ", "; qs += "'"+_.toString()+"'"; qs += "'"+MSW::encodeDate(_)+"'"; qs += "'"+MSW::escapeString(_.toString(), connection)+"'"; qs += "'"+MSW::escapeString(NLMISC::toString(_), connection)+"'"; qs += ", "; qs += "'"+_.toString()+"'"; qs += "'"+MSW::encodeDate(_)+"'"; qs += "'"+MSW::escapeString(_.toString(), connection)+"'"; qs += "'"+MSW::escapeString(NLMISC::toString(_), connection)+"'"; qs += ", "; qs += " = '"+_.toString()+"'"; qs += " = '"+MSW::encodeDate(_)+"'"; qs += " = '"+MSW::escapeString(_.toString(), connection)+"'"; qs += " = '"+MSW::escapeString(NLMISC::toString(_), connection)+"'"; qs += ", "; qs += " = '"+_.toString()+"'"; qs += " = '"+MSW::encodeDate(_)+"'"; qs += " = '"+MSW::escapeString(_.toString(), connection)+"'"; qs += " = '"+MSW::escapeString(NLMISC::toString(_), connection)+"'"; qs += ", "; qs += " WHERE = '"+NLMISC::toString(_)+"'"; qs += " WHERE = '"+NLMISC::toString()+"'"; ERROR : You must have ONE and ONLY one unique_id property in class '_' ///////////////////////////////////////////////////////////////// // WARNING : this is a generated file, don't change it ! ///////////////////////////////////////////////////////////////// class { protected: friend class ; std::map < uint32, Ptr > *_; std::vector < Ptr > *_; ERROR : You must define the cont="" property with either 'vector' or 'map' value in the child_class element for class '' , child '_' friend class ; bool _Loaded; Ptr _; public: bool operator == (const &other) const { return _ == other._ && ; } // constructor () { // Default initialisation _ = ; } void send(const std::string &serviceName) { NLNET::CMessage msg(""); serial(msg); sendMessageViaMirror( serviceName, msg ); } void send(NLNET::TServiceId serviceId) { NLNET::CMessage msg(""); serial(msg); sendMessageViaMirror( serviceId, msg ); } private: // private constructor, you must use 'createTransient' to get an instance () : _PtrList(NULL), _ObjectState(NOPE::os_transient), _(NOPE::INVALID_OBJECT_ID) { // Default initialisation _ = ; _ = NULL; _Loaded = false; // register the cache for this class (if not already done) registerUpdatable(); } // Destructor, delete any children ~(); /// utility func to remove this object from the released object container void removeFromReleased(); public: /// Create a new instance in the transient space static Ptr createTransient(const char *filename, uint32 lineNum) { return Ptr(new (), filename, lineNum); } /** Create a new object in the database from the current object data. * The object MUST be in transient state (i.e, it must be a new * object created by user and not comming from the databse). * If identifier is autogenerated, the generated id can be read after * this call. */ bool create(MSW::CConnection &connection); /** Update the database with the current object state. * The object MUST be either in clean or dirty state. * Return true if the object has been effectively stored * in the database. * After this call, the object is in 'clean' state. */ bool update(MSW::CConnection &connection); /** Remove the current object from the persistent storage. * The object must be in clean or dirty state. * Return true if the object has been correctly * updated in the database. * After the call, the object is in 'clean' state. */ bool remove(MSW::CConnection &connection); /** Remove an object from the persistent storage by specifying * the id to remove. * Return true if an entry as been effectively removed from * the database. * After the call, the object is in 'removed' state and should * no more be used. A good pratice should be to delete * the transient object just after the remove call. */ static bool removeById(MSW::CConnection &connection, uint32 id); /** Load an instance from the database. * This call allocate a new object and load the property value * from the database. * Return NULL if the object id is not found. */ static Ptr load(MSW::CConnection &connection, uint32 id, const char *filename, uint32 lineNum); /** Load all objects children of and * return them by using the specified output iterator. */ static bool loadChildrenOf(MSW::CConnection &connection, uint32 parentId, std::vector < Ptr > &children, const char *filename, uint32 lineNum); static bool loadChildrenOf(MSW::CConnection &connection, uint32 parentId, std::map < uint32, Ptr > &children, const char *filename, uint32 lineNum); ERROR : parent/child relation support only 'map' or 'vector' cont specification in definition /** Load the object child of and * return true if no error, false in case of error (in SQL maybe). * If no such object is found, fill the child pointer with NULL. */ static bool loadChildOf(MSW::CConnection &connection, uint32 parentId, Ptr &childPtr, const char *filename, uint32 lineNum); /// Load child(ren) object(s). bool load(MSW::CConnection &connection, const char *filename, uint32 lineNum); void serial(NLMISC::IStream &s) { s.serial(_); } private: /// add a child in the container void insertChild( &child) { nlassert(std::find(_.begin(), _.end(), child) == _.end()); _.push_back(child); } // remove a child from the container void removeXXChild() { } private: friend class CPersistentCache; friend class Ptr; typedef std::map<uint32, *> TObjectCache; typedef std::set<*> TObjectSet; typedef std::map<time_t, TObjectSet> TReleasedObject; /// The complete set of object currently in memory (either active or released) excluding transient instance static TObjectCache _ObjectCache; /// The set of object in memory ut released (no pointer on them) and waiting for decommit static TReleasedObject _ReleasedObject; /// The current object state NOPE::TObjectState _ObjectState; /// For object in released state, this is the release date (used to trigger deletion of the object from memory) time_t _ReleaseDate; /// The linked list of pointer on this object Ptr *_PtrList; // Try to load the specified object from the memory cache, return NULL if the object is not in the cache static *loadFromCache(uint32 objectId, bool unrelease); // Receive and execute command from the cache manager. static uint32 cacheCmd(NOPE::TCacheCmd cmd); static void dump(); static void updateCache(); public: static void clearCache(); private: void registerUpdatable(); // set the pointer on the first pointer of the pointer list (set to null when there is no more pointer) void setFirstPtr(Ptr *ptr); // return the first pointer of the pointer list (can be null) Ptr *getFirstPtr() { return _PtrList; } public: /** Return the object identifier (witch is unique) * You can only call this method on a persistent instance. * (because transient instance can have invalid id) */ uint32 getObjectId() const { nlassert(getPersistentState() != NOPE::os_transient); return _; } /** Set the object unique ID. * You can only set the object id on a transient object * having a non autogenerated unique id. * Furthermore, you MUST set the id before calling create() * if the id is not autogenerated. */ void setObjectId(uint32 objectId) { // can only be set when in transient state nlassert(getPersistentState() == NOPE::os_transient); // can only be set once nlassert(_ == NOPE::INVALID_OBJECT_ID); _ = objectId; } /** Return the current persistent state of the object.*/ NOPE::TObjectState getPersistentState() const { return _ObjectState; } private: // Set the persistent state of the object and do some house keeping void setPersistentState(NOPE::TObjectState state); }; ERROR : You must have ONE and ONLY one unique_id property in class '_' ::TObjectCache ::_ObjectCache; ::TReleasedObject ::_ReleasedObject; // Destructor, delete any children ::~() { // release childs reference if (_ != NULL) delete _; if (_PtrList != NULL) { nlwarning("ERROR : someone try to delete this object, but there are still ptr on it !"); Ptr *ptr = _PtrList; do { nlwarning(" Pointer created from '%s', line %u", ptr->_FileName, ptr->_LineNum); ptr = _PtrList->getNextPtr(); } while(ptr != _PtrList); nlstop; } // remove object from cache map if (_ != NOPE::INVALID_OBJECT_ID && _ObjectState != NOPE::os_removed && _ObjectState != NOPE::os_transient) { nldebug("NOPE: clearing @%p from cache with id %u", this, static_cast<uint32>(_)); nlverify(_ObjectCache.erase(_) == 1); } else if (_ObjectState != NOPE::os_transient) { nlassert(_ObjectCache.find(_) == _ObjectCache.end()); } if (_ObjectState == NOPE::os_released) { removeFromReleased(); } else { TReleasedObject::iterator it(_ReleasedObject.find(_ReleaseDate)); if (it != _ReleasedObject.end()) { nlassert(it->second.find(this) == it->second.end()); } } } void ::removeFromReleased() { TReleasedObject::iterator it(_ReleasedObject.find(_ReleaseDate)); nlassert(it != _ReleasedObject.end()); TObjectSet &os = it->second; nlverify(os.erase(this) == 1); // nb : _ReleasedObject time entry are removed by the cache update } bool ::create(MSW::CConnection &connection) { nlassert(getPersistentState() == NOPE::os_transient); nlassert(_ != 0); std::string qs; qs = "INSERT INTO ("; qs += ") VALUES ("; qs += ")"; if (connection.query(qs)) { uint32 _id_ = connection.getLastGeneratedId(); setObjectId(_id_); setPersistentState(NOPE::os_clean); // update the parent class instance in cache if any if ( != 0) { // need to update the parent class child list if it is in the cache *parent = ::loadFromCache(, false); if (parent && parent->_ != NULL) { nlverify(parent->_->insert(std::make_pair(getObjectId(), Ptr(this, __FILE__, __LINE__))).second); nlassert(std::find(parent->_->begin(), parent->_->end(), Ptr(this, __FILE__, __LINE__)) == parent->_->end()); parent->_->push_back(Ptr(this, __FILE__, __LINE__)); } } if ( != 0) { // need to update the parent class child if it is in the cache *parent = ::loadFromCache(, false); if (parent && parent->_Loaded) { nlassert(parent->_ == NULL); parent->_ = Ptr(this, __FILE__, __LINE__); } } return true; } return false; } bool ::update(MSW::CConnection &connection) { nlassert(getPersistentState() == NOPE::os_dirty || getPersistentState() == NOPE::os_clean); if (getPersistentState() == NOPE::os_clean) // the object is clean, just ignore the save return true; std::string qs; qs = "UPDATE SET "; if (connection.query(qs)) { if (connection.getAffectedRows() == 1) { setPersistentState(NOPE::os_clean); return true; } } return false; } bool ::remove(MSW::CConnection &connection) { nlassert(getPersistentState() == NOPE::os_dirty || getPersistentState() == NOPE::os_clean); std::string qs; qs = "DELETE FROM "; if (connection.query(qs)) { if (connection.getAffectedRows() == 1) { { // cascading deletion for vector child nlassert(load(connection, __FILE__, __LINE__)); const std::vector < Ptr > & childs = get(); while (!childs.empty()) { getByIndex(childs.size()-1)->remove(connection); } } { // cascading deletion for map child nlassert(load(connection, __FILE__, __LINE__)); const std::map < uint32, Ptr > & childs = get(); while (!childs.empty()) { getById(childs.begin()->first)->remove(connection); } } { // cascading deletion for single child nlassert(load(connection, __FILE__, __LINE__)); if (get() != NULL) get()->remove(connection); } { // unreference (and update) for vector child nlassert(load(connection, __FILE__, __LINE__)); const std::vector < Ptr > & childs = get(); for (uint i=0; i < childs.size(); ++i) { getByIndex(i)->set(0); getByIndex(i)->update(connection); } } { // unreference (and update) for map child nlassert(load(connection, __FILE__, __LINE__)); const std::map < uint32, Ptr > & childs = get(); std::map< uint32, Ptr >::const_iterator first(childs.begin()), last(childs.end()); for (; first != last; ++first) { getById(it->first)->set(0); getById(it->first)->update(connection); } } { // unreference (and update) for single child nlassert(load(connection, __FILE__, __LINE__)); if (get() != NULL) { get()->set(0); get()->update(connection); } } // change the persistant state to 'removed'. setPersistentState(NOPE::os_removed); // need to remove ref from parent class container (if any) { ERROR : parent/child relation : can't find parent param with db_col '' in definition Ptr parent(::loadFromCache(_, true), __FILE__, __LINE__); if (parent != NULL && parent->_ != NULL) { parent->_->erase(getObjectId()); std::vector < Ptr >::iterator it = std::find(parent->_->begin(), parent->_->end(), this); if (it != parent->_->end()) { parent->_->erase(it); } ERROR : parent/child relation support only 'map' or 'vector' cont specification in definition } } // need to remove ref from parent (if any) { Ptr parent(::loadFromCache(_, true), __FILE__, __LINE__); if (parent != NULL && parent->_Loaded) { // assign a new NULL pointer parent->_.assign(Ptr(), __FILE__, __LINE__); } } return true; } } return false; } bool ::removeById(MSW::CConnection &connection, uint32 id) { *object = loadFromCache(id, true); if (object != NULL) { return object->remove(connection); } // not in cache, run a SQL query std::string qs; qs = "DELETE FROM "; if (connection.query(qs)) { if (connection.getAffectedRows() == 1) { // ok, the row is removed return true; } } return false; } // Try to load the specified object from the memory cache, return NULL if the object is not in the cache *::loadFromCache(uint32 objectId, bool unrelease) { // look in the cache TObjectCache::iterator it(_ObjectCache.find(objectId)); if (it == _ObjectCache.end()) { // not found, return null return NULL; } else { *object = it->second; if (object->_ObjectState == NOPE::os_released) { if (unrelease) { // we need to remove this object from the released object set. object->removeFromReleased(); object->_ObjectState = NOPE::os_clean; } } return it->second; } } // Receive and execute command from the cache manager. uint32 ::cacheCmd(NOPE::TCacheCmd cmd) { if (cmd == NOPE::cc_update) { updateCache(); } else if (cmd == NOPE::cc_clear) { clearCache(); } else if (cmd == NOPE::cc_dump) { dump(); } else if (cmd == NOPE::cc_instance_count) { return _ObjectCache.size(); } // default return value return 0; } void ::dump() { nlinfo(" Cache info for class :"); nlinfo(" There are %u object instances in cache", _ObjectCache.size()); // count the number of object in the released object set uint32 nbReleased = 0; TReleasedObject::iterator first(_ReleasedObject.begin()), last(_ReleasedObject.end()); for (; first != last; ++first) { nbReleased += first->second.size(); } nlinfo(" There are %u object instances in cache not referenced (waiting deletion or re-use))", nbReleased); } void ::updateCache() { if (_ReleasedObject.empty()) return; // 30 s hold in cache const time_t MAX_CACHE_OLD_TIME = 30; time_t now = NLMISC::CTime::getSecondsSince1970(); // look for object set older than MAX_CACHE_OLD_TIME and delete them while (!_ReleasedObject.empty() && _ReleasedObject.begin()->first < now-MAX_CACHE_OLD_TIME) { TObjectSet &delSet = _ReleasedObject.begin()->second; // unload this objects while (!delSet.empty()) { *object = *delSet.begin(); delete object; } _ReleasedObject.erase(_ReleasedObject.begin()); } } void ::clearCache() { // remove any unreferenced object from the cache while (!_ReleasedObject.empty()) { TObjectSet &delSet = _ReleasedObject.begin()->second; // unload this objects while (!delSet.empty()) { *object = *delSet.begin(); delete object; } _ReleasedObject.erase(_ReleasedObject.begin()); } } void ::registerUpdatable() { static bool registered = false; if (!registered) { NOPE::CPersistentCache::getInstance().registerCache(&::cacheCmd); registered = true; } } // set the pointer on the first pointer of the pointer list (set to null when there is no more pointer) void ::setFirstPtr(Ptr *ptr) { _PtrList = ptr; if (ptr == NULL) { // this is the last pointer ! if (_ObjectState == NOPE::os_transient || _ObjectState == NOPE::os_removed) { // not a persistent object, or removed object, just delet it delete this; } else if (_ObjectState != NOPE::os_removed) { setPersistentState(NOPE::os_released); } } } // Set the persistent state of the object and do some house keeping void ::setPersistentState(NOPE::TObjectState state) { nlassert(NOPE::AllowedTransition[_ObjectState][state] == true); if(_ObjectState == NOPE::os_released && state == NOPE::os_removed) { // a release object gets removed (e.g. by remove by id) // delete the object delete this; // no more to do return; } if (_ObjectState == NOPE::os_transient && state != NOPE::os_transient) { nldebug("NOPE: inserting @%p in cache with id %u", this, static_cast<uint32>(_)); nlverify(_ObjectCache.insert(std::make_pair(_, this)).second); } if (_ObjectState != NOPE::os_transient) nlassert(_ObjectCache.find(_) != _ObjectCache.end()); _ObjectState = state; if (state == NOPE::os_released) { _ReleaseDate = NLMISC::CTime::getSecondsSince1970(); nlverify(_ReleasedObject[_ReleaseDate].insert(this).second); } else if (state == NOPE::os_removed) { nldebug("NOPE: erasing @%p in cache with id %u", this, static_cast<uint32>(_)); nlverify(_ObjectCache.erase(_) == 1); } } Ptr ::load(MSW::CConnection &connection, uint32 id, const char *filename, uint32 lineNum) { *inCache = loadFromCache(id, true); if (inCache != NULL) { return Ptr(inCache, filename, lineNum); } std::string qs; qs = "SELECT "; qs += " FROM "; Ptr ret; if (!connection.query(qs)) { return ret; } MSW::CStoreResult *result = connection.storeResult().release(); nlassert(result->getNumRows() <= 1); if (result->getNumRows() == 1) { ret.assign(new , filename, lineNum); // ok, we have an object result->fetchRow(); { std::string s; result->getField(, s); ret->_ = (s); } result->getDateField(, ret->_); result->getMD5Field(, ret->_); result->getField(, ret->_); ret->setPersistentState(NOPE::os_clean); } delete result; return ret; } bool ::loadChildrenOf(MSW::CConnection &connection, uint32 parentId, std::map < uint32, Ptr > & container, const char *filename, uint32 lineNum) bool ::loadChildrenOf(MSW::CConnection &connection, uint32 parentId, std::vector < Ptr > & container, const char *filename, uint32 lineNum) ERROR : parent/child relation support only 'map' or 'vector' cont specification in , parent definition { std::string qs; qs = "SELECT "; qs += " FROM "; qs += " WHERE = '"+NLMISC::toString(parentId)+"'"; if (!connection.query(qs)) { return false; } std::auto_ptr<MSW::CStoreResult> result = connection.storeResult(); for (uint i=0; i<result->getNumRows(); ++i) { *ret = new (); // ok, we have an object result->fetchRow(); { std::string s; result->getField(, s); ret->_ = (s); } result->getDateField(, ret->_); result->getMD5Field(, ret->_); result->getField(, ret->_); *inCache = loadFromCache(ret->_, true); if (inCache != NULL) { container.insert(std::make_pair(inCache->getObjectId(), Ptr(inCache, filename, lineNum))); container.push_back(Ptr(inCache, filename, lineNum)); // no more needed delete ret; } else { ret->setPersistentState(NOPE::os_clean); container.insert(std::make_pair(ret->getObjectId(), Ptr(ret, filename, lineNum))); container.push_back(Ptr(ret, filename, lineNum)); } } return true; } bool ::loadChildOf(MSW::CConnection &connection, uint32 parentId, Ptr &childPtr, const char *filename, uint32 lineNum) { std::string qs; qs = "SELECT "; qs += " FROM "; qs += " WHERE = '"+NLMISC::toString(parentId)+"'"; Ptr ret; if (!connection.query(qs)) { childPtr = Ptr(); return false; } std::auto_ptr<MSW::CStoreResult> result = connection.storeResult(); // check that the data description is consistent with database content nlassert(result->getNumRows() <= 1); if (result->getNumRows() == 1) { *object = new ; // ok, we have an object result->fetchRow(); { std::string s; result->getField(, s); object->_ = (s); } result->getDateField(, object->_); result->getMD5Field(, ret->_); result->getField(, object->_); *inCache = loadFromCache(object->_, true); if (inCache != NULL) { ret.assign(inCache, filename, lineNum); // no more needed delete object; } else { object->setPersistentState(NOPE::os_clean); ret.assign(object, filename, lineNum); } childPtr = ret; return true; } // no result, but no error childPtr = Ptr(); return true; } bool ::load(MSW::CConnection &connection, const char *filename, uint32 lineNum) { bool ret = true; if (_ != NULL) { // the children are already loaded, just return true return true; } // allocate the container _ = new std::map < uint32, Ptr >; _ = new std::vector < Ptr >; // load the childs ret &= ::loadChildrenOf(connection, getObjectId(), *_, filename, lineNum); return ret; } const std::vector<Ptr> &::get() const { nlassert(_ != NULL); return *_; } Ptr &::getByIndex(uint32 index) const { nlassert(_ != NULL); nlassert(index < _->size()); return const_cast< Ptr & >(_->operator[](index)); } Ptr &::getById(uint32 id) const { nlassert(_ != NULL); std::vector<Ptr >::const_iterator first(_->begin()), last(_->end()); for (; first != last; ++first) { const Ptr &child = *first; if (child->getObjectId() == id) { return const_cast< Ptr & >(child); } } // no object with this id, return a null pointer static Ptr nil; return nil; } const std::map<uint32, Ptr> &::get() const { nlassert(_ != NULL); return *_; } Ptr &::getById(uint32 id) const { nlassert(_ != NULL); std::map<uint32, Ptr>::const_iterator it(_->find(id)); if (it == _->end()) { // no object with this id, return a null pointer static Ptr nil; return nil; } return const_cast< Ptr & >(it->second); } ERROR : Invalide container, child must be either map or vector for child in class bool ::load(MSW::CConnection &connection, const char *filename, uint32 lineNum) { if (_Loaded) { // the child is already loaded, just return true return true; } bool ret = ::loadChildOf(connection, getObjectId(), _, filename, lineNum); _Loaded = true; return ret; } /** Return the one child object (or null if not) */ Ptr ::get() { nlassert(_Loaded); return _; } class Itf : public Itf class Itf { protected: /// the callback server adaptor std::auto_ptr<ICallbackServerAdaptor> _CallbackServer; void getCallbakArray(NLNET::TCallbackItem *&arrayPtr, uint32 &arraySize) { static NLNET::TCallbackItem callbackArray[] = { { "", Itf::cb_ }, }; arrayPtr = callbackArray; arraySize = sizeofarray(callbackArray); } static void _cbConnection(NLNET::TSockId from, void *arg) { H_AUTO(__cbConnection); Itf *_this = reinterpret_cast<Itf *>(arg); _this->on__Connection(from); } static void _cbDisconnection(NLNET::TSockId from, void *arg) { H_AUTO(__cbDisconnection); Itf *_this = reinterpret_cast<Itf *>(arg); _this->on__Disconnection(from); } public: /** Constructor, if you specify a replacement adaptor, then the object * become owner of the adaptor (and it will be released with the * interface). */ Itf(ICallbackServerAdaptor *replacementAdaptor = NULL) : Itf(replacementAdaptor) {} Itf(ICallbackServerAdaptor *replacementAdaptor = NULL) { if (replacementAdaptor == NULL) { // use default callback server _CallbackServer = std::auto_ptr<ICallbackServerAdaptor>(new CNelCallbackServerAdaptor(this)); } else { // use the replacement one _CallbackServer = std::auto_ptr<ICallbackServerAdaptor>(replacementAdaptor); } } virtual ~Itf() { } /// Open the interface socket in the specified port void openItf(uint16 port) { NLNET::TCallbackItem *arrayPtr; uint32 arraySize; // add callback array of the base interface class Itf::getCallbakArray(arrayPtr, arraySize); _CallbackServer->addCallbackArray(arrayPtr, arraySize); getCallbakArray(arrayPtr, arraySize); _CallbackServer->addCallbackArray(arrayPtr, arraySize); _CallbackServer->setConnectionCallback (_cbConnection, this); _CallbackServer->setDisconnectionCallback (_cbDisconnection, this); _CallbackServer->init(port); } /** Must be called evenly, update the network subclass to receive message * and dispatch method invokation. */ void update() { H_AUTO(_update); try { _CallbackServer->update(); } catch (...) { nlwarning(" : Exception launch in callback server update"); } } void (NLNET::TSockId dest) { H_AUTO(_); #ifdef NL_DEBUG nldebug(":: called"); #endif NLNET::CMessage message(""); _CallbackServer->send(message, dest); } static void cb_ (NLNET::CMessage &message, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase) { H_AUTO(_on_); #ifdef NL_DEBUG nldebug("::cb_ received from class '%s'", typeid(netbase).name()); #endif ICallbackServerAdaptor *adaptor = static_cast< ICallbackServerAdaptor *>(netbase.getUserData()); Itf *callback = (Itf *)adaptor->getContainerClass(); if (callback == NULL) return; ; std::vector<> ; #ifdef NL_DEBUG nldebug("::cb_ : calling on_"); #endif callback->on_(from, ); retValue; std::vector<> retValue; retValue = callback->on_(from, ); NLNET::CMessage retMsg("R_"); nlWrite(retMsg, serial, retValue); nlWrite(retMsg, serialCont, retValue); callback->_CallbackServer->send(retMsg, from); } /// Connection callback : a new interface client connect virtual void on__Connection(NLNET::TSockId from) =0; /// Disconnection callback : one of the interface client disconnect virtual void on__Disconnection(NLNET::TSockId from) =0; virtual void on_(NLNET::TSockId from) =0; virtual on_(NLNET::TSockId from) =0; virtual std::vector<> on_(NLNET::TSockId from) =0; }; /** This is the client side of the interface * Derive from this class to invoke method on the callback server */ class ClientItf : public ClientItf class ClientItf { protected: /// the callback client adaptor std::auto_ptr < ICallbackClientAdaptor > _CallbackClient; void getCallbakArray(NLNET::TCallbackItem *&arrayPtr, uint32 &arraySize) { arrayPtr = NULL; arraySize = 0; static NLNET::TCallbackItem callbackArray[] = { { "", ClientItf::cb_ }, }; arrayPtr = callbackArray; arraySize = sizeofarray(callbackArray); } static void _cbDisconnection(NLNET::TSockId from, void *arg) { ClientItf *_this = reinterpret_cast<ClientItf *>(arg); _this->on_Client_Disconnection(from); } public: /// Retreive the message name for a given callback name static const std::string &getMessageName(const std::string &methodName) { static std::map<std::string, std::string> messageNames; static bool initialized = false; if (!initialized) { messageNames.insert(std::make_pair(std::string("on_"), std::string(""))); initialized = true; } std::map < std::string, std::string>::const_iterator it(messageNames.find(methodName)); if (it != messageNames.end()) return it->second; // try with the base class return ClientItf::getMessageName(methodName); static std::string emptyString; return emptyString; } ClientItf(ICallbackClientAdaptor *adaptorReplacement = NULL) : ClientItf(adaptorReplacement) {} ClientItf(ICallbackClientAdaptor *adaptorReplacement = NULL) { if (adaptorReplacement == NULL) { // use the default Nel adaptor _CallbackClient = std::auto_ptr < ICallbackClientAdaptor >(new CNelCallbackClientAdaptor(this)); } else { // use the replacement one _CallbackClient = std::auto_ptr < ICallbackClientAdaptor >(adaptorReplacement); } } /// Connect the interface client to the callback server at the specified address and port virtual void connectItf(NLNET::CInetAddress address) { NLNET::TCallbackItem *arrayPtr; uint32 arraySize; static bool callbackAdded = false; if (!callbackAdded) { // add callback array of the base interface class ClientItf::getCallbakArray(arrayPtr, arraySize); _CallbackClient->addCallbackArray(arrayPtr, arraySize); callbackAdded = true; // add callback array of this interface getCallbakArray(arrayPtr, arraySize); _CallbackClient->addCallbackArray(arrayPtr, arraySize); } _CallbackClient->setDisconnectionCallback (_cbDisconnection, this); _CallbackClient->connect(address); } /** Must be called evenly, update the network subclass to receive message * and dispatch invokation returns. */ virtual void update() { H_AUTO(_update); try { _CallbackClient->update(); } catch (...) { nlwarning(" : Exception launch in callback client update"); } } void () { #ifdef NL_DEBUG nldebug("Client:: called"); #endif NLNET::CMessage message(""); _CallbackClient->send(message); } static void cb_ (NLNET::CMessage &message, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase) { #ifdef NL_DEBUG nldebug("Client::cb_ received from class '%s'", typeid(netbase).name()); #endif ICallbackClientAdaptor *adaptor = static_cast< ICallbackClientAdaptor *>(netbase.getUserData()); ClientItf *callback = (ClientItf *)adaptor->getContainerClass(); if (callback == NULL) return; ; std::vector<> ; #ifdef NL_DEBUG nldebug("Client::cb_ : calling on_"); #endif callback->on_(from, ); } /// Disconnection callback : the connection to the server is lost virtual void on_Client_Disconnection(NLNET::TSockId from) =0; virtual void on_(NLNET::TSockId from) =0; }; ERROR : PHP interface only support uint8, uint32, enum and std::string parameter in callback interface '.' <?php ///////////////////////////////////////////////////////////////// // WARNING : this is a generated file, don't change it ! ///////////////////////////////////////////////////////////////// require_once('../tools/nel_message.php'); class extends CCallbackClient { function () { $msg = new CMessage; $msg->setName(""); return parent::sendMessage($msg); $ret = ""; $ret = parent::sendMessage($msg); if ($ret == false) { // error during send $this->invokeError("", "Error in 'sendMessage'"); return false; } $retMsg = parent::waitMessage(); if ($ret == false) { // error during send $this->invokeError("", "Error in 'waitMessage'"); return false; } if (!($retMsg->MsgName === "R_")) { // error during send $this->invokeError("", "Invalid response, awaited 'R_', received '".$retMsg->MsgName."'"); return false; } // serial the return value $ = new _; // return the return value return $retValue; } function waitCallback() { $message = parent::waitMessage(); if ($message == false) return false; switch($message->MsgName) { case "": $this->_skel($message); break; default: return false; } return true; } function _skel(&$message) { $ = new _; $this->(); } ///////////////////////////////////////////////////////////////// // Copy paste this part of code in your derived class // and implement code to ract to incoming message ///////////////////////////////////////////////////////////////// function () { } } ?> $nbElem = 0; ->serialUInt32($nbElem); $ = array(); for ($i=0; $i<$nbElem;$i++) { ->($item); $[] = $item; } ->($); ->serialUint32(count($)); foreach($ as $key=>$value) ->($value); ->($); $, $, class { friend class ; const char *_FileName; uint32 _LineNum; // linked list of smart ptr *_NextPtr; *_PrevPtr; *_Ptr; void linkPtr(); void unlinkPtr(); public: () : _FileName(NULL), _LineNum(0), _Ptr(NULL), _NextPtr(NULL), _PrevPtr(NULL) { } (const &other, const char *filename, uint32 lineNum) : _FileName(filename), _LineNum(lineNum), _NextPtr(NULL), _PrevPtr(NULL) { // point the same object _Ptr = other._Ptr; // insert the pointer in the list linkPtr(); } (const &other) : _FileName(other._FileName), _LineNum(other._LineNum), _NextPtr(NULL), _PrevPtr(NULL) { // point the same object _Ptr = other._Ptr; // insert the pointer in the list linkPtr(); } ( *objectPtr, const char *filename, uint32 lineNum) : _FileName(filename), _LineNum(lineNum), _NextPtr(NULL), _PrevPtr(NULL) { _Ptr = objectPtr; linkPtr(); } &assign(const &other, const char *filename, uint32 lineNum) { _FileName = filename; _LineNum = lineNum; unlinkPtr(); _Ptr = other._Ptr; linkPtr(); return *this; } ~() { unlinkPtr(); } &assign( *objectPtr, const char *filename, uint32 lineNum) { _FileName = filename; _LineNum = lineNum; unlinkPtr(); _Ptr = objectPtr; linkPtr(); return *this; } &operator =(const &other) { return assign(other, __FILE__, __LINE__); } *operator ->() { return _Ptr; } const *operator ->() const { return _Ptr; } bool operator == (const &other) const { return _Ptr == other._Ptr; } bool operator != (const &other) const { return !operator ==(other); } bool operator == (const *object) const { return _Ptr == object; } bool operator != (const *object) const { return !operator ==(object); } /// Less then comparator : comparison on pointer object address bool operator < (const &other) const { return _Ptr < other._Ptr; } /// Used to walk thrue the linked list of pointer *getNextPtr() { return _NextPtr; } }; void ::linkPtr() { nlassert(_NextPtr == NULL); nlassert(_PrevPtr == NULL); if (_Ptr != NULL) { _NextPtr = _Ptr->getFirstPtr(); if (_NextPtr != NULL) { _PrevPtr = _NextPtr->_PrevPtr; _PrevPtr->_NextPtr = this; _NextPtr->_PrevPtr = this; } else { _NextPtr = this; _PrevPtr = this; _Ptr->setFirstPtr(this); } } } void ::unlinkPtr() { if (_NextPtr == NULL) { nlassert(_PrevPtr == NULL); return; } if (_Ptr != NULL) { if (_NextPtr == this) { nlassert(_PrevPtr == this); // last pointer ! _Ptr->setFirstPtr(NULL); } else { if (_Ptr->getFirstPtr() == this) { // the first ptr is the current one, we need to switch to next one _Ptr->setFirstPtr(_NextPtr); } } } if (_NextPtr != this) { nlassert(_PrevPtr != this); _NextPtr->_PrevPtr = _PrevPtr; _PrevPtr->_NextPtr = _NextPtr; } _NextPtr = NULL; _PrevPtr = NULL; }