Upstream tarball 20080901
[amule.git] / src / StatTree.cpp
blob7bdd7ab004d36d5e2e0593bac2bb050aa5d89538
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 #ifndef AMULE_DAEMON
34 #include <common/Format.h> // Needed for CFormat
36 #define a_brackets_b(a,b) (a + wxT(" (") + b + wxT(")"))
38 #endif /* !AMULE_DAEMON */
40 #endif /* !EC_REMOTE */
42 #include <ec/cpp/ECTag.h> // Needed for CECTag
44 #ifdef EC_REMOTE
45 #include <ec/cpp/ECSpecialTags.h> // Needed for CEC_StatTree_Node_Tag
46 #endif
49 #ifndef EC_REMOTE
50 uint32_t NewStatTreeItemId()
52 static uint32_t lastid = 0;
54 return ++lastid;
56 #endif
58 /* CStatTreeItemBase */
60 #ifdef EC_REMOTE
61 CStatTreeItemBase::CStatTreeItemBase(const CECTag *tag)
62 : m_label(((CEC_StatTree_Node_Tag*)tag)->GetDisplayString())
63 , m_uniqueid(tag->GetTagByNameSafe(EC_TAG_STATTREE_NODEID)->GetInt())
65 wxASSERT(tag->GetTagName() == EC_TAG_STATTREE_NODE);
67 for (int i = 0; i < tag->GetTagCount(); ++i) {
68 const CECTag *tmp = tag->GetTagByIndex(i);
69 if (tmp->GetTagName() == EC_TAG_STATTREE_NODE) {
70 m_children.push_back(new CStatTreeItemBase(tmp));
74 #endif /* EC_REMOTE */
76 CStatTreeItemBase::~CStatTreeItemBase()
78 for (std::list<CStatTreeItemBase*>::iterator it = m_children.begin();
79 it != m_children.end(); ++it) {
80 delete *it;
82 m_children.clear();
85 #ifndef EC_REMOTE
86 CStatTreeItemBase* CStatTreeItemBase::AddChild(
87 CStatTreeItemBase* child,
88 uint32_t id,
89 bool skipOneLevel)
91 wxMutexLocker lock(m_lock);
93 if (skipOneLevel) {
94 child->m_parent = m_parent;
95 } else {
96 child->m_parent = this;
98 child->m_id = id;
100 if (m_flags & stSortChildren) {
101 std::list<CStatTreeItemBase*>::iterator it = m_children.begin();
102 while (it != m_children.end() && id < (*it)->m_id) {
103 ++it;
105 m_children.insert(it, child);
106 } else {
107 m_children.push_back(child);
109 return child;
111 #endif /* !EC_REMOTE */
113 bool CStatTreeItemBase::HasVisibleChildren()
115 wxMutexLocker lock(m_lock);
117 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
118 it != m_children.end(); ++it) {
119 if ((*it)->IsVisible()) {
120 return true;
123 return false;
126 #ifndef EC_REMOTE
127 bool CStatTreeItemBase::HasChildWithId(uint32_t id)
129 wxMutexLocker lock(m_lock);
131 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
132 it != m_children.end(); ++it) {
133 if ((*it)->m_id == id) {
134 return true;
137 return false;
140 CStatTreeItemBase* CStatTreeItemBase::GetChildById(uint32_t id)
142 wxMutexLocker lock(m_lock);
144 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
145 it != m_children.end(); ++it) {
146 if ((*it)->m_id == id) {
147 return *it;
150 return NULL;
152 #endif /* !EC_REMOTE */
154 // Note: these functions do not lock the list, because it is already locked at the time they're called
155 #ifndef EC_REMOTE
156 StatTreeItemIterator CStatTreeItemBase::GetFirstVisibleChild(uint32_t max_children)
158 StatTreeItemIterator it = m_children.begin();
159 m_visible_counter = --max_children;
160 while (it != m_children.end() && !(*it)->IsVisible()) ++it;
161 return it;
164 void CStatTreeItemBase::GetNextVisibleChild(StatTreeItemIterator& it)
166 if (m_flags & stCapChildren) {
167 if (m_visible_counter == 0) {
168 it = m_children.end();
169 return;
170 } else {
171 --m_visible_counter;
174 if (it != m_children.end()) ++it;
175 while (it != m_children.end() && !(*it)->IsVisible()) ++it;
177 #endif
180 // Anything below is only for core.
182 #ifndef EC_REMOTE
184 bool CStatTreeItemBase::ValueSort(CStatTreeItemBase* a, CStatTreeItemBase* b)
186 if (a->m_id < 0x00000100 || a->m_id > 0x7fffffff || b->m_id < 0x00000100 || b->m_id > 0x7fffffff) {
187 return a->m_id > b->m_id;
188 } else {
189 return ((CStatTreeItemCounter*)a)->GetValue() > ((CStatTreeItemCounter*)b)->GetValue();
193 #ifndef AMULE_DAEMON
194 wxString CStatTreeItemBase::GetDisplayString() const
196 return wxGetTranslation(m_label);
198 #endif
200 CECTag *CStatTreeItemBase::CreateECTag(uint32_t max_children)
202 if (IsVisible()) {
203 wxMutexLocker lock(m_lock);
204 CECTag *tag = new CECTag(EC_TAG_STATTREE_NODE, m_label);
205 tag->AddTag(CECTag(EC_TAG_STATTREE_NODEID, m_uniqueid));
206 AddECValues(tag);
207 m_visible_counter = max_children - 1;
208 for (std::list<CStatTreeItemBase*>::const_iterator it = m_children.begin();
209 it != m_children.end(); ++it) {
210 CECTag *tmp = (*it)->CreateECTag(max_children);
211 if (tmp) {
212 tag->AddTag(*tmp);
213 delete tmp;
214 if (m_flags & stCapChildren) {
215 if (m_visible_counter == 0) {
216 break;
217 } else {
218 --m_visible_counter;
223 return tag;
224 } else {
225 return NULL;
230 /* CStatTreeItemSimple */
232 #ifndef AMULE_DAEMON
233 wxString CStatTreeItemSimple::GetDisplayString() const
235 switch (m_valuetype) {
236 case vtInteger:
237 switch (m_displaymode) {
238 case dmTime: return CFormat(wxGetTranslation(m_label)) % CastSecondsToHM(m_intvalue);
239 case dmBytes: return CFormat(wxGetTranslation(m_label)) % CastItoXBytes(m_intvalue);
240 default: return CFormat(wxGetTranslation(m_label)) % m_intvalue;
242 case vtFloat: return wxString::Format(wxGetTranslation(m_label), m_floatvalue);
243 case vtString: return CFormat(wxGetTranslation(m_label)) % m_stringvalue;
244 default: return wxGetTranslation(m_label);
247 #endif
249 bool CStatTreeItemSimple::IsVisible() const
251 if (m_flags & stHideIfZero) {
252 switch (m_valuetype) {
253 case vtInteger: return m_intvalue != 0;
254 case vtFloat: return m_floatvalue != 0.0;
255 case vtString: return !m_stringvalue.IsEmpty();
256 default: return false;
259 return true;
262 void CStatTreeItemSimple::AddECValues(CECTag *tag) const
264 switch (m_valuetype) {
265 case vtInteger: {
266 if (m_displaymode == dmTime) {
267 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)m_intvalue);
268 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME));
269 tag->AddTag(value);
270 } else {
271 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint64)m_intvalue);
272 if (m_displaymode == dmBytes) {
273 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
275 tag->AddTag(value);
277 break;
279 case vtFloat: {
280 CECTag value(EC_TAG_STAT_NODE_VALUE, m_floatvalue);
281 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_DOUBLE));
282 tag->AddTag(value);
283 break;
285 case vtString: {
286 CECTag value(EC_TAG_STAT_NODE_VALUE, m_stringvalue);
287 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
288 tag->AddTag(value);
289 break;
291 default:
292 break;
297 /* CStatTreeItemCounterTmpl */
299 #ifndef AMULE_DAEMON
300 template<typename _Tp>
301 wxString CStatTreeItemCounterTmpl<_Tp>::GetDisplayString() const
303 wxString my_label = wxGetTranslation(m_label);
304 // This is needed for client names, for example
305 if (my_label == m_label) {
306 if (m_label.Right(4) == wxT(": %s")) {
307 my_label = wxGetTranslation(
308 m_label.Mid(0, m_label.Length() - 4)) +
309 wxString(wxT(": %s"));
312 CFormat label(my_label);
313 if (m_displaymode == dmBytes) {
314 return label % CastItoXBytes(m_value);
315 } else {
316 wxString result = CFormat(wxT("%u")) % m_value;
317 if ((m_flags & stShowPercent) && m_parent) {
318 result.append(wxString::Format(wxT(" (%.2f%%)"),
319 ((double)m_value / ((CStatTreeItemCounterTmpl<_Tp>*)m_parent)->m_value) * 100.0));
321 return label % result;
325 template wxString CStatTreeItemCounter::GetDisplayString() const;
326 template wxString CStatTreeItemNativeCounter::GetDisplayString() const;
328 #endif
330 template<typename _Tp>
331 void CStatTreeItemCounterTmpl<_Tp>::AddECValues(CECTag *tag) const
333 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint64)m_value);
334 if (m_displaymode == dmBytes) {
335 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
336 } else {
337 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISTRING));
338 if ((m_flags & stShowPercent) && m_parent) {
339 CECTag tmp(EC_TAG_STAT_NODE_VALUE,
340 ((double)m_value / ((CStatTreeItemCounterTmpl<_Tp>*)m_parent)->m_value) * 100.0);
341 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_DOUBLE));
342 value.AddTag(tmp);
345 tag->AddTag(value);
348 template void CStatTreeItemCounter::AddECValues(CECTag *tag) const;
349 template void CStatTreeItemNativeCounter::AddECValues(CECTag *tag) const;
351 /* CStatTreeItemUlDlCounter */
353 #ifndef AMULE_DAEMON
354 wxString CStatTreeItemUlDlCounter::GetDisplayString() const
356 return CFormat(wxGetTranslation(m_label)) %
357 a_brackets_b(CastItoXBytes(m_value), CastItoXBytes(m_value + m_totalfunc()));
359 #endif
361 void CStatTreeItemUlDlCounter::AddECValues(CECTag *tag) const
363 CECTag value(EC_TAG_STAT_NODE_VALUE, m_value);
364 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
365 CECTag tmp(EC_TAG_STAT_NODE_VALUE, m_value + m_totalfunc());
366 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
367 value.AddTag(tmp);
368 tag->AddTag(value);
372 /* CStatTreeItemCounterMax */
374 #ifndef AMULE_DAEMON
375 wxString CStatTreeItemCounterMax::GetDisplayString() const
377 return wxString::Format(wxGetTranslation(m_label), m_value);
379 #endif
381 void CStatTreeItemCounterMax::AddECValues(CECTag *tag) const
383 tag->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE, (uint64)m_value));
387 /* CStatTreeItemPackets */
389 #ifndef AMULE_DAEMON
390 wxString CStatTreeItemPackets::GetDisplayString() const
392 return CFormat(wxGetTranslation(m_label)) %
393 a_brackets_b(CastItoXBytes(m_bytes), CastItoIShort(m_packets));
395 #endif
397 void CStatTreeItemPackets::AddECValues(CECTag *tag) const
399 CECTag value(EC_TAG_STAT_NODE_VALUE, m_bytes);
400 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
401 CECTag tmp(EC_TAG_STAT_NODE_VALUE, (uint64)m_packets);
402 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISHORT));
403 value.AddTag(tmp);
404 tag->AddTag(value);
408 /* CStatTreeItemPacketTotals */
410 #ifndef AMULE_DAEMON
411 wxString CStatTreeItemPacketTotals::GetDisplayString() const
413 uint32_t tmp_packets = m_packets;
414 uint64_t tmp_bytes = m_bytes;
415 for (std::vector<CStatTreeItemPackets*>::const_iterator it = m_counters.begin();
416 it != m_counters.end(); ++it) {
417 tmp_packets += (*it)->m_packets;
418 tmp_bytes += (*it)->m_bytes;
421 return CFormat(wxGetTranslation(m_label)) %
422 a_brackets_b(CastItoXBytes(tmp_bytes), CastItoIShort(tmp_packets));
424 #endif
426 void CStatTreeItemPacketTotals::AddECValues(CECTag *tag) const
428 uint32_t tmp_packets = m_packets;
429 uint64_t tmp_bytes = m_bytes;
430 for (std::vector<CStatTreeItemPackets*>::const_iterator it = m_counters.begin();
431 it != m_counters.end(); ++it) {
432 tmp_packets += (*it)->m_packets;
433 tmp_bytes += (*it)->m_bytes;
436 CECTag value(EC_TAG_STAT_NODE_VALUE, tmp_bytes);
437 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
438 CECTag tmp(EC_TAG_STAT_NODE_VALUE, (uint64)tmp_packets);
439 tmp.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_ISHORT));
440 value.AddTag(tmp);
441 tag->AddTag(value);
445 /* CStatTreeItemTimer */
447 #ifndef AMULE_DAEMON
448 wxString CStatTreeItemTimer::GetDisplayString() const
450 return CFormat(wxGetTranslation(m_label)) %
451 CastSecondsToHM(m_value ? GetTimerSeconds() : 0);
453 #endif
455 void CStatTreeItemTimer::AddECValues(CECTag *tag) const
457 CECTag value(EC_TAG_STAT_NODE_VALUE,
458 m_value ? (uint32)GetTimerSeconds() : (uint32)0);
459 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME));
460 tag->AddTag(value);
464 /* CStatTreeItemAverage */
466 #ifndef AMULE_DAEMON
467 wxString CStatTreeItemAverage::GetDisplayString() const
469 if ((*m_divisor) != 0) {
470 switch (m_displaymode) {
471 case dmBytes:
472 return CFormat(wxGetTranslation(m_label)) %
473 CastItoXBytes((*m_dividend)/(*m_divisor));
474 case dmTime:
475 return CFormat(wxGetTranslation(m_label)) %
476 CastSecondsToHM((*m_dividend)/(*m_divisor));
477 default:
478 return CFormat(wxGetTranslation(m_label)) %
479 (CFormat(wxT("%u")) % ((uint64)(*m_dividend)/(*m_divisor))).GetString();
481 } else {
482 return CFormat(wxGetTranslation(m_label)) % wxT("-");
485 #endif
487 void CStatTreeItemAverage::AddECValues(CECTag *tag) const
489 if ((*m_divisor) != 0) {
490 uint64 data = (*m_dividend)/(*m_divisor);
491 if (m_displaymode == dmTime) {
492 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)data);
493 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_TIME));
494 tag->AddTag(value);
495 } else {
496 CECTag value(EC_TAG_STAT_NODE_VALUE, data);
497 if (m_displaymode == dmBytes) {
498 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_BYTES));
500 tag->AddTag(value);
502 } else {
503 CECTag value(EC_TAG_STAT_NODE_VALUE, wxString(wxT("-")));
504 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
505 tag->AddTag(value);
510 /* CStatTreeItemAverageSpeed */
512 #ifndef AMULE_DAEMON
513 wxString CStatTreeItemAverageSpeed::GetDisplayString() const
515 uint64 time = m_timer->GetTimerSeconds();
516 if (time) {
517 return CFormat(wxGetTranslation(m_label)) % CastItoSpeed((*m_counter)/time);
518 } else {
519 return CFormat(wxGetTranslation(m_label)) % CastItoSpeed(0);
522 #endif
524 void CStatTreeItemAverageSpeed::AddECValues(CECTag *tag) const
526 uint64 time = m_timer->GetTimerSeconds();
527 if (time) {
528 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)((*m_counter)/time));
529 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_SPEED));
530 tag->AddTag(value);
531 } else {
532 CECTag value(EC_TAG_STAT_NODE_VALUE, (uint32)0);
533 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_SPEED));
534 tag->AddTag(value);
539 /* CStatTreeItemRatio */
541 #ifndef AMULE_DAEMON
542 wxString CStatTreeItemRatio::GetDisplayString() const
544 if (m_counter1->GetValue() && m_counter2->GetValue()) {
545 if ((*m_counter2) < (*m_counter1)) {
546 return CFormat(wxGetTranslation(m_label)) %
547 wxString::Format(wxT("%.2f : 1"),
548 (float)(*m_counter1)/(*m_counter2));
549 } else {
550 return CFormat(wxGetTranslation(m_label)) %
551 wxString::Format(wxT("1 : %.2f"),
552 (float)(*m_counter2)/(*m_counter1));
554 } else {
555 return CFormat(wxGetTranslation(m_label)) % _("Not available");
558 #endif
560 void CStatTreeItemRatio::AddECValues(CECTag *tag) const
562 wxString result;
563 if (m_counter1->GetValue() && m_counter2->GetValue()) {
564 if ((*m_counter2) < (*m_counter1)) {
565 result = wxString::Format(wxT("%.2f : 1"), (float)(*m_counter1)/(*m_counter2));
566 } else {
567 result = wxString::Format(wxT("1 : %.2f"), (float)(*m_counter2)/(*m_counter1));
569 } else {
570 result = wxTRANSLATE("Not available");
573 CECTag value(EC_TAG_STAT_NODE_VALUE, result);
574 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
575 tag->AddTag(value);
579 /* CStatTreeItemReconnects */
581 #ifndef AMULE_DAEMON
582 wxString CStatTreeItemReconnects::GetDisplayString() const
584 return CFormat(wxGetTranslation(m_label)) % (m_value ? m_value - 1 : 0);
586 #endif
588 void CStatTreeItemReconnects::AddECValues(CECTag *tag) const
590 tag->AddTag(CECTag(EC_TAG_STAT_NODE_VALUE,
591 m_value ? (uint64)(m_value - 1) : (uint64)0));
594 /* CStatTreeItemMaxConnLimitReached */
596 #ifndef AMULE_DAEMON
597 wxString CStatTreeItemMaxConnLimitReached::GetDisplayString() const
599 if (m_count) {
600 return CFormat(wxGetTranslation(m_label)) %
601 (wxString::Format(wxT("%i : "), m_count) +
602 m_time.FormatISODate() +
603 wxT(" ") +
604 m_time.FormatISOTime());
605 } else {
606 return CFormat(wxGetTranslation(m_label)) % _("Never");
609 #endif
611 void CStatTreeItemMaxConnLimitReached::AddECValues(CECTag *tag) const
613 wxString result;
614 if (m_count) {
615 result = wxString::Format(wxT("%i : "), m_count) +
616 m_time.FormatISODate() +
617 wxT(" ") +
618 m_time.FormatISOTime();
619 } else {
620 result = wxTRANSLATE("Never");
622 CECTag value(EC_TAG_STAT_NODE_VALUE, result);
623 value.AddTag(CECTag(EC_TAG_STAT_VALUE_TYPE, (uint8)EC_VALUE_STRING));
624 tag->AddTag(value);
627 /* CStatTreeItemTotalClients */
629 #ifndef AMULE_DAEMON
630 wxString CStatTreeItemTotalClients::GetDisplayString() const
632 return CFormat(wxGetTranslation(m_label)) %
633 (m_known->GetValue() + m_unknown->GetValue()) %
634 m_known->GetValue();
636 #endif
638 void CStatTreeItemTotalClients::AddECValues(CECTag *tag) const
640 CECTag value1(EC_TAG_STAT_NODE_VALUE,
641 (uint64)(m_known->GetValue() + m_unknown->GetValue()));
642 tag->AddTag(value1);
643 CECTag value2(EC_TAG_STAT_NODE_VALUE,
644 (uint64)m_known->GetValue());
645 tag->AddTag(value2);
648 #endif /* !EC_REMOTE */
649 // File_checked_for_headers