// ====================================================================== // // Persister.h // copyright (c) 2001 Sony Online Entertainment // // ====================================================================== #ifndef INCLUDED_Persister_H #define INCLUDED_Persister_H // ====================================================================== #include #include #include #include #include //TODO: remove when we clean up newCharacterLock hack #include "Unicode.h" #include "serverNetworkMessages/MessageToPayload.h" #include "sharedDatabaseInterface/DbModeQuery.h" #include "sharedFoundation/NetworkId.h" #include "sharedFoundation/StationId.h" #include "sharedFoundation/Tag.h" #include "sharedMessageDispatch/Receiver.h" class AddResourceTypeMessage; class BaselinesMessage; class BountyHunterTargetMessage; class DeltasMessage; class Snapshot; class TransferAccountData; class TransferCharacterData; class DBCSRequestMessage; namespace DB { class TaskQueue; } // ====================================================================== /** * Singleton that organizes messages to be persisted to the database. * * For now, directs all changes to a "snapshot" object. For the future, * may want to have a snapshot for each server so that we can do more in * parallel. This might be implemented by having multiple instances * of Persister. * * This is an abstract base class. A game-specific Persister should * be derived from it. */ class Persister : public MessageDispatch::Receiver { public: static Persister &getInstance(); void handleDeleteMessage (uint32 serverId, const NetworkId &objectId, int reasonCode, bool immediate, bool demandLoadedContainer, bool cascadeReason); void handleMessageTo (uint32 sourceServer, const MessageToPayload &data); void handleMessageToAck (uint32 sourceServer, const MessageToId &messageId); void update(real updateTime); void onFrameBarrierReached(); bool isIdle(); bool isSaveInProgress(); void newObject(uint32 serverId, const NetworkId &objectId, int templateId, Tag typeId, const NetworkId &container); void beginBaselines(const NetworkId &newObject) const; void endBaselines(const NetworkId &newObject, uint32 serverId); void saveCompleted (Snapshot *completedSnapshot); void onNewCharacterSaved (uint32 stationId, const NetworkId &characterObject, const Unicode::String &characterName, const int templateId, bool special) const; void receiveMessage(const MessageDispatch::Emitter & source, const MessageDispatch::MessageBase & message); void shutdown(); int getTimeSinceLastSave(); int getLastSaveTime(); int getLastSaveTotalObjectCount(); int getLastSaveNewObjectCount(); std::string getLastSaveCompletionTime(); void unloadCharacter(const NetworkId &characterId, uint32 sourceServer); bool hasDataForObject(const NetworkId &objectId) const; void renameCharacter(uint32 sourceServer, int8 renameCharacterMessageSource, uint32 stationId, const NetworkId &characterId, const Unicode::String &newName, const Unicode::String &oldName, bool lastNameChangeOnly, const NetworkId &requestedBy, const TransferCharacterData * renameRequest); void changeStationId(const TransferAccountData * transferRequest); void handleCSRequest( const DBCSRequestMessage & msg ); void handleCSMovePlayer( const DBCSRequestMessage & msg ); void handleCsUndelete(const NetworkId & character, const NetworkId & item, const std::string & message, bool move); virtual void startLoadCommodities() =0; protected: DB::TaskQueue *taskQueue; DB::TaskQueue *m_newCharacterTaskQueue; private: struct PendingCharacter { uint32 stationId; Unicode::String name; bool special; }; typedef std::map ServerSnapshotMap; typedef std::unordered_map ObjectSnapshotMap; typedef std::map PendingCharactersType; typedef std::vector SnapshotListType; typedef std::set NewCharacterLockType; typedef std::vector > CharactersToDeleteType; ServerSnapshotMap m_currentSnapshots; ServerSnapshotMap m_newObjectSnapshots; ServerSnapshotMap m_newCharacterSnapshots; ObjectSnapshotMap m_objectSnapshotMap; PendingCharactersType m_pendingCharacters; SnapshotListType m_savingSnapshots; SnapshotListType m_savingCharacterSnapshots; NewCharacterLockType m_newCharacterLock; CharactersToDeleteType * m_charactersToDeleteThisSaveCycle; CharactersToDeleteType * m_charactersToDeleteNextSaveCycle; real m_timeSinceLastSave; Snapshot * m_messageSnapshot; Snapshot * m_commoditiesSnapshot; Snapshot * m_arbitraryGameDataSnapshot; int m_saveStartTime; int m_totalSaveTime; int m_maxSaveTime; int m_saveCount; int m_newObjectCount; int m_lastSaveTime; int m_lastSaveTotalObjectCount; int m_lastSaveNewObjectCount; std::string m_lastSaveCompletionTime; int m_saveCounter; bool m_startSaveWhenPossible; bool m_inMagicMinute; bool m_clusterShuttingDown; protected: virtual void startSave() = 0; Snapshot *getSnapshotForObject(const NetworkId &networkId, uint32 serverId); Snapshot *getSnapshotForServer(uint32 serverId); private: void handleDeltasMessage (uint32 serverId, const DeltasMessage &msg); void handleBaselinesMessage (uint32 serverId, const BaselinesMessage &msg); void handleAddResourceTypeMessage(uint32 const serverId, AddResourceTypeMessage const & message); void handlePurgeCompleteMessage(uint32 const serverId, StationId stationId); void addCharacter (uint32 stationId, const NetworkId &characterObject, uint32 creationGameServer, const Unicode::String &name, bool special); void deleteCharacter (StationId stationId, const NetworkId &characterId); void recordMoneyTransaction (uint32 sourceServer, const NetworkId &transactionId, const int transactionType, const NetworkId &sourceId, const std::string &sourceString, const NetworkId &targetId, const std::string &targetString, int amount); void moveToPlayer (uint32 sourceServer, const NetworkId &objectId, const NetworkId &targetPlayer, int maxDepth, bool useBank, bool useDatapad); void fixLoadWith (uint32 sourceServer, const NetworkId &topmostObject, const NetworkId &startingLoadWith, int maxDepth); void moveToContainer (uint32 sourceServer, NetworkId const & objectId, NetworkId const & targetContainer); void userRequestedSave (uint32 sourceGameServer, const NetworkId &whoRequested); void centralRequestedSave (); void planetRequestedSave (); Snapshot *getCommoditiesSnapshot(uint32 serverId); /** * Derived class should override this to make a game-specific derived Snapshot. */ virtual Snapshot *makeSnapshot(DB::ModeQuery::Mode mode) const =0; virtual Snapshot *makeCommoditiesSnapshot(DB::ModeQuery::Mode mode) const =0; /** * Admin functions */ virtual void restoreHouse(const NetworkId &houseId, const std::string &whoRequested)=0; virtual void restoreCharacter(const NetworkId &characterId, const std::string &whoRequested)=0; virtual void undeleteItem(const NetworkId &itemId, const std::string &whoRequested)=0; virtual void moveToPlayer(const NetworkId &oid, const NetworkId &player, const std::string &whoRequested)=0; /** * Misc game-specific persistence steps */ virtual void getMoneyFromOfflineObject(uint32 replyServer, NetworkId const & sourceObject, int amount, NetworkId const & replyTo, std::string const & successCallback, std::string const & failCallback, std::vector const & packedDictionary)=0; protected: Persister(); virtual ~Persister(); static void installDerived(Persister *derivedInstance); private: Persister(const Persister&); //disable Persister &operator=(const Persister&); //disable private: static void remove(); static Persister *ms_instance; }; // ---------------------------------------------------------------------- inline Persister &Persister::getInstance() { NOT_NULL(ms_instance); return *ms_instance; } // ---------------------------------------------------------------------- inline int Persister::getTimeSinceLastSave() { return static_cast(m_timeSinceLastSave); } // ---------------------------------------------------------------------- inline int Persister::getLastSaveTime() { return m_lastSaveTime; } // ---------------------------------------------------------------------- inline int Persister::getLastSaveTotalObjectCount() { return m_lastSaveTotalObjectCount; } // ---------------------------------------------------------------------- inline int Persister::getLastSaveNewObjectCount() { return m_lastSaveNewObjectCount; } // ====================================================================== #endif