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/>.
19 #ifndef NL_IMPULSE_ENCODER_H
20 #define NL_IMPULSE_ENCODER_H
25 #include "nel/misc/types_nl.h"
26 #include "nel/misc/bit_mem_stream.h"
27 #include "nel/misc/debug.h"
28 #include "nel/misc/time_nl.h"
30 //#include "../common/action.h"
31 #include "game_share/action_factory.h"
33 extern bool verboseImpulsions
;
36 #define LOG_IMPULSION_INFO ;
37 #define LOG_IMPULSION_DEBUG ;
39 #define LOG_IMPULSION_INFO if (!verboseImpulsions) {} else nlinfo
40 #define LOG_IMPULSION_DEBUG if (!verboseImpulsions) {} else nldebug
51 typedef void (*TImpulseReceivedCallback
)(CClientHost
*, CLFECOMMON::CAction
*);
54 // CActionFactory header + CActionGeneric header + 1/8 (the follow bit)
55 const sint IMPULSE_ACTION_HEADER_BITSIZE
= 4*8 + 4*8 + 1;
56 extern uint MaxImpulseBitSizes
[3];
59 class CClientImpulseStat
65 const uint IMPULSE_STAT_MEAN_TIME
= 30; // seconds
66 const double IMPULSE_STAT_SMOOTH
= 2.0;
74 CTimedSize(NLMISC::TTime t
, uint32 s
) : Time(t
), Size(s
) {}
79 void serial(NLMISC::IStream
& s
);
81 typedef std::deque
<CTimedSize
> TSendRateQueue
;
86 * \author Benjamin Legros
87 * \author Nevrax France
93 typedef std::deque
<CLFECOMMON::CActionImpulsion
*> TActionQueue
;
100 TSendRateQueue SendRateQueue
;
107 uint TotalBitsInImpulseQueue
;
110 uint32 Level
, Channel
;
113 CImpulseQueue() : TotalBitsInImpulseQueue(0), FirstSent(0), SentData(0), FlushTimes(0) {}
118 void setup(uint maxBitSize
, uint level
, uint channel
) { MaxBitSize
= maxBitSize
; Level
= level
; Channel
= channel
; }
119 void add(CLFECOMMON::CActionImpulsion
*action
) { Queue
.push_back(action
); }
121 void flush(uint packet
, CClientHost
*client
, std::vector
<uint8
> &impcounts
);
123 uint32
send(TActionQueue
& sourceQueue
, uint32 packet
, NLMISC::CBitMemStream
&outbox
, uint32
&sentActions
);
125 void reinit() { FirstSent
= 0; }
131 for (i
=0; i
<Queue
.size(); ++i
)
133 CLFECOMMON::CActionFactory::getInstance()->remove(Queue
[i
]);
136 TotalBitsInImpulseQueue
= 0;
140 void removeReferences(CLFECOMMON::TCLEntityId id
)
142 TActionQueue::iterator it
;
143 for (it
=Queue
.begin(); it
<Queue
.end(); )
144 if ((*it
)->Slot
== id
)
146 CLFECOMMON::CActionFactory::getInstance()->remove(*it
);
147 it
= Queue
.erase(it
);
159 /// Count next effective sent
160 void countEffectiveSent(uint bitSent
)
162 NLMISC::TTime ctime
= NLMISC::CTime::getLocalTime();
163 flushSendRateQueue(ctime
);
168 //nlinfo("sent effectively %d bits in level %d, channel %d", bitSent, Level, Channel);
170 SendRateQueue
.push_back(CTimedSize(ctime
, bitSent
));
174 /// Flush SendRateQueue
175 void flushSendRateQueue(NLMISC::TTime ctime
)
177 while (!SendRateQueue
.empty() && ctime
> SendRateQueue
.front().Time
+(IMPULSE_STAT_MEAN_TIME
*1000))
178 SendRateQueue
.pop_front();
181 /// Get Current Effective Send Rate (based on flush rate) (in bits per second)
182 uint
effectiveSendRate();
184 /// Total send data in this queue (based on flush rate) (in bits per second)
185 uint64
totalSentData();
187 /// Dump queue to xml stream
188 void dump(NLMISC::IStream
& s
);
197 * The impulse encoder, used to post important actions the client must receive.
198 * \author Benjamin Legros
199 * \author Nevrax France
202 class CImpulseEncoder
207 * Warning: the numbers of queues by channels is hardcoded in the acknowledgement system
210 CImpulseQueue _Level0
[1];
211 CImpulseQueue _Level1
[2];
212 CImpulseQueue _Level2
[4];
214 CClientHost
*_ClientHost
;
216 //uint _MaxBitSizes[4];
218 std::vector
<uint8
> _QueuedImpulses
;
220 typedef std::deque
<CLFECOMMON::CActionImpulsion
*> TActionQueue
;
222 TActionQueue _MainQueues
[3];
224 uint32 _TotalPackets
;
227 friend class CImpulseQueue
;
229 static TImpulseReceivedCallback _Callbacks
[256];
231 TSendRateQueue _AddRateQueues
[3];
241 /// Return the number of bits that the specified level can manage (biggest action it can manage) (no bound check)
242 static uint
maxBitSize( uint level
) { return MaxImpulseBitSizes
[level
]; }
244 /// Return the number of bits that can be sent at most using all levels
245 static uint
maxBitSizeTotal() { return MaxImpulseBitSizes
[0]+MaxImpulseBitSizes
[1]+MaxImpulseBitSizes
[2] - - (IMPULSE_ACTION_HEADER_BITSIZE
*3/8); }
248 void setClientHost(CClientHost
*clientHost
) { _ClientHost
= clientHost
; }
250 /// Adds an action at a given level of priority.
251 void add(CLFECOMMON::CActionImpulsion
*action
, uint level
);
253 /// Packs/sends impulse on the given outbox, using the previously added actions
254 uint32
send(uint32 packet
, NLMISC::CBitMemStream
&outbox
, uint32
&sentActions
);
256 /// Acknowledges a message and flushes involved queues (only positive acks).
257 void ack(uint32 packet
);
259 /// Reinits the whole queues
262 /// Unmarks all queues (act as if the awaiting actions were cleared up and readded at once)
265 /// Gets the total number of messages still to be sent
266 uint
queueSize() const;
268 /// Gets the number of messages still to be sent at a given level
269 uint
queueSize(uint level
) const;
271 /// Sets a callback for a specific type of action (-1 for all types of action)
272 static void setReceivedCallback(TImpulseReceivedCallback cb
, sint actionCode
= -1);
274 /// Gets the maximum bit size that can be sent through a channel (specific for a given level)
275 //uint getMaxBitSize(uint level) const { return _MaxBitSizes[level]; }
277 /// Returns true if the encoder has actions referencing a given entity (by its client entity id)
278 bool hasEntityReferences(CLFECOMMON::TCLEntityId id
) const
280 return (_QueuedImpulses
[id
] != 0);
283 /// Removes all actions referencing a given entity (if there are some)
284 void removeEntityReferences(CLFECOMMON::TCLEntityId id
);
289 /// Get Enqueued actions size in bits for a specified level
290 uint
getEnqueuedSize(uint level
) const;
292 /// Dump stats to XML stream
293 void dump(NLMISC::IStream
& s
);
295 /// Count Added action
296 void countAddedAction(CLFECOMMON::CActionImpulsion
*action
, uint level
);
298 /// Effective Add Rate
299 uint
effectiveAddRate(uint level
);
301 /// Effective Send Rate (cumulated send of each channel)
302 uint
effectiveSendRate(uint level
);
305 float efficiencyRatio(uint level
);
307 /// Get least efficiency
308 float leastEfficiencyRatio();
310 /// Get biggest queue size
311 uint
biggestQueueSize();
317 #endif // NL_IMPULSE_ENCODER_H
319 /* End of impulse_encoder.h */