LCOV - code coverage report
Current view: top level - stdcasa - UtilJ.cc (source / functions) Hit Total Coverage
Test: casacpp_coverage.info Lines: 0 230 0.0 %
Date: 2024-12-11 20:54:31 Functions: 0 35 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Utilj.cc
       3             :  *
       4             :  *  Created on: Nov 4, 2010
       5             :  *      Author: jjacobs
       6             :  */
       7             : 
       8             : #include <cstdarg>
       9             : #include <cstdio>
      10             : #include <cstring>
      11             : #include <errno.h>
      12             : 
      13             : #include <casacore/casa/aips.h>
      14             : #include <casacore/casa/aipstype.h>
      15             : #include <casacore/casa/BasicSL/String.h>
      16             : #include <casacore/casa/Utilities/CountedPtr.h>
      17             : #include <sys/time.h>
      18             : #include <execinfo.h>
      19             : #include <algorithm>
      20             : #include <math.h>
      21             : #include <fstream>
      22             : #include <unistd.h>
      23             : #include <sys/time.h>
      24             : #include <sys/resource.h>
      25             : 
      26             : using std::max;
      27             : using std::min;
      28             : 
      29             : using namespace casacore;
      30             : using namespace std;
      31             : 
      32             : #include "UtilJ.h"
      33             : 
      34             : using namespace casacore;
      35             : namespace casa {
      36             : 
      37             : namespace utilj {
      38             : 
      39             : // Leave a tag to allow manual verification of build setting
      40             : 
      41             : #if defined (CASA_THREAD_NEUTRAL)
      42             :       String CasaThreadNeutral = "CasaThreadNeutral:YES";
      43             : #else
      44             :       String CasaThreadNeutral = "CasaThreadNeutral:NO";
      45             : #endif // defined (CASA_THREAD_NEUTRAL)
      46             : 
      47             : String
      48           0 : formatV (const String & formatString, va_list vaList)
      49             : {
      50             :         char buffer [4096];
      51           0 :         int nPrinted = vsnprintf (buffer, sizeof (buffer), formatString.c_str(), vaList);
      52             : 
      53           0 :         if (nPrinted >= (int) sizeof (buffer) - 1){
      54           0 :                 buffer [sizeof (buffer) - 2] = '|'; // mark as truncated
      55             :         }
      56             : 
      57           0 :         return buffer;
      58             : }
      59             : 
      60             : /*String
      61             : format (const char * formatString, ...)
      62             : {
      63             : 
      64             :         // Return a String object created using the printf-like format string
      65             :         // and the provided arguments.  If the text is truncated because the
      66             :         // internal buffer is too small, the last character will be a pipe "|".
      67             : 
      68             :         va_list vaList;
      69             : 
      70             :         va_start (vaList, formatString);
      71             : 
      72             :         String result = formatV (formatString, vaList);
      73             : 
      74             :         va_end (vaList);
      75             : 
      76             :         return result;
      77             : }*/
      78             : 
      79             : 
      80             : Bool
      81           0 : getEnv (const String & name, const Bool & defaultValue)
      82             : {
      83           0 :         char * value = getenv (name.c_str());
      84             : 
      85           0 :         if (value == NULL){
      86           0 :                 return defaultValue;
      87             :         }
      88             :         else{
      89           0 :                 String stringValue = value;
      90           0 :                 stringValue.downcase();
      91           0 :                 Bool truthValue = true;
      92             : 
      93           0 :                 if (stringValue == "false" ||
      94           0 :                         stringValue == "f" ||
      95           0 :                         stringValue == "0" ||
      96           0 :                         stringValue == "no"){
      97             : 
      98           0 :                         truthValue = false;
      99             :                 }
     100             : 
     101           0 :                 return truthValue;
     102           0 :         }
     103             : }
     104             : 
     105             : Int
     106           0 : getEnv (const String & name, const Int & defaultValue)
     107             : {
     108           0 :         char * value = getenv (name.c_str());
     109             : 
     110           0 :         if (value == NULL){
     111           0 :                 return defaultValue;
     112             :         }
     113             :         else{
     114             : 
     115             :                 char * next;
     116           0 :                 long longValue = strtol (value, & next, 10);
     117             : 
     118             :                 // If all of the value characters weren't consumed, assume
     119             :                 // an error occurred and use the default value.
     120             : 
     121           0 :                 if (* next != '\0')
     122           0 :                         longValue = defaultValue;
     123             : 
     124           0 :                 return longValue;
     125             :         }
     126             : }
     127             : 
     128             : 
     129             : String
     130           0 : getTimestamp ()
     131             : {
     132             :         // Get a possibly decent resolution time value
     133             : 
     134             :         struct timeval now;
     135           0 :         gettimeofday (& now, NULL);
     136             : 
     137             :         // Convert from UTC to local time
     138             : 
     139           0 :         struct tm localNow = * localtime (& now.tv_sec);
     140             : 
     141             :         // Output the seconds portion of the time in the format
     142             :         // hh:mm:ss
     143             : 
     144             :         char buffer [128];
     145           0 :         strftime (buffer, sizeof(buffer), "%X", & localNow);
     146             : 
     147             :         // Add on the higher resolution portion (if any) of the time
     148             :         // as milliseconds
     149             : 
     150             :         char buffer2 [128];
     151             : 
     152           0 :         snprintf (buffer2, sizeof(buffer2), "%s.%03d", buffer, (int) now.tv_usec/1000);
     153             : 
     154             :         // Return the final result in the format "hh:mm:ss.ttt"
     155             : 
     156           0 :         return buffer2;
     157             : }
     158             : 
     159             : Bool
     160           0 : isEnvDefined (const String & name)
     161             : {
     162           0 :         char * value = getenv (name.c_str());
     163             : 
     164           0 :         return value != NULL;
     165             : }
     166             : 
     167             : void
     168           0 : printBacktrace (ostream & os, const String & prefix)
     169             : {
     170             :     void * stack [512];
     171           0 :     int nUsed = backtrace (stack, 512);
     172           0 :     char ** trace = backtrace_symbols (stack, nUsed);
     173           0 :     if (! prefix.empty()){
     174           0 :         os << prefix << endl;
     175             :     }
     176           0 :     os << "*** Stack trace (use c++filt to demangle):" << endl;
     177           0 :     for (int i = 0; i < nUsed; i++){
     178           0 :         os << trace[i] << endl;
     179             :     }
     180           0 :     os.flush();
     181           0 :     delete trace;
     182           0 : }
     183             : 
     184             : AipsError
     185           0 : repackageAipsError (AipsError & error, const String & message, const String & file, Int line, const String & func)
     186             : {
     187           0 :     ostringstream os;
     188             : 
     189           0 :     AipsError tmp (message, file, line);
     190           0 :     os << func << ": " << tmp.what() << "\n   " << error.what();
     191             : 
     192           0 :     return AipsError (os.str());
     193           0 : }
     194             : 
     195             : long
     196           0 : round (Double d)
     197             : {
     198           0 :     Double sign = (d < 0) ? -1.0 : 1.0;
     199             : 
     200           0 :     d += 0.5 * sign;
     201             : 
     202           0 :     long result = (long) d;
     203             : 
     204           0 :     return result;
     205             : }
     206             : 
     207             : 
     208             : void
     209           0 : sleepMs (Int milliseconds)
     210             : {
     211             :     struct timespec t, tRemaining;
     212           0 :     t.tv_sec = milliseconds / 1000;
     213           0 :     t.tv_nsec = (milliseconds - t.tv_sec) * 1000000;
     214             : 
     215             :     // Because nanosleep can be interrupted by a signal, it is necessary
     216             :     // to continue the wait if errno is EINTR.  When interrupted, nanosleep
     217             :     // copies the amount of time remaining in the wait into tRemaining; so
     218             :     // the remainder of one interation becomes the wait value proper on the
     219             :     // next iteration.
     220             : 
     221             :     Bool done;
     222             :     do {
     223           0 :         done = nanosleep (& t, & tRemaining) == 0 || errno != EINTR;
     224           0 :         t = tRemaining;
     225           0 :     } while (! done);
     226             : 
     227           0 : }
     228             : 
     229             : vector<String>
     230           0 : split (const String & string, const String & splitter, Bool ignoreConsecutiveSplitters)
     231             : {
     232           0 :     vector<String> result;
     233             : 
     234           0 :     Int start = 0;
     235             : 
     236             :     while (true){
     237             : 
     238           0 :         Int matchStart = string.find (splitter, start);
     239             : 
     240           0 :         if (matchStart == (int) String::npos){
     241             : 
     242             :             // No match: put rest of string into the result
     243             : 
     244           0 :             String text = string.substr (start);
     245             : 
     246           0 :             if (! text.empty()){
     247             : 
     248           0 :                 result.push_back (string.substr (start));
     249             :             }
     250             : 
     251           0 :             break;
     252           0 :         }
     253             : 
     254           0 :         String text = string.substr (start, matchStart - start);
     255             : 
     256           0 :         if (! (text.empty() &&  ignoreConsecutiveSplitters)){
     257             : 
     258             :             // If the text is nonempty or we're not ignored consecutive
     259             :             // occurrences of splitters, then push text onto the result.
     260             : 
     261           0 :             result.push_back (text);
     262             :         }
     263             : 
     264           0 :         start = matchStart + splitter.length();
     265           0 :     }
     266             : 
     267           0 :     return result;
     268           0 : }
     269             : 
     270             : void
     271           0 : toStdError (const String & m, const String & prefix)
     272             : {
     273           0 :     cerr << prefix << m << endl;
     274           0 :     cerr.flush();
     275           0 : }
     276             : 
     277             : 
     278             : void
     279           0 : throwIf (bool condition, const String & message, const String & file, Int line, const String & func)
     280             : {
     281             : 
     282             :         // If the condition is met then throw an AipsError
     283             : 
     284           0 :         if (condition) {
     285           0 :             String m = func + ": " + message;
     286           0 :             AipsErrorTrace e (m.c_str(), file.c_str(), line);
     287             : 
     288             : #       if defined (NDEBUG)
     289             :                 toStdError (e.what());
     290             : #       endif
     291             : 
     292           0 :             throw e;
     293           0 :         }
     294           0 : }
     295             : 
     296             : void
     297           0 : throwIfError (int errorCode, const String & prefix, const String & file, Int line, const String & func)
     298             : {
     299             :         // If the provided error code is not equal to success (0) then
     300             :         // throw an AipsError using the provided suffix and then details
     301             :         // of the error.
     302             : 
     303           0 :         if (errorCode != 0) {
     304           0 :                 AipsErrorTrace e (String::format ("%s: %s (errno=%d):%s", func.c_str(), prefix.c_str(),
     305           0 :                                                   errorCode, strerror (errorCode)), file.c_str(), line);
     306             : 
     307             : #       if defined (NDEBUG)
     308             :                 toStdError (e.what());
     309             : #       endif
     310             : 
     311           0 :             throw e;
     312           0 :         }
     313           0 : }
     314             : 
     315             : DeltaThreadTimes
     316           0 : ThreadTimes::operator- (const ThreadTimes & tEarlier) const
     317             : {
     318           0 :     return DeltaThreadTimes (this->elapsed() - tEarlier.elapsed(),
     319           0 :                              this->cpu() - tEarlier.cpu());
     320             : }
     321             : 
     322             : DeltaThreadTimes &
     323           0 : DeltaThreadTimes::operator+= (const DeltaThreadTimes & other)
     324             : {
     325           0 :     cpu_p += other.cpu();
     326           0 :     elapsed_p += other.elapsed();
     327           0 :     n_p += 1;
     328             : 
     329           0 :     if (doStats_p){
     330           0 :         cpuSsq_p += other.cpu() * other.cpu();
     331           0 :         cpuMin_p = min (cpuMin_p, other.cpu());
     332           0 :         cpuMax_p = max (cpuMax_p, other.cpu());
     333           0 :         elapsedSsq_p += other.elapsed() * other.elapsed();
     334           0 :         elapsedMin_p = min (elapsedMin_p, other.elapsed());
     335           0 :         elapsedMax_p = max (elapsedMax_p, other.elapsed());
     336             :     }
     337             : 
     338           0 :     return * this;
     339             : }
     340             : 
     341             : 
     342             : String
     343           0 : DeltaThreadTimes::formatAverage (const String & floatFormat,
     344             :                            Double scale,
     345             :                            const String & units) const // to convert to ms
     346             : {
     347             :     String realFormat = String::format ("(el=%s,cp=%s,%%4.1f%%%%) %s",
     348           0 :                                         floatFormat.c_str(), floatFormat.c_str(), units.c_str());
     349           0 :     Int n = n_p != 0 ? n_p : 1;
     350           0 :     Double c = cpu_p / n * scale;
     351           0 :     Double e = elapsed_p / n * scale;
     352           0 :     Double p = c / e * 100;
     353             : 
     354           0 :     String result = String::format (realFormat.c_str(), e, c, p);
     355             : 
     356           0 :     return result;
     357           0 : }
     358             : 
     359             : String
     360           0 : DeltaThreadTimes::formatStats (const String & floatFormat,
     361             :                          Double scale,
     362             :                          const String & units) const  // to convert to ms
     363             : {
     364             :     String realFormat = String::format ("(el=%s {%s-%s,%s}, cp=%s {%s-%s,%s}, %%4.1f%%%%) %s",
     365             :                                          floatFormat.c_str(),
     366             :                                          floatFormat.c_str(),
     367             :                                          floatFormat.c_str(),
     368             :                                          floatFormat.c_str(),
     369             :                                          floatFormat.c_str(),
     370             :                                          floatFormat.c_str(),
     371             :                                          floatFormat.c_str(),
     372             :                                          floatFormat.c_str(),
     373           0 :                                          units.c_str());
     374           0 :     Int n = n_p != 0 ? n_p : 1;
     375           0 :     Double c = cpu_p / n * scale;
     376           0 :     Double cS = sqrt (cpuSsq_p / n_p - c * c);
     377           0 :     Double e = elapsed_p / n * scale;
     378           0 :     Double eS = sqrt (elapsedSsq_p / n_p - e * e);
     379           0 :     Double p = c / e * 100;
     380             : 
     381           0 :     String result = String::format (realFormat.c_str(), e, elapsedMin_p, elapsedMax_p, eS,
     382           0 :                                     c, cpuMin_p, cpuMax_p, cS, p);
     383             : 
     384           0 :     return result;
     385           0 : }
     386             : 
     387           0 : AipsErrorTrace::AipsErrorTrace ( const String &msg, const String &filename, uInt lineNumber,
     388           0 :                                  Category c)
     389           0 : : AipsError (msg, filename, lineNumber, c)
     390             : {
     391             :     void * stack [512];
     392           0 :     int n = backtrace (stack, 512);
     393           0 :     char ** trace = backtrace_symbols (stack, n);
     394             : 
     395           0 :     message += "\nStack trace (use c++filt to demangle):\n";
     396           0 :     for (int i = 0; i < n; i++){
     397           0 :         message += trace[i] + String ("\n");
     398             :     }
     399           0 :     free (trace);
     400           0 : }
     401             : 
     402             : 
     403             : 
     404           0 : MemoryStatistics::MemoryStatistics ()
     405             : {
     406             :     char buffer [128];
     407             : 
     408           0 :     pid_t pid = getpid ();
     409             : 
     410           0 :     sprintf (buffer, "/proc/%d/statm", pid);
     411             : 
     412           0 :     filename_p = buffer;
     413             : 
     414           0 :     pageSize_p = getpagesize ();
     415             : 
     416           0 :     bytesPerMb_p = 1024 * 1024.0;
     417           0 : }
     418             : 
     419             : double
     420           0 : MemoryStatistics::getVmInMB() const
     421             : {
     422           0 :     return getVmInBytes () / bytesPerMb_p;
     423             : }
     424             : 
     425             : int64_t
     426           0 : MemoryStatistics::getVmInBytes() const
     427             : {
     428           0 :     return vmPages_p * pageSize_p;
     429             : }
     430             : 
     431             : double
     432           0 : MemoryStatistics::getRssInMB() const
     433             : {
     434           0 :     return getRssInBytes () / bytesPerMb_p;
     435             : }
     436             : 
     437             : int64_t
     438           0 : MemoryStatistics::getRssInBytes() const
     439             : {
     440           0 :     return rssPages_p * pageSize_p;
     441             : }
     442             : 
     443             : 
     444             : void
     445           0 : MemoryStatistics::update ()
     446             : {
     447           0 :     ifstream is (filename_p.c_str());
     448             : 
     449           0 :     is >> vmPages_p >> rssPages_p;
     450             : 
     451           0 :     is.close ();
     452           0 : }
     453             : 
     454           0 : IoStatistics::IoStatistics ()
     455             : {
     456           0 :     Int pid = getpid();
     457           0 :     ostringstream os;
     458             : 
     459           0 :     statFile_p = String::format ("/proc/%d/io", pid);
     460             : 
     461           0 :     capture ();
     462           0 : }
     463             : 
     464             : IoStatistics
     465           0 : IoStatistics::operator- (const IoStatistics & other) const
     466             : {
     467           0 :     IoStatistics result;
     468           0 :     result.nBytesRead_p = nBytesRead_p - other.nBytesRead_p;
     469           0 :     result.nBytesWritten_p = nBytesWritten_p - other.nBytesWritten_p;
     470           0 :     result.nReads_p = nReads_p - other.nReads_p;
     471           0 :     result.nWrites_p = nWrites_p - other.nWrites_p;
     472             : 
     473           0 :     return result;
     474             : }
     475             : 
     476             : IoStatistics
     477           0 : IoStatistics::operator+ (const IoStatistics & other) const
     478             : {
     479           0 :     IoStatistics result;
     480             : 
     481           0 :     result.nBytesRead_p = nBytesRead_p + other.nBytesRead_p;
     482           0 :     result.nBytesWritten_p = nBytesWritten_p + other.nBytesWritten_p;
     483           0 :     result.nReads_p = nReads_p + other.nReads_p;
     484           0 :     result.nWrites_p = nWrites_p + other.nWrites_p;
     485             : 
     486           0 :     return result;
     487             : }
     488             : 
     489             : IoStatistics
     490           0 : IoStatistics::operator* (Double f) const
     491             : {
     492           0 :     IoStatistics result;
     493             : 
     494           0 :     result.nBytesRead_p = nBytesRead_p * f;
     495           0 :     result.nBytesWritten_p = nBytesWritten_p * f;
     496           0 :     result.nReads_p = nReads_p * f;
     497           0 :     result.nWrites_p = nWrites_p * f;
     498             : 
     499           0 :     return result;
     500             : }
     501             : 
     502             : IoStatistics
     503           0 : IoStatistics::operator/ (const IoStatistics & other) const
     504             : {
     505           0 :     IoStatistics result;
     506             : 
     507           0 :     result.nBytesRead_p = nBytesRead_p / other.nBytesRead_p;
     508           0 :     result.nBytesWritten_p = nBytesWritten_p / other.nBytesWritten_p;
     509           0 :     result.nReads_p = nReads_p / other.nReads_p;
     510           0 :     result.nWrites_p = nWrites_p / other.nWrites_p;
     511             : 
     512           0 :     return result;
     513             : }
     514             : 
     515             : 
     516             : void
     517           0 : IoStatistics::capture ()
     518             : {
     519           0 :     ifstream is (statFile_p.c_str());
     520             : 
     521           0 :     ThrowIf (! is.good(), String::format ("Failed to open %s file", statFile_p.c_str()));
     522             : 
     523           0 :     String tag;
     524             : 
     525           0 :     is >> tag;
     526           0 :     ThrowIf (tag != "rchar:",
     527             :              String::format ("Expected 'rchar:', got '%s'", tag.c_str()));
     528           0 :     is >> nBytesRead_p;
     529             : 
     530           0 :     is >> tag;
     531           0 :     ThrowIf (tag != "wchar:",
     532             :              String::format ("Expected 'wchar:', got '%s'", tag.c_str()));
     533           0 :     is >> nBytesWritten_p;
     534             : 
     535             : 
     536           0 :     is >> tag;
     537           0 :     ThrowIf (tag != "syscr:",
     538             :              String::format ("Expected 'syscr:', got '%s'", tag.c_str()));
     539           0 :     is >> nReads_p;
     540             : 
     541             : 
     542           0 :     is >> tag;
     543           0 :     ThrowIf (tag != "syscw:",
     544             :              String::format ("Expected 'syscw:', got '%s'", tag.c_str()));
     545           0 :     is >> nWrites_p;
     546             : 
     547           0 :     is.close();
     548           0 : }
     549             : 
     550             : Double
     551           0 : IoStatistics::getBytesRead () const
     552             : {
     553           0 :     return nBytesRead_p;
     554             : }
     555             : 
     556             : Double
     557           0 : IoStatistics::getBytesWritten () const
     558             : {
     559           0 :     return nBytesWritten_p;
     560             : }
     561             : 
     562             : Double
     563           0 : IoStatistics::getNReads () const
     564             : {
     565           0 :     return nReads_p;
     566             : }
     567             : 
     568             : Double
     569           0 : IoStatistics::getNWrites () const
     570             : {
     571           0 :     return nWrites_p;
     572             : }
     573             : 
     574             : String
     575           0 : IoStatistics::report (float scale, const String & scaleTag) const
     576             : {
     577           0 :     IoStatistics t = (* this) * scale;
     578             : 
     579             :     return String::format ("read: %.3f %sB, %.3f %sOps; write: %.3f %sB, %.3f %sOps",
     580             :                            t.nBytesRead_p, scaleTag.c_str(), t.nReads_p, scaleTag.c_str(),
     581           0 :                            t.nBytesWritten_p, scaleTag.c_str(), t.nWrites_p, scaleTag.c_str());
     582             : 
     583             : 
     584           0 : }
     585             : } // end namespace utilj
     586             : 
     587             : using namespace casacore;
     588             : } // end namespace casa

Generated by: LCOV version 1.16