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 {
00011 struct timespec tm;
00012 if (clock_gettime(CLOCK_REALTIME, &tm) == 0)
00013 return tm.tv_sec * 1e9 + tm.tv_nsec;
00014 return 0;
00015 }
00016
00017 std::string
00018 StorageAccount::summaryText (bool banner )
00019 {
00020 bool first = true;
00021 std::ostringstream os;
00022 if (banner)
00023 os << "stats: class/operation/attempts/successes/amount/time-total/time-min/time-max\n";
00024 for (StorageStats::iterator i = s_stats.begin (); i != s_stats.end(); ++i)
00025 for (OperationStats::iterator j = i->second->begin (); j != i->second->end (); ++j, first = false)
00026 os << (first ? "" : "; ")
00027 << i->first << '/'
00028 << j->first << '='
00029 << j->second.attempts << '/'
00030 << j->second.successes << '/'
00031 << (j->second.amount / 1024 / 1024) << "MB/"
00032 << (j->second.timeTotal / 1000 / 1000) << "ms/"
00033 << (j->second.timeMin / 1000 / 1000) << "ms/"
00034 << (j->second.timeMax / 1000 / 1000) << "ms";
00035
00036 return os.str ();
00037 }
00038
00039 std::string
00040 StorageAccount::summaryXML (void)
00041 {
00042 bool first = true;
00043 std::ostringstream os;
00044 os << "<storage-timing-summary>\n";
00045 for (StorageStats::iterator i = s_stats.begin (); i != s_stats.end(); ++i)
00046 for (OperationStats::iterator j = i->second->begin (); j != i->second->end (); ++j, first = false)
00047 os << " <counter-value subsystem='" << i->first
00048 << "' counter-name='" << j->first
00049 << "' num-operations='" << j->second.attempts
00050 << "' num-successful-operations='" << j->second.successes
00051 << "' total-megabytes='" << (j->second.amount / 1024 / 1024)
00052 << "' total-msecs='" << (j->second.timeTotal / 1000 / 1000)
00053 << "' min-msecs='" << (j->second.timeMin / 1000 / 1000)
00054 << "' max-msecs='" << (j->second.timeMax / 1000 / 1000) << "'/>\n";
00055 os << "</storage-timing-summary>";
00056 return os.str ();
00057 }
00058
00059 const StorageAccount::StorageStats &
00060 StorageAccount::summary (void)
00061 { return s_stats; }
00062
00063 StorageAccount::Counter &
00064 StorageAccount::counter (const std::string &storageClass, const std::string &operation)
00065 {
00066 boost::mutex::scoped_lock lock (s_mutex);
00067 boost::shared_ptr<OperationStats> &opstats = s_stats [storageClass];
00068 if (! opstats) opstats.reset(new OperationStats);
00069
00070 OperationStats::iterator pos = opstats->find (operation);
00071 if (pos == opstats->end ())
00072 {
00073 Counter x = { 0, 0, 0, 0, 0 };
00074 pos = opstats->insert (OperationStats::value_type (operation, x)).first;
00075 }
00076
00077 return pos->second;
00078 }
00079
00080 StorageAccount::Stamp::Stamp (Counter &counter)
00081 : m_counter (counter),
00082 m_start (timeRealNanoSecs ())
00083 {
00084 boost::mutex::scoped_lock lock (s_mutex);
00085 m_counter.attempts++;
00086 }
00087
00088 void
00089 StorageAccount::Stamp::tick (double amount) const
00090 {
00091 boost::mutex::scoped_lock lock (s_mutex);
00092 double elapsed = timeRealNanoSecs () - m_start;
00093 m_counter.successes++;
00094 m_counter.amount += amount;
00095 m_counter.timeTotal += elapsed;
00096 if (elapsed < m_counter.timeMin || m_counter.successes == 1)
00097 m_counter.timeMin = elapsed;
00098 if (elapsed > m_counter.timeMax)
00099 m_counter.timeMax = elapsed;
00100 }