Go to the documentation of this file.00001 #include "Utilities/StorageFactory/interface/StorageAccount.h"
00002 #include <boost/thread/mutex.hpp>
00003 #include <sstream>
00004 #include <unistd.h>
00005
00006 boost::mutex s_mutex;
00007 StorageAccount::StorageStats s_stats;
00008
00009 static double timeRealNanoSecs (void) {
00010 #if _POSIX_TIMERS > 0
00011 struct timespec tm;
00012 if (clock_gettime(CLOCK_REALTIME, &tm) == 0)
00013 return tm.tv_sec * 1e9 + tm.tv_nsec;
00014 #else
00015 struct timeval tm;
00016 if (gettimeofday(&tm, 0) == 0)
00017 return tm.tv_sec * 1e9 + tm.tv_usec * 1e3;
00018 #endif
00019 return 0;
00020 }
00021
00022 static std::string i2str(int i) {
00023 std::ostringstream t;
00024 t << i;
00025 return t.str();
00026 }
00027
00028 static std::string d2str(double d) {
00029 std::ostringstream t;
00030 t << d;
00031 return t.str();
00032 }
00033
00034 std::string
00035 StorageAccount::summaryText (bool banner ) {
00036 bool first = true;
00037 std::ostringstream os;
00038 if (banner)
00039 os << "stats: class/operation/attempts/successes/amount/time-total/time-min/time-max\n";
00040 for (StorageStats::iterator i = s_stats.begin (); i != s_stats.end(); ++i)
00041 for (OperationStats::iterator j = i->second->begin (); j != i->second->end (); ++j, first = false)
00042 os << (first ? "" : "; ")
00043 << i->first << '/'
00044 << j->first << '='
00045 << j->second.attempts << '/'
00046 << j->second.successes << '/'
00047 << (j->second.amount / 1024 / 1024) << "MB/"
00048 << (j->second.timeTotal / 1000 / 1000) << "ms/"
00049 << (j->second.timeMin / 1000 / 1000) << "ms/"
00050 << (j->second.timeMax / 1000 / 1000) << "ms";
00051
00052 return os.str ();
00053 }
00054
00055 std::string
00056 StorageAccount::summaryXML (void) {
00057 bool first = true;
00058 std::ostringstream os;
00059 os << "<storage-timing-summary>\n";
00060 for (StorageStats::iterator i = s_stats.begin (); i != s_stats.end(); ++i)
00061 for (OperationStats::iterator j = i->second->begin (); j != i->second->end (); ++j, first = false)
00062 os << " <counter-value subsystem='" << i->first
00063 << "' counter-name='" << j->first
00064 << "' num-operations='" << j->second.attempts
00065 << "' num-successful-operations='" << j->second.successes
00066 << "' total-megabytes='" << (j->second.amount / 1024 / 1024)
00067 << "' total-msecs='" << (j->second.timeTotal / 1000 / 1000)
00068 << "' min-msecs='" << (j->second.timeMin / 1000 / 1000)
00069 << "' max-msecs='" << (j->second.timeMax / 1000 / 1000) << "'/>\n";
00070 os << "</storage-timing-summary>";
00071 return os.str ();
00072 }
00073
00074 void
00075 StorageAccount::fillSummary(std::map<std::string, std::string>& summary) {
00076 int const oneM = 1000 * 1000;
00077 int const oneMeg = 1024 * 1024;
00078 for (StorageStats::iterator i = s_stats.begin (); i != s_stats.end(); ++i) {
00079 for (OperationStats::iterator j = i->second->begin(); j != i->second->end(); ++j) {
00080 std::ostringstream os;
00081 os << "Timing-" << i->first << "-" << j->first << "-";
00082 summary.insert(std::make_pair(os.str() + "numOperations", i2str(j->second.attempts)));
00083 summary.insert(std::make_pair(os.str() + "numSuccessfulOperations", i2str(j->second.successes)));
00084 summary.insert(std::make_pair(os.str() + "totalMegabytes", d2str(j->second.amount / oneMeg)));
00085 summary.insert(std::make_pair(os.str() + "totalMsecs", d2str(j->second.timeTotal / oneM)));
00086 summary.insert(std::make_pair(os.str() + "minMsecs", d2str(j->second.timeMin / oneM)));
00087 summary.insert(std::make_pair(os.str() + "maxMsecs", d2str(j->second.timeMax / oneM)));
00088 }
00089 }
00090 }
00091
00092 const StorageAccount::StorageStats&
00093 StorageAccount::summary (void)
00094 { return s_stats; }
00095
00096 StorageAccount::Counter&
00097 StorageAccount::counter (const std::string &storageClass, const std::string &operation) {
00098 boost::mutex::scoped_lock lock (s_mutex);
00099 boost::shared_ptr<OperationStats> &opstats = s_stats [storageClass];
00100 if (!opstats) opstats.reset(new OperationStats);
00101
00102 OperationStats::iterator pos = opstats->find (operation);
00103 if (pos == opstats->end ()) {
00104 Counter x = { 0, 0, 0, 0, 0 };
00105 pos = opstats->insert (OperationStats::value_type (operation, x)).first;
00106 }
00107
00108 return pos->second;
00109 }
00110
00111 StorageAccount::Stamp::Stamp (Counter &counter)
00112 : m_counter (counter),
00113 m_start (timeRealNanoSecs ())
00114 {
00115 boost::mutex::scoped_lock lock (s_mutex);
00116 m_counter.attempts++;
00117 }
00118
00119 void
00120 StorageAccount::Stamp::tick (double amount) const
00121 {
00122 boost::mutex::scoped_lock lock (s_mutex);
00123 double elapsed = timeRealNanoSecs () - m_start;
00124 m_counter.successes++;
00125 m_counter.amount += amount;
00126 m_counter.timeTotal += elapsed;
00127 if (elapsed < m_counter.timeMin || m_counter.successes == 1)
00128 m_counter.timeMin = elapsed;
00129 if (elapsed > m_counter.timeMax)
00130 m_counter.timeMax = elapsed;
00131 }