@@ -41,9 +41,96 @@ void BWGraphSource::update()
4141 std::cerr << " got " << std::dec << thc.in_rstcl .size () << " in clues" << std::endl;
4242#endif
4343
44- // keep track of them, in case we need to change the sorting
44+ // This does two important things:
45+ // 1 - look into the previous record and add the missing ones to the current record with cumulated sizes only, in order to
46+ // remove gaps in the traffic clues history when some elements are not present.
47+ // 2 - if the received data contains duplicates, zero the cumulative data of all similar elements except one which is set to the max
48+ // so that they can be added without creating errors when e.g. adding all elements of the same service.
49+
50+ auto add_missing_elements = [](std::list<RSTrafficClue>& existing_lst,const std::list<RSTrafficClue>& to_add) {
51+
52+ auto some_hash_function = [](const RSTrafficClue& tc) -> uint64_t {
53+ return tc.peer_id .toByteArray ()[0 ]+(tc.peer_id .toByteArray ()[1 ] << 8 ) + (tc.peer_id .toByteArray ()[2 ] << 16 )
54+ + (tc.peer_id .toByteArray ()[3 ] << 24 ) + ((uint64_t )tc.service_id << 32 ) + ((uint64_t )tc.service_sub_id << 48 );
55+ };
56+ // map containing for each (service_id,service_sub_id,peer) the total and max cumulated size and cumulated count so far.
57+
58+ struct MaxRecord {
59+ uint64_t max_cumulated_size;
60+ uint64_t max_cumulated_count;
61+
62+ MaxRecord () : max_cumulated_size(0 ),max_cumulated_count(0 ){}
63+ };
64+
65+ std::map<uint64_t ,MaxRecord> present;
66+ uint64_t ts = existing_lst.empty ()?0 :existing_lst.front ().TS ;
67+
68+ auto correct_max_total = [](uint64_t & proposed_value,uint64_t & maximum_so_far) {
69+ uint64_t mx = std::max (proposed_value,maximum_so_far);
70+
71+ if (proposed_value <= mx)
72+ proposed_value = 0 ;
73+ else
74+ {
75+ proposed_value -= maximum_so_far;
76+ maximum_so_far = mx;
77+ }
78+ };
79+
80+ for (auto & c:existing_lst)
81+ {
82+ std::cerr << " inserting element with hash " << some_hash_function (c) << " peer=" << c.peer_id << " service " << c.service_id
83+ << " (" << (int )c.service_sub_id << " )" << std::endl;
4584
85+ uint64_t hash = some_hash_function (c);
86+ auto it = present.find (hash);
87+
88+ if (it != present.end ())
89+ {
90+ // One record is already there. So we prevent the duplicate count of cumulated values by making sure
91+ // that it->second + c = max(it->second,c)
92+
93+ correct_max_total (c.cumulated_size ,it->second .max_cumulated_size );
94+ correct_max_total (c.cumulated_count ,it->second .max_cumulated_count );
95+ }
96+ else
97+ {
98+ MaxRecord mx;
99+ mx.max_cumulated_size = c.cumulated_size ;
100+ mx.max_cumulated_count = c.cumulated_count ;
101+ present[hash] = mx;
102+ }
103+ }
104+
105+ for (const auto & x:to_add)
106+ if (present.find (some_hash_function (x)) == present.end ()) // each missing element is added only once
107+ {
108+ auto x_cpy (x);
109+ x_cpy.size = 0 ;
110+ x_cpy.count = 0 ;
111+ x_cpy.TS = ts;
112+
113+ std::cerr << " Adding new element with hash " << some_hash_function (x) << " peer=" << x.peer_id << " service " << x.service_id
114+ << " (" << (int )x.service_sub_id << " )" << std::endl;
115+ existing_lst.push_back (x_cpy);
116+ present[some_hash_function (x)] = MaxRecord (); // we dont' care for values here.
117+ }
118+ };
46119 thc.time_stamp = getTime () ;
120+
121+ if (!mTrafficHistory .empty ())
122+ {
123+ add_missing_elements (thc.out_rstcl ,mTrafficHistory .back ().out_rstcl );
124+ // add_missing_elements(thc.in_rstcl ,mTrafficHistory.back().in_rstcl);
125+ }
126+
127+ std::cerr << " Traffic detail:" << std::endl;
128+ for (const auto & tc:thc.out_rstcl )
129+ std::cerr << " TS=" << tc.TS << " peer=" << tc.peer_id << " service " << tc.service_id << " ("
130+ << (int )tc.service_sub_id << " ) " << tc.size << " ( " << tc.cumulated_size << " )" << tc.count << " ( " << tc.cumulated_count << " )" << std::endl;
131+
132+ // keep track of them, in case we need to change the sorting
133+
47134 mTrafficHistory .push_back (thc) ;
48135
49136 std::set<RsPeerId> fds ;
@@ -200,6 +287,19 @@ void BWGraphSource::update()
200287#endif
201288}
202289
290+ void BWGraphSource::clear ()
291+ {
292+ _total_sent =0 ;
293+ _total_recv =0 ;
294+
295+ _total_duration_seconds =0 ;
296+
297+ mTrafficHistory .clear () ;
298+
299+ mVisibleFriends .clear () ;
300+ mVisibleServices .clear () ;
301+
302+ }
203303void BWGraphSource::getCumulatedValues (std::vector<float >& vals) const
204304{
205305 if (_current_unit == UNIT_KILOBYTES && _total_duration_seconds > 0.0 )
@@ -244,23 +344,23 @@ void BWGraphSource::convertTrafficClueToValues(const std::list<RSTrafficClue>& l
244344 {
245345 std::vector<RSTrafficClue> clue_per_sub_id (256 ) ;
246346
247- for (std::list<RSTrafficClue>::const_iterator it (lst.begin ());it!=lst.end ();++it)
248- if (it->peer_id == _current_selected_friend && it->service_id == _current_selected_service)
249- clue_per_sub_id[it->service_sub_id ] += *it ;
347+ for (std::list<RSTrafficClue>::const_iterator it (lst.begin ());it!=lst.end ();++it)
348+ if (it->peer_id == _current_selected_friend && it->service_id == _current_selected_service)
349+ clue_per_sub_id[it->service_sub_id ] += *it ;
250350
251- for (uint32_t i=0 ;i<256 ;++i)
252- if (clue_per_sub_id[i].count > 0 )
351+ for (uint32_t i=0 ;i<256 ;++i)
352+ if (clue_per_sub_id[i].cumulated_count > 0 ) // checks if i corresponds to an active service
253353 vals[makeSubItemName (clue_per_sub_id[i].service_id ,i)] = select_value (clue_per_sub_id[i]);
254- }
354+ }
255355 break ;
256356
257357 case GRAPH_TYPE_ALL: // single friend, all services => one curve per service id
258358 {
259359 std::map<uint16_t ,RSTrafficClue> clue_per_id ;
260360
261- for (std::list<RSTrafficClue>::const_iterator it (lst.begin ());it!=lst.end ();++it)
262- if (it->peer_id == _current_selected_friend)
263- clue_per_id[it->service_id ] += *it ;
361+ for (std::list<RSTrafficClue>::const_iterator it (lst.begin ());it!=lst.end ();++it)
362+ if (it->peer_id == _current_selected_friend)
363+ clue_per_id[it->service_id ] += *it ;
264364
265365 for (std::map<uint16_t ,RSTrafficClue>::const_iterator it (clue_per_id.begin ());it!=clue_per_id.end ();++it)
266366 vals[mServiceInfoMap [it->first ].mServiceName ] = select_value (it->second );
@@ -271,9 +371,9 @@ void BWGraphSource::convertTrafficClueToValues(const std::list<RSTrafficClue>& l
271371 RSTrafficClue total ;
272372 std::map<uint16_t ,RSTrafficClue> clue_per_id ;
273373
274- for (std::list<RSTrafficClue>::const_iterator it (lst.begin ());it!=lst.end ();++it)
275- if (it->peer_id == _current_selected_friend)
276- total += *it ;
374+ for (std::list<RSTrafficClue>::const_iterator it (lst.begin ());it!=lst.end ();++it)
375+ if (it->peer_id == _current_selected_friend)
376+ total += *it ;
277377
278378 vals[visibleFriendName (_current_selected_friend)] = select_value (total);
279379 }
@@ -328,7 +428,7 @@ void BWGraphSource::convertTrafficClueToValues(const std::list<RSTrafficClue>& l
328428 }
329429
330430 for (uint32_t i=0 ;i<256 ;++i)
331- if (clue_per_sub_id[i].count > 0 )
431+ if (clue_per_sub_id[i].cumulated_count > 0 ) // checks if this corresponds to an active service
332432 vals[makeSubItemName (clue_per_sub_id[i].service_id ,i)] = select_value (clue_per_sub_id[i]);
333433 }
334434 break ;
@@ -353,6 +453,8 @@ void BWGraphSource::convertTrafficClueToValues(const std::list<RSTrafficClue>& l
353453 total += *it;
354454
355455 vals[QString (" Total" ).toStdString ()] = select_value (total);
456+ std::cerr << " Total is " << total << std::endl;
457+ std::cerr << " Value is " << select_value (total) << std::endl;
356458 }
357459 break ;
358460 }
@@ -555,6 +657,7 @@ void BWGraphSource::setDirection(int dir)
555657
556658void BWGraphSource::setTiming (int t)
557659{
660+ std::cerr << " BWGraphSource: updating" << std::endl;
558661 if (t == _current_timing)
559662 return ;
560663
@@ -563,7 +666,7 @@ void BWGraphSource::setTiming(int t)
563666}
564667void BWGraphSource::recomputeCurrentCurves ()
565668{
566- #ifdef BWGRAPH_DEBUG
669+ #ifndef BWGRAPH_DEBUG
567670 std::cerr << " BWGraphSource: recomputing current curves." << std::endl;
568671#endif
569672
0 commit comments