Upstream tarball 10020
[amule.git] / src / StatTree.cpp
blob24606c25c27e0caa768e486761cc366749a2f5fe
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) 2005-2008 Dévai Tamás ( gonosztopi@amule.org )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "StatTree.h"
28 #include <wx/intl.h>
29 #include "OtherFunctions.h"
31 #ifndef CLIENT_GUI
33 #include <common/Format.h> // Needed for CFormat
35 #define a_brackets_b(a,b) (a + wxT(" (") + b + wxT(")"))
37 #endif /* !CLIENT_GUI */
39 #include <ec/cpp/ECTag.h> // Needed for CECTag
41 #ifdef CLIENT_GUI
42 #include <ec/cpp/ECSpecialTags.h> // Needed for CEC_StatTree_Node_Tag
44 #else
46 uint32_t NewStatTreeItemId()
48 static uint32_t lastid = 0;
50 return ++lastid;
52 #endif
54 /* CStatTreeItemBase */
56 #ifdef CLIENT_GUI
57 CStatTreeItemBase::CStatTreeItemBase(const CECTag *tag)
58 : m_label(((CEC_StatTree_Node_Tag*)tag)->GetDisplayString())
59 , m_uniqueid(tag->GetTagByNameSafe(EC_TAG_STATTREE_NODEID)->GetInt())
61 wxASSERT(tag->GetTagName() == EC_TAG_STATTREE_NODE);
63 for (size_t i = 0; i < tag->GetTagCount(); ++i) {
64 const CECTag *tmp = tag->GetTagByIndex(i);
65 if (tmp->GetTagName() == EC_TAG_STATTREE_NODE) {
66 m_children.push_back(new CStatTreeItemBase(tmp));
70 #endif /* CLIENT_GUI */
72 CStatTreeItemBase::~CStatTreeItemBase()
74 DeleteContents(m_children);
77 #ifndef CLIENT_GUI
78 CStatTreeItemBase* CStatTreeItemBase::AddChild(
79 CStatTreeItemBase* child,
80 uint32_t id,
81 bool skipOneLevel)
83 wxMutexLocker lock(m_lock);
85 if (skipOneLevel) {
86 child->m_parent = m_parent;
87 } else {
88 child->m_parent = this;
90 child->m_id = id;
92 if (m_flags & stSortChildren) {
93 std::list<CStatTreeItemBase*>::iterator it = m_children.begin();
94 while (it != m_children.end() && id < (*it)->m_id) {
95 ++it;
97 m_children.insert(it, child);
98 } else {
99 m_children.push_back(child);
101 return child;
103 #endif /* !CLIENT_GUI */
105 bool CStatTreeItemBase::HasVisibleChildren()
107 wxMutexLocker lock(m_lock);
109 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
110 it != m_children.end(); ++it) {
111 if ((*it)->IsVisible()) {
112 return true;
115 return false;
118 #ifndef CLIENT_GUI
119 bool CStatTreeItemBase::HasChildWithId(uint32_t id)
121 wxMutexLocker lock(m_lock);
123 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
124 it != m_children.end(); ++it) {
125 if ((*it)->m_id == id) {
126 return true;
129 return false;
132 CStatTreeItemBase* CStatTreeItemBase::GetChildById(uint32_t id)
134 wxMutexLocker lock(m_lock);
136 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
137 it != m_children.end(); ++it) {
138 if ((*it)->m_id == id) {
139 return *it;
142 return NULL;
145 // Note: these functions do not lock the list, because it is already locked at the time they're called
146 StatTreeItemIterator CStatTreeItemBase::GetFirstVisibleChild(uint32_t max_children)
148 StatTreeItemIterator it = m_children.begin();
149 m_visible_counter = --max_children;
150 while (it != m_children.end() && !(*it)->IsVisible()) ++it;
151 return it;
154 void CStatTreeItemBase::GetNextVisibleChild(StatTreeItemIterator& it)
156 if (m_flags & stCapChildren) {
157 if (m_visible_counter == 0) {
158 it = m_children.end();
159 return;
160 } else {
161 --m_visible_counter;
164 if (it != m_children.end()) ++it;
165 while (it != m_children.end() && !(*it)->IsVisible()) ++it;
169 // Anything below is only for core.
172 bool CStatTreeItemBase::ValueSort(const CStatTreeItemBase* a, const CStatTreeItemBase* b)
174 if (a->m_id < 0x00000100 || a->m_id > 0x7fffffff || b->m_id < 0x00000100 || b->m_id > 0x7fffffff) {
175 return a->m_id > b->m_id;
176 } else {
177 return ((CStatTreeItemCounter*)a)->GetValue() > ((CStatTreeItemCounter*)b)->GetValue();
181 #ifndef AMULE_DAEMON
182 wxString CStatTreeItemBase::GetDisplayString() const
184 return wxGetTranslation(m_label);
186 #endif
188 CECTag *CStatTreeItemBase::CreateECTag(uint32_t max_children)
190 if (IsVisible()) {
191 wxMutexLocker lock(m_lock);
192 CECTag *tag = new CECTag(EC_TAG_STATTREE_NODE, m_label);
193 tag->AddTag(CECTag(EC_TAG_STATTREE_NODEID, m_uniqueid));
194 AddECValues(tag);
195 m_visible_counter = max_children - 1;
196 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
197 it != m_children.end(); ++it) {
198 CECTag *tmp = (*it)->CreateECTag(max_children);
199 if (tmp) {
200 tag->AddTag(*tmp);
201 delete tmp;
202 if (m_flags & stCapChildren) {
203 if (m_visible_counter == 0) {
204 break;
205 } else {
206 --m_visible_counter;
211 return tag;
212 } else {
213 return NULL;
218 /* CStatTreeItemSimple */
220 #ifndef AMULE_DAEMON
221 wxString CStatTreeItemSimple::GetDisplayString() const
223 switch (m_valuetype) {
224 case vtInteger:
225 switch (m_displaymode) {
226 case dmTime: return CFormat(wxGetTranslation(m_label)) % CastSecondsToHM(m_intvalue);
227 case dmBytes: return CFormat(wxGetTranslation(m_label)) % CastItoXBytes(m_intvalue);
228 default: return CFormat(wxGetTranslation(m_label)) % m_intvalue;
230 case vtFloat: return wxString::Format(wxGetTranslation(m_label), m_floatvalue);
231 case vtString: return CFormat(wxGetTranslation(m_label)) % m_stringvalue;
232 default: return wxGetTranslation(m_label);
235 #endif
237 bool CStatTreeItemSimple::IsVisible() const
239 if (m_flags & stHideIfZero) {
240 switch (m_valuetype) {
241 case vtInteger: return m_intvalue != 0;
242 case vtFloat: return m_floatvalue != 0.0;
243 case vtString: return !m_stringvalue.IsEmpty();
244 default: return false;
247 return true;
250 void CStatTreeItemSimple::AddECValues(CECTag *tag) const
252 switch (m_valuetype) {
253 case vtInteger: {
254 if (m_displaymode == dmTime) {
255 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)m_intvalue);
256 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME));
257 tag->AddTag(value);
258 } else {
259 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint64)m_intvalue);
260 if (m_displaymode == dmBytes) {
261 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
263 tag->AddTag(value);
265 break;
267 case vtFloat: {
268 CECTag value(EC_TAG_STAT_NODE_VALUE, m_floatvalue);
269 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_DOUBLE));
270 tag->AddTag(value);
271 break;
273 case vtString: {
274 CECTag value(EC_TAG_STAT_NODE_VALUE, m_stringvalue);
275 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
276 tag->AddTag(value);
277 break;
279 default:
280 break;
285 /* CStatTreeItemCounterTmpl */
287 #ifndef AMULE_DAEMON
288 template<typename _Tp>
289 wxString CStatTreeItemCounterTmpl<_Tp>::GetDisplayString() const
291 wxString my_label = wxGetTranslation(m_label);
292 // This is needed for client names, for example
293 if (my_label == m_label) {
294 if (m_label.Right(4) == wxT(": %s")) {
295 my_label = wxGetTranslation(
296 m_label.Mid(0, m_label.Length() - 4)) +
297 wxString(wxT(": %s"));
300 CFormat label(my_label);
301 if (m_displaymode == dmBytes) {
302 return label % CastItoXBytes(m_value);
303 } else {
304 wxString result = CFormat(wxT("%u")) % m_value;
305 if ((m_flags & stShowPercent) && m_parent) {
306 result.append(wxString::Format(wxT(" (%.2f%%)"),
307 ((double)m_value / ((CStatTreeItemCounterTmpl<_Tp>*)m_parent)->m_value) * 100.0));
309 return label % result;
313 template wxString CStatTreeItemCounter::GetDisplayString() const;
314 template wxString CStatTreeItemNativeCounter::GetDisplayString() const;
316 #endif
318 template<typename _Tp>
319 void CStatTreeItemCounterTmpl<_Tp>::AddECValues(CECTag *tag) const
321 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint64)m_value);
322 if (m_displaymode == dmBytes) {
323 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
324 } else {
325 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISTRING));
326 if ((m_flags & stShowPercent) && m_parent) {
327 CECTag tmp(EC_TAG_STAT_NODE_VALUE,
328 ((double)m_value / ((CStatTreeItemCounterTmpl<_Tp>*)m_parent)->m_value) * 100.0);
329 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_DOUBLE));
330 value.AddTag(tmp);
333 tag->AddTag(value);
336 template void CStatTreeItemCounter::AddECValues(CECTag *tag) const;
337 template void CStatTreeItemNativeCounter::AddECValues(CECTag *tag) const;
339 /* CStatTreeItemUlDlCounter */
341 #ifndef AMULE_DAEMON
342 wxString CStatTreeItemUlDlCounter::GetDisplayString() const
344 return CFormat(wxGetTranslation(m_label)) %
345 a_brackets_b(CastItoXBytes(m_value), CastItoXBytes(m_value + m_totalfunc()));
347 #endif
349 void CStatTreeItemUlDlCounter::AddECValues(CECTag *tag) const
351 CECTag value(EC_TAG_STAT_NODE_VALUE, m_value);
352 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
353 CECTag tmp(EC_TAG_STAT_NODE_VALUE, m_value + m_totalfunc());
354 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
355 value.AddTag(tmp);
356 tag->AddTag(value);
360 /* CStatTreeItemCounterMax */
362 #ifndef AMULE_DAEMON
363 wxString CStatTreeItemCounterMax::GetDisplayString() const
365 return wxString::Format(wxGetTranslation(m_label), m_value);
367 #endif
369 void CStatTreeItemCounterMax::AddECValues(CECTag *tag) const
371 tag->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE, (uint64)m_value));
375 /* CStatTreeItemPackets */
377 #ifndef AMULE_DAEMON
378 wxString CStatTreeItemPackets::GetDisplayString() const
380 return CFormat(wxGetTranslation(m_label)) %
381 a_brackets_b(CastItoXBytes(m_bytes), CastItoIShort(m_packets));
383 #endif
385 void CStatTreeItemPackets::AddECValues(CECTag *tag) const
387 CECTag value(EC_TAG_STAT_NODE_VALUE, m_bytes);
388 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
389 CECTag tmp(EC_TAG_STAT_NODE_VALUE, (uint64)m_packets);
390 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISHORT));
391 value.AddTag(tmp);
392 tag->AddTag(value);
396 /* CStatTreeItemPacketTotals */
398 #ifndef AMULE_DAEMON
399 wxString CStatTreeItemPacketTotals::GetDisplayString() const
401 uint32_t tmp_packets = m_packets;
402 uint64_t tmp_bytes = m_bytes;
403 for (std::vector<CStatTreeItemPackets*>::const_iterator it = m_counters.begin();
404 it != m_counters.end(); ++it) {
405 tmp_packets += (*it)->m_packets;
406 tmp_bytes += (*it)->m_bytes;
409 return CFormat(wxGetTranslation(m_label)) %
410 a_brackets_b(CastItoXBytes(tmp_bytes), CastItoIShort(tmp_packets));
412 #endif
414 void CStatTreeItemPacketTotals::AddECValues(CECTag *tag) const
416 uint32_t tmp_packets = m_packets;
417 uint64_t tmp_bytes = m_bytes;
418 for (std::vector<CStatTreeItemPackets*>::const_iterator it = m_counters.begin();
419 it != m_counters.end(); ++it) {
420 tmp_packets += (*it)->m_packets;
421 tmp_bytes += (*it)->m_bytes;
424 CECTag value(EC_TAG_STAT_NODE_VALUE, tmp_bytes);
425 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
426 CECTag tmp(EC_TAG_STAT_NODE_VALUE, (uint64)tmp_packets);
427 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISHORT));
428 value.AddTag(tmp);
429 tag->AddTag(value);
433 /* CStatTreeItemTimer */
435 #ifndef AMULE_DAEMON
436 wxString CStatTreeItemTimer::GetDisplayString() const
438 return CFormat(wxGetTranslation(m_label)) %
439 CastSecondsToHM(m_value ? GetTimerSeconds() : 0);
441 #endif
443 void CStatTreeItemTimer::AddECValues(CECTag *tag) const
445 CECTag value(EC_TAG_STAT_NODE_VALUE,
446 m_value ? (uint32)GetTimerSeconds() : (uint32)0);
447 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME));
448 tag->AddTag(value);
452 /* CStatTreeItemAverage */
454 #ifndef AMULE_DAEMON
455 wxString CStatTreeItemAverage::GetDisplayString() const
457 if ((*m_divisor) != 0) {
458 switch (m_displaymode) {
459 case dmBytes:
460 return CFormat(wxGetTranslation(m_label)) %
461 CastItoXBytes((*m_dividend)/(*m_divisor));
462 case dmTime:
463 return CFormat(wxGetTranslation(m_label)) %
464 CastSecondsToHM((*m_dividend)/(*m_divisor));
465 default:
466 return CFormat(wxGetTranslation(m_label)) %
467 (CFormat(wxT("%u")) % ((uint64)(*m_dividend)/(*m_divisor))).GetString();
469 } else {
470 return CFormat(wxGetTranslation(m_label)) % wxT("-");
473 #endif
475 void CStatTreeItemAverage::AddECValues(CECTag *tag) const
477 if ((*m_divisor) != 0) {
478 uint64 data = (*m_dividend)/(*m_divisor);
479 if (m_displaymode == dmTime) {
480 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)data);
481 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME));
482 tag->AddTag(value);
483 } else {
484 CECTag value(EC_TAG_STAT_NODE_VALUE, data);
485 if (m_displaymode == dmBytes) {
486 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
488 tag->AddTag(value);
490 } else {
491 CECTag value(EC_TAG_STAT_NODE_VALUE, wxString(wxT("-")));
492 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
493 tag->AddTag(value);
498 /* CStatTreeItemAverageSpeed */
500 #ifndef AMULE_DAEMON
501 wxString CStatTreeItemAverageSpeed::GetDisplayString() const
503 uint64 time = m_timer->GetTimerSeconds();
504 if (time) {
505 return CFormat(wxGetTranslation(m_label)) % CastItoSpeed((*m_counter)/time);
506 } else {
507 return CFormat(wxGetTranslation(m_label)) % CastItoSpeed(0);
510 #endif
512 void CStatTreeItemAverageSpeed::AddECValues(CECTag *tag) const
514 uint64 time = m_timer->GetTimerSeconds();
515 if (time) {
516 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)((*m_counter)/time));
517 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_SPEED));
518 tag->AddTag(value);
519 } else {
520 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)0);
521 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_SPEED));
522 tag->AddTag(value);
527 /* CStatTreeItemRatio */
529 wxString CStatTreeItemRatio::GetString() const
531 wxString ret;
532 double v1 = m_counter1->GetValue();
533 double v2 = m_counter2->GetValue();
534 if (v1 > 0 && v2 > 0) {
535 if (v2 < v1) {
536 ret = CFormat(wxT("%.2f : 1")) % (v1 / v2);
537 } else {
538 ret = CFormat(wxT("1 : %.2f")) % (v2 / v1);
541 if (m_totalfunc1 && m_totalfunc2) {
542 double t1 = m_totalfunc1() + v1;
543 double t2 = m_totalfunc2() + v2;
544 if (t2 < t1) {
545 ret += CFormat(wxT(" (%.2f : 1)")) % (t1 / t2);
546 } else {
547 ret += CFormat(wxT(" (1 : %.2f)")) % (t2 / t1);
550 } else {
551 ret = _("Not available");
553 return ret;
556 #ifndef AMULE_DAEMON
557 wxString CStatTreeItemRatio::GetDisplayString() const
559 return CFormat(wxGetTranslation(m_label)) % GetString();
561 #endif
563 void CStatTreeItemRatio::AddECValues(CECTag *tag) const
565 CECTag value(EC_TAG_STAT_NODE_VALUE, GetString());
566 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
567 tag->AddTag(value);
571 /* CStatTreeItemReconnects */
573 #ifndef AMULE_DAEMON
574 wxString CStatTreeItemReconnects::GetDisplayString() const
576 return CFormat(wxGetTranslation(m_label)) % (m_value ? m_value - 1 : 0);
578 #endif
580 void CStatTreeItemReconnects::AddECValues(CECTag *tag) const
582 tag->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE,
583 m_value ? (uint64)(m_value - 1) : (uint64)0));
586 /* CStatTreeItemMaxConnLimitReached */
588 #ifndef AMULE_DAEMON
589 wxString CStatTreeItemMaxConnLimitReached::GetDisplayString() const
591 if (m_count) {
592 return CFormat(wxGetTranslation(m_label)) %
593 (wxString::Format(wxT("%i : "), m_count) +
594 m_time.FormatISODate() +
595 wxT(" ") +
596 m_time.FormatISOTime());
597 } else {
598 return CFormat(wxGetTranslation(m_label)) % _("Never");
601 #endif
603 void CStatTreeItemMaxConnLimitReached::AddECValues(CECTag *tag) const
605 wxString result;
606 if (m_count) {
607 result = wxString::Format(wxT("%i : "), m_count) +
608 m_time.FormatISODate() +
609 wxT(" ") +
610 m_time.FormatISOTime();
611 } else {
612 result = wxTRANSLATE("Never");
614 CECTag value(EC_TAG_STAT_NODE_VALUE, result);
615 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
616 tag->AddTag(value);
619 /* CStatTreeItemTotalClients */
621 #ifndef AMULE_DAEMON
622 wxString CStatTreeItemTotalClients::GetDisplayString() const
624 return CFormat(wxGetTranslation(m_label)) %
625 (m_known->GetValue() + m_unknown->GetValue()) %
626 m_known->GetValue();
628 #endif
630 void CStatTreeItemTotalClients::AddECValues(CECTag *tag) const
632 CECTag value1(EC_TAG_STAT_NODE_VALUE,
633 (uint64)(m_known->GetValue() + m_unknown->GetValue()));
634 tag->AddTag(value1);
635 CECTag value2(EC_TAG_STAT_NODE_VALUE,
636 (uint64)m_known->GetValue());
637 tag->AddTag(value2);
640 #endif /* !CLIENT_GUI */
641 // File_checked_for_headers