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