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 RY_PD_MESSAGES_H
18 #define RY_PD_MESSAGES_H
23 #include <nel/misc/types_nl.h>
24 #include <nel/misc/common.h>
25 #include <nel/misc/time_nl.h>
26 #include <nel/misc/stream.h>
27 #include <nel/misc/entity_id.h>
28 #include <nel/misc/sheet_id.h>
29 #include <nel/misc/variable.h>
30 #include <nel/misc/hierarchical_timer.h>
36 #include "db_description_parser.h"
37 #include "timestamp.h"
42 #define MAX_MESSAGE_REMAP 32767
43 #define MESSAGE_REMAP_MASK 0x7fff
44 #define MESSAGE_REMAP_ENTITYID_PRESENT 0x8000
45 #define MESSAGE_SETPARENT_ENTITYID_PRESENT 0x8000
49 * Object Circular Mapper
50 * Allows to map an object value through little sized uint (uint8 or uint16), allowing to reallocate
51 * mapping when all values are used.
52 * This is used to map long values (CEntityIds for instance) that are expected to appear frequently
53 * in a stream with short keys, without making sure all values fit in mapping table.
54 * For instance, if using uint8 as mapping key, when all 256 values are used, previously used key
55 * 0 is remapped to the new object value that appears in stream and so on (reallocations are done
56 * circularly through key values). Mask value is for test purposes only, not to be changed!
58 template<typename Key
, typename Object
, uint32 Mask
= 0xffffffff, typename TBackMap
= std::map
<Object
, Key
> >
67 // prepare mapping table
68 _FrontMap
.resize(getMappingSize()+1);
72 * Serialise object from stream
74 void serial(NLMISC::IStream
& s
, Object
& o
)
77 serial(s
, o
, fakeFlags
);
81 * Serialise object from stream, with flags added to msbits
82 * WARNING: flags should NEVER interfere with Mask!
83 * WARNING: when stream is reading, lower bits of flags are unspecified!
85 void serial(NLMISC::IStream
& s
, Object
& o
, Key
& flags
)
92 // remove flags from read key
95 // if key is next value to be mapped
98 // serial in object value to map
99 _Next
= ((_Next
+1)&Mask
);
106 // already seen key? just copy object value
112 // search for object value in map
113 typename
TBackMap::iterator it
= _BackMap
.find(o
);
114 // not yet found or mapping key is just next key to alloc
115 if (it
== _BackMap
.end() || (*it
).second
== _Next
)
117 // if mapping key is next, we have to force reallocation
118 // as serial in code can't know if value is new or not...
120 _Next
= ((_Next
+1)&Mask
);
121 // if new key as already circle'd down, unmap previous association
125 typename
TBackMap::iterator it
= _BackMap
.find(_FrontMap
[k
]);
126 nlassert(it
!= _BackMap
.end() && (*it
).second
== k
);
129 _BackMap
.erase(_FrontMap
[k
]);
134 // else just increase max seen key...
141 k
|= (flags
& (~Mask
));
147 // mapping found and correct, only serial key out
148 Key k
= ((*it
).second
| (flags
& (~Mask
)));
156 /// Back Mapping, from object values to keys
159 /// Front Mapping, from keys to object values
160 typedef typename
std::vector
<Object
> TFrontMap
;
168 uint
getMappingSize() const
170 return (((uint
)1)<<(sizeof(Key
)*8))-1;
174 typedef CObjCircMapper
<uint8
, NLMISC::CEntityId
> TEntityIdCircMapper
;
177 class CMsgObjectIndex
181 CMsgObjectIndex() : Raw(0) {}
182 CMsgObjectIndex(uint8 table
, uint32 row
)
188 void set(uint8 table
, uint32 row
)
205 void serial(NLMISC::IStream
& f
) { f
.serial(Table
, Row
); }
207 bool operator < (const CMsgObjectIndex
& a
) const
213 typedef CObjCircMapper
<uint8
, CMsgObjectIndex
, 0x7f> TObjectIndexCircMapper
;
216 * Database update message
222 CDbMessage() : Selected(false), ContextDepth(0), _ObjectIdPresent(false) { }
225 /// Type of message, 4bits -> 16 message types available
234 EndRemapMessages
= 4,
250 /// \name setup message methods
255 void updateValue(TColumnIndex column
, const T
& value
)
257 setHeader(UpdateValue
);
261 // update 20101119 by packpro
262 if (sizeof(value
) == 1)
265 memcpy(&(_Value0
[0]), &value
, sizeof(value
));
267 else if (sizeof(value
) == 2)
270 memcpy(&(_Value1
[0]), &value
, sizeof(value
));
272 else if (sizeof(value
) == 4)
275 memcpy(&(_Value2
[0]), &value
, sizeof(value
));
277 else if (sizeof(value
) == 8)
280 memcpy(&(_Value3
[0]), &value
, sizeof(value
));
283 //if (sizeof(value) == 1) { sz = 0; _Value0[0] = *(uint8*)(&value); }
284 //else if (sizeof(value) == 2) { sz = 1; _Value1[0] = *(uint16*)(&value); }
285 //else if (sizeof(value) == 4) { sz = 2; _Value2[0] = *(uint32*)(&value); }
286 //else if (sizeof(value) == 8) { sz = 3; _Value3[0] = *(uint64*)(&value); }
287 _ColumnAndSize
= (uint16
)(column
| (sz
<< 14));
292 void updateValue(TColumnIndex column
, const T
& value
, const NLMISC::CEntityId
& objectId
)
294 setHeader(UpdateValue
);
298 // update 20101119 by packpro
299 if (sizeof(value
) == 1)
302 memcpy(&(_Value0
[0]), &value
, sizeof(value
));
304 else if (sizeof(value
) == 2)
307 memcpy(&(_Value1
[0]), &value
, sizeof(value
));
309 else if (sizeof(value
) == 4)
312 memcpy(&(_Value2
[0]), &value
, sizeof(value
));
314 else if (sizeof(value
) == 8)
317 memcpy(&(_Value3
[0]), &value
, sizeof(value
));
319 //if (sizeof(value) == 1) { sz = 0; _Value0[0] = *(uint8*)(&value); }
320 //else if (sizeof(value) == 2) { sz = 1; _Value1[0] = *(uint16*)(&value); }
321 //else if (sizeof(value) == 4) { sz = 2; _Value2[0] = *(uint32*)(&value); }
322 //else if (sizeof(value) == 8) { sz = 3; _Value3[0] = *(uint64*)(&value); }
324 _ColumnAndSize
= (uint16
)(column
| (sz
<< 14));
326 //_MapTableRow |= MESSAGE_REMAP_ENTITYID_PRESENT;
327 _ObjectIdPresent
= true;
328 _ObjectId
= objectId
;
332 void setParent(TColumnIndex column
, const CObjectIndex
& parent
)
334 setHeader(SetParent
);
336 _ColumnAndSize
= (uint16
)column
;
337 _Value3
[0] = *(uint64
*)(&parent
);
340 /// set parent, only child object has an entityId as key
341 void setParent(TColumnIndex column
, const CObjectIndex
& parent
, const NLMISC::CEntityId
& objectId
)
343 setHeader(SetParent
);
345 _ColumnAndSize
= (uint16
)column
;
346 _Value3
[0] = *(uint64
*)(&parent
);
348 //_MapTableRow |= MESSAGE_REMAP_ENTITYID_PRESENT;
349 _ObjectIdPresent
= true;
350 _ObjectId
= objectId
;
353 /// set parent, only parent object has an entityId as key
354 void setParent(TColumnIndex column
, const CObjectIndex
& parent
, const NLMISC::CEntityId
& newParentId
, const NLMISC::CEntityId
& previousParentId
)
356 setHeader(SetParent
);
358 _ColumnAndSize
= (uint16
)column
;
359 _Value3
[0] = *(uint64
*)(&parent
);
361 _ColumnAndSize
|= MESSAGE_SETPARENT_ENTITYID_PRESENT
;
362 _NewParentId
= newParentId
;
363 _PreviousParentId
= previousParentId
;
366 /// set parent, both child and parent objects have an entityId as key
367 void setParent(TColumnIndex column
, const CObjectIndex
& parent
, const NLMISC::CEntityId
& objectId
, const NLMISC::CEntityId
& newParentId
, const NLMISC::CEntityId
& previousParentId
)
369 setHeader(SetParent
);
371 _ColumnAndSize
= (uint16
)column
;
372 _Value3
[0] = *(uint64
*)(&parent
);
374 //_MapTableRow |= MESSAGE_REMAP_ENTITYID_PRESENT;
375 _ObjectIdPresent
= true;
376 _ObjectId
= objectId
;
378 _ColumnAndSize
|= MESSAGE_SETPARENT_ENTITYID_PRESENT
;
379 _NewParentId
= newParentId
;
380 _PreviousParentId
= previousParentId
;
383 /// Is Object EntityId present
384 bool objectEntityIdPresent() const
386 //return (_MapTableRow & MESSAGE_REMAP_ENTITYID_PRESENT) != 0;
387 return _ObjectIdPresent
;
390 /// Are Parents EntityId present
391 bool parentsEntityIdPresent() const
393 return (_ColumnAndSize
& MESSAGE_SETPARENT_ENTITYID_PRESENT
) != 0;
397 void allocRow(uint64 key
)
407 setHeader(DeallocRow
);
411 void allocRow(uint64 key
, const NLMISC::CEntityId
& objectId
)
415 //_MapTableRow |= MESSAGE_REMAP_ENTITYID_PRESENT;
416 _ObjectIdPresent
= true;
417 _ObjectId
= objectId
;
423 void deallocRow(const NLMISC::CEntityId
& objectId
)
425 setHeader(DeallocRow
);
427 //_MapTableRow |= MESSAGE_REMAP_ENTITYID_PRESENT;
428 _ObjectIdPresent
= true;
429 _ObjectId
= objectId
;
433 void loadRow(TTableIndex table
, uint64 key
)
437 _ObjectIndex
.set((uint8
)table
, 0);
438 //_Table = (uint8)table;
445 void addString(uint64 skey
, const ucstring
& str
)
447 setHeader(AddString
);
454 void unmapString(uint64 skey
)
456 setHeader(UnmapString
);
461 /// Release a row in memory
464 setHeader(ReleaseRow
);
472 void log(uint logId
, uint bufferByteSize
)
476 _LogBuffer
.resize(bufferByteSize
);
479 /// Push Log Parameter
481 void pushParameter(uint byteOffset
, const T
& parameter
)
483 nlassertex(byteOffset
+sizeof(T
) <= _LogBuffer
.size(), ("Internal error! failed to push parameter at %d (size=%d), beyond buffer limit (%d)", byteOffset
, sizeof(T
), _LogBuffer
.size()));
484 memcpy(&(_LogBuffer
[byteOffset
]), ¶meter
, sizeof(parameter
));
487 /// Push Log Parameter (string)
488 void pushParameter(uint byteOffset
, const std::string
& parameter
)
490 nlassertex(byteOffset
+sizeof(uint16
) <= _LogBuffer
.size(), ("Internal error! failed to push parameter at %d (size=%d), beyond buffer limit (%d)", byteOffset
, sizeof(uint16
), _LogBuffer
.size()));
491 // get current string index
492 uint16 bo
= (uint16
)_ExtLogBuffer
.size();
493 _ExtLogBuffer
.resize(bo
+parameter
.size()+1);
494 memcpy(&(_ExtLogBuffer
[bo
]), parameter
.c_str(), parameter
.size()+1);
495 memcpy(&(_LogBuffer
[byteOffset
]), &bo
, sizeof(uint16
));
501 setHeader(PushContext
);
507 setHeader(PopContext
);
513 /// Log Chat sentence
514 void logChat(const ucstring
& sentence
, const NLMISC::CEntityId
& sender
, const std::vector
<NLMISC::CEntityId
>& receivers
)
518 *(NLMISC::CEntityId
*)(&(_Value3
[0])) = sender
;
520 uint bufferSize
= (uint
)receivers
.size()*sizeof(NLMISC::CEntityId
);
523 _LogBuffer
.resize(bufferSize
);
524 NLMISC::CEntityId
* srcBuffer
= (NLMISC::CEntityId
*)(&(receivers
[0]));
525 NLMISC::CEntityId
* dstBuffer
= (NLMISC::CEntityId
*)(&(_LogBuffer
[0]));
526 memcpy(dstBuffer
, srcBuffer
, bufferSize
);
539 THeaderType
getType() const { return _Type
; }
541 /// Set Type of message
542 void setType(THeaderType type
) { _Type
= type
; }
546 /// \name common part methods
549 TTableIndex
getTable() const { return (TTableIndex
)_ObjectIndex
.Table
; }
550 TRowIndex
getRow() const { return (TRowIndex
)_ObjectIndex
.Row
; }
551 uint32
getStringId() const { return _StringId
; }
557 /// \name Update database value specific methods
560 TColumnIndex
getColumn() const { return (TColumnIndex
)(_ColumnAndSize
&0x3fff); }
561 const void* getData() const { return &_Value0
[0]; }
562 uint
getDatasize() const { return 1 << (_ColumnAndSize
>>14); }
563 uint8
getValue8bits() const { return _Value0
[0]; }
564 uint16
getValue16bits() const { return _Value1
[0]; }
565 uint32
getValue32bits() const { return _Value2
[0]; }
566 uint64
getValue64bits() const { return _Value3
[0]; }
567 CObjectIndex
getObjectIndex() const { return *(CObjectIndex
*)(&(_Value3
[0])); }
568 const ucstring
& getString() const { return _String
; }
570 bool asBool() const { return _Value0
[0] != 0; }
571 char asChar() const { return (char)_Value0
[0]; }
572 ucchar
asUCChar() const { return (ucchar
)_Value1
[0]; }
573 uint8
asUint8() const { return (uint8
)_Value0
[0]; }
574 uint16
asUint16() const { return (uint16
)_Value1
[0]; }
575 uint32
asUint32() const { return (uint32
)_Value2
[0]; }
576 uint64
asUint64() const { return (uint64
)_Value3
[0]; }
577 sint8
asSint8() const { return (sint8
)_Value0
[0]; }
578 sint16
asSint16() const { return (sint16
)_Value1
[0]; }
579 sint32
asSint32() const { return (sint32
)_Value2
[0]; }
580 sint64
asSint64() const { return (sint64
)_Value3
[0]; }
581 float asFloat() const { return (float)_ValueFloat
[0]; }
582 double asDouble() const { return (double)_ValueDouble
[0]; }
583 const NLMISC::CSheetId
& asSheetId() const { return *(NLMISC::CSheetId
*)(&_Value2
[0]); }
584 const NLMISC::CEntityId
& asEntityId() const { return *(NLMISC::CEntityId
*)(&_Value3
[0]); }
586 const NLMISC::CEntityId
& getObjectId() const { return _ObjectId
; }
587 const NLMISC::CEntityId
& getNewParentId() const { return _NewParentId
; }
588 const NLMISC::CEntityId
& getPreviousParentId() const { return _PreviousParentId
; }
590 uint16
getLogId() const { return _LogId
; }
591 const std::vector
<uint8
>& getLogBuffer() const { return _LogBuffer
; }
593 void setupTableAndRow(TTableIndex table
, TRowIndex row
)
595 _ObjectIndex
.set((uint8
)table
, (uint32
)row
);
600 /// \name Log analysis/display
603 /// Dump Message content to string as a human readable message
604 void getHRContent(const CDBDescriptionParser
& description
, std::string
& result
) const;
606 /// Does message contains CEntityId?
607 bool contains(const CDBDescriptionParser
& description
, const NLMISC::CEntityId
& id
);
609 /// Does message contains string?
610 bool contains(const CDBDescriptionParser
& description
, const std::string
& str
);
613 std::string
buildLogString(const CDBDescriptionParser
& description
) const;
615 /// Is Value modified
616 bool valueModified(uint table
, uint column
)
618 return ((getType() == UpdateValue
|| getType() == SetParent
) && getTable() == table
&& getColumn() == column
);
621 /// Is message selected
623 /// Message context depth
628 /// \name Serializing
632 void serial(NLMISC::IStream
&f
, TObjectIndexCircMapper
& indexMapper
, TEntityIdCircMapper
& eidMapper
);
634 /// Get Message Header Size
635 uint32
getMessageHeaderSize();
643 * Type is not serialised directly in message, but in containing folder
650 * Refers to the 'entity' used/updated by the message
661 uint16 _ColumnAndSize
;
663 CMsgObjectIndex _ObjectIndex
;
671 float _ValueFloat
[2];
672 double _ValueDouble
[1];
675 bool _ObjectIdPresent
;
676 NLMISC::CEntityId _ObjectId
;
677 NLMISC::CEntityId _NewParentId
;
678 NLMISC::CEntityId _PreviousParentId
;
681 std::vector
<uint8
> _LogBuffer
;
682 std::vector
<uint8
> _ExtLogBuffer
;
686 void setHeader(THeaderType type
) { _Type
= type
; }
695 * A Folder a Db Messages, all of the same kind.
696 * Based on the assumption that update value messages are the main kind of messages
697 * and that the follow in series...
698 * Thus, it should save one byte per message...
700 class CDbMessageFolder
713 CDbMessageFolder(uint8 type
)
723 uint8
getType() const { return _Type
; }
726 * Get Number of messages in folder
728 uint32
getNumMessages() const { return _NumMessages
; }
733 bool full() const { return _NumMessages
== MAX_MESSAGE_REMAP
; }
736 * Add a message to folder
738 void addMessage(const CDbMessage
& msg
)
740 nlassert(_NumMessages
< MAX_MESSAGE_REMAP
);
741 nlassert(msg
.getType() == _Type
);
748 void serial(NLMISC::IStream
& f
)
750 f
.serial(_Type
, _NumMessages
);
751 nlassert(_Type
< CDbMessage::End
);
756 /// Type of messages in folder
759 /// Number of messages in folder
771 * A Queue of messages
773 class CDbMessageQueue
795 * Get Next Message to be written
797 CDbMessage
& nextMessage()
799 _Messages
.resize(_Messages
.size()+1);
800 return _Messages
.back();
804 * Get Current Message to be written
806 CDbMessage
& currentMessage()
808 nlassert(!_Messages
.empty());
809 return _Messages
.back();
814 * Get Number of Messages in queue
816 uint32
getNumMessages() const
818 return (uint32
)_Messages
.size();
824 CDbMessage
& getMessage(uint32 message
)
826 nlassert(message
< _Messages
.size());
827 return _Messages
[message
];
831 * Serialise message queue
833 void serial(NLMISC::IStream
& f
)
835 H_AUTO(PDLIB_MsgQueue_serial
);
837 // build folders first if writing to stream
843 uint32 numFolders
= (uint32
)_Folders
.size();
844 uint32 numMessages
= (uint32
)_Messages
.size();
846 f
.serial(numFolders
);
847 f
.serial(numMessages
);
851 _Folders
.resize(numFolders
);
852 _Messages
.resize(numMessages
);
855 //f.serialCont(_BackRemap);
857 TEntityIdCircMapper EIdMapper
;
858 TObjectIndexCircMapper IndexMapper
;
860 // for each folder, write message stored in it
862 for (i
=0; i
<_Folders
.size(); ++i
)
864 CDbMessageFolder
& folder
= _Folders
[i
];
868 for (j
=0; j
<folder
.getNumMessages(); ++j
)
870 nlassert(message
< numMessages
);
872 CDbMessage
& msg
= _Messages
[message
++];
873 msg
.setType((CDbMessage::THeaderType
)folder
.getType());
875 msg
.serial(f
, IndexMapper
, EIdMapper
);
882 uint currentDepth
= 0;
883 for (i
=0; i
<_Messages
.size(); ++i
)
885 CDbMessage
& msg
= _Messages
[i
];
887 if (msg
.getType() == CDbMessage::PopContext
)
889 msg
.ContextDepth
= currentDepth
;
890 if (msg
.getType() == CDbMessage::PushContext
)
900 std::vector
<CDbMessage
> _Messages
;
903 std::vector
<CDbMessageFolder
> _Folders
;
907 * Build message folders
914 for (i
=0; i
<_Messages
.size(); ++i
)
916 if (_Folders
.empty() || _Folders
.back().full() || _Messages
[i
].getType() != _Folders
.back().getType())
917 _Folders
.push_back(CDbMessageFolder(_Messages
[i
].getType()));
919 _Folders
.back().addMessage(_Messages
[i
]);
931 * Handle multiple queues, so one update may be splitted into multiple messages
933 class CDbMessageSplitQueue
940 CDbMessageSplitQueue()
953 * Get Next Message to be written, no mapping to be done
955 CDbMessage
& nextMessage()
960 return _Queues
.back().nextMessage();
964 * Get Next Remappable Message to be written
966 CDbMessage
& nextMessage(uint8 table
, uint32 row
)
971 // here, queue allows to map message
972 CDbMessage
& msg
= _Queues
.back().nextMessage();
974 msg
.setupTableAndRow(table
, row
);
981 * Get Current Message
983 CDbMessage
& currentMessage()
985 return _Queues
.back().currentMessage();
989 * Force MsgQueue to fill next queue
991 void forceNextQueue()
993 if (_Queues
.empty() || _Queues
.back().getNumMessages() > 0)
995 _Queues
.push_back(CDbMessageQueue());
1004 return _Queues
.empty();
1008 * Number of message in queue
1010 uint32
getNumMessagesEnqueued() const
1012 std::list
<CDbMessageQueue
>::const_iterator it
;
1013 uint32 totalMessages
= 0;
1014 for (it
=_Queues
.begin(); it
!=_Queues
.end(); ++it
)
1015 totalMessages
+= (*it
).getNumMessages();
1017 return totalMessages
;
1024 std::list
<CDbMessageQueue
>::iterator
begin() { return _Queues
.begin(); }
1029 std::list
<CDbMessageQueue
>::iterator
end() { return _Queues
.end(); }
1034 uint
size() const { return (uint
)_Queues
.size(); }
1039 CDbMessageQueue
& get(uint i
)
1041 std::list
<CDbMessageQueue
>::iterator it
= _Queues
.begin();
1051 std::list
<CDbMessageQueue
> _Queues
;
1063 CUpdateLog() : UpdateId(0xffffffff), _OwnUpdates(false), _Updates(NULL
) { }
1067 /// UpdateId sent by client for this update
1070 /// Start date for this update
1071 CTimestamp StartStamp
;
1073 /// Start date for this update
1074 CTimestamp EndStamp
;
1077 void serial(NLMISC::IStream
& f
);
1079 /// Display UpdateLog content (using a database description)
1080 void display(const CDBDescriptionParser
& description
, NLMISC::CLog
& log
, bool onlySelected
= false);
1086 * Check log timestamp boundaries
1088 bool checkTimestampBoundaries(const CTimestamp
& begin
, const CTimestamp
& end
);
1096 * Select contexts and messages containing a given entityId
1097 * return true if there were at least one message selected
1099 bool selectMessages(const CDBDescriptionParser
& description
, const NLMISC::CEntityId
& id
);
1102 * Select contexts and messages containing a given string
1103 * return true if there were at least one message selected
1105 bool selectMessages(const CDBDescriptionParser
& description
, const std::string
& str
);
1108 * Select contexts and messages containing modification of a value for a given entityId
1109 * return true if there were at least one message selected
1111 bool selectMessages(const CDBDescriptionParser
& description
, const NLMISC::CEntityId
& id
, const std::string
& valuePath
);
1114 * Select contexts and messages containing a list of entityIds (limited at most to 32 entityIds)
1115 * return true if there were at least one message selected
1117 bool selectMessages(const CDBDescriptionParser
& description
, const std::vector
<NLMISC::CEntityId
>& ids
);
1122 /// process log, return true if some messages were selected
1123 virtual bool processLog(CUpdateLog
& log
, const CDBDescriptionParser
& description
) = 0;
1127 * Apply process on log files
1129 static void processLogs(const std::string
& path
,
1130 const CTimestamp
& begin
,
1131 const CTimestamp
& end
,
1133 CLogProcessor
* processor
,
1134 float* progress
= NULL
);
1137 * Display log for a given entity id, between 2 dates
1139 static void displayLogs(const CDBDescriptionParser
& description
,
1140 const NLMISC::CEntityId
& id
,
1141 const CTimestamp
& begin
,
1142 const CTimestamp
& end
,
1143 const std::string
& path
,
1145 float* progress
= NULL
);
1148 * Display log between 2 dates
1150 static void displayLogs(const std::string
& path
,
1151 const CTimestamp
& begin
,
1152 const CTimestamp
& end
,
1154 float* progress
= NULL
);
1157 * Display log for a given entity id, between 2 dates
1159 static void displayLogs(const std::string
& path
,
1160 const NLMISC::CEntityId
& id
,
1161 const CTimestamp
& begin
,
1162 const CTimestamp
& end
,
1164 float* progress
= NULL
);
1167 * Display log for a given entity id and a specified value to be modified, between 2 dates
1169 static void displayLogs(const std::string
& path
,
1170 const NLMISC::CEntityId
& id
,
1171 const std::string
& valuePath
,
1172 const CTimestamp
& begin
,
1173 const CTimestamp
& end
,
1175 float* progress
= NULL
);
1178 * Display log for a list of given entity id, between 2 dates
1180 static void displayLogs(const std::string
& path
,
1181 const std::vector
<NLMISC::CEntityId
>& ids
,
1182 const CTimestamp
& begin
,
1183 const CTimestamp
& end
,
1185 float* progress
= NULL
);
1188 * Display log for a list of given entity id, between 2 dates
1190 static void displayLogs(const std::string
& path
,
1191 const std::string
& str
,
1192 const CTimestamp
& begin
,
1193 const CTimestamp
& end
,
1195 float* progress
= NULL
);
1198 * Elect matching description
1200 static std::string
electDescription(const std::string
& logFile
);
1208 void setUpdates(CDbMessageQueue
* updates
);
1213 void createUpdates();
1218 CDbMessageQueue
* getUpdates() { return _Updates
; }
1224 /// Updates contained in message
1225 CDbMessageQueue
* _Updates
;
1227 /// Release Updates (and delete if owned)
1228 void releaseUpdates()
1230 if (_OwnUpdates
&& _Updates
!= NULL
)
1234 _OwnUpdates
= false;
1243 // CDbMessage inline methods
1246 inline void CDbMessage::serial(NLMISC::IStream
&f
, TObjectIndexCircMapper
& indexMapper
, TEntityIdCircMapper
& eidMapper
)
1252 uint8 flags
= (objectEntityIdPresent() ? 0x80 : 0);
1253 indexMapper
.serial(f
, _ObjectIndex
, flags
);
1254 _ObjectIdPresent
= ((flags
& 0x80) != 0);
1256 f
.serial(_ColumnAndSize
);
1258 switch (_ColumnAndSize
& 0xc000)
1260 case 0x0000: f
.serial(_Value0
[0]); break;
1261 case 0x4000: f
.serial(_Value1
[0]); break;
1262 case 0x8000: f
.serial(_Value2
[0]); break;
1263 case 0xc000: f
.serial(_Value3
[0]); break;
1266 // serial owner CEntityId if present
1267 if (objectEntityIdPresent())
1268 eidMapper
.serial(f
, _ObjectId
);
1274 uint8 flags
= (objectEntityIdPresent() ? 0x80 : 0);
1275 indexMapper
.serial(f
, _ObjectIndex
, flags
);
1276 _ObjectIdPresent
= ((flags
& 0x80) != 0);
1277 f
.serial(_ColumnAndSize
);
1278 f
.serial(_Value3
[0]);
1280 // serial object CEntityId if present
1281 if (objectEntityIdPresent())
1282 eidMapper
.serial(f
, _ObjectId
);
1284 // serial parents CEntityId if present
1285 if ((_ColumnAndSize
& MESSAGE_SETPARENT_ENTITYID_PRESENT
) != 0)
1287 eidMapper
.serial(f
, _NewParentId
);
1288 eidMapper
.serial(f
, _PreviousParentId
);
1295 uint8 flags
= (objectEntityIdPresent() ? 0x80 : 0);
1296 indexMapper
.serial(f
, _ObjectIndex
, flags
);
1297 _ObjectIdPresent
= ((flags
& 0x80) != 0);
1298 f
.serial(_Value3
[0]);
1300 // serial owner CEntityId if present
1301 if (objectEntityIdPresent())
1302 eidMapper
.serial(f
, _ObjectId
);
1308 uint8 flags
= (objectEntityIdPresent() ? 0x80 : 0);
1309 indexMapper
.serial(f
, _ObjectIndex
, flags
);
1310 _ObjectIdPresent
= ((flags
& 0x80) != 0);
1311 // serial owner CEntityId if present
1312 if (objectEntityIdPresent())
1313 eidMapper
.serial(f
, _ObjectId
);
1318 f
.serial(_ObjectIndex
.Table
);
1319 f
.serial(_Value3
[0]);
1323 f
.serial(_Value3
[0]);
1328 f
.serial(_Value3
[0]);
1332 indexMapper
.serial(f
, _ObjectIndex
);
1344 _LogBuffer
.resize(sz
);
1346 f
.serialBuffer(&(_LogBuffer
[0]), sz
);
1349 _ExtLogBuffer
.resize(sz
);
1351 f
.serialBuffer(&(_ExtLogBuffer
[0]), sz
);
1356 nlassert(_LogBuffer
.size() <= 255);
1357 sz
= (uint8
)_LogBuffer
.size();
1360 f
.serialBuffer(&(_LogBuffer
[0]), sz
);
1362 nlassert(_ExtLogBuffer
.size() <= 255);
1363 sz
= (uint8
)_ExtLogBuffer
.size();
1366 f
.serialBuffer(&(_ExtLogBuffer
[0]), sz
);
1378 // serial chat sentence
1381 f
.serial(_Value3
[0]);
1382 // serial receivers list (whole buffer as uint8*)
1383 f
.serialCont(_LogBuffer
);
1387 nlerror("CDbMessage::serial(): unable to serial message type '%d'", _Type
);
1393 * Get Message Header Size
1395 inline uint32
CDbMessage::getMessageHeaderSize()
1403 size
+= sizeof(_ObjectIndex
.Table
)+sizeof(_ObjectIndex
.Row
);
1404 size
+= sizeof(_ColumnAndSize
);
1408 size
+= sizeof(_ObjectIndex
.Table
)+sizeof(_ObjectIndex
.Row
);
1412 size
+= sizeof(_ObjectIndex
.Table
)+sizeof(_ObjectIndex
.Row
);
1416 size
+= sizeof(_ObjectIndex
.Table
);
1417 size
+= sizeof(_Value3
[0]);
1421 size
+= sizeof(_ObjectIndex
.Table
)+sizeof(_ObjectIndex
.Row
);
1425 size
+= sizeof(_LogId
);
1439 inline void CUpdateLog::serial(NLMISC::IStream
& f
)
1441 f
.serialCheck(NELID("ULOG"));
1443 uint version
= f
.serialVersion(1);
1449 f
.serial(StartStamp
);
1456 _Updates
= new RY_PDS::CDbMessageQueue();
1460 f
.serial(*_Updates
);
1466 #endif //RY_PD_MESSAGES_H