1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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"
32 * A memory cache for table
33 * \author Benjamin Legros
34 * \author Nevrax France
37 class CTableBuffer
: public CPDSLogger
51 void init(uint32 tableId
, uint32 rowSize
, bool mapped
);
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);
65 typedef uint8
* TRowData
;
68 typedef CHashMap
<RY_PDS::TRowIndex
, TRowData
> TRowMap
;
71 * Row Accessor, embeds any row access
78 RY_PDS::TRowIndex
row() const { return (*_MapIt
).first
; }
81 TRowData
data() { return (*_MapIt
).second
+ (_Mapped
? sizeof(CMappedHeader
) : sizeof(CHeader
)); }
84 TRowData
data() const { return (*_MapIt
).second
+ (_Mapped
? sizeof(CMappedHeader
) : sizeof(CHeader
)); }
86 /// Default Constructor, should never be used
87 explicit CAccessor() { }
92 bool allocated() const { return ((CHeader
*)fullRow())->allocated(); }
95 bool mapped() const { return _Mapped
&& ((CMappedHeader
*)fullRow())->mapped(); }
98 bool dirty() const { return ((CHeader
*)fullRow())->dirty(); }
101 uint32
dirtyStamp() const { return ((CHeader
*)fullRow())->getDirtStamp(); }
104 uint64
key() const { return mapped() ? ((CMappedHeader
*)fullRow())->getKey() : 0; }
106 /// Get Full Row Data
107 TRowData
fullRow() const { return (*_MapIt
).second
; }
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
);
122 friend class CTableBuffer
;
124 /// Accessor in table map
125 typedef TRowMap::iterator TMapIt
;
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
);
153 * Row is marked as non releasable until it is released enough time
155 bool acquireRow(CAccessor accessor
);
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
);
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
);
173 * To be called when client disconnects, so all loaded rows may be released without
174 * client releasing them manually
181 * Mark a Row as being dirty for later delta save
183 bool dirtyRow(CAccessor accessor
);
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();
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
);
238 * \param row is the row index to allocate
239 * Return true if succeded
241 bool allocate(RY_PDS::TRowIndex row
, CAccessor
& accessor
);
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(); }
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
);
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(); }
309 uint32
getMemoryLoad() const { return (uint32
)_RowMap
.size()*_InternalRowSize
; }
316 bool buildRowMapper();
319 * Process Rows, apply external row processing after rows are loaded
321 bool processRows(IRowProcessor
* processor
);
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
; }
343 uint
getRowSize() const { return _InternalRowSize
; }
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();
370 * Setup debug delta file
372 bool setupDebugDeltaFile(const std::string
& filename
, CDBDeltaFile
& delta
) const;
377 uint8
* getDeltaRow(uint32
& row
, CDBDeltaFile
& delta
) const;
385 virtual std::string
getLoggerIdentifier() const { return "buffer"; }
398 /// Internal Row Size
399 uint32 _InternalRowSize
;
402 std::string _RefRootPath
;
405 std::string _RefPath
;
407 /// Rows per ref file
410 /// Maximum ref file size
411 static uint32 _MaxRefFileSize
;
416 /// Map of purgeable rows
417 typedef std::set
<RY_PDS::TRowIndex
> TReleaseSet
;
420 TReleaseSet _ReleaseSet
;
422 /// List of dirty rows
423 typedef std::vector
<CAccessor
> TDirtyList
;
426 TDirtyList _DirtyList
;
428 /// List of ref files -- a vector or pointer, to avoid realloc issues
429 typedef std::vector
<CDBReferenceFile
*> TRefFileMap
;
432 TRefFileMap _RefFileMap
;
434 /// Index and Allocation Map
435 CRowMapper _RowMapper
;
441 uint32 _CurrentDeltaId
;
444 /// Current reference stamp
445 uint32 _ReferenceStamp
;
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
);
487 void clear() { _Flags
= 0; _Acquire
= 0; _DirtStamp
= 0; }
490 uint8
getFlags() const { return _Flags
; }
493 bool dirty() const { return checkFlags(Dirty
); }
497 bool allocated() const { return checkFlags(Allocated
); }
501 void setFlags(uint8 flags
) { _Flags
|= flags
; }
504 void clearFlags(uint8 flags
) { _Flags
&= (~flags
); }
507 bool checkFlags(uint8 testflags
) const { return (_Flags
& testflags
) != 0; }
514 /// Clear DirtStamp (set initial dirt stamp as 'no dirt stamp' value)
515 void clearDirtStamp() { _DirtStamp
= 0; clearFlags(Dirty
); }
518 uint32
getDirtStamp() const { return _DirtStamp
; }
522 /// Acquire, return true the first time it is acquired
526 return _Acquire
== 1;
529 /// Release, return true if row can be release effectively
535 return !isAcquired();
538 /// Clear Acquire count
539 void clearAcquireCount() { _Acquire
= 0; }
542 bool isAcquired() const { return _Acquire
> 0; }
552 /// Row Dirty Timestamp
557 /// Header of a mapped row
558 class CMappedHeader
: public CHeader
563 void clear() { CHeader::clear(); _Key
= 0; }
566 void setKey(uint64 key
) { _Key
= key
; }
569 uint64
getKey() const { return _Key
; }
572 bool mapped() const { return _Key
!= 0; }
578 * The key of the row in table map, 0 means this row is not mapped
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
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 */