1// 2// This file is part of the aMule Project. 3// 4// Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org ) 5// Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net ) 6// Copyright (c) 2005-2011 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. 11// 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. 16// 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 25// 26 27#ifndef STATISTICS_H 28#define STATISTICS_H 29 30#include "Constants.h" // Needed for StatsGraphType 31#include "StatTree.h" // Needed for CStatTreeItem* classes 32 33#include <deque> // Needed for std::deque 34 35typedef struct UpdateInfo { 36 double timestamp; 37 float downloads[3]; 38 float uploads[3]; 39 float connections[3]; 40 float kadnodes[3]; 41} GraphUpdateInfo; 42 43typedef struct HistoryRecord { 44 double kBytesSent; 45 double kBytesReceived; 46 float kBpsUpCur; 47 float kBpsDownCur; 48 double sTimestamp; 49 uint16 cntDownloads; 50 uint16 cntUploads; 51 uint16 cntConnections; 52 uint16 kadNodesCur; 53 uint64 kadNodesTotal; 54} HR; 55 56 57#ifndef CLIENT_GUI 58 59/** 60 * Counts precise rate/average on added bytes/values. 61 * 62 * @note This class is MT-safe. 63 */ 64class CPreciseRateCounter { 65 friend class CStatistics; // for playing dirty tricks to compute running average :P 66 public: 67 68 /** 69 * Constructor 70 * 71 * @param timespan Desired timespan for rate calculations. 72 * @param count_average Counts average instead of rate. 73 */ 74 CPreciseRateCounter(uint32_t timespan, bool count_average = false) 75 : m_timespan(timespan), m_total(0), m_rate(0.0), m_max_rate(0.0), m_tmp_sum(0), m_count_average(count_average) 76 { 77 if (!count_average) { 78 uint64_t cur_time = GetTickCount64(); 79 uint64_t target_time = cur_time - timespan; 80 while (cur_time > target_time) { 81 m_tick_history.push_front(cur_time); 82 m_byte_history.push_front(0); 83 cur_time -= 100; // default update period 84 } 85 m_tick_history.push_front(cur_time); 86 } 87 } 88 89 /** 90 * Calculate current rate. 91 * 92 * This function should be called reasonably often, to 93 * keep rates up-to-date, and prevent history growing 94 * to the skies. 95 */ 96 void CalculateRate(uint64_t now); 97 98 /** 99 * Get current rate. 100 * 101 * @return Current rate in bytes/second. 102 */ 103 double GetRate() { wxMutexLocker lock(m_mutex); return m_rate; }; 104 105 /** 106 * Gets ever seen maximal rate. 107 * 108 * @return The maximal rate which occured. 109 */ 110 double GetMaxRate() { wxMutexLocker lock(m_mutex); return m_max_rate; } 111 112 /** 113 * Sets desired timespan for rate calculations. 114 * 115 * If new timespan is greater than the old was, then the change 116 * takes effect with time. The exact time needed for the change 117 * to take effect is new minus old value of the timespan. 118 * 119 * If the new timespan is lower than the old, the change takes 120 * effect immediately at the next call to CalculateRate(). 121 */ 122 void SetTimespan(uint32_t timespan) { wxMutexLocker lock(m_mutex); m_timespan = timespan; } 123 124 /** 125 * Add bytes to be tracked for rate-counting. 126 */ 127 void operator+=(uint32_t bytes) { wxMutexLocker lock(m_mutex); m_tmp_sum += bytes; } 128 129 protected: 130 131 std::deque<uint32> m_byte_history; 132 std::deque<uint64> m_tick_history; 133 uint32_t m_timespan; 134 uint32_t m_total; 135 double m_rate; 136 double m_max_rate; 137 uint32_t m_tmp_sum; 138 wxMutex m_mutex; 139 bool m_count_average; 140}; 141 142 143class CECTag; 144 145/** 146 * Stat tree item for rates/averages. 147 */ 148class CStatTreeItemRateCounter : public CStatTreeItemBase, public CPreciseRateCounter { 149 public: 150 151 /** 152 * @see CStatTreeItemBase::CStatTreeItemBase, CPreciseRateCounter::CPreciseRateCounter 153 * 154 * @param show_maxrate If true, shows max rate instead of current rate. 155 */ 156 CStatTreeItemRateCounter(const wxString& label, bool show_maxrate, uint32_t timespan, bool count_average = false) 157 : CStatTreeItemBase(label, stNone), CPreciseRateCounter(timespan, count_average), m_show_maxrate(show_maxrate) 158 {} 159 160#ifndef AMULE_DAEMON 161 /** 162 * @see CStatTreeItemBase::GetDisplayString() 163 */ 164 virtual wxString GetDisplayString() const; 165#endif 166 167 protected: 168 /** 169 * Add values to EC tag being generated. 170 * 171 * @param tag The tag to which values should be added. 172 * 173 * @see CStatTreeItemBase::AddECValues 174 */ 175 virtual void AddECValues(CECTag* tag) const; 176 177 //! Whether to show max rate instead of actual rate. 178 bool m_show_maxrate; 179}; 180 181 182/** 183 * Stat tree item for Peak Connections. 184 */ 185class CStatTreeItemPeakConnections : public CStatTreeItemBase { 186 public: 187 188 /** 189 * @see CStatTreeItemBase::CStatTreeItemBase 190 */ 191 CStatTreeItemPeakConnections(const wxString& label) 192 : CStatTreeItemBase(label) 193 {} 194 195#ifndef AMULE_DAEMON 196 /** 197 * @see CStatTreeItemBase::GetDisplayString() 198 */ 199 virtual wxString GetDisplayString() const; 200#endif 201 202 protected: 203 /** 204 * Add values to EC tag being generated. 205 * 206 * @param tag The tag to which values should be added. 207 * 208 * @see CStatTreeItemBase::AddECValues 209 */ 210 virtual void AddECValues(CECTag* tag) const; 211}; 212 213 214class CUpDownClient; 215 216class CStatistics { 217 friend class CStatisticsDlg; // to access CStatistics::GetTreeRoot() 218 public: 219 CStatistics(); 220 ~CStatistics(); 221 222 static void Load(); 223 static void Save(); 224 225 /* Statistics graph functions */ 226 227 void RecordHistory(); 228 unsigned GetHistoryForWeb(unsigned cntPoints, double sStep, double *sStart, uint32 **graphData); 229 unsigned GetHistory(unsigned cntPoints, double sStep, double sFinal, const std::vector<float *> &ppf, StatsGraphType which_graph); 230 GraphUpdateInfo GetPointsForUpdate(); 231 232 /* Statistics tree functions */ 233 234 void UpdateStatsTree(); 235 236 /* Access to the tree */ 237 238 // uptime 239 static uint64 GetUptimeMillis() { return s_uptime->GetTimerValue(); } 240 static uint64 GetUptimeSeconds() { return s_uptime->GetTimerSeconds(); } 241 static uint64 GetStartTime() { return s_uptime->GetTimerStart(); } 242 243 // Upload 244 static uint64 GetTotalSentBytes() { return s_totalSent; } 245 static uint64 GetSessionSentBytes() { return (*s_sessionUpload); } 246 static void AddUpOverheadFileRequest(uint32 size) { (*s_fileReqUpOverhead) += size; (*s_upOverheadRate) += size; } 247 static void AddUpOverheadSourceExchange(uint32 size){ (*s_sourceXchgUpOverhead) += size; (*s_upOverheadRate) += size; } 248 static void AddUpOverheadServer(uint32 size) { (*s_serverUpOverhead) += size; (*s_upOverheadRate) += size; } 249 static void AddUpOverheadKad(uint32 size) { (*s_kadUpOverhead) += size; (*s_upOverheadRate) += size; } 250 static void AddUpOverheadCrypt(uint32_t size) { (*s_cryptUpOverhead) += size; } 251 static void AddUpOverheadOther(uint32 size) { (*s_totalUpOverhead) += size; (*s_upOverheadRate) += size; } 252 static double GetUpOverheadRate() { return s_upOverheadRate->GetRate(); } 253 static void AddSuccessfulUpload() { ++(*s_totalSuccUploads); } 254 static void AddFailedUpload() { ++(*s_totalFailedUploads); } 255 static void AddUploadTime(uint32 time) { (*s_totalUploadTime) += time; } 256 static void AddUploadingClient() { ++(*s_activeUploads); } 257 static void RemoveUploadingClient() { --(*s_activeUploads); } 258 static uint32 GetActiveUploadsCount() { return (*s_activeUploads); } 259 static void AddWaitingClient() { ++(*s_waitingUploads); } 260 static void RemoveWaitingClient() { --(*s_waitingUploads); } 261 static uint32 GetWaitingUserCount() { return (*s_waitingUploads); } 262 static double GetUploadRate() { return s_uploadrate->GetRate(); } 263 264 // Download 265 static uint64 GetTotalReceivedBytes() { return s_totalReceived; } 266 static uint64 GetSessionReceivedBytes() { return (*s_sessionDownload); } 267 static void AddDownOverheadFileRequest(uint32 size) { (*s_fileReqDownOverhead) += size; (*s_downOverheadRate) += size; } 268 static void AddDownOverheadSourceExchange(uint32 size){ (*s_sourceXchgDownOverhead) += size; (*s_downOverheadRate) += size; } 269 static void AddDownOverheadServer(uint32 size) { (*s_serverDownOverhead) += size; (*s_downOverheadRate) += size; } 270 static void AddDownOverheadKad(uint32 size) { (*s_kadDownOverhead) += size; (*s_downOverheadRate) += size; } 271 static void AddDownOverheadCrypt(uint32_t size) { (*s_cryptDownOverhead) += size; } 272 static void AddDownOverheadOther(uint32 size) { (*s_totalDownOverhead) += size; (*s_downOverheadRate) += size; } 273 static double GetDownOverheadRate() { return s_downOverheadRate->GetRate(); } 274 static void AddFoundSource() { ++(*s_foundSources); } 275 static void RemoveFoundSource() { --(*s_foundSources); } 276 static uint32 GetFoundSources() { return (*s_foundSources); } 277 static void AddSourceOrigin(unsigned origin); 278 static void RemoveSourceOrigin(unsigned origin); 279 static void AddDownloadingSource() { ++(*s_activeDownloads); } 280 static void RemoveDownloadingSource() { --(*s_activeDownloads); } 281 static uint32 GetDownloadingSources() { return (*s_activeDownloads); } 282 static double GetDownloadRate() { return s_downloadrate->GetRate(); } 283 284 // Connection 285 static CStatTreeItemTimer* GetServerConnectTimer() { return s_sinceConnected; } 286 static void AddReconnect() { ++(*s_reconnects); } 287 static void AddActiveConnection() { ++(*s_activeConnections); } 288 static void RemoveActiveConnection() { --(*s_activeConnections); } 289 static uint32 GetActiveConnections() { return s_activeConnections->GetValue(); } 290 static uint32 GetPeakConnections() { return s_activeConnections->GetMaxValue(); } 291 static void AddMaxConnectionLimitReached() { ++(*s_limitReached); } 292 293 // Clients 294 static void AddFilteredClient() { ++(*s_filtered); } 295 static void AddUnknownClient() { ++(*s_unknown); } 296 static void RemoveUnknownClient() { --(*s_unknown); } 297 static void AddKnownClient(CUpDownClient *pClient); 298 static void RemoveKnownClient(uint32 clientSoft, uint32 clientVersion, const wxString& OSInfo); 299#ifdef __DEBUG__ 300 static void SocketAssignedToClient() { ++(*s_hasSocket); } 301 static void SocketUnassignedFromClient() { --(*s_hasSocket); } 302#endif 303 static uint32 GetBannedCount() { return (*s_banned); } 304 static void AddBannedClient() { ++(*s_banned); } 305 static void RemoveBannedClient() { --(*s_banned); } 306 307 // Servers 308 static void AddServer() { ++(*s_totalServers); } 309 static void DeleteServer() { ++(*s_deletedServers); --(*s_totalServers); } 310 static void DeleteAllServers() { (*s_deletedServers) += (*s_totalServers); (*s_totalServers) = 0; } 311 static void AddFilteredServer() { ++(*s_filteredServers); } 312 313 // Shared files 314 static void ClearSharedFilesInfo() { (*s_numberOfShared) = 0; (*s_sizeOfShare) = 0; } 315 static void AddSharedFile(uint64 size) { ++(*s_numberOfShared); (*s_sizeOfShare) += size; } 316 static void RemoveSharedFile(uint64 size) { --(*s_numberOfShared); (*s_sizeOfShare) -= size; } 317 static uint32 GetSharedFileCount() { return (*s_numberOfShared); } 318 319 // Kad nodes 320 static void AddKadNode() { ++s_kadNodesCur; } 321 static void RemoveKadNode() { --s_kadNodesCur; } 322 323 324 // Other 325 static void CalculateRates(); 326 327 static void AddReceivedBytes(uint32 bytes) 328 { 329 if (!s_sinceFirstTransfer->IsRunning()) { 330 s_sinceFirstTransfer->StartTimer(); 331 } 332 333 (*s_sessionDownload) += bytes; 334 (*s_downloadrate) += bytes; 335 s_totalReceived += bytes; 336 s_statsNeedSave = true; 337 } 338 339 static void AddSentBytes(uint32 bytes) 340 { 341 if (!s_sinceFirstTransfer->IsRunning()) { 342 s_sinceFirstTransfer->StartTimer(); 343 } 344 345 (*s_sessionUpload) += bytes; 346 (*s_uploadrate) += bytes; 347 s_totalSent += bytes; 348 s_statsNeedSave = true; 349 } 350 351 static void AddDownloadFromSoft(uint8 SoftType, uint32 bytes); 352 static void AddUploadToSoft(uint8 SoftType, uint32 bytes); 353 354 // EC 355 static CECTag* GetECStatTree(uint8 tree_capping_value) { return s_statTree->CreateECTag(tree_capping_value); } 356 357 void SetAverageMinutes(uint8 minutes) { average_minutes = minutes; } 358 359 private: 360 std::list<HR> listHR; 361 typedef std::list<HR>::iterator listPOS; 362 typedef std::list<HR>::reverse_iterator listRPOS; 363 364 /* Graph-related functions */ 365 366 void ComputeAverages(HR **pphr, listRPOS pos, unsigned cntFilled, 367 double sStep, const std::vector<float *> &ppf, StatsGraphType which_graph); 368 369 int GetPointsPerRange() 370 { 371 return (1280/2) - 80; // This used to be a calc. based on GUI width 372 } 373 374 /* Graphs-related vars */ 375 376 CPreciseRateCounter m_graphRunningAvgDown; 377 CPreciseRateCounter m_graphRunningAvgUp; 378 CPreciseRateCounter m_graphRunningAvgKad; 379 380 381 uint8 average_minutes; 382 int nHistRanges; 383 int bitsHistClockMask; 384 int nPointsPerRange; 385 listPOS* aposRecycle; 386 387 HR hrInit; 388 389 /* Rate/Average counters */ 390 static CPreciseRateCounter* s_upOverheadRate; 391 static CPreciseRateCounter* s_downOverheadRate; 392 static CStatTreeItemRateCounter* s_uploadrate; 393 static CStatTreeItemRateCounter* s_downloadrate; 394 395 /* Tree-related functions */ 396 397 static void InitStatsTree(); 398 399 static CStatTreeItemBase* GetTreeRoot() { return s_statTree; } 400 401 /* Tree-related vars */ 402 403 // the tree 404 static CStatTreeItemBase* s_statTree; 405 406 // Uptime 407 static CStatTreeItemTimer* s_uptime; 408 409 // Upload 410 static CStatTreeItemUlDlCounter* s_sessionUpload; 411 static CStatTreeItemPacketTotals* s_totalUpOverhead; 412 static CStatTreeItemPackets* s_fileReqUpOverhead; 413 static CStatTreeItemPackets* s_sourceXchgUpOverhead; 414 static CStatTreeItemPackets* s_serverUpOverhead; 415 static CStatTreeItemPackets* s_kadUpOverhead; 416 static CStatTreeItemCounter* s_cryptUpOverhead; 417 static CStatTreeItemNativeCounter* s_activeUploads; 418 static CStatTreeItemNativeCounter* s_waitingUploads; 419 static CStatTreeItemCounter* s_totalSuccUploads; 420 static CStatTreeItemCounter* s_totalFailedUploads; 421 static CStatTreeItemCounter* s_totalUploadTime; 422 423 // Download 424 static CStatTreeItemUlDlCounter* s_sessionDownload; 425 static CStatTreeItemPacketTotals* s_totalDownOverhead; 426 static CStatTreeItemPackets* s_fileReqDownOverhead; 427 static CStatTreeItemPackets* s_sourceXchgDownOverhead; 428 static CStatTreeItemPackets* s_serverDownOverhead; 429 static CStatTreeItemPackets* s_kadDownOverhead; 430 static CStatTreeItemCounter* s_cryptDownOverhead; 431 static CStatTreeItemNativeCounter* s_foundSources; 432 static CStatTreeItemNativeCounter* s_activeDownloads; 433 434 // Connection 435 static CStatTreeItemReconnects* s_reconnects; 436 static CStatTreeItemTimer* s_sinceFirstTransfer; 437 static CStatTreeItemTimer* s_sinceConnected; 438 static CStatTreeItemCounterMax* s_activeConnections; 439 static CStatTreeItemMaxConnLimitReached* s_limitReached; 440 static CStatTreeItemSimple* s_avgConnections; 441 442 // Clients 443 static CStatTreeItemHiddenCounter* s_clients; 444 static CStatTreeItemCounter* s_unknown; 445 //static CStatTreeItem s_lowID; 446 //static CStatTreeItem s_secIdentOnOff; 447#ifdef __DEBUG__ 448 static CStatTreeItemNativeCounter* s_hasSocket; 449#endif 450 static CStatTreeItemNativeCounter* s_filtered; 451 static CStatTreeItemNativeCounter* s_banned; 452 453 // Servers 454 static CStatTreeItemSimple* s_workingServers; 455 static CStatTreeItemSimple* s_failedServers; 456 static CStatTreeItemNativeCounter* s_totalServers; 457 static CStatTreeItemNativeCounter* s_deletedServers; 458 static CStatTreeItemNativeCounter* s_filteredServers; 459 static CStatTreeItemSimple* s_usersOnWorking; 460 static CStatTreeItemSimple* s_filesOnWorking; 461 static CStatTreeItemSimple* s_totalUsers; 462 static CStatTreeItemSimple* s_totalFiles; 463 static CStatTreeItemSimple* s_serverOccupation; 464 465 // Shared files 466 static CStatTreeItemCounter* s_numberOfShared; 467 static CStatTreeItemCounter* s_sizeOfShare; 468 469 // Kad nodes 470 static uint64_t s_kadNodesTotal; 471 static uint16_t s_kadNodesCur; 472 473 // Total sent/received bytes 474 static uint64_t s_totalSent; 475 static uint64_t s_totalReceived; 476 477 static bool s_statsNeedSave; 478}; 479 480#else /* CLIENT_GUI */ 481 482class CECPacket; 483class CRemoteConnect; 484 485enum StatDataIndex { 486 sdUpload, 487 sdUpOverhead, 488 sdDownload, 489 sdDownOverhead, 490 sdWaitingClients, 491 sdBannedClients, 492 sdED2KUsers, 493 sdKadUsers, 494 sdED2KFiles, 495 sdKadFiles, 496 sdKadFirewalledUDP, 497 sdKadIndexedSources, 498 sdKadIndexedKeywords, 499 sdKadIndexedNotes, 500 sdKadIndexedLoad, 501 sdKadIPAdress, 502 sdBuddyStatus, 503 sdBuddyIP, 504 sdBuddyPort, 505 sdKadInLanMode, 506 sdTotalSentBytes, 507 sdTotalReceivedBytes, 508 sdSharedFileCount, 509 510 sdTotalItems 511}; 512 513class CStatistics { 514 friend class CStatisticsDlg; // to access CStatistics::GetTreeRoot() 515 516private: 517 CRemoteConnect &m_conn; 518 static CStatTreeItemBase* s_statTree; 519 static uint64 s_start_time; 520 static uint64 s_statData[sdTotalItems]; 521 uint8 average_minutes; 522 523 public: 524 CStatistics(CRemoteConnect &conn); 525 ~CStatistics(); 526 527 static uint64 GetUptimeMillis(); 528 static uint64 GetUptimeSeconds(); 529 530 static uint64 GetTotalSentBytes() { return s_statData[sdTotalSentBytes]; } 531 static double GetUploadRate() { return (double)s_statData[sdUpload]; } 532 static double GetUpOverheadRate() { return (double)s_statData[sdUpOverhead]; } 533 534 static uint64 GetTotalReceivedBytes() { return s_statData[sdTotalReceivedBytes]; } 535 static double GetDownloadRate() { return (double)s_statData[sdDownload]; } 536 static double GetDownOverheadRate() { return (double)s_statData[sdDownOverhead]; } 537 538 static uint32 GetWaitingUserCount() { return s_statData[sdWaitingClients]; } 539 static uint32 GetBannedCount() { return s_statData[sdBannedClients]; } 540 541 static uint32 GetSharedFileCount() { return s_statData[sdSharedFileCount]; } 542 543 static uint32 GetED2KUsers() { return s_statData[sdED2KUsers]; } 544 static uint32 GetKadUsers() { return s_statData[sdKadUsers]; } 545 static uint32 GetED2KFiles() { return s_statData[sdED2KFiles]; } 546 static uint32 GetKadFiles() { return s_statData[sdKadFiles]; } 547 548 static bool IsFirewalledKadUDP() { return s_statData[sdKadFirewalledUDP] != 0; } 549 static uint32 GetKadIndexedSources() { return s_statData[sdKadIndexedSources]; } 550 static uint32 GetKadIndexedKeywords() { return s_statData[sdKadIndexedKeywords]; } 551 static uint32 GetKadIndexedNotes() { return s_statData[sdKadIndexedNotes]; } 552 static uint32 GetKadIndexedLoad() { return s_statData[sdKadIndexedLoad]; } 553 static uint32 GetKadIPAdress() { return s_statData[sdKadIPAdress]; } 554 static uint8 GetBuddyStatus() { return s_statData[sdBuddyStatus]; } 555 static uint32 GetBuddyIP() { return s_statData[sdBuddyIP]; } 556 static uint32 GetBuddyPort() { return s_statData[sdBuddyPort]; } 557 static bool IsKadRunningInLanMode() { return s_statData[sdKadInLanMode] != 0; } 558 559 static void UpdateStats(const CECPacket* stats); 560 561 void UpdateStatsTree(); 562 void RebuildStatTreeRemote(const CECTag *); 563 void SetAverageMinutes(uint8 minutes) { average_minutes = minutes; } 564 565 private: 566 static CStatTreeItemBase* GetTreeRoot() { return s_statTree; } 567}; 568 569#endif /* !CLIENT_GUI / CLIENT_GUI */ 570 571 572/** 573 * Shortcut for CStatistics 574 */ 575typedef CStatistics theStats; 576 577#endif // STATISTICS_H 578// File_checked_for_headers 579