Fix a bug in Kademlia LAN mode detection which effectively disabled it
[amule.git] / src / Statistics.h
blob7f2f5a6515731a79d9f51d13b029e8a37487a339
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2008 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2008 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6 // Copyright (c) 2005-2008 Dévai Tamás ( gonosztopi@amule.org )
7 //
8 // Any parts of this program derived from the xMule, lMule or eMule project,
9 // or contributed by third-party developers are copyrighted by their
10 // respective authors.
12 // This program is free software; you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation; either version 2 of the License, or
15 // (at your option) any later version.
17 // This program is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 // GNU General Public License for more details.
21 //
22 // You should have received a copy of the GNU General Public License
23 // along with this program; if not, write to the Free Software
24 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #ifndef STATISTICS_H
28 #define STATISTICS_H
30 #include "StatTree.h" // Needed for CStatTreeItem* classes
31 #include "GetTickCount.h" // Needed for GetTickCount64()
33 #include <deque> // Needed for std::deque
35 enum StatsGraphType {
36 GRAPH_INVALID = 0,
37 GRAPH_DOWN,
38 GRAPH_UP,
39 GRAPH_CONN,
40 GRAPH_KAD
43 typedef struct UpdateInfo {
44 double timestamp;
45 float downloads[3];
46 float uploads[3];
47 float connections[3];
48 float kadnodes[3];
49 } GraphUpdateInfo;
51 typedef struct HistoryRecord {
52 double kBytesSent;
53 double kBytesReceived;
54 float kBpsUpCur;
55 float kBpsDownCur;
56 double sTimestamp;
57 uint16 cntDownloads;
58 uint16 cntUploads;
59 uint16 cntConnections;
60 uint16 kadNodesCur;
61 uint64 kadNodesTotal;
62 } HR;
65 #ifndef CLIENT_GUI
67 /**
68 * Counts precise rate/average on added bytes/values.
70 * @note This class is MT-safe.
72 class CPreciseRateCounter {
73 friend class CStatistics; // for playing dirty tricks to compute running average :P
74 public:
76 /**
77 * Constructor
79 * @param timespan Desired timespan for rate calculations.
80 * @param count_average Counts average instead of rate.
82 CPreciseRateCounter(uint32_t timespan, bool count_average = false)
83 : m_timespan(timespan), m_total(0), m_rate(0.0), m_max_rate(0.0), m_tmp_sum(0), m_count_average(count_average)
85 if (!count_average) {
86 uint64_t cur_time = GetTickCount64();
87 uint64_t target_time = cur_time - timespan;
88 while (cur_time > target_time) {
89 m_tick_history.push_front(cur_time);
90 m_byte_history.push_front(0);
91 cur_time -= 100; // default update period
93 m_tick_history.push_front(cur_time);
97 /**
98 * Calculate current rate.
100 * This function should be called reasonably often, to
101 * keep rates up-to-date, and prevent history growing
102 * to the skies.
104 void CalculateRate(uint64_t now);
107 * Get current rate.
109 * @return Current rate in bytes/second.
111 double GetRate() { wxMutexLocker lock(m_mutex); return m_rate; };
114 * Gets ever seen maximal rate.
116 * @return The maximal rate which occured.
118 double GetMaxRate() { wxMutexLocker lock(m_mutex); return m_max_rate; }
121 * Sets desired timespan for rate calculations.
123 * If new timespan is greater than the old was, then the change
124 * takes effect with time. The exact time needed for the change
125 * to take effect is new minus old value of the timespan.
127 * If the new timespan is lower than the old, the change takes
128 * effect immediately at the next call to CalculateRate().
130 void SetTimespan(uint32_t timespan) { wxMutexLocker lock(m_mutex); m_timespan = timespan; }
133 * Add bytes to be tracked for rate-counting.
135 void operator+=(uint32_t bytes) { wxMutexLocker lock(m_mutex); m_tmp_sum += bytes; }
137 protected:
139 std::deque<uint32> m_byte_history;
140 std::deque<uint64> m_tick_history;
141 uint32_t m_timespan;
142 uint32_t m_total;
143 double m_rate;
144 double m_max_rate;
145 uint32_t m_tmp_sum;
146 wxMutex m_mutex;
147 bool m_count_average;
151 class CECTag;
154 * Stat tree item for rates/averages.
156 class CStatTreeItemRateCounter : public CStatTreeItemBase, public CPreciseRateCounter {
157 public:
160 * @see CStatTreeItemBase::CStatTreeItemBase, CPreciseRateCounter::CPreciseRateCounter
162 * @param show_maxrate If true, shows max rate instead of current rate.
164 CStatTreeItemRateCounter(const wxString& label, bool show_maxrate, uint32_t timespan, bool count_average = false)
165 : CStatTreeItemBase(label, stNone), CPreciseRateCounter(timespan, count_average), m_show_maxrate(show_maxrate)
168 #ifndef AMULE_DAEMON
170 * @see CStatTreeItemBase::GetDisplayString()
172 virtual wxString GetDisplayString() const;
173 #endif
175 protected:
177 * Add values to EC tag being generated.
179 * @param tag The tag to which values should be added.
181 * @see CStatTreeItemBase::AddECValues
183 virtual void AddECValues(CECTag* tag) const;
185 //! Whether to show max rate instead of actual rate.
186 bool m_show_maxrate;
191 * Stat tree item for Peak Connections.
193 class CStatTreeItemPeakConnections : public CStatTreeItemBase {
194 public:
197 * @see CStatTreeItemBase::CStatTreeItemBase
199 CStatTreeItemPeakConnections(const wxString& label)
200 : CStatTreeItemBase(label)
203 #ifndef AMULE_DAEMON
205 * @see CStatTreeItemBase::GetDisplayString()
207 virtual wxString GetDisplayString() const;
208 #endif
210 protected:
212 * Add values to EC tag being generated.
214 * @param tag The tag to which values should be added.
216 * @see CStatTreeItemBase::AddECValues
218 virtual void AddECValues(CECTag* tag) const;
222 class CUpDownClient;
224 class CStatistics {
225 friend class CStatisticsDlg; // to access CStatistics::GetTreeRoot()
226 public:
227 CStatistics();
228 ~CStatistics();
230 /* Statistics graph functions */
232 void RecordHistory();
233 unsigned GetHistoryForWeb(unsigned cntPoints, double sStep, double *sStart, uint32 **graphData);
234 unsigned GetHistory(unsigned cntPoints, double sStep, double sFinal, const std::vector<float *> &ppf, StatsGraphType which_graph);
235 GraphUpdateInfo GetPointsForUpdate();
237 /* Statistics tree functions */
239 void UpdateStatsTree();
241 /* Access to the tree */
243 // uptime
244 static uint64 GetUptimeMillis() { return s_uptime->GetTimerValue(); }
245 static uint64 GetUptimeSeconds() { return s_uptime->GetTimerSeconds(); }
246 static uint64 GetStartTime() { return s_uptime->GetTimerStart(); }
248 // Upload
249 static uint64 GetSessionSentBytes() { return (*s_sessionUpload); }
250 static void AddUpOverheadFileRequest(uint32 size) { (*s_fileReqUpOverhead) += size; (*s_upOverheadRate) += size; }
251 static void AddUpOverheadSourceExchange(uint32 size){ (*s_sourceXchgUpOverhead) += size; (*s_upOverheadRate) += size; }
252 static void AddUpOverheadServer(uint32 size) { (*s_serverUpOverhead) += size; (*s_upOverheadRate) += size; }
253 static void AddUpOverheadKad(uint32 size) { (*s_kadUpOverhead) += size; (*s_upOverheadRate) += size; }
254 static void AddUpOverheadCrypt(uint32_t size) { (*s_cryptUpOverhead) += size; }
255 static void AddUpOverheadOther(uint32 size) { (*s_totalUpOverhead) += size; (*s_upOverheadRate) += size; }
256 static double GetUpOverheadRate() { return s_upOverheadRate->GetRate(); }
257 static void AddSuccessfulUpload() { ++(*s_totalSuccUploads); }
258 static void AddFailedUpload() { ++(*s_totalFailedUploads); }
259 static void AddUploadTime(uint32 time) { (*s_totalUploadTime) += time; }
260 static void AddUploadingClient() { ++(*s_activeUploads); }
261 static void RemoveUploadingClient() { --(*s_activeUploads); }
262 static uint32 GetActiveUploadsCount() { return (*s_activeUploads); }
263 static void AddWaitingClient() { ++(*s_waitingUploads); }
264 static void RemoveWaitingClient() { --(*s_waitingUploads); }
265 static uint32 GetWaitingUserCount() { return (*s_waitingUploads); }
266 static double GetUploadRate() { return s_uploadrate->GetRate(); }
268 // Download
269 static uint64 GetSessionReceivedBytes() { return (*s_sessionDownload); }
270 static void AddDownOverheadFileRequest(uint32 size) { (*s_fileReqDownOverhead) += size; (*s_downOverheadRate) += size; }
271 static void AddDownOverheadSourceExchange(uint32 size){ (*s_sourceXchgDownOverhead) += size; (*s_downOverheadRate) += size; }
272 static void AddDownOverheadServer(uint32 size) { (*s_serverDownOverhead) += size; (*s_downOverheadRate) += size; }
273 static void AddDownOverheadKad(uint32 size) { (*s_kadDownOverhead) += size; (*s_downOverheadRate) += size; }
274 static void AddDownOverheadCrypt(uint32_t size) { (*s_cryptDownOverhead) += size; }
275 static void AddDownOverheadOther(uint32 size) { (*s_totalDownOverhead) += size; (*s_downOverheadRate) += size; }
276 static double GetDownOverheadRate() { return s_downOverheadRate->GetRate(); }
277 static void AddFoundSource() { ++(*s_foundSources); }
278 static void RemoveFoundSource() { --(*s_foundSources); }
279 static uint32 GetFoundSources() { return (*s_foundSources); }
280 static void AddSourceOrigin(unsigned origin);
281 static void RemoveSourceOrigin(unsigned origin);
282 static void AddDownloadingSource() { ++(*s_activeDownloads); }
283 static void RemoveDownloadingSource() { --(*s_activeDownloads); }
284 static uint32 GetDownloadingSources() { return (*s_activeDownloads); }
285 static double GetDownloadRate() { return s_downloadrate->GetRate(); }
287 // Connection
288 static CStatTreeItemTimer* GetServerConnectTimer() { return s_sinceConnected; }
289 static void AddReconnect() { ++(*s_reconnects); }
290 static void AddActiveConnection() { ++(*s_activeConnections); }
291 static void RemoveActiveConnection() { --(*s_activeConnections); }
292 static uint32 GetActiveConnections() { return s_activeConnections->GetValue(); }
293 static uint32 GetPeakConnections() { return s_activeConnections->GetMaxValue(); }
294 static void AddMaxConnectionLimitReached() { ++(*s_limitReached); }
296 // Clients
297 static void AddFilteredClient() { ++(*s_filtered); }
298 static void AddUnknownClient() { ++(*s_unknown); }
299 static void RemoveUnknownClient() { --(*s_unknown); }
300 static void AddKnownClient(CUpDownClient *pClient);
301 static void RemoveKnownClient(uint32 clientSoft, uint32 clientVersion, const wxString& OSInfo);
302 #ifdef __DEBUG__
303 static void SocketAssignedToClient() { ++(*s_hasSocket); }
304 static void SocketUnassignedFromClient() { --(*s_hasSocket); }
305 #endif
306 static uint32 GetBannedCount() { return (*s_banned); }
307 static void AddBannedClient() { ++(*s_banned); }
308 static void RemoveBannedClient() { --(*s_banned); }
310 // Servers
311 static void AddServer() { ++(*s_totalServers); }
312 static void DeleteServer() { ++(*s_deletedServers); --(*s_totalServers); }
313 static void DeleteAllServers() { (*s_deletedServers) += (*s_totalServers); (*s_totalServers) = 0; }
314 static void AddFilteredServer() { ++(*s_filteredServers); }
316 // Shared files
317 static void ClearSharedFilesInfo() { (*s_numberOfShared) = 0; (*s_sizeOfShare) = 0; }
318 static void AddSharedFile(uint64 size) { ++(*s_numberOfShared); (*s_sizeOfShare) += size; }
319 static void RemoveSharedFile(uint64 size) { --(*s_numberOfShared); (*s_sizeOfShare) -= size; }
320 static uint32 GetSharedFileCount() { return (*s_numberOfShared); }
322 // Kad nodes
323 static void AddKadNode() { ++s_kadNodesCur; }
324 static void RemoveKadNode() { --s_kadNodesCur; }
327 // Other
328 static void CalculateRates();
330 static void AddReceivedBytes(uint32 bytes)
332 if (!s_sinceFirstTransfer->IsRunning()) {
333 s_sinceFirstTransfer->StartTimer();
336 (*s_sessionDownload) += bytes;
337 (*s_downloadrate) += bytes;
340 static void AddSentBytes(uint32 bytes)
342 if (!s_sinceFirstTransfer->IsRunning()) {
343 s_sinceFirstTransfer->StartTimer();
346 (*s_sessionUpload) += bytes;
347 (*s_uploadrate) += bytes;
350 static void AddDownloadFromSoft(uint8 SoftType, uint32 bytes);
351 static void AddUploadToSoft(uint8 SoftType, uint32 bytes);
353 // EC
354 static CECTag* GetECStatTree(uint8 tree_capping_value) { return s_statTree->CreateECTag(tree_capping_value); }
356 void SetAverageMinutes(uint8 minutes) { average_minutes = minutes; }
358 private:
359 std::list<HR> listHR;
360 typedef std::list<HR>::iterator listPOS;
361 typedef std::list<HR>::reverse_iterator listRPOS;
363 /* Graph-related functions */
365 void ComputeAverages(HR **pphr, listRPOS pos, unsigned cntFilled,
366 double sStep, const std::vector<float *> &ppf, StatsGraphType which_graph);
368 int GetPointsPerRange()
370 return (1280/2) - 80; // This used to be a calc. based on GUI width
373 /* Graphs-related vars */
375 CPreciseRateCounter m_graphRunningAvgDown;
376 CPreciseRateCounter m_graphRunningAvgUp;
377 CPreciseRateCounter m_graphRunningAvgKad;
380 uint8 average_minutes;
381 int nHistRanges;
382 int bitsHistClockMask;
383 int nPointsPerRange;
384 listPOS* aposRecycle;
386 HR hrInit;
388 /* Rate/Average counters */
389 static CPreciseRateCounter* s_upOverheadRate;
390 static CPreciseRateCounter* s_downOverheadRate;
391 static CStatTreeItemRateCounter* s_uploadrate;
392 static CStatTreeItemRateCounter* s_downloadrate;
394 /* Tree-related functions */
396 static void InitStatsTree();
398 static CStatTreeItemBase* GetTreeRoot() { return s_statTree; }
400 /* Tree-related vars */
402 // the tree
403 static CStatTreeItemBase* s_statTree;
405 // Uptime
406 static CStatTreeItemTimer* s_uptime;
408 // Upload
409 static CStatTreeItemUlDlCounter* s_sessionUpload;
410 static CStatTreeItemPacketTotals* s_totalUpOverhead;
411 static CStatTreeItemPackets* s_fileReqUpOverhead;
412 static CStatTreeItemPackets* s_sourceXchgUpOverhead;
413 static CStatTreeItemPackets* s_serverUpOverhead;
414 static CStatTreeItemPackets* s_kadUpOverhead;
415 static CStatTreeItemCounter* s_cryptUpOverhead;
416 static CStatTreeItemNativeCounter* s_activeUploads;
417 static CStatTreeItemNativeCounter* s_waitingUploads;
418 static CStatTreeItemCounter* s_totalSuccUploads;
419 static CStatTreeItemCounter* s_totalFailedUploads;
420 static CStatTreeItemCounter* s_totalUploadTime;
422 // Download
423 static CStatTreeItemUlDlCounter* s_sessionDownload;
424 static CStatTreeItemPacketTotals* s_totalDownOverhead;
425 static CStatTreeItemPackets* s_fileReqDownOverhead;
426 static CStatTreeItemPackets* s_sourceXchgDownOverhead;
427 static CStatTreeItemPackets* s_serverDownOverhead;
428 static CStatTreeItemPackets* s_kadDownOverhead;
429 static CStatTreeItemCounter* s_cryptDownOverhead;
430 static CStatTreeItemNativeCounter* s_foundSources;
431 static CStatTreeItemNativeCounter* s_activeDownloads;
433 // Connection
434 static CStatTreeItemReconnects* s_reconnects;
435 static CStatTreeItemTimer* s_sinceFirstTransfer;
436 static CStatTreeItemTimer* s_sinceConnected;
437 static CStatTreeItemCounterMax* s_activeConnections;
438 static CStatTreeItemMaxConnLimitReached* s_limitReached;
439 static CStatTreeItemSimple* s_avgConnections;
441 // Clients
442 static CStatTreeItemHiddenCounter* s_clients;
443 static CStatTreeItemCounter* s_unknown;
444 //static CStatTreeItem s_lowID;
445 //static CStatTreeItem s_secIdentOnOff;
446 #ifdef __DEBUG__
447 static CStatTreeItemNativeCounter* s_hasSocket;
448 #endif
449 static CStatTreeItemNativeCounter* s_filtered;
450 static CStatTreeItemNativeCounter* s_banned;
452 // Servers
453 static CStatTreeItemSimple* s_workingServers;
454 static CStatTreeItemSimple* s_failedServers;
455 static CStatTreeItemNativeCounter* s_totalServers;
456 static CStatTreeItemNativeCounter* s_deletedServers;
457 static CStatTreeItemNativeCounter* s_filteredServers;
458 static CStatTreeItemSimple* s_usersOnWorking;
459 static CStatTreeItemSimple* s_filesOnWorking;
460 static CStatTreeItemSimple* s_totalUsers;
461 static CStatTreeItemSimple* s_totalFiles;
462 static CStatTreeItemSimple* s_serverOccupation;
464 // Shared files
465 static CStatTreeItemCounter* s_numberOfShared;
466 static CStatTreeItemCounter* s_sizeOfShare;
468 // Kad nodes
469 static uint64 s_kadNodesTotal;
470 static uint16 s_kadNodesCur;
473 #else /* CLIENT_GUI */
475 class CECPacket;
476 class CRemoteConnect;
478 enum StatDataIndex {
479 sdUpload,
480 sdUpOverhead,
481 sdDownload,
482 sdDownOverhead,
483 sdWaitingClients,
484 sdBannedClients,
485 sdED2KUsers,
486 sdKadUsers,
487 sdED2KFiles,
488 sdKadFiles,
489 sdKadFirewalledUDP,
490 sdKadIndexedSources,
491 sdKadIndexedKeywords,
492 sdKadIndexedNotes,
493 sdKadIndexedLoad,
494 sdKadIPAdress,
495 sdBuddyStatus,
496 sdBuddyIP,
497 sdBuddyPort,
498 sdKadInLanMode,
500 sdTotalItems
503 class CStatistics {
504 friend class CStatisticsDlg; // to access CStatistics::GetTreeRoot()
506 private:
507 CRemoteConnect &m_conn;
508 static CStatTreeItemBase* s_statTree;
509 static uint64 s_start_time;
510 static uint64 s_statData[sdTotalItems];
511 uint8 average_minutes;
513 public:
514 CStatistics(CRemoteConnect &conn);
515 ~CStatistics();
517 static uint64 GetUptimeMillis() { return GetTickCount64() - s_start_time; }
518 static uint64 GetUptimeSeconds() { return (GetTickCount64() - s_start_time) / 1000; }
520 static uint64 GetSessionSentBytes() { return 0; } // TODO
521 static double GetUploadRate() { return (double)s_statData[sdUpload]; }
522 static double GetUpOverheadRate() { return (double)s_statData[sdUpOverhead]; }
524 static uint64 GetSessionReceivedBytes() { return 0; } // TODO
525 static double GetDownloadRate() { return (double)s_statData[sdDownload]; }
526 static double GetDownOverheadRate() { return (double)s_statData[sdDownOverhead]; }
528 static uint32 GetWaitingUserCount() { return s_statData[sdWaitingClients]; }
529 static uint32 GetBannedCount() { return s_statData[sdBannedClients]; }
531 static uint32 GetSharedFileCount() { return 0; } // TODO
533 static uint32 GetED2KUsers() { return s_statData[sdED2KUsers]; }
534 static uint32 GetKadUsers() { return s_statData[sdKadUsers]; }
535 static uint32 GetED2KFiles() { return s_statData[sdED2KFiles]; }
536 static uint32 GetKadFiles() { return s_statData[sdKadFiles]; }
538 static bool IsFirewalledKadUDP() { return s_statData[sdKadFirewalledUDP] != 0; }
539 static uint32 GetKadIndexedSources() { return s_statData[sdKadIndexedSources]; }
540 static uint32 GetKadIndexedKeywords() { return s_statData[sdKadIndexedKeywords]; }
541 static uint32 GetKadIndexedNotes() { return s_statData[sdKadIndexedNotes]; }
542 static uint32 GetKadIndexedLoad() { return s_statData[sdKadIndexedLoad]; }
543 static uint32 GetKadIPAdress() { return s_statData[sdKadIPAdress]; }
544 static uint8 GetBuddyStatus() { return s_statData[sdBuddyStatus]; }
545 static uint32 GetBuddyIP() { return s_statData[sdBuddyIP]; }
546 static uint32 GetBuddyPort() { return s_statData[sdBuddyPort]; }
547 static bool IsKadRunningInLanMode() { return s_statData[sdKadInLanMode] != 0; }
549 static void UpdateStats(const CECPacket* stats);
551 void UpdateStatsTree();
552 void SetAverageMinutes(uint8 minutes) { average_minutes = minutes; }
554 private:
555 static CStatTreeItemBase* GetTreeRoot() { return s_statTree; }
558 #endif /* !CLIENT_GUI / CLIENT_GUI */
562 * Shortcut for CStatistics
564 typedef CStatistics theStats;
566 #endif // STATISTICS_H
567 // File_checked_for_headers