Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / pd_lib / pds_table_buffer.h
blobceb0b7f10bff82bf8c23e232fda9d67f043e86eb
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef NL_PDS_TABLE_BUFFER_H
18 #define NL_PDS_TABLE_BUFFER_H
20 #include <nel/misc/types_nl.h>
21 #include <nel/misc/path.h>
23 #include "../pd_lib/pd_utils.h"
24 #include "../pd_lib/pd_server_utils.h"
25 #include "../pd_lib/db_reference_file.h"
26 #include "../pd_lib/db_delta_file.h"
29 class IRowProcessor;
31 /**
32 * A memory cache for table
33 * \author Benjamin Legros
34 * \author Nevrax France
35 * \date 2003
37 class CTableBuffer : public CPDSLogger
39 public:
41 /// Constructor
42 CTableBuffer();
44 /// Destructor
45 ~CTableBuffer();
47 /// Clear all
48 void clear();
50 /// Init
51 void init(uint32 tableId, uint32 rowSize, bool mapped);
53 /// Setup Ref
54 void setupRef(CRefIndex& ref);
59 /// Init, only for reference builder
60 void init(uint32 tableId, const std::string& refRootPath, const std::string& refPath); //CRefIndex& ref);
64 /// Row Data Type
65 typedef uint8* TRowData;
67 /// Map of Rows
68 typedef CHashMap<RY_PDS::TRowIndex, TRowData> TRowMap;
70 /**
71 * Row Accessor, embeds any row access
73 class CAccessor
75 public:
77 /// Get row index
78 RY_PDS::TRowIndex row() const { return (*_MapIt).first; }
80 /// Get row data
81 TRowData data() { return (*_MapIt).second + (_Mapped ? sizeof(CMappedHeader) : sizeof(CHeader)); }
83 /// Get row data
84 TRowData data() const { return (*_MapIt).second + (_Mapped ? sizeof(CMappedHeader) : sizeof(CHeader)); }
86 /// Default Constructor, should never be used
87 explicit CAccessor() { }
91 /// Is Row Allocated
92 bool allocated() const { return ((CHeader*)fullRow())->allocated(); }
94 /// Is Row Mapped
95 bool mapped() const { return _Mapped && ((CMappedHeader*)fullRow())->mapped(); }
97 /// Is Row Dirty
98 bool dirty() const { return ((CHeader*)fullRow())->dirty(); }
100 /// Get Dirt stamp
101 uint32 dirtyStamp() const { return ((CHeader*)fullRow())->getDirtStamp(); }
103 /// Get Map Key
104 uint64 key() const { return mapped() ? ((CMappedHeader*)fullRow())->getKey() : 0; }
106 /// Get Full Row Data
107 TRowData fullRow() const { return (*_MapIt).second; }
110 /// Equals
111 bool operator == (const CAccessor& access) const { return _Mapped == access._Mapped && _MapIt == access._MapIt; }
115 * Copy header info from another accessor
116 * Warning, this is only a local copy of header, data won't been updated in parent CTableBuffer
118 void copyHeader(const CAccessor& access);
120 private:
122 friend class CTableBuffer;
124 /// Accessor in table map
125 typedef TRowMap::iterator TMapIt;
126 TMapIt _MapIt;
128 bool _Mapped;
130 /// Constructor for CTableBuffer
131 CAccessor(TMapIt it, bool mapped) : _MapIt(it), _Mapped(mapped) { }
133 /// Get Full Row Data
134 TRowData fullRow() { return (*_MapIt).second; }
140 * Return a pointer to straight row data
141 * If row is not loaded, data are loaded from table file
143 CAccessor getRow(RY_PDS::TRowIndex row);
146 * Return a pointer to straight new row data
147 * Row is filled with blank, not loaded from file
149 CAccessor getEmptyRow(RY_PDS::TRowIndex row);
152 * Acquire a Row
153 * Row is marked as non releasable until it is released enough time
155 bool acquireRow(CAccessor accessor);
158 * Release a Row
159 * Row is marked as purgeable, and will be purged as soon as possible,
160 * unless it is reactivated before purge
162 bool releaseRow(CAccessor accessor);
165 * Release a Row
166 * Row is marked as purgeable, and will be purged as soon as possible,
167 * unless it is reactivated before purge
169 bool releaseRow(RY_PDS::TRowIndex row);
172 * Release all rows
173 * To be called when client disconnects, so all loaded rows may be released without
174 * client releasing them manually
176 bool releaseAll();
181 * Mark a Row as being dirty for later delta save
183 bool dirtyRow(CAccessor accessor);
188 * Build Delta
190 bool buildDelta(const CTimestamp& starttimestamp, const CTimestamp& endtimestamp);
193 * Apply delta changes from a file
195 bool applyDeltaChanges(const std::string& filename);
198 * Flush Released Rows from memory
200 void flushReleased();
203 * Reset dirty tags
205 void resetDirty();
208 * Flush Reference files
210 void flushRefFiles();
213 * Purge all references
214 * Flush loaded reference files, and close them all.
216 bool purgeReferences();
219 * Open all reference files in reference directory to update
221 bool openAllRefFilesWrite();
224 * Open all reference files in reference directory to read
226 bool openAllRefFilesRead();
229 * Update delta ids for all references
231 bool updateDeltaIds(uint32 start, uint32 end);
237 * Allocate a row
238 * \param row is the row index to allocate
239 * Return true if succeded
241 bool allocate(RY_PDS::TRowIndex row, CAccessor& accessor);
244 * Deallocate a row
245 * \param row is the row index to deallocate
246 * Return true if succeded
248 bool deallocate(RY_PDS::TRowIndex row);
251 * Tells if a row is allocated
252 * \param row is the row to check
254 bool isAllocated(RY_PDS::TRowIndex row) const { return _RowMapper.allocated(row); }
257 * Get number of actually allocated rows
259 uint32 numAllocated() const { return _RowMapper.numAllocated(); }
262 * Get Max row index used
264 RY_PDS::TRowIndex maxRowIndex() const { return _RowMapper.maxRowIndex(); }
268 * Get Next Unalloocated row
270 RY_PDS::TRowIndex nextUnallocatedRow() const { return _RowMapper.nextUnallocatedRow(); }
274 * Map a row
275 * \param index is the index to map
276 * \param key is the 64 bits row key
277 * Return true if succeded
279 bool mapRow(const RY_PDS::CObjectIndex &index, uint64 key);
282 * Unmap a row in a table
283 * \param key is the 64 bits row key
284 * Return true if succeded
286 bool unmapRow(const RY_PDS::CObjectIndex &index, uint64 key);
289 * Get a mapped row
290 * \param key is the 64 bits row key
291 * Return a valid CObjectIndex if success
293 RY_PDS::CObjectIndex getMappedRow(uint64 key) const;
296 * Get number of actually allocated rows
298 uint32 numMapped() const { return _RowMapper.numMapped(); }
302 * Get the number of actually loaded rows
304 uint32 getLoadedRows() const { return (uint32)_RowMap.size(); }
307 * Get memory load
309 uint32 getMemoryLoad() const { return (uint32)_RowMap.size()*_InternalRowSize; }
314 * Build RowMapper
316 bool buildRowMapper();
319 * Process Rows, apply external row processing after rows are loaded
321 bool processRows(IRowProcessor* processor);
324 * Link RowMapper
326 void linkRowMapper(CTableBuffer* link) { _RowMapper.link(&(link->_RowMapper)); }
331 * Get Size of Row Header (depends on whether table is mapped or not)
333 uint getHeaderSize() const { return _Mapped ? sizeof(CMappedHeader) : sizeof(CHeader); }
336 * Get Internal Row Size
338 uint getInternalRowSize() const { return _InternalRowSize; }
341 * Get User Row Size
343 uint getRowSize() const { return _InternalRowSize; }
348 * Update a Row
349 * Update in reference file the whole row
351 bool updateRow(CAccessor accessor);
354 * Get current Timestamp
356 static uint32 getCommonStamp() { return _CommonStamp; }
359 * Update common Timestamp
361 static void updateCommonStamp();
366 /// \name Debug
367 // @{
370 * Setup debug delta file
372 bool setupDebugDeltaFile(const std::string& filename, CDBDeltaFile& delta) const;
375 * Get Delta file Row
377 uint8* getDeltaRow(uint32& row, CDBDeltaFile& delta) const;
379 // @}
383 protected:
385 virtual std::string getLoggerIdentifier() const { return "buffer"; }
387 private:
389 /// Initialised
390 bool _Init;
392 /// Table Id
393 uint32 _TableId;
395 /// Row Size
396 uint32 _RowSize;
398 /// Internal Row Size
399 uint32 _InternalRowSize;
401 /// Ref Root Path
402 std::string _RefRootPath;
404 /// Ref Path
405 std::string _RefPath;
407 /// Rows per ref file
408 uint32 _RowsPerFile;
410 /// Maximum ref file size
411 static uint32 _MaxRefFileSize;
413 /// Row Map
414 TRowMap _RowMap;
416 /// Map of purgeable rows
417 typedef std::set<RY_PDS::TRowIndex> TReleaseSet;
419 /// Release Map
420 TReleaseSet _ReleaseSet;
422 /// List of dirty rows
423 typedef std::vector<CAccessor> TDirtyList;
425 /// Dirty List
426 TDirtyList _DirtyList;
428 /// List of ref files -- a vector or pointer, to avoid realloc issues
429 typedef std::vector<CDBReferenceFile*> TRefFileMap;
431 /// Reference files
432 TRefFileMap _RefFileMap;
434 /// Index and Allocation Map
435 CRowMapper _RowMapper;
437 /// Rows are mapped?
438 bool _Mapped;
440 /// Current Delta Id
441 uint32 _CurrentDeltaId;
444 /// Current reference stamp
445 uint32 _ReferenceStamp;
447 /// Common stamp
448 static uint32 _CommonStamp;
451 /// Load a row from the appropriate reference file
452 bool loadRow(RY_PDS::TRowIndex row, TRowData rowData);
454 /// Init Number of Rows per File
455 bool initRowsPerFile();
457 /// Check reference file is ready
458 bool checkRef(uint32 refFile);
460 /// Acquire a row, internal version
461 bool acquireRow(TRowMap::iterator it);
463 /// Release a row, internal version
464 bool releaseRow(TRowMap::iterator it, bool forceNotAcquired = false);
466 /// Update a Row -- rowdata is _InternalByteSize long, this is a full buffer row with header
467 bool updateRow(RY_PDS::TRowIndex row, const TRowData rowData, bool forceWriteToDisk);
469 /// Get Reference Files list
470 void getReferenceFilesList(std::vector<std::string> &result);
472 /// Process row for RowMapper
473 bool processRow(CAccessor& accessor);
475 /// Header of a row
476 class CHeader
478 public:
480 enum
482 Dirty = 1,
483 Allocated = 2,
486 /// Clear
487 void clear() { _Flags = 0; _Acquire = 0; _DirtStamp = 0; }
489 /// GetFlags
490 uint8 getFlags() const { return _Flags; }
492 /// Is Row Dirty
493 bool dirty() const { return checkFlags(Dirty); }
496 /// Is Row Allocated
497 bool allocated() const { return checkFlags(Allocated); }
500 /// Set flags
501 void setFlags(uint8 flags) { _Flags |= flags; }
503 /// Set flags
504 void clearFlags(uint8 flags) { _Flags &= (~flags); }
506 /// Check Flags
507 bool checkFlags(uint8 testflags) const { return (_Flags & testflags) != 0; }
511 /// Set Row As Dirty
512 void setDirty();
514 /// Clear DirtStamp (set initial dirt stamp as 'no dirt stamp' value)
515 void clearDirtStamp() { _DirtStamp = 0; clearFlags(Dirty); }
517 /// Get DirtStamp
518 uint32 getDirtStamp() const { return _DirtStamp; }
522 /// Acquire, return true the first time it is acquired
523 bool acquire()
525 ++_Acquire;
526 return _Acquire == 1;
529 /// Release, return true if row can be release effectively
530 bool unacquire()
532 --_Acquire;
533 if (_Acquire < 0)
534 _Acquire = 0;
535 return !isAcquired();
538 /// Clear Acquire count
539 void clearAcquireCount() { _Acquire = 0; }
541 /// Is acquired
542 bool isAcquired() const { return _Acquire > 0; }
544 protected:
546 /// Row flags
547 uint8 _Flags;
549 /// Acquire counter
550 sint16 _Acquire;
552 /// Row Dirty Timestamp
553 uint32 _DirtStamp;
557 /// Header of a mapped row
558 class CMappedHeader : public CHeader
560 public:
562 /// Clear up header
563 void clear() { CHeader::clear(); _Key = 0; }
565 /// Set Row Key
566 void setKey(uint64 key) { _Key = key; }
568 /// Get Row Key
569 uint64 getKey() const { return _Key; }
571 /// Is Row Mapped?
572 bool mapped() const { return _Key != 0; }
574 protected:
577 * Row map key
578 * The key of the row in table map, 0 means this row is not mapped
580 uint64 _Key;
584 friend class CAccessor;
585 friend class CDatabaseAdapter;
589 * A callback interface for row processing at loading
590 * \author Benjamin Legros
591 * \author Nevrax France
592 * \date 2003
594 class IRowProcessor
596 public:
598 virtual bool processRow(RY_PDS::TTableIndex table, CTableBuffer::CAccessor& accessor) = 0;
602 #include "pds_table_buffer_inline.h"
605 #endif // NL_PDS_TABLE_BUFFER_H
607 /* End of pds_table_buffer.h */