//=========================================================================== // $Name: arts++-1-1-a12 $ // $Id: ArtsRttTimeSeriesTableData.cc,v 1.3 2004/06/23 16:57:27 youngh Exp $ //=========================================================================== // Copyright Notice // // By accessing this software, arts++, you are duly informed // of and agree to be bound by the conditions described below in this // notice: // // This software product, arts++, is developed by Daniel W. McRobb, and // copyrighted(C) 1998 by the University of California, San Diego // (UCSD), with all rights reserved. UCSD administers the CAIDA grant, // NCR-9711092, under which part of this code was developed. // // There is no charge for arts++ software. You can redistribute it // and/or modify it under the terms of the GNU Lesser General Public // License, Version 2.1, February 1999, which is incorporated by // reference herein. // // arts++ is distributed WITHOUT ANY WARRANTY, IMPLIED OR EXPRESS, OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE or that the use // of it will not infringe on any third party's intellectual // property rights. // // You should have received a copy of the GNU Lesser General Public // License along with arts++. Copies can also be obtained from: // // http://www.gnu.org/copyleft/lesser.html // // or by writing to: // // Free Software Foundation, Inc. // 59 Temple Place, Suite 330 // Boston, MA 02111-1307 // USA // // Or contact: // // info@caida.org //=========================================================================== extern "C" { #include "artslocal.h" #include #include #include #include #include #include } #include #include #ifdef HAVE_IOMANIP #include #else #include #endif #include "ArtsRttTimeSeriesTableData.hh" #include "ArtsPrimitive.hh" using namespace std; static const std::string rcsid = "@(#) $Name: arts++-1-1-a12 $ $Id: ArtsRttTimeSeriesTableData.cc,v 1.3 2004/06/23 16:57:27 youngh Exp $"; //---------------------------------------------------------------------------- // ArtsRttTimeSeriesTableEntry::ArtsRttTimeSeriesTableEntry() //............................................................................ // //---------------------------------------------------------------------------- ArtsRttTimeSeriesTableEntry::ArtsRttTimeSeriesTableEntry() { this->_rtt = 0; this->_timestamp.tv_sec = 0; this->_timestamp.tv_usec = 0; #ifndef NDEBUG ++_numObjects; #endif } //---------------------------------------------------------------------------- // ArtsRttTimeSeriesTableEntry:: // ArtsRttTimeSeriesTableEntry(const ArtsRttTimeSeriesTableEntry & rttEntry) //............................................................................ // //---------------------------------------------------------------------------- ArtsRttTimeSeriesTableEntry:: ArtsRttTimeSeriesTableEntry(const ArtsRttTimeSeriesTableEntry & rttEntry) { this->Rtt(rttEntry.Rtt()); this->Timestamp(rttEntry.Timestamp()); #ifndef NDEBUG ++_numObjects; #endif } //---------------------------------------------------------------------------- // ArtsRttTimeSeriesTableEntry::~ArtsRttTimeSeriesTableEntry() //............................................................................ // //---------------------------------------------------------------------------- ArtsRttTimeSeriesTableEntry::~ArtsRttTimeSeriesTableEntry() { #ifndef NDEBUG --_numObjects; #endif } //---------------------------------------------------------------------------- // uint32_t ArtsRttTimeSeriesTableEntry::Rtt() const //............................................................................ // //---------------------------------------------------------------------------- uint32_t ArtsRttTimeSeriesTableEntry::Rtt() const { return(this->_rtt); } //---------------------------------------------------------------------------- // uint32_t ArtsRttTimeSeriesTableEntry::Rtt(uint32_t rtt) //............................................................................ // //---------------------------------------------------------------------------- uint32_t ArtsRttTimeSeriesTableEntry::Rtt(uint32_t rtt) { this->_rtt = rtt; return(this->_rtt); } //---------------------------------------------------------------------------- // const struct timeval & ArtsRttTimeSeriesTableEntry::Timestamp() const //............................................................................ // //---------------------------------------------------------------------------- const struct timeval & ArtsRttTimeSeriesTableEntry::Timestamp() const { return(this->_timestamp); } //---------------------------------------------------------------------------- // const struct timeval & // ArtsRttTimeSeriesTableEntry::Timestamp(const struct timeval & timestamp) //............................................................................ // //---------------------------------------------------------------------------- const struct timeval & ArtsRttTimeSeriesTableEntry::Timestamp(const struct timeval & timestamp) { this->_timestamp.tv_sec = timestamp.tv_sec; this->_timestamp.tv_usec = timestamp.tv_usec; return(this->_timestamp); } //---------------------------------------------------------------------------- // ArtsRttTimeSeriesTableEntry & // ArtsRttTimeSeriesTableEntry:: // operator = (const ArtsRttTimeSeriesTableEntry & rttEntry) //............................................................................ // //---------------------------------------------------------------------------- ArtsRttTimeSeriesTableEntry & ArtsRttTimeSeriesTableEntry:: operator = (const ArtsRttTimeSeriesTableEntry & rttEntry) { this->Rtt(rttEntry.Rtt()); this->Timestamp(rttEntry.Timestamp()); return(*this); } static uint8_t BytesNeededForUint32(uint32_t value) { if (value > 0x00FFFFFF) return(4); else if (value > 0x0000FFFF) return(3); else if (value > 0x000000FF) return(2); else return(1); } //---------------------------------------------------------------------------- // ostream & ArtsRttTimeSeriesTableEntry::write(ostream & os, // uint32_t timeBase, // uint32_t prevSecsOffset, // uint8_t version) const //............................................................................ // //---------------------------------------------------------------------------- ostream & ArtsRttTimeSeriesTableEntry::write(ostream & os, uint32_t timeBase, uint32_t prevSecsOffset, uint8_t version) const { uint8_t rleFlags = 0; uint8_t timestampSecsLength = 0; uint8_t timestampUsecsLength = 0; uint8_t rttLength = 0; uint32_t timestampSecsOffset; if (this->_rtt != k_droppedPacketRtt) { rttLength = BytesNeededForUint32(this->_rtt); rleFlags |= ((rttLength - 1) << 4); } else { rleFlags |= 0x80; } timestampSecsOffset = this->_timestamp.tv_sec - timeBase; if (timestampSecsOffset != prevSecsOffset) { rleFlags |= 0x40; timestampSecsLength = BytesNeededForUint32(timestampSecsOffset); rleFlags |= ((timestampSecsLength - 1) << 2); } timestampUsecsLength = BytesNeededForUint32(this->_timestamp.tv_usec); rleFlags |= (timestampUsecsLength - 1); os.write((char*)&rleFlags,sizeof(rleFlags)); if (rttLength > 0) g_ArtsLibInternal_Primitive.WriteUint32(os,this->_rtt,rttLength); if (timestampSecsLength > 0) g_ArtsLibInternal_Primitive.WriteUint32(os,timestampSecsOffset, timestampSecsLength); g_ArtsLibInternal_Primitive.WriteUint32(os,this->_timestamp.tv_usec, timestampUsecsLength); return(os); } //---------------------------------------------------------------------------- // int ArtsRttTimeSeriesTableEntry::write(int fd, // uint32_t timeBase, // uint32_t prevSecsOffset, // uint8_t version) const //............................................................................ // //---------------------------------------------------------------------------- int ArtsRttTimeSeriesTableEntry::write(int fd, uint32_t timeBase, uint32_t prevSecsOffset, uint8_t version) const { uint8_t rleFlags = 0; uint8_t timestampSecsLength = 0; uint8_t timestampUsecsLength = 0; uint8_t rttLength = 0; uint32_t timestampSecsOffset; if (this->_rtt != k_droppedPacketRtt) { rttLength = BytesNeededForUint32(this->_rtt); rleFlags |= ((rttLength - 1) << 4); } else { rleFlags |= 0x80; } timestampSecsOffset = this->_timestamp.tv_sec - timeBase; if (timestampSecsOffset != prevSecsOffset) { rleFlags |= 0x40; timestampSecsLength = BytesNeededForUint32(timestampSecsOffset); rleFlags |= ((timestampSecsLength - 1) << 2); } timestampUsecsLength = BytesNeededForUint32(this->_timestamp.tv_usec); rleFlags |= (timestampUsecsLength - 1); int rc = g_ArtsLibInternal_Primitive.FdWrite(fd,&rleFlags,sizeof(rleFlags)); if (rc < sizeof(rleFlags)) return(-1); int bytesWritten = rc; if (rttLength > 0) { rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_rtt,rttLength); if (rc < rttLength) return(-1); bytesWritten += rc; } if (timestampSecsLength > 0) { rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,timestampSecsOffset, timestampSecsLength); if (rc < timestampSecsLength) return(-1); bytesWritten += rc; } rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_timestamp.tv_usec, timestampUsecsLength); if (rc < timestampUsecsLength) return(-1); bytesWritten += rc; return(bytesWritten); } //---------------------------------------------------------------------------- // uint32_t ArtsRttTimeSeriesTableEntry::Length(uint32_t timeBase, // uint32_t prevSecsOffset, // uint8_t version) const //............................................................................ // //---------------------------------------------------------------------------- uint32_t ArtsRttTimeSeriesTableEntry::Length(uint32_t timeBase, uint32_t prevSecsOffset, uint8_t version) const { uint32_t length = sizeof(uint8_t); // always have rleFlags if (this->_rtt != k_droppedPacketRtt) { length += BytesNeededForUint32(this->_rtt); } uint32_t timestampSecsOffset = this->_timestamp.tv_sec - timeBase; if (timestampSecsOffset != prevSecsOffset) { length += BytesNeededForUint32(timestampSecsOffset); } length += BytesNeededForUint32(this->_timestamp.tv_usec); return(length); } //---------------------------------------------------------------------------- // istream & ArtsRttTimeSeriesTableEntry::read(istream & is, // uint32_t timeBase, // uint32_t prevSecsOffset, // uint8_t version) //............................................................................ // //---------------------------------------------------------------------------- istream & ArtsRttTimeSeriesTableEntry::read(istream & is, uint32_t timeBase, uint32_t prevSecsOffset, uint8_t version) { uint8_t rleFlags = 0; uint8_t timestampUsecsLength = 0; uint32_t timeVal; is.read((char*)&rleFlags,sizeof(rleFlags)); if (rleFlags & 0x80) { // it's a dropped packet; RTT length is 0 this->_rtt = k_droppedPacketRtt; } else { uint8_t rttLength = ((rleFlags >> 4) & 0x03) + 1; g_ArtsLibInternal_Primitive.ReadUint32(is,this->_rtt,rttLength); } if (rleFlags & 0x40) { uint8_t timestampSecsLength = ((rleFlags >> 2) & 0x03) + 1; g_ArtsLibInternal_Primitive.ReadUint32(is,timeVal, timestampSecsLength); this->_timestamp.tv_sec = timeVal + timeBase; } else { this->_timestamp.tv_sec = timeBase + prevSecsOffset; } timestampUsecsLength = (rleFlags & 0x03) + 1; g_ArtsLibInternal_Primitive.ReadUint32(is,timeVal, timestampUsecsLength); this->_timestamp.tv_usec = timeVal; return(is); } //---------------------------------------------------------------------------- // int ArtsRttTimeSeriesTableEntry::read(int fd, uint32_t timeBase, // uint32_t prevSecsOffset, // uint8_t version) //............................................................................ // //---------------------------------------------------------------------------- int ArtsRttTimeSeriesTableEntry::read(int fd, uint32_t timeBase, uint32_t prevSecsOffset, uint8_t version) { uint8_t rleFlags = 0; uint8_t timestampUsecsLength = 0; uint32_t timeVal; int rc = g_ArtsLibInternal_Primitive.FdRead(fd,&rleFlags,sizeof(rleFlags)); if (rc < sizeof(rleFlags)) { return(-1); } int bytesRead = rc; if (rleFlags & 0x80) { // it's a dropped packet; RTT length is 0 this->_rtt = k_droppedPacketRtt; } else { uint8_t rttLength = ((rleFlags >> 4) & 0x03) + 1; rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,this->_rtt,rttLength); if (rc < rttLength) { return(-1); } bytesRead += rc; } if (rleFlags & 0x40) { uint8_t timestampSecsLength = ((rleFlags >> 2) & 0x03) + 1; rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,timeVal, timestampSecsLength); if (rc < timestampSecsLength) { return(-1); } bytesRead += rc; this->_timestamp.tv_sec = timeVal + timeBase; } else { this->_timestamp.tv_sec = timeBase + prevSecsOffset; } timestampUsecsLength = (rleFlags & 0x03) + 1; rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,timeVal, timestampUsecsLength); if (rc < timestampUsecsLength) { return(-1); } bytesRead += rc; this->_timestamp.tv_usec = timeVal; return(bytesRead); } //---------------------------------------------------------------------------- // bool ArtsRttTimeSeriesTableEntryGreaterRtt:: // operator () (const ArtsRttTimeSeriesTableEntry & rttEntry1, // const ArtsRttTimeSeriesTableEntry & rttEntry2) //............................................................................ // //---------------------------------------------------------------------------- bool ArtsRttTimeSeriesTableEntryGreaterRtt:: operator () (const ArtsRttTimeSeriesTableEntry & rttEntry1, const ArtsRttTimeSeriesTableEntry & rttEntry2) { if (rttEntry1.Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { if (rttEntry2.Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { return(true); } return(false); } if (rttEntry2.Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { return(false); } return(rttEntry1.Rtt() > rttEntry2.Rtt()); } //---------------------------------------------------------------------------- // bool ArtsRttTimeSeriesTableEntryLessRtt:: // operator () (const ArtsRttTimeSeriesTableEntry & rttEntry1, // const ArtsRttTimeSeriesTableEntry & rttEntry2) //............................................................................ // //---------------------------------------------------------------------------- bool ArtsRttTimeSeriesTableEntryLessRtt:: operator () (const ArtsRttTimeSeriesTableEntry & rttEntry1, const ArtsRttTimeSeriesTableEntry & rttEntry2) { if (rttEntry1.Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { if (rttEntry2.Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { return(false); } return(true); } if (rttEntry2.Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { return(true); } return(rttEntry1.Rtt() < rttEntry2.Rtt()); } //---------------------------------------------------------------------------- // ArtsRttTimeSeriesTableData::ArtsRttTimeSeriesTableData() //............................................................................ // //---------------------------------------------------------------------------- ArtsRttTimeSeriesTableData::ArtsRttTimeSeriesTableData() { this->_timeBase = 0; #ifndef NDEBUG ++_numObjects; #endif } //---------------------------------------------------------------------------- // ArtsRttTimeSeriesTableData:: // ArtsRttTimeSeriesTableData(const ArtsRttTimeSeriesTableData & rttTable) //............................................................................ // //---------------------------------------------------------------------------- ArtsRttTimeSeriesTableData:: ArtsRttTimeSeriesTableData(const ArtsRttTimeSeriesTableData & rttTable) { this->_timeBase = rttTable.TimeBase(); this->_rttEntries = rttTable.RttEntries(); #ifndef NDEBUG ++_numObjects; #endif } //---------------------------------------------------------------------------- // ArtsRttTimeSeriesTableData::~ArtsRttTimeSeriesTableData() //............................................................................ // //---------------------------------------------------------------------------- ArtsRttTimeSeriesTableData::~ArtsRttTimeSeriesTableData() { this->_rttEntries.erase(this->_rttEntries.begin(),this->_rttEntries.end()); #ifndef NDEBUG --_numObjects; #endif } //---------------------------------------------------------------------------- // ArtsRttTimeSeriesTableData & // ArtsRttTimeSeriesTableData:: // operator = (const ArtsRttTimeSeriesTableData & rttTable) //............................................................................ // //---------------------------------------------------------------------------- ArtsRttTimeSeriesTableData & ArtsRttTimeSeriesTableData:: operator = (const ArtsRttTimeSeriesTableData & rttTable) { this->_rttEntries = rttTable.RttEntries(); return(*this); } //---------------------------------------------------------------------------- // uint32_t ArtsRttTimeSeriesTableData::TimeBase() const //............................................................................ // //---------------------------------------------------------------------------- uint32_t ArtsRttTimeSeriesTableData::TimeBase() const { if (this->_rttEntries.size() > 0) if (this->_timeBase == 0 || this->_timeBase > this->_rttEntries[0].Timestamp().tv_sec) this->_timeBase = this->_rttEntries[0].Timestamp().tv_sec; return(this->_timeBase); } //---------------------------------------------------------------------------- // uint32_t ArtsRttTimeSeriesTableData::TimeBase(uint32_t timeBase) //............................................................................ // //---------------------------------------------------------------------------- uint32_t ArtsRttTimeSeriesTableData::TimeBase(uint32_t timeBase) { this->_timeBase = timeBase; return(this->_timeBase); } //---------------------------------------------------------------------------- // vector & // ArtsRttTimeSeriesTableData::RttEntries() const //............................................................................ // //---------------------------------------------------------------------------- vector & ArtsRttTimeSeriesTableData::RttEntries() const { return(this->_rttEntries); } //---------------------------------------------------------------------------- // void ArtsRttTimeSeriesTableData:: // AddRttEntry(const ArtsRttTimeSeriesTableEntry & rttEntry) //............................................................................ // //---------------------------------------------------------------------------- void ArtsRttTimeSeriesTableData:: AddRttEntry(const ArtsRttTimeSeriesTableEntry & rttEntry) { this->_rttEntries.push_back(rttEntry); if (this->_timeBase == 0 || this->_timeBase > rttEntry.Timestamp().tv_sec) this->_timeBase = rttEntry.Timestamp().tv_sec; return; } //---------------------------------------------------------------------------- // istream & ArtsRttTimeSeriesTableData::read(istream& is, // uint8_t version) //............................................................................ // //---------------------------------------------------------------------------- istream & ArtsRttTimeSeriesTableData::read(istream& is, uint8_t version) { uint32_t numRttEntries, rttEntryNum; ArtsRttTimeSeriesTableEntry rttEntry; uint32_t rttUsecs; uint32_t timestampSecs, timestampUsecs; struct timeval tv; if (! this->_rttEntries.empty()) this->_rttEntries.clear(); g_ArtsLibInternal_Primitive.ReadUint32(is,this->_timeBase, sizeof(this->_timeBase)); g_ArtsLibInternal_Primitive.ReadUint32(is,numRttEntries, sizeof(numRttEntries)); uint32_t prevSecsOffset = 0; for (rttEntryNum = 0; rttEntryNum != numRttEntries; ++rttEntryNum) { rttEntry.read(is,this->_timeBase,prevSecsOffset,version); prevSecsOffset = rttEntry.Timestamp().tv_sec - this->_timeBase; this->_rttEntries.push_back(rttEntry); } return(is); } //---------------------------------------------------------------------------- // int ArtsRttTimeSeriesTableData::read(int fd, uint8_t version) //............................................................................ // //---------------------------------------------------------------------------- int ArtsRttTimeSeriesTableData::read(int fd, uint8_t version) { uint32_t numRttEntries, rttEntryNum; ArtsRttTimeSeriesTableEntry rttEntry; uint32_t rttUsecs; uint32_t timestampSecs, timestampUsecs; struct timeval tv; if (this->_rttEntries.size() > 0) this->_rttEntries.clear(); int rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,this->_timeBase, sizeof(this->_timeBase)); if (rc < sizeof(this->_timeBase)) return(-1); int bytesRead = rc; rc = g_ArtsLibInternal_Primitive.ReadUint32(fd,numRttEntries, sizeof(numRttEntries)); if (rc < sizeof(numRttEntries)) return(-1); bytesRead += rc; uint32_t prevSecsOffset = 0; for (rttEntryNum = 0; rttEntryNum < numRttEntries; ++rttEntryNum) { rc = rttEntry.read(fd,this->_timeBase,prevSecsOffset,version); if (rc < 0) return(-1); bytesRead += rc; prevSecsOffset = rttEntry.Timestamp().tv_sec - this->_timeBase; this->_rttEntries.push_back(rttEntry); } return(bytesRead); } //---------------------------------------------------------------------------- // uint32_t ArtsRttTimeSeriesTableData::Length(uint8_t version) const //............................................................................ // //---------------------------------------------------------------------------- uint32_t ArtsRttTimeSeriesTableData::Length(uint8_t version) const { uint32_t length = 0; uint32_t rttEntryNum, numRttEntries; uint32_t timestampSecs; length += sizeof(this->_timeBase); length += sizeof(numRttEntries); // number of entries timestampSecs = this->_rttEntries[0].Timestamp().tv_sec; numRttEntries = this->_rttEntries.size(); uint32_t prevSecsOffset = 0; for (rttEntryNum = 0; rttEntryNum != numRttEntries; ++rttEntryNum) { length += this->_rttEntries[rttEntryNum].Length(timestampSecs, prevSecsOffset,version); prevSecsOffset = this->_rttEntries[rttEntryNum].Timestamp().tv_sec - timestampSecs; } return(length); } //---------------------------------------------------------------------------- // ostream & ArtsRttTimeSeriesTableData::write(ostream & os, // uint8_t version) const //............................................................................ // //---------------------------------------------------------------------------- ostream & ArtsRttTimeSeriesTableData::write(ostream & os, uint8_t version) const { uint32_t numRttEntries, rttEntryNum; uint32_t rttUsecs; uint32_t timestampSecs, timestampUsecs; uint32_t timestampSecsOffset; uint8_t prevTimestampSecsSize = 1; uint32_t prevOffset = 0; if (this->_rttEntries.size() > 0) { if (this->_timeBase == 0 || this->_timeBase > this->_rttEntries[0].Timestamp().tv_sec) { this->_timeBase = this->_rttEntries[0].Timestamp().tv_sec; } } g_ArtsLibInternal_Primitive.WriteUint32(os,this->_timeBase, sizeof(this->_timeBase)); numRttEntries = this->_rttEntries.size(); g_ArtsLibInternal_Primitive.WriteUint32(os,numRttEntries, sizeof(numRttEntries)); for (rttEntryNum = 0; rttEntryNum != numRttEntries; ++rttEntryNum) { this->_rttEntries[rttEntryNum].write(os,this->_timeBase,prevOffset, version); prevOffset = this->_rttEntries[rttEntryNum].Timestamp().tv_sec - this->_timeBase; } return(os); } //---------------------------------------------------------------------------- // int ArtsRttTimeSeriesTableData::write(int fd, uint8_t version) const //............................................................................ // //---------------------------------------------------------------------------- int ArtsRttTimeSeriesTableData::write(int fd, uint8_t version) const { uint32_t numRttEntries, rttEntryNum; uint32_t rttUsecs; uint32_t timestampSecs, timestampUsecs; uint32_t timestampSecsOffset; uint8_t prevTimestampSecsSize = 1; uint32_t prevOffset = 0; if (this->_rttEntries.size() > 0) { if (this->_timeBase == 0 || this->_timeBase > this->_rttEntries[0].Timestamp().tv_sec) { this->_timeBase = this->_rttEntries[0].Timestamp().tv_sec; } } int rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,this->_timeBase, sizeof(this->_timeBase)); if (rc < sizeof(this->_timeBase)) return(-1); int bytesWritten = rc; numRttEntries = this->_rttEntries.size(); rc = g_ArtsLibInternal_Primitive.WriteUint32(fd,numRttEntries, sizeof(numRttEntries)); if (rc < sizeof(numRttEntries)) return(-1); bytesWritten += rc; for (rttEntryNum = 0; rttEntryNum != numRttEntries; ++rttEntryNum) { rc = this->_rttEntries[rttEntryNum].write(fd,this->_timeBase,prevOffset, version); if (rc < 0) return(-1); bytesWritten += rc; prevOffset = this->_rttEntries[rttEntryNum].Timestamp().tv_sec - this->_timeBase; } return(bytesWritten); } //---------------------------------------------------------------------------- // void ArtsRttTimeSeriesTableData::SortEntriesByTimestamp() //............................................................................ // //---------------------------------------------------------------------------- void ArtsRttTimeSeriesTableData::SortEntriesByTimestamp() { sort(this->_rttEntries.begin(),this->_rttEntries.end(), ArtsRttTimeSeriesTableEntryTimestampsLess()); if (this->_rttEntries.size() > 0) if (this->_timeBase == 0 || this->_timeBase > this->_rttEntries[0].Timestamp().tv_sec) this->_timeBase = this->_rttEntries[0].Timestamp().tv_sec; return; } //---------------------------------------------------------------------------- // const ArtsRttTimeSeriesTableEntry & // ArtsRttTimeSeriesTableData::RttMax() const //............................................................................ // //---------------------------------------------------------------------------- const ArtsRttTimeSeriesTableEntry & ArtsRttTimeSeriesTableData::RttMax() const { vector rttVect; vector::const_iterator rttIter; static ArtsRttTimeSeriesTableEntry rttEntry; for (rttIter = this->_rttEntries.begin(); rttIter != this->_rttEntries.end(); ++rttIter) { if ((*rttIter).Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { rttVect.push_back(*rttIter); } } if (rttVect.size() > 0) { rttEntry = *(max_element(rttVect.begin(),rttVect.end(), ArtsRttTimeSeriesTableEntryLessRtt())); return(rttEntry); } else { struct timeval timestamp; timestamp.tv_sec = 0; timestamp.tv_usec = 0; rttEntry.Rtt(0); rttEntry.Timestamp(timestamp); return(rttEntry); } } //---------------------------------------------------------------------------- // const ArtsRttTimeSeriesTableEntry & // ArtsRttTimeSeriesTableData::RttMin() const //............................................................................ // //---------------------------------------------------------------------------- const ArtsRttTimeSeriesTableEntry & ArtsRttTimeSeriesTableData::RttMin() const { vector rttVect; vector::const_iterator rttIter; static ArtsRttTimeSeriesTableEntry rttEntry; for (rttIter = this->_rttEntries.begin(); rttIter != this->_rttEntries.end(); ++rttIter) { if ((*rttIter).Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { rttVect.push_back(*rttIter); } } if (rttVect.size() > 0) { rttEntry = *(min_element(rttVect.begin(),rttVect.end(), ArtsRttTimeSeriesTableEntryLessRtt())); return(rttEntry); } else { struct timeval timestamp; timestamp.tv_sec = 0; timestamp.tv_usec = 0; rttEntry.Rtt(0); rttEntry.Timestamp(timestamp); return(rttEntry); } } //---------------------------------------------------------------------------- // const ArtsRttTimeSeriesTableEntry & // ArtsRttTimeSeriesTableData::RttPercentile() const //............................................................................ // //---------------------------------------------------------------------------- const ArtsRttTimeSeriesTableEntry & ArtsRttTimeSeriesTableData::RttPercentile(int percentile) const { int percentilePosition; vector rttVect; vector::const_iterator rttIter; static ArtsRttTimeSeriesTableEntry rttEntry; assert((percentile >= 0) && (percentile <= 100)); for (rttIter = this->_rttEntries.begin(); rttIter != this->_rttEntries.end(); ++rttIter) { if ((*rttIter).Rtt() != ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { rttVect.push_back(*rttIter); } } if (rttVect.size() > 0) { percentilePosition = (int)((rttVect.size() - 1) * (percentile/100.0)); nth_element(rttVect.begin(),rttVect.begin() + percentilePosition, rttVect.end(),ArtsRttTimeSeriesTableEntryLessRtt()); rttEntry = rttVect[percentilePosition]; return(rttEntry); } else { struct timeval timestamp; timestamp.tv_sec = 0; timestamp.tv_usec = 0; rttEntry.Rtt(0); rttEntry.Timestamp(timestamp); return(rttEntry); } } //---------------------------------------------------------------------------- // size_t ArtsRttTimeSeriesTableData:: // RttPercentiles(const vector & percentiles, // vector & results) const //............................................................................ // //---------------------------------------------------------------------------- size_t ArtsRttTimeSeriesTableData:: RttPercentiles(const vector & percentiles, vector & results) const { vector rttVect(this->_rttEntries); if (! results.empty()) results.clear(); if (! rttVect.empty()) { int percentilePosition; vector::const_iterator pctIter; for (pctIter = percentiles.begin(); pctIter != percentiles.end(); ++pctIter) { assert((*pctIter >= 0) && (*pctIter <= 100)); percentilePosition = (int)((rttVect.size() - 1) * (*pctIter/100.0)); nth_element(rttVect.begin(),rttVect.begin() + percentilePosition, rttVect.end(),ArtsRttTimeSeriesTableEntryLessRtt()); results.push_back(rttVect[percentilePosition].Rtt()); } } return(results.size()); } //---------------------------------------------------------------------------- // const ArtsRttTimeSeriesTableEntry & // ArtsRttTimeSeriesTableData::RttMedian() const //............................................................................ // //---------------------------------------------------------------------------- const ArtsRttTimeSeriesTableEntry & ArtsRttTimeSeriesTableData::RttMedian() const { return(this->RttPercentile(50)); } //---------------------------------------------------------------------------- // const ArtsRttTimeSeriesTableEntry & // ArtsRttTimeSeriesTableData::RttLowerQuartile() const //............................................................................ // //---------------------------------------------------------------------------- const ArtsRttTimeSeriesTableEntry & ArtsRttTimeSeriesTableData::RttLowerQuartile() const { return(this->RttPercentile(25)); } //---------------------------------------------------------------------------- // const ArtsRttTimeSeriesTableEntry & // ArtsRttTimeSeriesTableData::RttUpperQuartile() const //............................................................................ // //---------------------------------------------------------------------------- const ArtsRttTimeSeriesTableEntry & ArtsRttTimeSeriesTableData::RttUpperQuartile() const { return(this->RttPercentile(75)); } //---------------------------------------------------------------------------- // double ArtsRttTimeSeriesTableData::AveragePacketLoss() const //............................................................................ // //---------------------------------------------------------------------------- double ArtsRttTimeSeriesTableData::AveragePacketLoss() const { if (this->_rttEntries.size() > 0) { uint32_t droppedPackets = 0; vector::const_iterator rttIter; for (rttIter = this->_rttEntries.begin(); rttIter != this->_rttEntries.end(); ++rttIter) { if (rttIter->Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { ++droppedPackets; } } double pktLoss = (droppedPackets * 100.0) / this->_rttEntries.size(); return(pktLoss); } else { return(0.0); } } //---------------------------------------------------------------------------- // void ArtsRttTimeSeriesTableData::ClearRttData() //............................................................................ // //---------------------------------------------------------------------------- void ArtsRttTimeSeriesTableData::ClearRttData() { if (this->_rttEntries.size() > 0) { this->_rttEntries.clear(); } this->_timeBase = 0; return; } //---------------------------------------------------------------------------- // ostream& operator << (ostream& os, // const ArtsRttTimeSeriesTableData & rttTimeSeriesTable) //............................................................................ // //---------------------------------------------------------------------------- ostream& operator << (ostream& os, const ArtsRttTimeSeriesTableData & rttTimeSeriesTable) { struct in_addr addrIn; uint32_t rttNum; struct tm *Tm; time_t tsSecs; double tsSecsFraction; os << "RTT TIME SERIES OBJECT DATA" << endl; for (rttNum = 0; rttNum < rttTimeSeriesTable.RttEntries().size(); ++rttNum) { tsSecs = rttTimeSeriesTable.RttEntries()[rttNum].Timestamp().tv_sec; tsSecsFraction = rttTimeSeriesTable.RttEntries()[rttNum].Timestamp().tv_usec / 1000.0; Tm = localtime(&tsSecs); os << setiosflags(ios::internal); os << "\t timestamp: " << setfill('0') << setw(2) << Tm->tm_mon+1 << "/" << setw(2) << Tm->tm_mday << "/" << setw(4) << Tm->tm_year+1900 << " " << setw(2) << Tm->tm_hour << ":" << setw(2) << Tm->tm_min << ":" << setw(2) << Tm->tm_sec << "." << setw(3) << (int)(tsSecsFraction) << " (" << hex << (int)(tsSecs) << ")" << dec; os << setfill(' '); os << resetiosflags(ios::internal); os << " RTT: "; if (rttTimeSeriesTable.RttEntries()[rttNum].Rtt() == ArtsRttTimeSeriesTableEntry::k_droppedPacketRtt) { os << "lost packet" << endl; } else { os << rttTimeSeriesTable.RttEntries()[rttNum].Rtt()/1000.0 << " ms" << endl; } } return(os); } uint32_t ArtsRttTimeSeriesTableEntry::_numObjects = 0; uint32_t ArtsRttTimeSeriesTableData::_numObjects = 0;