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 std::ostringstream os;
00058 os << "<storage-timing-summary>\n";
00059 for (StorageStats::iterator i = s_stats.begin (); i != s_stats.end(); ++i)
00060 for (OperationStats::iterator j = i->second->begin (); j != i->second->end (); ++j)
00061 os << " <counter-value subsystem='" << i->first
00062 << "' counter-name='" << j->first
00063 << "' num-operations='" << j->second.attempts
00064 << "' num-successful-operations='" << j->second.successes
00065 << "' total-megabytes='" << (j->second.amount / 1024 / 1024)
00066 << "' total-msecs='" << (j->second.timeTotal / 1000 / 1000)
00067 << "' min-msecs='" << (j->second.timeMin / 1000 / 1000)
00068 << "' max-msecs='" << (j->second.timeMax / 1000 / 1000) << "'/>\n";
00069 os << "</storage-timing-summary>";
00070 return os.str ();
00071 }
00072
00073 void
00074 StorageAccount::fillSummary(std::map<std::string, std::string>& summary) {
00075 int const oneM = 1000 * 1000;
00076 int const oneMeg = 1024 * 1024;
00077 for (StorageStats::iterator i = s_stats.begin (); i != s_stats.end(); ++i) {
00078 for (OperationStats::iterator j = i->second->begin(); j != i->second->end(); ++j) {
00079 std::ostringstream os;
00080 os << "Timing-" << i->first << "-" << j->first << "-";
00081 summary.insert(std::make_pair(os.str() + "numOperations", i2str(j->second.attempts)));
00082 summary.insert(std::make_pair(os.str() + "numSuccessfulOperations", i2str(j->second.successes)));
00083 summary.insert(std::make_pair(os.str() + "totalMegabytes", d2str(j->second.amount / oneMeg)));
00084 summary.insert(std::make_pair(os.str() + "totalMsecs", d2str(j->second.timeTotal / oneM)));
00085 summary.insert(std::make_pair(os.str() + "minMsecs", d2str(j->second.timeMin / oneM)));
00086 summary.insert(std::make_pair(os.str() + "maxMsecs", d2str(j->second.timeMax / oneM)));
00087 }
00088 }
00089 }
00090
00091 const StorageAccount::StorageStats&
00092 StorageAccount::summary (void)
00093 { return s_stats; }
00094
00095 StorageAccount::Counter&
00096 StorageAccount::counter (const std::string &storageClass, const std::string &operation) {
00097 boost::mutex::scoped_lock lock (s_mutex);
00098 boost::shared_ptr<OperationStats> &opstats = s_stats [storageClass];
00099 if (!opstats) opstats.reset(new OperationStats);
00100
00101 OperationStats::iterator pos = opstats->find (operation);
00102 if (pos == opstats->end ()) {
00103 Counter x = { 0, 0, 0, 0, 0 };
00104 pos = opstats->insert (OperationStats::value_type (operation, x)).first;
00105 }
00106
00107 return pos->second;
00108 }
00109
00110 StorageAccount::Stamp::Stamp (Counter &counter)
00111 : m_counter (counter),
00112 m_start (timeRealNanoSecs ())
00113 {
00114 boost::mutex::scoped_lock lock (s_mutex);
00115 m_counter.attempts++;
00116 }
00117
00118 void
00119 StorageAccount::Stamp::tick (double amount) const
00120 {
00121 boost::mutex::scoped_lock lock (s_mutex);
00122 double elapsed = timeRealNanoSecs () - m_start;
00123 m_counter.successes++;
00124 m_counter.amount += amount;
00125 m_counter.timeTotal += elapsed;
00126 if (elapsed < m_counter.timeMin || m_counter.successes == 1)
00127 m_counter.timeMin = elapsed;
00128 if (elapsed > m_counter.timeMax)
00129 m_counter.timeMax = elapsed;
00130 }