1 //===========================================================================
2 // $Name: arts++-1-1-a13 $
3 // $Id: ArtsRttTimeSeriesTableData.cc,v 1.3 2004/06/23 16:57:27 youngh Exp $
4 //===========================================================================
5 // Copyright Notice
6 //
7 // By accessing this software, arts++, you are duly informed
8 // of and agree to be bound by the conditions described below in this
9 // notice:
10 //
11 // This software product, arts++, is developed by Daniel W. McRobb, and
12 // copyrighted(C) 1998 by the University of California, San Diego
13 // (UCSD), with all rights reserved. UCSD administers the CAIDA grant,
14 // NCR-9711092, under which part of this code was developed.
15 //
16 // There is no charge for arts++ software. You can redistribute it
17 // and/or modify it under the terms of the GNU Lesser General Public
18 // License, Version 2.1, February 1999, which is incorporated by
19 // reference herein.
20 //
21 // arts++ is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF
22 // MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use
23 // of it will not infringe on any third party's intellectual
24 // property rights.
25 //
26 // You should have received a copy of the GNU Lesser General Public
27 // License along with arts++. Copies can also be obtained from:
28 //
29 // http://www.gnu.org/copyleft/lesser.html
30 //
31 // or by writing to:
32 //
33 // Free Software Foundation, Inc.
34 // 59 Temple Place, Suite 330
35 // Boston, MA 02111-1307
36 // USA
37 //
38 // Or contact:
39 //
40 // info@caida.org
41 //===========================================================================
42
43 extern "C" {
44 #include "artslocal.h"
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
49 #include <time.h>
50 #include <assert.h>
51 }
52
53 #include <string>
54 #include <algorithm>
55
56 #ifdef HAVE_IOMANIP
57 #include <iomanip>
58 #else
59 #include <iomanip.h>
60 #endif
61
62 #include "ArtsRttTimeSeriesTableData.hh"
63 #include "ArtsPrimitive.hh"
64
65 using namespace std;
66
67 static const std::string rcsid = "@(#) $Name: arts++-1-1-a13 $ $Id: ArtsRttTimeSeriesTableData.cc,v 1.3 2004/06/23 16:57:27 youngh Exp $";
68
69 //----------------------------------------------------------------------------
70 // ArtsRttTimeSeriesTableEntry::ArtsRttTimeSeriesTableEntry()
71 //............................................................................
72 //
73 //----------------------------------------------------------------------------
ArtsRttTimeSeriesTableEntry()74 ArtsRttTimeSeriesTableEntry::ArtsRttTimeSeriesTableEntry()
75 {
76 this->_rtt = 0;
77 this->_timestamp.tv_sec = 0;
78 this->_timestamp.tv_usec = 0;
79
80 #ifndef NDEBUG
81 ++_numObjects;
82 #endif
83 }
84
85 //----------------------------------------------------------------------------
86 // ArtsRttTimeSeriesTableEntry::
87 // ArtsRttTimeSeriesTableEntry(const ArtsRttTimeSeriesTableEntry & rttEntry)
88 //............................................................................
89 //
90 //----------------------------------------------------------------------------
91 ArtsRttTimeSeriesTableEntry::
ArtsRttTimeSeriesTableEntry(const ArtsRttTimeSeriesTableEntry & rttEntry)92 ArtsRttTimeSeriesTableEntry(const ArtsRttTimeSeriesTableEntry & rttEntry)
93 {
94 this->Rtt(rttEntry.Rtt());
95 this->Timestamp(rttEntry.Timestamp());
96
97 #ifndef NDEBUG
98 ++_numObjects;
99 #endif
100 }
101
102 //----------------------------------------------------------------------------
103 // ArtsRttTimeSeriesTableEntry::~ArtsRttTimeSeriesTableEntry()
104 //............................................................................
105 //
106 //----------------------------------------------------------------------------
~ArtsRttTimeSeriesTableEntry()107 ArtsRttTimeSeriesTableEntry::~ArtsRttTimeSeriesTableEntry()
108 {
109 #ifndef NDEBUG
110 --_numObjects;
111 #endif
112 }
113
114 //----------------------------------------------------------------------------
115 // uint32_t ArtsRttTimeSeriesTableEntry::Rtt() const
116 //............................................................................
117 //
118 //----------------------------------------------------------------------------
Rtt() const119 uint32_t ArtsRttTimeSeriesTableEntry::Rtt() const
120 {
121 return(this->_rtt);
122 }
123
124 //----------------------------------------------------------------------------
125 // uint32_t ArtsRttTimeSeriesTableEntry::Rtt(uint32_t rtt)
126 //............................................................................
127 //
128 //----------------------------------------------------------------------------
Rtt(uint32_t rtt)129 uint32_t ArtsRttTimeSeriesTableEntry::Rtt(uint32_t rtt)
130 {
131 this->_rtt = rtt;
132 return(this->_rtt);
133 }
134
135 //----------------------------------------------------------------------------
136 // const struct timeval & ArtsRttTimeSeriesTableEntry::Timestamp() const
137 //............................................................................
138 //
139 //----------------------------------------------------------------------------
Timestamp() const140 const struct timeval & ArtsRttTimeSeriesTableEntry::Timestamp() const
141 {
142 return(this->_timestamp);
143 }
144
145 //----------------------------------------------------------------------------
146 // const struct timeval &
147 // ArtsRttTimeSeriesTableEntry::Timestamp(const struct timeval & timestamp)
148 //............................................................................
149 //
150 //----------------------------------------------------------------------------
151 const struct timeval &
Timestamp(const struct timeval & timestamp)152 ArtsRttTimeSeriesTableEntry::Timestamp(const struct timeval & timestamp)
153 {
154 this->_timestamp.tv_sec = timestamp.tv_sec;
155 this->_timestamp.tv_usec = timestamp.tv_usec;
156 return(this->_timestamp);
157 }
158
159 //----------------------------------------------------------------------------
160 // ArtsRttTimeSeriesTableEntry &
161 // ArtsRttTimeSeriesTableEntry::
162 // operator = (const ArtsRttTimeSeriesTableEntry & rttEntry)
163 //............................................................................
164 //
165 //----------------------------------------------------------------------------
166 ArtsRttTimeSeriesTableEntry &
167 ArtsRttTimeSeriesTableEntry::
operator =(const ArtsRttTimeSeriesTableEntry & rttEntry)168 operator = (const ArtsRttTimeSeriesTableEntry & rttEntry)
169 {
170 this->Rtt(rttEntry.Rtt());
171 this->Timestamp(rttEntry.Timestamp());
172 return(*this);
173 }
174
BytesNeededForUint32(uint32_t value)175 static uint8_t BytesNeededForUint32(uint32_t value)
176 {
177 if (value > 0x00FFFFFF)
178 return(4);
179 else if (value > 0x0000FFFF)
180 return(3);
181 else if (value > 0x000000FF)
182 return(2);
183 else
184 return(1);
185 }
186
187 //----------------------------------------------------------------------------
188 // ostream & ArtsRttTimeSeriesTableEntry::write(ostream & os,
189 // uint32_t timeBase,
190 // uint32_t prevSecsOffset,
191 // uint8_t version) const
192 //............................................................................
193 //
194 //----------------------------------------------------------------------------
write(ostream & os,uint32_t timeBase,uint32_t prevSecsOffset,uint8_t version) const195 ostream & ArtsRttTimeSeriesTableEntry::write(ostream & os,
196 uint32_t timeBase,
197 uint32_t prevSecsOffset,
198 uint8_t version) const
199 {
200 uint8_t rleFlags = 0;
201 uint8_t timestampSecsLength = 0;
202 uint8_t timestampUsecsLength = 0;
203 uint8_t rttLength = 0;
204 uint32_t timestampSecsOffset;
205
206 if (this->_rtt != k_droppedPacketRtt) {
207 rttLength = BytesNeededForUint32(this->_rtt);
208 rleFlags |= ((rttLength - 1) << 4);
209 }
210 else {
211 rleFlags |= 0x80;
212 }
213
214 timestampSecsOffset = this->_timestamp.tv_sec - timeBase;
215 if (timestampSecsOffset != prevSecsOffset) {
216 rleFlags |= 0x40;
217 timestampSecsLength = BytesNeededForUint32(timestampSecsOffset);
218 rleFlags |= ((timestampSecsLength - 1) << 2);
219 }
220
221 timestampUsecsLength = BytesNeededForUint32(this->_timestamp.tv_usec);
222 rleFlags |= (timestampUsecsLength - 1);
223 os.write((char*)&rleFlags,sizeof(rleFlags));
224 if (rttLength > 0)
225 g_ArtsLibInternal_Primitive.WriteUint32(os,this->_rtt,rttLength);
226 if (timestampSecsLength > 0)
227 g_ArtsLibInternal_Primitive.WriteUint32(os,timestampSecsOffset,
228 timestampSecsLength);
229 g_ArtsLibInternal_Primitive.WriteUint32(os,this->_timestamp.tv_usec,
230 timestampUsecsLength);
231 return(os);
232 }
233
234 //----------------------------------------------------------------------------
235 // int ArtsRttTimeSeriesTableEntry::write(int fd,
236 // uint32_t timeBase,
237 // uint32_t prevSecsOffset,
238 // uint8_t version) const
239 //............................................................................
240 //
241 //----------------------------------------------------------------------------
write(int fd,uint32_t timeBase,uint32_t prevSecsOffset,uint8_t version) const242 int ArtsRttTimeSeriesTableEntry::write(int fd,
243 uint32_t timeBase,
244 uint32_t prevSecsOffset,
245 uint8_t version) const
246 {
247 uint8_t rleFlags = 0;
248 uint8_t timestampSecsLength = 0;
249 uint8_t timestampUsecsLength = 0;
250 uint8_t rttLength = 0;
251 uint32_t timestampSecsOffset;
252
253 if (this->_rtt != k_droppedPacketRtt) {
254 rttLength = BytesNeededForUint32(this->_rtt);
255 rleFlags |= ((rttLength - 1) << 4);
256 }
257 else {
258 rleFlags |= 0x80;
259 }
260
261 timestampSecsOffset = this->_timestamp.tv_sec - timeBase;
262 if (timestampSecsOffset != prevSecsOffset) {
263 rleFlags |= 0x40;
264 timestampSecsLength = BytesNeededForUint32(timestampSecsOffset);
265 rleFlags |= ((timestampSecsLength - 1) << 2);
266 }
267
268 timestampUsecsLength = BytesNeededForUint32(this->_timestamp.tv_usec);
269 rleFlags |= (timestampUsecsLength - 1);
270 int rc = g_ArtsLibInternal_Primitive.FdWrite(fd,&rleFlags,sizeof(rleFlags));
271 if (rc < sizeof(rleFlags))
272 return(-1);
273 int bytesWritten = rc;
274
275 if (rttLength > 0) {
276 rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_rtt,rttLength);
277 if (rc < rttLength)
278 return(-1);
279 bytesWritten += rc;
280 }
281
282 if (timestampSecsLength > 0) {
283 rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,timestampSecsOffset,
284 timestampSecsLength);
285 if (rc < timestampSecsLength)
286 return(-1);
287 bytesWritten += rc;
288 }
289
290 rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_timestamp.tv_usec,
291 timestampUsecsLength);
292 if (rc < timestampUsecsLength)
293 return(-1);
294 bytesWritten += rc;
295
296 return(bytesWritten);
297 }
298
299 //----------------------------------------------------------------------------
300 // uint32_t ArtsRttTimeSeriesTableEntry::Length(uint32_t timeBase,
301 // uint32_t prevSecsOffset,
302 // uint8_t version) const
303 //............................................................................
304 //
305 //----------------------------------------------------------------------------
Length(uint32_t timeBase,uint32_t prevSecsOffset,uint8_t version) const306 uint32_t ArtsRttTimeSeriesTableEntry::Length(uint32_t timeBase,
307 uint32_t prevSecsOffset,
308 uint8_t version) const
309 {
310 uint32_t length = sizeof(uint8_t); // always have rleFlags
311 if (this->_rtt != k_droppedPacketRtt) {
312 length += BytesNeededForUint32(this->_rtt);
313 }
314
315 uint32_t timestampSecsOffset = this->_timestamp.tv_sec - timeBase;
316 if (timestampSecsOffset != prevSecsOffset) {
317 length += BytesNeededForUint32(timestampSecsOffset);
318 }
319
320 length += BytesNeededForUint32(this->_timestamp.tv_usec);
321
322 return(length);
323 }
324
325 //----------------------------------------------------------------------------
326 // istream & ArtsRttTimeSeriesTableEntry::read(istream & is,
327 // uint32_t timeBase,
328 // uint32_t prevSecsOffset,
329 // uint8_t version)
330 //............................................................................
331 //
332 //----------------------------------------------------------------------------
read(istream & is,uint32_t timeBase,uint32_t prevSecsOffset,uint8_t version)333 istream & ArtsRttTimeSeriesTableEntry::read(istream & is,
334 uint32_t timeBase,
335 uint32_t prevSecsOffset,
336 uint8_t version)
337 {
338 uint8_t rleFlags = 0;
339 uint8_t timestampUsecsLength = 0;
340 uint32_t timeVal;
341
342 is.read((char*)&rleFlags,sizeof(rleFlags));
343
344 if (rleFlags & 0x80) {
345 // it's a dropped packet; RTT length is 0
346 this->_rtt = k_droppedPacketRtt;
347 }
348 else {
349 uint8_t rttLength = ((rleFlags >> 4) & 0x03) + 1;
350 g_ArtsLibInternal_Primitive.ReadUint32(is,this->_rtt,rttLength);
351 }
352
353 if (rleFlags & 0x40) {
354 uint8_t timestampSecsLength = ((rleFlags >> 2) & 0x03) + 1;
355 g_ArtsLibInternal_Primitive.ReadUint32(is,timeVal,
356 timestampSecsLength);
357 this->_timestamp.tv_sec = timeVal + timeBase;
358 }
359 else {
360 this->_timestamp.tv_sec = timeBase + prevSecsOffset;
361 }
362
363 timestampUsecsLength = (rleFlags & 0x03) + 1;
364 g_ArtsLibInternal_Primitive.ReadUint32(is,timeVal,
365 timestampUsecsLength);
366 this->_timestamp.tv_usec = timeVal;
367
368 return(is);
369 }
370
371 //----------------------------------------------------------------------------
372 // int ArtsRttTimeSeriesTableEntry::read(int fd, uint32_t timeBase,
373 // uint32_t prevSecsOffset,
374 // uint8_t version)
375 //............................................................................
376 //
377 //----------------------------------------------------------------------------
read(int fd,uint32_t timeBase,uint32_t prevSecsOffset,uint8_t version)378 int ArtsRttTimeSeriesTableEntry::read(int fd, uint32_t timeBase,
379 uint32_t prevSecsOffset,
380 uint8_t version)
381 {
382 uint8_t rleFlags = 0;
383 uint8_t timestampUsecsLength = 0;
384 uint32_t timeVal;
385
386 int rc = g_ArtsLibInternal_Primitive.FdRead(fd,&rleFlags,sizeof(rleFlags));
387 if (rc < sizeof(rleFlags)) {
388 return(-1);
389 }
390
391 int bytesRead = rc;
392
393 if (rleFlags & 0x80) {
394 // it's a dropped packet; RTT length is 0
395 this->_rtt = k_droppedPacketRtt;
396 }
397 else {
398 uint8_t rttLength = ((rleFlags >> 4) & 0x03) + 1;
399 rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,this->_rtt,rttLength);
400 if (rc < rttLength) {
401 return(-1);
402 }
403 bytesRead += rc;
404 }
405
406 if (rleFlags & 0x40) {
407 uint8_t timestampSecsLength = ((rleFlags >> 2) & 0x03) + 1;
408 rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,timeVal,
409 timestampSecsLength);
410 if (rc < timestampSecsLength) {
411 return(-1);
412 }
413 bytesRead += rc;
414 this->_timestamp.tv_sec = timeVal + timeBase;
415 }
416 else {
417 this->_timestamp.tv_sec = timeBase + prevSecsOffset;
418 }
419
420 timestampUsecsLength = (rleFlags & 0x03) + 1;
421 rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,timeVal,
422 timestampUsecsLength);
423 if (rc < timestampUsecsLength) {
424 return(-1);
425 }
426 bytesRead += rc;
427 this->_timestamp.tv_usec = timeVal;
428
429 return(bytesRead);
430 }
431
432 //----------------------------------------------------------------------------
433 // bool ArtsRttTimeSeriesTableEntryGreaterRtt::
434 // operator () (const ArtsRttTimeSeriesTableEntry & rttEntry1,
435 // const ArtsRttTimeSeriesTableEntry & rttEntry2)
436 //............................................................................
437 //
438 //----------------------------------------------------------------------------
439 bool ArtsRttTimeSeriesTableEntryGreaterRtt::
operator ()(const ArtsRttTimeSeriesTableEntry & rttEntry1,const ArtsRttTimeSeriesTableEntry & rttEntry2)440 operator () (const ArtsRttTimeSeriesTableEntry & rttEntry1,
441 const ArtsRttTimeSeriesTableEntry & rttEntry2)
442 {
443 if (rttEntry1.Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
444 if (rttEntry2.Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
445 return(true);
446 }
447 return(false);
448 }
449 if (rttEntry2.Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
450 return(false);
451 }
452
453 return(rttEntry1.Rtt() > rttEntry2.Rtt());
454 }
455
456 //----------------------------------------------------------------------------
457 // bool ArtsRttTimeSeriesTableEntryLessRtt::
458 // operator () (const ArtsRttTimeSeriesTableEntry & rttEntry1,
459 // const ArtsRttTimeSeriesTableEntry & rttEntry2)
460 //............................................................................
461 //
462 //----------------------------------------------------------------------------
463 bool ArtsRttTimeSeriesTableEntryLessRtt::
operator ()(const ArtsRttTimeSeriesTableEntry & rttEntry1,const ArtsRttTimeSeriesTableEntry & rttEntry2)464 operator () (const ArtsRttTimeSeriesTableEntry & rttEntry1,
465 const ArtsRttTimeSeriesTableEntry & rttEntry2)
466 {
467 if (rttEntry1.Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
468 if (rttEntry2.Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
469 return(false);
470 }
471 return(true);
472 }
473 if (rttEntry2.Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
474 return(true);
475 }
476
477 return(rttEntry1.Rtt() < rttEntry2.Rtt());
478 }
479
480 //----------------------------------------------------------------------------
481 // ArtsRttTimeSeriesTableData::ArtsRttTimeSeriesTableData()
482 //............................................................................
483 //
484 //----------------------------------------------------------------------------
ArtsRttTimeSeriesTableData()485 ArtsRttTimeSeriesTableData::ArtsRttTimeSeriesTableData()
486 {
487 this->_timeBase = 0;
488
489 #ifndef NDEBUG
490 ++_numObjects;
491 #endif
492 }
493
494 //----------------------------------------------------------------------------
495 // ArtsRttTimeSeriesTableData::
496 // ArtsRttTimeSeriesTableData(const ArtsRttTimeSeriesTableData & rttTable)
497 //............................................................................
498 //
499 //----------------------------------------------------------------------------
500 ArtsRttTimeSeriesTableData::
ArtsRttTimeSeriesTableData(const ArtsRttTimeSeriesTableData & rttTable)501 ArtsRttTimeSeriesTableData(const ArtsRttTimeSeriesTableData & rttTable)
502 {
503 this->_timeBase = rttTable.TimeBase();
504 this->_rttEntries = rttTable.RttEntries();
505
506 #ifndef NDEBUG
507 ++_numObjects;
508 #endif
509 }
510
511 //----------------------------------------------------------------------------
512 // ArtsRttTimeSeriesTableData::~ArtsRttTimeSeriesTableData()
513 //............................................................................
514 //
515 //----------------------------------------------------------------------------
~ArtsRttTimeSeriesTableData()516 ArtsRttTimeSeriesTableData::~ArtsRttTimeSeriesTableData()
517 {
518 this->_rttEntries.erase(this->_rttEntries.begin(),this->_rttEntries.end());
519
520 #ifndef NDEBUG
521 --_numObjects;
522 #endif
523 }
524
525 //----------------------------------------------------------------------------
526 // ArtsRttTimeSeriesTableData &
527 // ArtsRttTimeSeriesTableData::
528 // operator = (const ArtsRttTimeSeriesTableData & rttTable)
529 //............................................................................
530 //
531 //----------------------------------------------------------------------------
532 ArtsRttTimeSeriesTableData &
533 ArtsRttTimeSeriesTableData::
operator =(const ArtsRttTimeSeriesTableData & rttTable)534 operator = (const ArtsRttTimeSeriesTableData & rttTable)
535 {
536 this->_rttEntries = rttTable.RttEntries();
537 return(*this);
538 }
539
540 //----------------------------------------------------------------------------
541 // uint32_t ArtsRttTimeSeriesTableData::TimeBase() const
542 //............................................................................
543 //
544 //----------------------------------------------------------------------------
TimeBase() const545 uint32_t ArtsRttTimeSeriesTableData::TimeBase() const
546 {
547 if (this->_rttEntries.size() > 0)
548 if (this->_timeBase == 0 ||
549 this->_timeBase > this->_rttEntries[0].Timestamp().tv_sec)
550 this->_timeBase = this->_rttEntries[0].Timestamp().tv_sec;
551 return(this->_timeBase);
552 }
553
554 //----------------------------------------------------------------------------
555 // uint32_t ArtsRttTimeSeriesTableData::TimeBase(uint32_t timeBase)
556 //............................................................................
557 //
558 //----------------------------------------------------------------------------
TimeBase(uint32_t timeBase)559 uint32_t ArtsRttTimeSeriesTableData::TimeBase(uint32_t timeBase)
560 {
561 this->_timeBase = timeBase;
562 return(this->_timeBase);
563 }
564
565
566 //----------------------------------------------------------------------------
567 // vector<ArtsRttTimeSeriesTableEntry> &
568 // ArtsRttTimeSeriesTableData::RttEntries() const
569 //............................................................................
570 //
571 //----------------------------------------------------------------------------
572 vector<ArtsRttTimeSeriesTableEntry> &
RttEntries() const573 ArtsRttTimeSeriesTableData::RttEntries() const
574 {
575 return(this->_rttEntries);
576 }
577
578 //----------------------------------------------------------------------------
579 // void ArtsRttTimeSeriesTableData::
580 // AddRttEntry(const ArtsRttTimeSeriesTableEntry & rttEntry)
581 //............................................................................
582 //
583 //----------------------------------------------------------------------------
584 void ArtsRttTimeSeriesTableData::
AddRttEntry(const ArtsRttTimeSeriesTableEntry & rttEntry)585 AddRttEntry(const ArtsRttTimeSeriesTableEntry & rttEntry)
586 {
587 this->_rttEntries.push_back(rttEntry);
588 if (this->_timeBase == 0 || this->_timeBase > rttEntry.Timestamp().tv_sec)
589 this->_timeBase = rttEntry.Timestamp().tv_sec;
590
591 return;
592 }
593
594 //----------------------------------------------------------------------------
595 // istream & ArtsRttTimeSeriesTableData::read(istream& is,
596 // uint8_t version)
597 //............................................................................
598 //
599 //----------------------------------------------------------------------------
read(istream & is,uint8_t version)600 istream & ArtsRttTimeSeriesTableData::read(istream& is, uint8_t version)
601 {
602 uint32_t numRttEntries, rttEntryNum;
603 ArtsRttTimeSeriesTableEntry rttEntry;
604 uint32_t rttUsecs;
605 uint32_t timestampSecs, timestampUsecs;
606 struct timeval tv;
607
608 if (! this->_rttEntries.empty())
609 this->_rttEntries.clear();
610
611 g_ArtsLibInternal_Primitive.ReadUint32(is,this->_timeBase,
612 sizeof(this->_timeBase));
613 g_ArtsLibInternal_Primitive.ReadUint32(is,numRttEntries,
614 sizeof(numRttEntries));
615 uint32_t prevSecsOffset = 0;
616 for (rttEntryNum = 0; rttEntryNum != numRttEntries; ++rttEntryNum) {
617 rttEntry.read(is,this->_timeBase,prevSecsOffset,version);
618 prevSecsOffset = rttEntry.Timestamp().tv_sec - this->_timeBase;
619 this->_rttEntries.push_back(rttEntry);
620 }
621 return(is);
622 }
623
624 //----------------------------------------------------------------------------
625 // int ArtsRttTimeSeriesTableData::read(int fd, uint8_t version)
626 //............................................................................
627 //
628 //----------------------------------------------------------------------------
read(int fd,uint8_t version)629 int ArtsRttTimeSeriesTableData::read(int fd, uint8_t version)
630 {
631 uint32_t numRttEntries, rttEntryNum;
632 ArtsRttTimeSeriesTableEntry rttEntry;
633 uint32_t rttUsecs;
634 uint32_t timestampSecs, timestampUsecs;
635 struct timeval tv;
636
637 if (this->_rttEntries.size() > 0)
638 this->_rttEntries.clear();
639
640 int rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,this->_timeBase,
641 sizeof(this->_timeBase));
642 if (rc < sizeof(this->_timeBase))
643 return(-1);
644 int bytesRead = rc;
645
646 rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,numRttEntries,
647 sizeof(numRttEntries));
648 if (rc < sizeof(numRttEntries))
649 return(-1);
650 bytesRead += rc;
651
652 uint32_t prevSecsOffset = 0;
653 for (rttEntryNum = 0; rttEntryNum < numRttEntries; ++rttEntryNum) {
654 rc = rttEntry.read(fd,this->_timeBase,prevSecsOffset,version);
655 if (rc < 0)
656 return(-1);
657 bytesRead += rc;
658 prevSecsOffset = rttEntry.Timestamp().tv_sec - this->_timeBase;
659 this->_rttEntries.push_back(rttEntry);
660 }
661
662 return(bytesRead);
663 }
664
665 //----------------------------------------------------------------------------
666 // uint32_t ArtsRttTimeSeriesTableData::Length(uint8_t version) const
667 //............................................................................
668 //
669 //----------------------------------------------------------------------------
Length(uint8_t version) const670 uint32_t ArtsRttTimeSeriesTableData::Length(uint8_t version) const
671 {
672 uint32_t length = 0;
673 uint32_t rttEntryNum, numRttEntries;
674 uint32_t timestampSecs;
675
676 length += sizeof(this->_timeBase);
677 length += sizeof(numRttEntries); // number of entries
678
679 timestampSecs = this->_rttEntries[0].Timestamp().tv_sec;
680 numRttEntries = this->_rttEntries.size();
681
682 uint32_t prevSecsOffset = 0;
683 for (rttEntryNum = 0; rttEntryNum != numRttEntries; ++rttEntryNum) {
684 length += this->_rttEntries[rttEntryNum].Length(timestampSecs,
685 prevSecsOffset,version);
686 prevSecsOffset = this->_rttEntries[rttEntryNum].Timestamp().tv_sec -
687 timestampSecs;
688 }
689 return(length);
690 }
691
692 //----------------------------------------------------------------------------
693 // ostream & ArtsRttTimeSeriesTableData::write(ostream & os,
694 // uint8_t version) const
695 //............................................................................
696 //
697 //----------------------------------------------------------------------------
write(ostream & os,uint8_t version) const698 ostream & ArtsRttTimeSeriesTableData::write(ostream & os,
699 uint8_t version) const
700 {
701 uint32_t numRttEntries, rttEntryNum;
702 uint32_t rttUsecs;
703 uint32_t timestampSecs, timestampUsecs;
704 uint32_t timestampSecsOffset;
705 uint8_t prevTimestampSecsSize = 1;
706 uint32_t prevOffset = 0;
707
708 if (this->_rttEntries.size() > 0) {
709 if (this->_timeBase == 0 ||
710 this->_timeBase > this->_rttEntries[0].Timestamp().tv_sec) {
711 this->_timeBase = this->_rttEntries[0].Timestamp().tv_sec;
712 }
713 }
714 g_ArtsLibInternal_Primitive.WriteUint32(os,this->_timeBase,
715 sizeof(this->_timeBase));
716
717 numRttEntries = this->_rttEntries.size();
718 g_ArtsLibInternal_Primitive.WriteUint32(os,numRttEntries,
719 sizeof(numRttEntries));
720
721 for (rttEntryNum = 0; rttEntryNum != numRttEntries; ++rttEntryNum) {
722 this->_rttEntries[rttEntryNum].write(os,this->_timeBase,prevOffset,
723 version);
724 prevOffset =
725 this->_rttEntries[rttEntryNum].Timestamp().tv_sec - this->_timeBase;
726 }
727 return(os);
728 }
729
730 //----------------------------------------------------------------------------
731 // int ArtsRttTimeSeriesTableData::write(int fd, uint8_t version) const
732 //............................................................................
733 //
734 //----------------------------------------------------------------------------
write(int fd,uint8_t version) const735 int ArtsRttTimeSeriesTableData::write(int fd, uint8_t version) const
736 {
737 uint32_t numRttEntries, rttEntryNum;
738 uint32_t rttUsecs;
739 uint32_t timestampSecs, timestampUsecs;
740 uint32_t timestampSecsOffset;
741 uint8_t prevTimestampSecsSize = 1;
742 uint32_t prevOffset = 0;
743
744 if (this->_rttEntries.size() > 0) {
745 if (this->_timeBase == 0 ||
746 this->_timeBase > this->_rttEntries[0].Timestamp().tv_sec) {
747 this->_timeBase = this->_rttEntries[0].Timestamp().tv_sec;
748 }
749 }
750 int rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_timeBase,
751 sizeof(this->_timeBase));
752 if (rc < sizeof(this->_timeBase))
753 return(-1);
754 int bytesWritten = rc;
755
756 numRttEntries = this->_rttEntries.size();
757 rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,numRttEntries,
758 sizeof(numRttEntries));
759 if (rc < sizeof(numRttEntries))
760 return(-1);
761 bytesWritten += rc;
762
763 for (rttEntryNum = 0; rttEntryNum != numRttEntries; ++rttEntryNum) {
764 rc = this->_rttEntries[rttEntryNum].write(fd,this->_timeBase,prevOffset,
765 version);
766 if (rc < 0)
767 return(-1);
768 bytesWritten += rc;
769
770 prevOffset =
771 this->_rttEntries[rttEntryNum].Timestamp().tv_sec - this->_timeBase;
772 }
773
774 return(bytesWritten);
775 }
776
777 //----------------------------------------------------------------------------
778 // void ArtsRttTimeSeriesTableData::SortEntriesByTimestamp()
779 //............................................................................
780 //
781 //----------------------------------------------------------------------------
SortEntriesByTimestamp()782 void ArtsRttTimeSeriesTableData::SortEntriesByTimestamp()
783 {
784 sort(this->_rttEntries.begin(),this->_rttEntries.end(),
785 ArtsRttTimeSeriesTableEntryTimestampsLess());
786 if (this->_rttEntries.size() > 0)
787 if (this->_timeBase == 0 ||
788 this->_timeBase > this->_rttEntries[0].Timestamp().tv_sec)
789 this->_timeBase = this->_rttEntries[0].Timestamp().tv_sec;
790
791 return;
792 }
793
794 //----------------------------------------------------------------------------
795 // const ArtsRttTimeSeriesTableEntry &
796 // ArtsRttTimeSeriesTableData::RttMax() const
797 //............................................................................
798 //
799 //----------------------------------------------------------------------------
800 const ArtsRttTimeSeriesTableEntry &
RttMax() const801 ArtsRttTimeSeriesTableData::RttMax() const
802 {
803 vector<ArtsRttTimeSeriesTableEntry> rttVect;
804 vector<ArtsRttTimeSeriesTableEntry>::const_iterator rttIter;
805 static ArtsRttTimeSeriesTableEntry rttEntry;
806
807 for (rttIter = this->_rttEntries.begin();
808 rttIter != this->_rttEntries.end(); ++rttIter) {
809 if ((*rttIter).Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
810 rttVect.push_back(*rttIter);
811 }
812 }
813 if (rttVect.size() > 0) {
814 rttEntry = *(max_element(rttVect.begin(),rttVect.end(),
815 ArtsRttTimeSeriesTableEntryLessRtt()));
816 return(rttEntry);
817 }
818 else {
819 struct timeval timestamp;
820 timestamp.tv_sec = 0;
821 timestamp.tv_usec = 0;
822 rttEntry.Rtt(0);
823 rttEntry.Timestamp(timestamp);
824 return(rttEntry);
825 }
826 }
827
828 //----------------------------------------------------------------------------
829 // const ArtsRttTimeSeriesTableEntry &
830 // ArtsRttTimeSeriesTableData::RttMin() const
831 //............................................................................
832 //
833 //----------------------------------------------------------------------------
834 const ArtsRttTimeSeriesTableEntry &
RttMin() const835 ArtsRttTimeSeriesTableData::RttMin() const
836 {
837 vector<ArtsRttTimeSeriesTableEntry> rttVect;
838 vector<ArtsRttTimeSeriesTableEntry>::const_iterator rttIter;
839 static ArtsRttTimeSeriesTableEntry rttEntry;
840
841 for (rttIter = this->_rttEntries.begin();
842 rttIter != this->_rttEntries.end(); ++rttIter) {
843 if ((*rttIter).Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
844 rttVect.push_back(*rttIter);
845 }
846 }
847 if (rttVect.size() > 0) {
848 rttEntry = *(min_element(rttVect.begin(),rttVect.end(),
849 ArtsRttTimeSeriesTableEntryLessRtt()));
850 return(rttEntry);
851 }
852 else {
853 struct timeval timestamp;
854 timestamp.tv_sec = 0;
855 timestamp.tv_usec = 0;
856 rttEntry.Rtt(0);
857 rttEntry.Timestamp(timestamp);
858 return(rttEntry);
859 }
860 }
861
862 //----------------------------------------------------------------------------
863 // const ArtsRttTimeSeriesTableEntry &
864 // ArtsRttTimeSeriesTableData::RttPercentile() const
865 //............................................................................
866 //
867 //----------------------------------------------------------------------------
868 const ArtsRttTimeSeriesTableEntry &
RttPercentile(int percentile) const869 ArtsRttTimeSeriesTableData::RttPercentile(int percentile) const
870 {
871 int percentilePosition;
872 vector<ArtsRttTimeSeriesTableEntry> rttVect;
873 vector<ArtsRttTimeSeriesTableEntry>::const_iterator rttIter;
874 static ArtsRttTimeSeriesTableEntry rttEntry;
875
876 assert((percentile >= 0) && (percentile <= 100));
877
878 for (rttIter = this->_rttEntries.begin();
879 rttIter != this->_rttEntries.end(); ++rttIter) {
880 if ((*rttIter).Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
881 rttVect.push_back(*rttIter);
882 }
883 }
884
885 if (rttVect.size() > 0) {
886 percentilePosition = (int)((rttVect.size() - 1) * (percentile/100.0));
887 nth_element(rttVect.begin(),rttVect.begin() + percentilePosition,
888 rttVect.end(),ArtsRttTimeSeriesTableEntryLessRtt());
889 rttEntry = rttVect[percentilePosition];
890 return(rttEntry);
891 }
892 else {
893 struct timeval timestamp;
894 timestamp.tv_sec = 0;
895 timestamp.tv_usec = 0;
896 rttEntry.Rtt(0);
897 rttEntry.Timestamp(timestamp);
898 return(rttEntry);
899 }
900 }
901
902 //----------------------------------------------------------------------------
903 // size_t ArtsRttTimeSeriesTableData::
904 // RttPercentiles(const vector<int> & percentiles,
905 // vector<uint32_t> & results) const
906 //............................................................................
907 //
908 //----------------------------------------------------------------------------
909 size_t ArtsRttTimeSeriesTableData::
RttPercentiles(const vector<int> & percentiles,vector<uint32_t> & results) const910 RttPercentiles(const vector<int> & percentiles,
911 vector<uint32_t> & results) const
912 {
913 vector<ArtsRttTimeSeriesTableEntry> rttVect(this->_rttEntries);
914
915 if (! results.empty())
916 results.clear();
917
918 if (! rttVect.empty()) {
919 int percentilePosition;
920 vector<int>::const_iterator pctIter;
921 for (pctIter = percentiles.begin();
922 pctIter != percentiles.end(); ++pctIter) {
923 assert((*pctIter >= 0) && (*pctIter <= 100));
924 percentilePosition = (int)((rttVect.size() - 1) * (*pctIter/100.0));
925 nth_element(rttVect.begin(),rttVect.begin() + percentilePosition,
926 rttVect.end(),ArtsRttTimeSeriesTableEntryLessRtt());
927 results.push_back(rttVect[percentilePosition].Rtt());
928 }
929 }
930
931 return(results.size());
932 }
933
934 //----------------------------------------------------------------------------
935 // const ArtsRttTimeSeriesTableEntry &
936 // ArtsRttTimeSeriesTableData::RttMedian() const
937 //............................................................................
938 //
939 //----------------------------------------------------------------------------
940 const ArtsRttTimeSeriesTableEntry &
RttMedian() const941 ArtsRttTimeSeriesTableData::RttMedian() const
942 {
943 return(this->RttPercentile(50));
944 }
945
946 //----------------------------------------------------------------------------
947 // const ArtsRttTimeSeriesTableEntry &
948 // ArtsRttTimeSeriesTableData::RttLowerQuartile() const
949 //............................................................................
950 //
951 //----------------------------------------------------------------------------
952 const ArtsRttTimeSeriesTableEntry &
RttLowerQuartile() const953 ArtsRttTimeSeriesTableData::RttLowerQuartile() const
954 {
955 return(this->RttPercentile(25));
956 }
957
958 //----------------------------------------------------------------------------
959 // const ArtsRttTimeSeriesTableEntry &
960 // ArtsRttTimeSeriesTableData::RttUpperQuartile() const
961 //............................................................................
962 //
963 //----------------------------------------------------------------------------
964 const ArtsRttTimeSeriesTableEntry &
RttUpperQuartile() const965 ArtsRttTimeSeriesTableData::RttUpperQuartile() const
966 {
967 return(this->RttPercentile(75));
968 }
969
970 //----------------------------------------------------------------------------
971 // double ArtsRttTimeSeriesTableData::AveragePacketLoss() const
972 //............................................................................
973 //
974 //----------------------------------------------------------------------------
AveragePacketLoss() const975 double ArtsRttTimeSeriesTableData::AveragePacketLoss() const
976 {
977 if (this->_rttEntries.size() > 0) {
978 uint32_t droppedPackets = 0;
979 vector<ArtsRttTimeSeriesTableEntry>::const_iterator rttIter;
980
981 for (rttIter = this->_rttEntries.begin();
982 rttIter != this->_rttEntries.end(); ++rttIter) {
983 if (rttIter->Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
984 ++droppedPackets;
985 }
986 }
987
988 double pktLoss = (droppedPackets * 100.0) / this->_rttEntries.size();
989 return(pktLoss);
990 }
991 else {
992 return(0.0);
993 }
994 }
995
996 //----------------------------------------------------------------------------
997 // void ArtsRttTimeSeriesTableData::ClearRttData()
998 //............................................................................
999 //
1000 //----------------------------------------------------------------------------
ClearRttData()1001 void ArtsRttTimeSeriesTableData::ClearRttData()
1002 {
1003 if (this->_rttEntries.size() > 0) {
1004 this->_rttEntries.clear();
1005 }
1006 this->_timeBase = 0;
1007 return;
1008 }
1009
1010
1011 //----------------------------------------------------------------------------
1012 // ostream& operator << (ostream& os,
1013 // const ArtsRttTimeSeriesTableData & rttTimeSeriesTable)
1014 //............................................................................
1015 //
1016 //----------------------------------------------------------------------------
operator <<(ostream & os,const ArtsRttTimeSeriesTableData & rttTimeSeriesTable)1017 ostream& operator << (ostream& os,
1018 const ArtsRttTimeSeriesTableData & rttTimeSeriesTable)
1019 {
1020 struct in_addr addrIn;
1021 uint32_t rttNum;
1022 struct tm *Tm;
1023 time_t tsSecs;
1024 double tsSecsFraction;
1025
1026 os << "RTT TIME SERIES OBJECT DATA" << endl;
1027 for (rttNum = 0; rttNum < rttTimeSeriesTable.RttEntries().size(); ++rttNum) {
1028 tsSecs = rttTimeSeriesTable.RttEntries()[rttNum].Timestamp().tv_sec;
1029 tsSecsFraction =
1030 rttTimeSeriesTable.RttEntries()[rttNum].Timestamp().tv_usec / 1000.0;
1031
1032 Tm = localtime(&tsSecs);
1033 os << setiosflags(ios::internal);
1034 os << "\t timestamp: " << setfill('0') << setw(2) << Tm->tm_mon+1 << "/"
1035 << setw(2) << Tm->tm_mday << "/" << setw(4) << Tm->tm_year+1900
1036 << " " << setw(2) << Tm->tm_hour << ":" << setw(2)
1037 << Tm->tm_min << ":" << setw(2) << Tm->tm_sec
1038 << "." << setw(3) << (int)(tsSecsFraction)
1039 << " ("
1040 << hex << (int)(tsSecs) << ")" << dec;
1041 os << setfill(' ');
1042 os << resetiosflags(ios::internal);
1043 os << " RTT: ";
1044 if (rttTimeSeriesTable.RttEntries()[rttNum].Rtt() ==
1045 ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) {
1046 os << "lost packet" << endl;
1047 }
1048 else {
1049 os << rttTimeSeriesTable.RttEntries()[rttNum].Rtt()/1000.0
1050 << " ms" << endl;
1051 }
1052 }
1053 return(os);
1054 }
1055
1056 uint32_t ArtsRttTimeSeriesTableEntry::_numObjects = 0;
1057 uint32_t ArtsRttTimeSeriesTableData::_numObjects = 0;
1058