// ====================================================================== // // Snapshot.cpp // copyright (c) 2001 Sony Online Entertainment // // ====================================================================== #include "serverDatabase/FirstServerDatabase.h" #include "serverDatabase/Snapshot.h" #include "serverDatabase/AbstractTableBuffer.h" #include "serverDatabase/CustomPersistStep.h" #include "serverDatabase/ObjectLocator.h" #include "serverDatabase/SaveTimestampQuery.h" #include "serverUtility/ServerClock.h" #include "sharedDatabaseInterface/DbSession.h" #include "sharedFoundation/NetworkIdArchive.h" #include "sharedLog/Log.h" // ====================================================================== int Snapshot::ms_creationCount=0; int Snapshot::ms_deletionCount=0; // ====================================================================== Snapshot::Snapshot(DB::ModeQuery::Mode mode, bool useGoldDatabase) : m_universeAuthorityHack(false), m_isBeingSaved(false), m_useGoldDatabase(useGoldDatabase), m_mode(mode), m_timestamp(0) { LOG("Snapshot",("Created snapshot")); ++ms_creationCount; } // ---------------------------------------------------------------------- Snapshot::~Snapshot() { for (LocatorListType::iterator i=m_locatorList.begin(); i!=m_locatorList.end(); ++i) { delete *i; *i = nullptr; } for (CustomStepListType::iterator j=m_customStepList.begin(); j!=m_customStepList.end(); ++j) { delete *j; *j = nullptr; } m_locatorList.clear(); m_customStepList.clear(); ++ms_deletionCount; LOG("Snapshot",("Deleted snapshot. %i outstanding, %i created, %i deleted", ms_creationCount-ms_deletionCount,ms_creationCount,ms_deletionCount)); } // ---------------------------------------------------------------------- /** * Called by a worker thread. Saves the snapshot to the database * * Saves all the buffers in the list and runs any custom steps. */ bool Snapshot::saveToDB(DB::Session *session) { NOT_NULL(session); m_isBeingSaved = true; CustomStepListType::iterator step; for (step=m_customStepList.begin(); step !=m_customStepList.end(); ++step) { NOT_NULL(*step); if (!(*step)->beforePersist(session)) { m_isBeingSaved = false; return false; } } if (m_timestamp!=0) if (! saveTimestamp(session)) { m_isBeingSaved = false; return false; } for (step=m_customStepList.begin(); step !=m_customStepList.end(); ++step) { NOT_NULL(*step); if (!(*step)->afterPersist(session)){ m_isBeingSaved = false; return false; } } m_isBeingSaved = false; return true; } // ---------------------------------------------------------------------- /** * Called when a message is received to update an object's data. * * Identifies what package the message is part of, and invokes the * appropriate (virtual) function. */ void Snapshot::handleDeltasMessage(NetworkId & objectId, const DeltasMessage &msg) { unsigned char packageId=msg.getPackageId(); Tag typeId=msg.getTypeId(); Archive::ReadIterator bs=msg.getPackage().begin(); uint16 count; Archive::get(bs,count); DEBUG_REPORT_LOG(count==0,("Deltas package was empty.\n")); for (uint16 i=0; i< count; ++i) { unsigned short int index; Archive::get(bs,index); switch (packageId) { case DeltasMessage::DELTAS_SERVER: decodeServerData(objectId,typeId,index,bs,false); break; case DeltasMessage::DELTAS_SHARED: decodeSharedData(objectId,typeId,index,bs,false); break; case DeltasMessage::DELTAS_CLIENT_SERVER: decodeClientData(objectId,typeId,index,bs,false); break; case DeltasMessage::DELTAS_FIRST_PARENT_CLIENT_SERVER: decodeParentClientData(objectId,typeId,index,bs,false); break; case DeltasMessage::DELTAS_SERVER_NP: case DeltasMessage::DELTAS_SHARED_NP: case DeltasMessage::DELTAS_CLIENT_SERVER_NP: case DeltasMessage::DELTAS_FIRST_PARENT_CLIENT_SERVER_NP: case DeltasMessage::DELTAS_UI: break; default: FATAL(true,("PackageId was invalid.")); break; } } } // ---------------------------------------------------------------------- /** * Called when a message is received to update an object's data. * * Identifies what package the message is part of, and invokes the * appropriate (virtual) function. */ void Snapshot::handleBaselinesMessage(NetworkId &objectId, const BaselinesMessage &msg) { unsigned char packageId=msg.getPackageId(); Tag typeId=msg.getTypeId(); Archive::ReadIterator bs=msg.getPackage().begin(); uint16 count; Archive::get(bs,count); for (uint16 i=0; i< count; ++i) { switch (packageId){ case BaselinesMessage::BASELINES_SERVER : decodeServerData(objectId,typeId,i,bs,true); break; case BaselinesMessage::BASELINES_SHARED: decodeSharedData(objectId,typeId,i,bs,true); break; case BaselinesMessage::BASELINES_CLIENT_SERVER : decodeClientData(objectId,typeId,i,bs,true); break; case BaselinesMessage::BASELINES_FIRST_PARENT_CLIENT_SERVER: decodeParentClientData(objectId,typeId,i,bs,true); break; case BaselinesMessage::BASELINES_SERVER_NP : case BaselinesMessage::BASELINES_SHARED_NP : case BaselinesMessage::BASELINES_CLIENT_SERVER_NP : case BaselinesMessage::BASELINES_UI : case BaselinesMessage::BASELINES_FIRST_PARENT_CLIENT_SERVER_NP : break; default: FATAL(true,("PackageId was not BASELINES_SERVER, BASELINES_SHARED, or BASELINES_CLIENT.\n")); break; } } } // ---------------------------------------------------------------------- void Snapshot::addLocator(ObjectLocator *newLocator) { NOT_NULL(newLocator); m_locatorList.push_back(newLocator); } // ---------------------------------------------------------------------- int Snapshot::getLocatorCount() const { return m_locatorList.size(); } // ---------------------------------------------------------------------- void Snapshot::takeTimestamp() { DEBUG_FATAL(m_timestamp!=0,("takeTimestamp was invoked more than once.\n")); m_timestamp=ServerClock::getInstance().getGameTimeSeconds(); } // ---------------------------------------------------------------------- bool Snapshot::saveTimestamp(DB::Session *session) { DEBUG_FATAL(m_timestamp==0,("Can't save unset timestamp.\n")); NOT_NULL(session); DBQuery::SaveTimestampQuery stq(m_timestamp); return session->exec(&stq); } // ---------------------------------------------------------------------- void Snapshot::addCustomPersistStep(CustomPersistStep *newStep) { NOT_NULL(newStep); m_customStepList.push_back(newStep); } // ---------------------------------------------------------------------- void Snapshot::saveCompleted() { for (CustomStepListType::iterator step=m_customStepList.begin(); step !=m_customStepList.end(); ++step) { NOT_NULL(*step); (*step)->onComplete(); } } // ======================================================================