Main Page | Class List | File List | Class Members | File Members

PingTarget.cpp

Go to the documentation of this file.
00001 // PingTarget.cpp
00002 
00003 #include "PingTarget.h"
00004 #include <iomanip>
00005 #include <math.h>
00006 #include <float.h>
00007 #include <sstream>
00008 #include "format_system_time.h"
00009 #include "fit_text.h"
00010 #include "safe_assign.h"
00011 #include "trim_spaces.h"
00012 #include <iostream>
00013 #include <fstream>
00014 #include <sys/stat.h>
00015 
00016 
00017 PingTarget::PingTarget(PingTargets& targets, const char* name, in_addr inetAddr, long id)
00018   : m_targets(targets)
00019 {
00020   safe_assign(m_sName, name);
00021   m_inetAddr = inetAddr;
00022   m_lId = id;
00023   m_bResponseAdded = false;
00024 
00025   m_dCurrent = -1.0;
00026   m_lReceived = 0;
00027   m_lSkipped = 0;
00028   m_dMin = DBL_MAX;
00029   m_dMax = 0.0;
00030   m_dSum = 0.0;
00031   m_dSumSquares = 0.0;
00032 }
00033 
00034 const char* PingTarget::GetIpAddr() const
00035 {
00036   return inet_ntoa(m_inetAddr);
00037 }
00038 
00039 USHORT PingTarget::MakeSequence(long sequence) const
00040 {
00041   return m_targets.MakeSequence(m_lId, sequence);
00042 }
00043 
00044 void PingTarget::AddResponseTime(double ms)
00045 {
00046   m_bResponseAdded = true;
00047   m_dCurrent = ms;
00048   if (ms > -1)
00049   {
00050     if (ms < m_dMin)
00051       m_dMin = ms;
00052     if (ms > m_dMax)
00053       m_dMax = ms;
00054     m_dSum += ms;
00055     m_dSumSquares += ms*ms;
00056     m_lReceived++;
00057   }
00058   else
00059   {
00060     m_lSkipped++;
00061   }
00062 }
00063 
00064 void PingTarget::ClearResponseFlag()
00065 {
00066   m_bResponseAdded = false;
00067 }
00068 
00069 double PingTarget::GetMin() const
00070 {
00071   if (m_lReceived > 0)
00072     return m_dMin;
00073   else
00074     return 0.0;
00075 }
00076 
00077 double PingTarget::GetMax() const
00078 {
00079   if (m_lReceived > 0)
00080     return m_dMax;
00081   else
00082     return 0.0;
00083 }
00084 
00085 double PingTarget::GetAvg() const
00086 {
00087   if (m_lReceived > 0)
00088   {
00089     double rec = m_lReceived;
00090     return m_dSum/rec;
00091   }
00092   else
00093     return 0.0;
00094 }
00095 double PingTarget::GetStdDev() const
00096 {
00097   if (m_lReceived > 0)
00098   {
00099     double avg = GetAvg();
00100     double rec = m_lReceived;
00101     double stddev = sqrt(m_dSumSquares / rec - avg*avg);
00102     return stddev;
00103   }
00104   else
00105     return 0.0;
00106 }
00107 
00108 double PingTarget::GetSkippedPercent() const
00109 {
00110   double total = m_lReceived+m_lSkipped;
00111   if (total > 0.0)
00112   {
00113     double skipped = m_lSkipped;
00114     return 100.0*skipped/total;
00115   }
00116   else
00117     return 0.0;
00118 }
00119 
00120 std::ostream& operator<<(std::ostream& os, const PingTarget& t)
00121 {
00122   os.precision(6);
00123   os.unsetf(std::ios::showpoint | std::ios::fixed);
00124   os << t.GetName() << " (" << t.GetIpAddr() << ") id=" << t.GetId() << std::endl;
00125   os << "  responses=" << t.GetResponseCount();
00126   os << " skipped=" << t.GetSkipped();
00127   os << " (" <<  t.GetSkippedPercent() << "%)";
00128   os << std::endl;
00129   os << "  current=";
00130   if (t.GetCurrent() == -1.0)
00131     os << "(*)";
00132   else
00133     os << t.GetCurrent();
00134   os << " min=" << t.GetMin();
00135   os << " avg=" << t.GetAvg() << " max=" << t.GetMax();
00136   os << " stddev=" << t.GetStdDev();
00137   return os;
00138 }
00139 
00140 
00141 PingTargets::PingTargets()
00142 {
00143   m_lIdBits = 6;
00144   m_lIdMax = (1 << m_lIdBits) -1;
00145   m_lSequenceBits = sizeof(USHORT)*8 - m_lIdBits;
00146   m_uIdMask = (USHORT)(m_lIdMax << m_lSequenceBits);
00147   m_uSeqMask = m_uIdMask ^ (USHORT)0xffff;
00148   m_lSequenceMax = m_uSeqMask;
00149   m_lMaxNameWidth = 0;
00150 }
00151 
00152 PingTargets::~PingTargets()
00153 {
00154   for (const_iterator i = begin(); i != end(); ++i)
00155     delete *i;
00156   m_targets.clear();
00157 }
00158 
00159 PingTarget* PingTargets::AddTarget(const char* name)
00160 {
00161   in_addr inetAddr;
00162   inetAddr.S_un.S_addr = inet_addr(name);
00163   if (inetAddr.S_un.S_addr == INADDR_NONE)
00164   {
00165     hostent* pHost = gethostbyname(name);
00166     if (pHost && pHost->h_addrtype == AF_INET)
00167       memcpy(&inetAddr, pHost->h_addr_list[0], pHost->h_length);
00168   }
00169   if (inetAddr.S_un.S_addr == INADDR_NONE)
00170   {
00171     std::cerr << "Unable to add target. Target " << name << " cannot be resolved." << std::endl;
00172     return NULL;
00173   }
00174   if ((long)m_targets.size() < m_lIdMax)
00175   {
00176     PingTarget* pTarget = new PingTarget(*this, name, inetAddr, (long)m_targets.size()+1);
00177     m_targets.push_back(pTarget);
00178     m_lMaxNameWidth = max(m_lMaxNameWidth, (long)pTarget->m_sName.size());
00179     return pTarget;
00180   }
00181   else
00182   {
00183     std::cerr << "Unable to add target: " << name << std::endl;
00184     std::cerr << "Maximum target count " << GetMaxTargets() << " would be exceeded." << std::endl;
00185   }
00186   return NULL;
00187 }
00188 
00189 bool PingTargets::AddTargets(std::istream& is)
00190 {
00191   bool resolved = true;
00192   while (is && resolved)
00193   {
00194     std::string s;
00195     std::getline(is, s);
00196     s = trim_spaces(s.c_str());
00197     if (!s.empty())
00198     {
00199       if (!AddTarget(s.c_str()))
00200         resolved = false;
00201     }
00202   }
00203   return resolved;
00204 }
00205 
00206 bool PingTargets::AddTargets(const char* pszFilename)
00207 {
00208   std::ifstream is(pszFilename);
00209   if (is.is_open())
00210   {
00211     return AddTargets(is);
00212   }
00213   else
00214   {
00215     std::cerr << "Unable to open file " << pszFilename << " for reading." << std::endl;
00216     return false;
00217   }
00218 }
00219 
00220 long PingTargets::GetMaxTargets() const
00221 {
00222   return m_lIdMax;
00223 }
00224 
00225 PingTarget* PingTargets::Get(long id) const
00226 {
00227   if (id > 0 && id <= (long)size())
00228     return m_targets[id-1];
00229   else
00230     return NULL;
00231 }
00232 
00233 bool PingTargets::AddResponse(long id, double ms)
00234 {
00235   PingTarget* pTarget = Get(id);
00236   if (pTarget)
00237   {
00238     pTarget->AddResponseTime(ms);
00239     return true;
00240   }
00241   return false;
00242 }
00243 
00244 void PingTargets::ClearResponseFlags()
00245 {
00246   for (iterator i = m_targets.begin(); i != m_targets.end(); ++i)
00247     (*i)->m_bResponseAdded = false;
00248 }
00249 
00250 void PingTargets::AddUnreachableResponses()
00251 {
00252   for (iterator i = m_targets.begin(); i != m_targets.end(); ++i)
00253   {
00254     PingTarget& t = **i;
00255     if (!t.IsResponseAdded())
00256       t.AddResponseTime();
00257   }
00258 }
00259 
00260 long PingTargets::GetTargetId(USHORT sequence) const
00261 {
00262   return sequence >> m_lSequenceBits;
00263 }
00264 
00265 long PingTargets::GetSequence(USHORT sequence) const
00266 {
00267   return sequence & m_uSeqMask;
00268 }
00269 
00270 USHORT PingTargets::MakeSequence(long lId, long lSequence) const
00271 {
00272   return (USHORT)((lId << m_lSequenceBits) + lSequence);
00273 }
00274 
00275 void PingTargets::PrintStatisticsHeader(std::ostream& os, long lConsoleWidth) const
00276 {
00277   os << std::setfill(' ') << std::left;
00278   long lNameWidth = GetMaxNameWidth();
00279   if (lNameWidth > lConsoleWidth-7*8-1)
00280     lNameWidth = lConsoleWidth-7*8-1;
00281   os << std::right;
00282   os << std::setw(lNameWidth) << " ";
00283   os << std::setw(8) << "now";
00284   os << std::setw(8) << "minimum";
00285   os << std::setw(8) << "average";
00286   os << std::setw(8) << "maximum";
00287   os << std::setw(8) << "std.dev";
00288   os << std::setw(8) << "skipped";
00289   os << std::setw(8) << "skip%";
00290 }
00291 
00292 void PingTargets::PrintStatistics(std::ostream& os, long lConsoleWidth) const
00293 {
00294   long lNameWidth = GetMaxNameWidth();
00295   if (lNameWidth > lConsoleWidth-7*8-1)
00296     lNameWidth = lConsoleWidth-7*8-1;
00297   os.fill(' ');
00298   for (PingTargets::const_iterator i = begin(); i != end(); ++i)
00299   {
00300     if (i != begin())
00301       os << std::endl;
00302     const PingTarget& t = **i;
00303     os << std::left << std::setw(lNameWidth) << fit_text(t.GetName()) << std::right;
00304     os.precision(1);
00305     os.setf(std::ios::showpoint | std::ios::fixed);
00306     if (t.GetCurrent() == -1.0)
00307       os << std::setw(8) << "(*)";
00308     else
00309       os << std::setw(8) << t.GetCurrent();
00310     os << std::setw(8) << t.GetMin();
00311     os << std::setw(8) << t.GetAvg();
00312     os << std::setw(8) << t.GetMax();
00313     os << std::setw(8) << t.GetStdDev();
00314     os << std::setw(8) << t.GetSkipped();
00315     os << std::setw(8) << t.GetSkippedPercent();
00316   }
00317 }
00318 
00319 void PingTargets::PrintLogHeader(std::ostream& os) const
00320 {
00321   os << std::left;
00322   os << "Time/Target";
00323   for (PingTargets::const_iterator i = begin(); i != end(); ++i)
00324   {
00325     const PingTarget& t = **i;
00326     os << "\t" << t.GetName();
00327   }
00328 }
00329 
00330 void PingTargets::PrintLogCurrent(std::ostream& os, const SYSTEMTIME& systemtime) const
00331 {
00332   os << std::left;
00333   os << format_system_time(systemtime, format_system_time::show_seconds);
00334   os.precision(1);
00335   os.setf(std::ios::showpoint | std::ios::fixed);
00336   for (PingTargets::const_iterator i = begin(); i != end(); ++i)
00337   {
00338     const PingTarget& t = **i;
00339     os << "\t" << t.GetCurrent();
00340   }
00341 }
00342 
00343 bool PingTargets::PrintLogCurrent(const char* pszFilename, const SYSTEMTIME& systemtime,
00344   LOG_FILENAME_TYPE FilenameType, bool bNewFile) const
00345 {
00346   std::ostringstream osName;
00347   char path_buffer[_MAX_PATH];
00348   char drive[_MAX_DRIVE];
00349   char dir[_MAX_DIR];
00350   char fname[_MAX_FNAME];
00351   char ext[_MAX_EXT];
00352   _splitpath(pszFilename, drive, dir, fname, ext);
00353   switch(FilenameType)
00354   {
00355   case LOG_FILENAME_PLAIN:
00356   default:
00357     osName << fname;
00358     break;
00359   case LOG_FILENAME_DAILY:
00360     osName << fname;
00361     osName << std::setw(4) << std::setfill('0') << systemtime.wYear;
00362     osName << std::setw(2) << std::setfill('0') << systemtime.wMonth;
00363     osName << std::setw(2) << std::setfill('0') << systemtime.wDay;
00364     break;
00365   case LOG_FILENAME_HOURLY:
00366     osName << fname;
00367     osName << std::setw(4) << std::setfill('0') << systemtime.wYear;
00368     osName << std::setw(2) << std::setfill('0') << systemtime.wMonth;
00369     osName << std::setw(2) << std::setfill('0') << systemtime.wDay;
00370     osName << "_";
00371     osName << std::setw(2) << std::setfill('0') << systemtime.wHour;
00372     break;
00373   }
00374   _makepath(path_buffer, drive, dir, osName.str().c_str(), ext);
00375   bool bFileExists = false;
00376   struct _stat st;
00377   if (_stat(path_buffer, &st) == 0 && st.st_size > 0)
00378     bFileExists = true;
00379   std::ofstream os;
00380   os.imbue(std::locale(""));
00381   if (bNewFile)
00382     os.open(path_buffer);
00383   else
00384     os.open(path_buffer, std::ios::app);
00385   if (!os.is_open())
00386   {
00387     std::cerr << "Unable to create or open log file " << path_buffer<< std::endl;
00388     return false;
00389   }
00390   if (bNewFile || !bFileExists)
00391   {
00392     PrintLogHeader(os);
00393     os << std::endl;
00394   }
00395   PrintLogCurrent(os, systemtime);
00396   os << std::endl;
00397   return true;
00398 }
00399 
00400 std::ostream& operator<<(std::ostream& os, const PingTargets& targets)
00401 {
00402   for (PingTargets::const_iterator i = targets.begin(); i != targets.end(); ++i)
00403     os << **i << std::endl;
00404   return os;
00405 }

Generated on Sun Jun 26 13:43:46 2005 for pingem by  doxygen 1.4.3