mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-12-24 09:58:46 +00:00
535 lines
11 KiB
C
535 lines
11 KiB
C
|
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||
|
// Copyright (C) 2010 Winch Gate Property Limited
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero General Public License as
|
||
|
// published by the Free Software Foundation, either version 3 of the
|
||
|
// License, or (at your option) any later version.
|
||
|
//
|
||
|
// This program is distributed in the hope that it will be useful,
|
||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
// GNU Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
#ifndef RY_PDS_DATABASE_H
|
||
|
#define RY_PDS_DATABASE_H
|
||
|
|
||
|
//
|
||
|
// NeL includes
|
||
|
//
|
||
|
#include <nel/misc/types_nl.h>
|
||
|
#include <nel/misc/common.h>
|
||
|
#include <nel/misc/time_nl.h>
|
||
|
#include <nel/misc/stream.h>
|
||
|
#include <nel/misc/i_xml.h>
|
||
|
|
||
|
//
|
||
|
// PDS includes
|
||
|
//
|
||
|
#include "../pd_lib/pds_types.h"
|
||
|
#include "../pd_lib/pds_common.h"
|
||
|
#include "../pd_lib/db_description_parser.h"
|
||
|
|
||
|
#include "../pd_lib/pd_utils.h"
|
||
|
#include "../pd_lib/pd_server_utils.h"
|
||
|
//#include "../pd_lib/pd_string_manager.h"
|
||
|
#include "../pd_lib/pd_string_mapper.h"
|
||
|
|
||
|
//
|
||
|
// stl includes
|
||
|
//
|
||
|
#include <vector>
|
||
|
#include <deque>
|
||
|
|
||
|
class CType;
|
||
|
class CTable;
|
||
|
class CAttribute;
|
||
|
class CColumn;
|
||
|
|
||
|
namespace RY_PDS
|
||
|
{
|
||
|
class CDbMessageQueue;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Definition of the database
|
||
|
* This class contains tables and types definitions
|
||
|
* \author Benjamin Legros
|
||
|
* \author Nevrax France
|
||
|
* \date 2004
|
||
|
*/
|
||
|
class CDatabase : public CPDSLogger, public ITaskEventListener, public RY_PDS::ITableContainer
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*/
|
||
|
CDatabase(uint32 id);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Destructor
|
||
|
*/
|
||
|
~CDatabase();
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Massive Database clear
|
||
|
*/
|
||
|
void clear();
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Init database
|
||
|
*/
|
||
|
bool init();
|
||
|
|
||
|
/**
|
||
|
* Map to a service
|
||
|
*/
|
||
|
void mapToService(NLNET::TServiceId serviceId) { _ServiceId = serviceId; }
|
||
|
|
||
|
/**
|
||
|
* Get Mapped Service Id
|
||
|
*/
|
||
|
NLNET::TServiceId getMappedService() const { return _ServiceId; }
|
||
|
|
||
|
|
||
|
/// Initialized yet?
|
||
|
bool initialised() const { return _Init; }
|
||
|
|
||
|
/**
|
||
|
* Adapt database to new description
|
||
|
* \param description is the latest xml description of the database
|
||
|
* \returns a pointer the valid database, or NULL if failed
|
||
|
*/
|
||
|
CDatabase* adapt(const std::string& description);
|
||
|
|
||
|
/**
|
||
|
* Initialise internal timestamps
|
||
|
*/
|
||
|
void initTimestamps();
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Checkup database
|
||
|
*/
|
||
|
bool checkup();
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Get Name
|
||
|
*/
|
||
|
const std::string& getName() const { return _State.Name; }
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Get Type
|
||
|
*/
|
||
|
const CType* getType(TTypeId typeId) const;
|
||
|
|
||
|
/**
|
||
|
* Get Type
|
||
|
*/
|
||
|
const CType* getType(const std::string &name) const;
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Get Table
|
||
|
*/
|
||
|
const CTable* getTable(TTypeId tableId) const;
|
||
|
|
||
|
/**
|
||
|
* Get Table
|
||
|
*/
|
||
|
const CTable* getTable(const std::string &name) const;
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Get Attribute
|
||
|
*/
|
||
|
const CAttribute* getAttribute(uint32 tableId, uint32 attributeId) const;
|
||
|
|
||
|
/**
|
||
|
* Get Column
|
||
|
*/
|
||
|
const CColumn* getColumn(uint32 tableId, uint32 columnId) const;
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Get value as a string
|
||
|
* \param path is of the form 'Table[index|key].attrib1.attrib2'
|
||
|
*/
|
||
|
std::string getValue(const CLocatePath::TLocatePath &path);
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Allocate a row in a table
|
||
|
* \param index is the table/row to allocate
|
||
|
* Return true if succeded
|
||
|
*/
|
||
|
bool allocate(const RY_PDS::CObjectIndex &index);
|
||
|
|
||
|
/**
|
||
|
* Deallocate a row in a table
|
||
|
* \param index is the table/row to deallocate
|
||
|
* Return true if succeded
|
||
|
*/
|
||
|
bool deallocate(const RY_PDS::CObjectIndex &index);
|
||
|
|
||
|
/**
|
||
|
* Map a row in a table
|
||
|
* \param index is the table/row to allocate
|
||
|
* \param key is the 64 bits row key
|
||
|
* Return true if succeded
|
||
|
*/
|
||
|
bool mapRow(const RY_PDS::CObjectIndex &index, uint64 key);
|
||
|
|
||
|
/**
|
||
|
* Unmap a row in a table
|
||
|
* \param tableIndex is the table to find row
|
||
|
* \param key is the 64 bits row key
|
||
|
* Return true if succeded
|
||
|
*/
|
||
|
bool unmapRow(RY_PDS::TTableIndex tableIndex, uint64 key);
|
||
|
|
||
|
/**
|
||
|
* Get a mapped row
|
||
|
* \param tableIndex is the table in which the row is mapped
|
||
|
* \param key is the 64 bits row key
|
||
|
* Return a valid CObjectIndex if success
|
||
|
*/
|
||
|
RY_PDS::CObjectIndex getMappedRow(RY_PDS::TTableIndex tableIndex, uint64 key) const;
|
||
|
|
||
|
/**
|
||
|
* Search object in database using its key
|
||
|
* \param key is the 64 bits row key to search through all tables
|
||
|
* Return true if key matches at lease one object
|
||
|
*/
|
||
|
bool searchObjectIndex(uint64 key, std::set<RY_PDS::CObjectIndex>& indexes) const;
|
||
|
|
||
|
/**
|
||
|
* Release a row in a table
|
||
|
* \param index is the table/row to release
|
||
|
* Return true if succeded
|
||
|
*/
|
||
|
bool release(const RY_PDS::CObjectIndex &index);
|
||
|
|
||
|
/**
|
||
|
* Release all rows in all table
|
||
|
* Typically, the client disconnected, there is no need to keep rows
|
||
|
*/
|
||
|
bool releaseAll();
|
||
|
|
||
|
/**
|
||
|
* Tells if an object is allocated
|
||
|
* \param object is the object index to test
|
||
|
*/
|
||
|
bool isAllocated(const RY_PDS::CObjectIndex &index) const;
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Set an item in database, located by its table, row and column.
|
||
|
* \param datasize is provided for validation check (1, 2, 4 or 8 bytes)
|
||
|
* \param dataptr points to raw data, which may be 1, 2, 4 or 8 bytes, as indicated by datasize
|
||
|
*/
|
||
|
bool set(RY_PDS::TTableIndex table, RY_PDS::TRowIndex row, RY_PDS::TColumnIndex column, uint datasize, const void* dataptr);
|
||
|
|
||
|
/**
|
||
|
* Set an object parent
|
||
|
*/
|
||
|
bool setParent(RY_PDS::TTableIndex table, RY_PDS::TRowIndex row, RY_PDS::TColumnIndex column, const RY_PDS::CObjectIndex &parent);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Set an item from database, located by its table, row and column.
|
||
|
* \param dataptr points to raw data, which may be 1, 2, 4 or 8 bytes long, as indicated by datasize, where to store data
|
||
|
* \param datasize is the size of the dataptr buffer. At return, it is the size of actual data stored in buffer, that may have been
|
||
|
* truncated, if possible
|
||
|
* \param type is the TDataType of data stored at dataptr
|
||
|
*/
|
||
|
bool get(RY_PDS::TTableIndex table, RY_PDS::TRowIndex row, RY_PDS::TColumnIndex column, uint& datasize, void* dataptr, TDataType& type);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Get Table (non const)
|
||
|
*/
|
||
|
CTable* getNonConstTable(RY_PDS::TTableIndex table);
|
||
|
|
||
|
/**
|
||
|
* Get Object list
|
||
|
*/
|
||
|
RY_PDS::CSetMap& getSetMap() { return _SetMap; }
|
||
|
|
||
|
/**
|
||
|
* Get Object list
|
||
|
*/
|
||
|
const RY_PDS::CSetMap& getSetMap() const { return _SetMap; }
|
||
|
|
||
|
/**
|
||
|
* Get String Manager
|
||
|
*/
|
||
|
// RY_PDS::CPDStringManager& getStringManager() { return _StringManager; }
|
||
|
|
||
|
/**
|
||
|
* Fetch data
|
||
|
*/
|
||
|
bool fetch(const RY_PDS::CObjectIndex& index, RY_PDS::CPData &data, bool fetchIndex = true);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Display database
|
||
|
*/
|
||
|
void display(NLMISC::CLog* log = NLMISC::InfoLog, bool displayHeader = false) const;
|
||
|
|
||
|
/**
|
||
|
* Set value with human readable parameters
|
||
|
*/
|
||
|
bool set(RY_PDS::TTableIndex table, RY_PDS::TRowIndex row, RY_PDS::TColumnIndex column, const std::string& type, const std::string &value);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Dump database content and info of an object to xml
|
||
|
*/
|
||
|
void dumpToXml(const RY_PDS::CObjectIndex& index, NLMISC::IStream& xml, sint expandDepth = -1);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Get Update Queue for id
|
||
|
* May return NULL if message was already received
|
||
|
*/
|
||
|
RY_PDS::CDbMessageQueue* getUpdateMessageQueue(uint32 updateId);
|
||
|
|
||
|
/**
|
||
|
* Receive update
|
||
|
*/
|
||
|
void receiveUpdate(uint32 id);
|
||
|
|
||
|
/**
|
||
|
* Get Last Update Id
|
||
|
*/
|
||
|
uint32 getLastUpdateId() const { return _State.LastUpdateId; }
|
||
|
|
||
|
/**
|
||
|
* Flush updates
|
||
|
*/
|
||
|
void flushUpdates(std::vector<uint32>& acknowledged);
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Serialise SheetId String Mapper
|
||
|
*/
|
||
|
void serialSheetIdStringMapper(NLMISC::IStream& f);
|
||
|
|
||
|
|
||
|
private:
|
||
|
|
||
|
/// Initialised yet?
|
||
|
bool _Init;
|
||
|
|
||
|
/// Current Database State
|
||
|
CDatabaseState _State;
|
||
|
|
||
|
/// Service Id mapped
|
||
|
NLNET::TServiceId _ServiceId;
|
||
|
|
||
|
/// Description
|
||
|
CDBDescriptionParser _Description;
|
||
|
|
||
|
/// Reference index
|
||
|
CRefIndex _Reference;
|
||
|
|
||
|
/// Types in database
|
||
|
std::vector<CType*> _Types;
|
||
|
|
||
|
/// Tables in database
|
||
|
std::vector<CTable*> _Tables;
|
||
|
|
||
|
/// Common object list
|
||
|
RY_PDS::CSetMap _SetMap;
|
||
|
|
||
|
/// String manager
|
||
|
// RY_PDS::CPDStringManager _StringManager;
|
||
|
|
||
|
/// Last Minute Update Timestamp
|
||
|
CTimestamp _MinuteUpdateTimestamp;
|
||
|
|
||
|
/// Last Minute Update Timestamp
|
||
|
CTimestamp _HourUpdateTimestamp;
|
||
|
|
||
|
/// Last Minute Update Timestamp
|
||
|
CTimestamp _DayUpdateTimestamp;
|
||
|
|
||
|
/// Creation Timestamp
|
||
|
CTimestamp _CreationTimestamp;
|
||
|
|
||
|
/// Received updates
|
||
|
std::vector<uint32> _ReceivedUpdates;
|
||
|
|
||
|
/// SheetId String Mapper
|
||
|
CPDStringMapper _SheetIdStringMapper;
|
||
|
|
||
|
|
||
|
|
||
|
/// FIFO of logs
|
||
|
typedef std::list<RY_PDS::CUpdateLog> TUpdateLogQueue;
|
||
|
|
||
|
/// Log of database updates
|
||
|
TUpdateLogQueue _LogQueue;
|
||
|
|
||
|
|
||
|
public:
|
||
|
|
||
|
/// \name RBS Task Event listener interface
|
||
|
// @{
|
||
|
|
||
|
/// Task ran successfully
|
||
|
virtual void taskSuccessful(void* arg);
|
||
|
|
||
|
/// Task failed!
|
||
|
virtual void taskFailed(void* arg);
|
||
|
|
||
|
// @}
|
||
|
|
||
|
/// \name ITableContainer interface
|
||
|
// @{
|
||
|
|
||
|
/// Get Table Index from name
|
||
|
virtual RY_PDS::TTableIndex getTableIndex(const std::string& tableName) const;
|
||
|
|
||
|
/// Get Table Index from name
|
||
|
virtual std::string getTableName(RY_PDS::TTableIndex index) const;
|
||
|
|
||
|
// @}
|
||
|
|
||
|
protected:
|
||
|
|
||
|
virtual std::string getLoggerIdentifier() const { return NLMISC::toString("db:%s", (_State.Name.empty() ? "<unnamed>" : _State.Name.c_str())); }
|
||
|
|
||
|
public:
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Load previous database state and create a new temporary reference if needed (after a crash, for instance)
|
||
|
*/
|
||
|
bool loadState();
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Check if reference is still the same
|
||
|
*/
|
||
|
bool checkReferenceChange();
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Create new database from scratch, setup everything needed (references, etc.)
|
||
|
* \param description is the xml database description
|
||
|
*/
|
||
|
bool createFromScratch(const std::string& description);
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Check if reference is up to date
|
||
|
* Returns true if reference is the latest valid database image
|
||
|
*/
|
||
|
bool isReferenceUpToDate();
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Build a up to date reference in a temp directory.
|
||
|
* Setup 'ref' file, so that it points to new reference.
|
||
|
*/
|
||
|
bool buildReference();
|
||
|
|
||
|
/**
|
||
|
* Build the delta files and purge all dirty rows in tables
|
||
|
*/
|
||
|
bool buildDelta(const CTimestamp& starttime, const CTimestamp& endtime);
|
||
|
|
||
|
/**
|
||
|
* Flush database from released rows
|
||
|
*/
|
||
|
bool flushReleased();
|
||
|
|
||
|
/**
|
||
|
* Notify a new reference is ready
|
||
|
*/
|
||
|
bool notifyNewReference(bool validateRef = true);
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Build index allocators
|
||
|
* One per table
|
||
|
*/
|
||
|
bool buildIndexAllocators(std::vector<RY_PDS::CIndexAllocator> &allocators);
|
||
|
|
||
|
/**
|
||
|
* Rebuild forwardrefs from backrefs
|
||
|
*/
|
||
|
bool rebuildForwardRefs();
|
||
|
|
||
|
/**
|
||
|
* Rebuild table maps
|
||
|
*/
|
||
|
bool rebuildTableMaps();
|
||
|
|
||
|
/**
|
||
|
* Reset dirty lists
|
||
|
*/
|
||
|
bool resetDirtyTags();
|
||
|
|
||
|
/**
|
||
|
* Reset and rebuild all maps, references, lists...
|
||
|
*/
|
||
|
bool rebuildVolatileData();
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Static Check for update rate
|
||
|
*/
|
||
|
static void checkUpdateRates();
|
||
|
|
||
|
/**
|
||
|
* Send Delta/Reference build commands
|
||
|
*/
|
||
|
bool sendBuildCommands(const CTimestamp& current);
|
||
|
|
||
|
|
||
|
private:
|
||
|
|
||
|
friend class CDatabaseAdapter;
|
||
|
};
|
||
|
|
||
|
|
||
|
// include inlines
|
||
|
#include "pds_database_inline.h"
|
||
|
|
||
|
#endif //RY_PDS_DATABASE_H
|
||
|
|