Upstream tarball 9741
[amule.git] / src / StatTree.cpp
blob44d171c711af865cb41722b220990aadcf53c116
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 EC_REMOTE
33 #include <common/Format.h> // Needed for CFormat
35 #define a_brackets_b(a,b) (a + wxT(" (") + b + wxT(")"))
37 #endif /* !EC_REMOTE */
39 #include <ec/cpp/ECTag.h> // Needed for CECTag
41 #ifdef EC_REMOTE
42 #include <ec/cpp/ECSpecialTags.h> // Needed for CEC_StatTree_Node_Tag
43 #endif
46 #ifndef EC_REMOTE
47 uint32_t NewStatTreeItemId()
49 static uint32_t lastid = 0;
51 return ++lastid;
53 #endif
55 /* CStatTreeItemBase */
57 #ifdef EC_REMOTE
58 CStatTreeItemBase::CStatTreeItemBase(const CECTag *tag)
59 : m_label(((CEC_StatTree_Node_Tag*)tag)->GetDisplayString())
60 , m_uniqueid(tag->GetTagByNameSafe(EC_TAG_STATTREE_NODEID)->GetInt())
62 wxASSERT(tag->GetTagName() == EC_TAG_STATTREE_NODE);
64 for (size_t i = 0; i < tag->GetTagCount(); ++i) {
65 const CECTag *tmp = tag->GetTagByIndex(i);
66 if (tmp->GetTagName() == EC_TAG_STATTREE_NODE) {
67 m_children.push_back(new CStatTreeItemBase(tmp));
71 #endif /* EC_REMOTE */
73 CStatTreeItemBase::~CStatTreeItemBase()
75 for (std::list<CStatTreeItemBase*>::iterator it = m_children.begin();
76 it != m_children.end(); ++it) {
77 delete *it;
79 m_children.clear();
82 #ifndef EC_REMOTE
83 CStatTreeItemBase* CStatTreeItemBase::AddChild(
84 CStatTreeItemBase* child,
85 uint32_t id,
86 bool skipOneLevel)
88 wxMutexLocker lock(m_lock);
90 if (skipOneLevel) {
91 child->m_parent = m_parent;
92 } else {
93 child->m_parent = this;
95 child->m_id = id;
97 if (m_flags & stSortChildren) {
98 std::list<CStatTreeItemBase*>::iterator it = m_children.begin();
99 while (it != m_children.end() && id < (*it)->m_id) {
100 ++it;
102 m_children.insert(it, child);
103 } else {
104 m_children.push_back(child);
106 return child;
108 #endif /* !EC_REMOTE */
110 bool CStatTreeItemBase::HasVisibleChildren()
112 wxMutexLocker lock(m_lock);
114 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
115 it != m_children.end(); ++it) {
116 if ((*it)->IsVisible()) {
117 return true;
120 return false;
123 #ifndef EC_REMOTE
124 bool CStatTreeItemBase::HasChildWithId(uint32_t id)
126 wxMutexLocker lock(m_lock);
128 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
129 it != m_children.end(); ++it) {
130 if ((*it)->m_id == id) {
131 return true;
134 return false;
137 CStatTreeItemBase* CStatTreeItemBase::GetChildById(uint32_t id)
139 wxMutexLocker lock(m_lock);
141 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
142 it != m_children.end(); ++it) {
143 if ((*it)->m_id == id) {
144 return *it;
147 return NULL;
149 #endif /* !EC_REMOTE */
151 // Note: these functions do not lock the list, because it is already locked at the time they're called
152 #ifndef EC_REMOTE
153 StatTreeItemIterator CStatTreeItemBase::GetFirstVisibleChild(uint32_t max_children)
155 StatTreeItemIterator it = m_children.begin();
156 m_visible_counter = --max_children;
157 while (it != m_children.end() && !(*it)->IsVisible()) ++it;
158 return it;
161 void CStatTreeItemBase::GetNextVisibleChild(StatTreeItemIterator& it)
163 if (m_flags & stCapChildren) {
164 if (m_visible_counter == 0) {
165 it = m_children.end();
166 return;
167 } else {
168 --m_visible_counter;
171 if (it != m_children.end()) ++it;
172 while (it != m_children.end() && !(*it)->IsVisible()) ++it;
174 #endif
177 // Anything below is only for core.
179 #ifndef EC_REMOTE
181 bool CStatTreeItemBase::ValueSort(const CStatTreeItemBase* a, const CStatTreeItemBase* b)
183 if (a->m_id < 0x00000100 || a->m_id > 0x7fffffff || b->m_id < 0x00000100 || b->m_id > 0x7fffffff) {
184 return a->m_id > b->m_id;
185 } else {
186 return ((CStatTreeItemCounter*)a)->GetValue() > ((CStatTreeItemCounter*)b)->GetValue();
190 #ifndef AMULE_DAEMON
191 wxString CStatTreeItemBase::GetDisplayString() const
193 return wxGetTranslation(m_label);
195 #endif
197 CECTag *CStatTreeItemBase::CreateECTag(uint32_t max_children)
199 if (IsVisible()) {
200 wxMutexLocker lock(m_lock);
201 CECTag *tag = new CECTag(EC_TAG_STATTREE_NODE, m_label);
202 tag->AddTag(CECTag(EC_TAG_STATTREE_NODEID, m_uniqueid));
203 AddECValues(tag);
204 m_visible_counter = max_children - 1;
205 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
206 it != m_children.end(); ++it) {
207 CECTag *tmp = (*it)->CreateECTag(max_children);
208 if (tmp) {
209 tag->AddTag(*tmp);
210 delete tmp;
211 if (m_flags & stCapChildren) {
212 if (m_visible_counter == 0) {
213 break;
214 } else {
215 --m_visible_counter;
220 return tag;
221 } else {
222 return NULL;
227 /* CStatTreeItemSimple */
229 #ifndef AMULE_DAEMON
230 wxString CStatTreeItemSimple::GetDisplayString() const
232 switch (m_valuetype) {
233 case vtInteger:
234 switch (m_displaymode) {
235 case dmTime: return CFormat(wxGetTranslation(m_label)) % CastSecondsToHM(m_intvalue);
236 case dmBytes: return CFormat(wxGetTranslation(m_label)) % CastItoXBytes(m_intvalue);
237 default: return CFormat(wxGetTranslation(m_label)) % m_intvalue;
239 case vtFloat: return wxString::Format(wxGetTranslation(m_label), m_floatvalue);
240 case vtString: return CFormat(wxGetTranslation(m_label)) % m_stringvalue;
241 default: return wxGetTranslation(m_label);
244 #endif
246 bool CStatTreeItemSimple::IsVisible() const
248 if (m_flags & stHideIfZero) {
249 switch (m_valuetype) {
250 case vtInteger: return m_intvalue != 0;
251 case vtFloat: return m_floatvalue != 0.0;
252 case vtString: return !m_stringvalue.IsEmpty();
253 default: return false;
256 return true;
259 void CStatTreeItemSimple::AddECValues(CECTag *tag) const
261 switch (m_valuetype) {
262 case vtInteger: {
263 if (m_displaymode == dmTime) {
264 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)m_intvalue);
265 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME));
266 tag->AddTag(value);
267 } else {
268 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint64)m_intvalue);
269 if (m_displaymode == dmBytes) {
270 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
272 tag->AddTag(value);
274 break;
276 case vtFloat: {
277 CECTag value(EC_TAG_STAT_NODE_VALUE, m_floatvalue);
278 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_DOUBLE));
279 tag->AddTag(value);
280 break;
282 case vtString: {
283 CECTag value(EC_TAG_STAT_NODE_VALUE, m_stringvalue);
284 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
285 tag->AddTag(value);
286 break;
288 default:
289 break;
294 /* CStatTreeItemCounterTmpl */
296 #ifndef AMULE_DAEMON
297 template<typename _Tp>
298 wxString CStatTreeItemCounterTmpl<_Tp>::GetDisplayString() const
300 wxString my_label = wxGetTranslation(m_label);
301 // This is needed for client names, for example
302 if (my_label == m_label) {
303 if (m_label.Right(4) == wxT(": %s")) {
304 my_label = wxGetTranslation(
305 m_label.Mid(0, m_label.Length() - 4)) +
306 wxString(wxT(": %s"));
309 CFormat label(my_label);
310 if (m_displaymode == dmBytes) {
311 return label % CastItoXBytes(m_value);
312 } else {
313 wxString result = CFormat(wxT("%u")) % m_value;
314 if ((m_flags & stShowPercent) && m_parent) {
315 result.append(wxString::Format(wxT(" (%.2f%%)"),
316 ((double)m_value / ((CStatTreeItemCounterTmpl<_Tp>*)m_parent)->m_value) * 100.0));
318 return label % result;
322 template wxString CStatTreeItemCounter::GetDisplayString() const;
323 template wxString CStatTreeItemNativeCounter::GetDisplayString() const;
325 #endif
327 template<typename _Tp>
328 void CStatTreeItemCounterTmpl<_Tp>::AddECValues(CECTag *tag) const
330 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint64)m_value);
331 if (m_displaymode == dmBytes) {
332 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
333 } else {
334 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISTRING));
335 if ((m_flags & stShowPercent) && m_parent) {
336 CECTag tmp(EC_TAG_STAT_NODE_VALUE,
337 ((double)m_value / ((CStatTreeItemCounterTmpl<_Tp>*)m_parent)->m_value) * 100.0);
338 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_DOUBLE));
339 value.AddTag(tmp);
342 tag->AddTag(value);
345 template void CStatTreeItemCounter::AddECValues(CECTag *tag) const;
346 template void CStatTreeItemNativeCounter::AddECValues(CECTag *tag) const;
348 /* CStatTreeItemUlDlCounter */
350 #ifndef AMULE_DAEMON
351 wxString CStatTreeItemUlDlCounter::GetDisplayString() const
353 return CFormat(wxGetTranslation(m_label)) %
354 a_brackets_b(CastItoXBytes(m_value), CastItoXBytes(m_value + m_totalfunc()));
356 #endif
358 void CStatTreeItemUlDlCounter::AddECValues(CECTag *tag) const
360 CECTag value(EC_TAG_STAT_NODE_VALUE, m_value);
361 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
362 CECTag tmp(EC_TAG_STAT_NODE_VALUE, m_value + m_totalfunc());
363 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
364 value.AddTag(tmp);
365 tag->AddTag(value);
369 /* CStatTreeItemCounterMax */
371 #ifndef AMULE_DAEMON
372 wxString CStatTreeItemCounterMax::GetDisplayString() const
374 return wxString::Format(wxGetTranslation(m_label), m_value);
376 #endif
378 void CStatTreeItemCounterMax::AddECValues(CECTag *tag) const
380 tag->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE, (uint64)m_value));
384 /* CStatTreeItemPackets */
386 #ifndef AMULE_DAEMON
387 wxString CStatTreeItemPackets::GetDisplayString() const
389 return CFormat(wxGetTranslation(m_label)) %
390 a_brackets_b(CastItoXBytes(m_bytes), CastItoIShort(m_packets));
392 #endif
394 void CStatTreeItemPackets::AddECValues(CECTag *tag) const
396 CECTag value(EC_TAG_STAT_NODE_VALUE, m_bytes);
397 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
398 CECTag tmp(EC_TAG_STAT_NODE_VALUE, (uint64)m_packets);
399 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISHORT));
400 value.AddTag(tmp);
401 tag->AddTag(value);
405 /* CStatTreeItemPacketTotals */
407 #ifndef AMULE_DAEMON
408 wxString CStatTreeItemPacketTotals::GetDisplayString() const
410 uint32_t tmp_packets = m_packets;
411 uint64_t tmp_bytes = m_bytes;
412 for (std::vector<CStatTreeItemPackets*>::const_iterator it = m_counters.begin();
413 it != m_counters.end(); ++it) {
414 tmp_packets += (*it)->m_packets;
415 tmp_bytes += (*it)->m_bytes;
418 return CFormat(wxGetTranslation(m_label)) %
419 a_brackets_b(CastItoXBytes(tmp_bytes), CastItoIShort(tmp_packets));
421 #endif
423 void CStatTreeItemPacketTotals::AddECValues(CECTag *tag) const
425 uint32_t tmp_packets = m_packets;
426 uint64_t tmp_bytes = m_bytes;
427 for (std::vector<CStatTreeItemPackets*>::const_iterator it = m_counters.begin();
428 it != m_counters.end(); ++it) {
429 tmp_packets += (*it)->m_packets;
430 tmp_bytes += (*it)->m_bytes;
433 CECTag value(EC_TAG_STAT_NODE_VALUE, tmp_bytes);
434 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
435 CECTag tmp(EC_TAG_STAT_NODE_VALUE, (uint64)tmp_packets);
436 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISHORT));
437 value.AddTag(tmp);
438 tag->AddTag(value);
442 /* CStatTreeItemTimer */
444 #ifndef AMULE_DAEMON
445 wxString CStatTreeItemTimer::GetDisplayString() const
447 return CFormat(wxGetTranslation(m_label)) %
448 CastSecondsToHM(m_value ? GetTimerSeconds() : 0);
450 #endif
452 void CStatTreeItemTimer::AddECValues(CECTag *tag) const
454 CECTag value(EC_TAG_STAT_NODE_VALUE,
455 m_value ? (uint32)GetTimerSeconds() : (uint32)0);
456 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME));
457 tag->AddTag(value);
461 /* CStatTreeItemAverage */
463 #ifndef AMULE_DAEMON
464 wxString CStatTreeItemAverage::GetDisplayString() const
466 if ((*m_divisor) != 0) {
467 switch (m_displaymode) {
468 case dmBytes:
469 return CFormat(wxGetTranslation(m_label)) %
470 CastItoXBytes((*m_dividend)/(*m_divisor));
471 case dmTime:
472 return CFormat(wxGetTranslation(m_label)) %
473 CastSecondsToHM((*m_dividend)/(*m_divisor));
474 default:
475 return CFormat(wxGetTranslation(m_label)) %
476 (CFormat(wxT("%u")) % ((uint64)(*m_dividend)/(*m_divisor))).GetString();
478 } else {
479 return CFormat(wxGetTranslation(m_label)) % wxT("-");
482 #endif
484 void CStatTreeItemAverage::AddECValues(CECTag *tag) const
486 if ((*m_divisor) != 0) {
487 uint64 data = (*m_dividend)/(*m_divisor);
488 if (m_displaymode == dmTime) {
489 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)data);
490 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME));
491 tag->AddTag(value);
492 } else {
493 CECTag value(EC_TAG_STAT_NODE_VALUE, data);
494 if (m_displaymode == dmBytes) {
495 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
497 tag->AddTag(value);
499 } else {
500 CECTag value(EC_TAG_STAT_NODE_VALUE, wxString(wxT("-")));
501 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
502 tag->AddTag(value);
507 /* CStatTreeItemAverageSpeed */
509 #ifndef AMULE_DAEMON
510 wxString CStatTreeItemAverageSpeed::GetDisplayString() const
512 uint64 time = m_timer->GetTimerSeconds();
513 if (time) {
514 return CFormat(wxGetTranslation(m_label)) % CastItoSpeed((*m_counter)/time);
515 } else {
516 return CFormat(wxGetTranslation(m_label)) % CastItoSpeed(0);
519 #endif
521 void CStatTreeItemAverageSpeed::AddECValues(CECTag *tag) const
523 uint64 time = m_timer->GetTimerSeconds();
524 if (time) {
525 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)((*m_counter)/time));
526 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_SPEED));
527 tag->AddTag(value);
528 } else {
529 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)0);
530 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_SPEED));
531 tag->AddTag(value);
536 /* CStatTreeItemRatio */
538 wxString CStatTreeItemRatio::GetString() const
540 wxString ret;
541 double v1 = m_counter1->GetValue();
542 double v2 = m_counter2->GetValue();
543 if (v1 > 0 && v2 > 0) {
544 if (v2 < v1) {
545 ret = CFormat(wxT("%.2f : 1")) % (v1 / v2);
546 } else {
547 ret = CFormat(wxT("1 : %.2f")) % (v2 / v1);
550 if (m_totalfunc1 && m_totalfunc2) {
551 double t1 = m_totalfunc1() + v1;
552 double t2 = m_totalfunc2() + v2;
553 if (t2 < t1) {
554 ret += CFormat(wxT(" (%.2f : 1)")) % (t1 / t2);
555 } else {
556 ret += CFormat(wxT(" (1 : %.2f)")) % (t2 / t1);
559 } else {
560 ret = _("Not available");
562 return ret;
565 #ifndef AMULE_DAEMON
566 wxString CStatTreeItemRatio::GetDisplayString() const
568 return CFormat(wxGetTranslation(m_label)) % GetString();
570 #endif
572 void CStatTreeItemRatio::AddECValues(CECTag *tag) const
574 CECTag value(EC_TAG_STAT_NODE_VALUE, GetString());
575 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
576 tag->AddTag(value);
580 /* CStatTreeItemReconnects */
582 #ifndef AMULE_DAEMON
583 wxString CStatTreeItemReconnects::GetDisplayString() const
585 return CFormat(wxGetTranslation(m_label)) % (m_value ? m_value - 1 : 0);
587 #endif
589 void CStatTreeItemReconnects::AddECValues(CECTag *tag) const
591 tag->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE,
592 m_value ? (uint64)(m_value - 1) : (uint64)0));
595 /* CStatTreeItemMaxConnLimitReached */
597 #ifndef AMULE_DAEMON
598 wxString CStatTreeItemMaxConnLimitReached::GetDisplayString() const
600 if (m_count) {
601 return CFormat(wxGetTranslation(m_label)) %
602 (wxString::Format(wxT("%i : "), m_count) +
603 m_time.FormatISODate() +
604 wxT(" ") +
605 m_time.FormatISOTime());
606 } else {
607 return CFormat(wxGetTranslation(m_label)) % _("Never");
610 #endif
612 void CStatTreeItemMaxConnLimitReached::AddECValues(CECTag *tag) const
614 wxString result;
615 if (m_count) {
616 result = wxString::Format(wxT("%i : "), m_count) +
617 m_time.FormatISODate() +
618 wxT(" ") +
619 m_time.FormatISOTime();
620 } else {
621 result = wxTRANSLATE("Never");
623 CECTag value(EC_TAG_STAT_NODE_VALUE, result);
624 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
625 tag->AddTag(value);
628 /* CStatTreeItemTotalClients */
630 #ifndef AMULE_DAEMON
631 wxString CStatTreeItemTotalClients::GetDisplayString() const
633 return CFormat(wxGetTranslation(m_label)) %
634 (m_known->GetValue() + m_unknown->GetValue()) %
635 m_known->GetValue();
637 #endif
639 void CStatTreeItemTotalClients::AddECValues(CECTag *tag) const
641 CECTag value1(EC_TAG_STAT_NODE_VALUE,
642 (uint64)(m_known->GetValue() + m_unknown->GetValue()));
643 tag->AddTag(value1);
644 CECTag value2(EC_TAG_STAT_NODE_VALUE,
645 (uint64)m_known->GetValue());
646 tag->AddTag(value2);
649 #endif /* !EC_REMOTE */
650 // File_checked_for_headers