|
xorp
|
00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*- 00002 // vim:set sts=4 ts=8: 00003 00004 // Copyright (c) 2001-2011 XORP, Inc and Others 00005 // 00006 // This program is free software; you can redistribute it and/or modify 00007 // it under the terms of the GNU Lesser General Public License, Version 00008 // 2.1, June 1999 as published by the Free Software Foundation. 00009 // Redistribution and/or modification of this program under the terms of 00010 // any other version of the GNU Lesser General Public License is not 00011 // permitted. 00012 // 00013 // This program is distributed in the hope that it will be useful, but 00014 // WITHOUT ANY WARRANTY; without even the implied warranty of 00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details, 00016 // see the GNU Lesser General Public License, Version 2.1, a copy of 00017 // which can be found in the XORP LICENSE.lgpl file. 00018 // 00019 // XORP, Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA; 00020 // http://xorp.net 00021 00022 // $XORP: xorp/libxorp/profile.hh,v 1.18 2008/10/02 21:57:32 bms Exp $ 00023 00024 #ifndef __LIBXORP_PROFILE_HH__ 00025 #define __LIBXORP_PROFILE_HH__ 00026 00027 #ifdef XORP_DISABLE_PROFILE 00028 00029 # define Profile int 00030 # define PROFILE(a) /* do nothing */ 00031 00032 #else 00033 00034 # define PROFILE(a) a 00035 00036 00037 00038 #include "xorp.h" 00039 #include "timeval.hh" 00040 #include "exceptions.hh" 00041 #include "ref_ptr.hh" 00042 00049 class PVariableUnknown : public XorpReasonedException { 00050 public: 00051 PVariableUnknown(const char* file, size_t line, const string init_why = "") 00052 : XorpReasonedException("PVariableUnknown", file, line, init_why) 00053 {} 00054 }; 00055 00056 class PVariableExists : public XorpReasonedException { 00057 public: 00058 PVariableExists(const char* file, size_t line, const string init_why = "") 00059 : XorpReasonedException("PVariableExists", file, line, init_why) 00060 {} 00061 }; 00062 00063 class PVariableNotEnabled : public XorpReasonedException { 00064 public: 00065 PVariableNotEnabled(const char* file, size_t line, 00066 const string init_why = "") 00067 : XorpReasonedException("PVariableNotEnabled", file, line, init_why) 00068 {} 00069 }; 00070 00071 class PVariableLocked : public XorpReasonedException { 00072 public: 00073 PVariableLocked(const char* file, size_t line, 00074 const string init_why = "") 00075 : XorpReasonedException("PVariableLocked", file, line, init_why) 00076 {} 00077 }; 00078 00079 class PVariableNotLocked : public XorpReasonedException { 00080 public: 00081 PVariableNotLocked(const char* file, size_t line, 00082 const string init_why = "") 00083 : XorpReasonedException("PVariableNotLocked", file, line, init_why) 00084 {} 00085 }; 00086 00087 class ProfileLogEntry { 00088 public: 00089 ProfileLogEntry() {} 00090 ProfileLogEntry(TimeVal time, string loginfo) 00091 : _time(time), _loginfo(loginfo) 00092 {} 00093 TimeVal time() {return _time;} 00094 string& loginfo() {return _loginfo;} 00095 private: 00096 TimeVal _time; // Time the profile was recorded. 00097 string _loginfo; // The profile data. 00098 }; 00099 00104 class Profile { 00105 public: 00106 typedef list<ProfileLogEntry> logentries; // Profiling info 00107 00108 class ProfileState { 00109 public: 00110 ProfileState() : _enabled(false), _locked(false), _log(NULL) {} 00111 ProfileState(const string& comment, bool enabled, bool locked, 00112 logentries *log) 00113 : _comment(comment), _enabled(enabled), _locked(locked), _log(log) 00114 {} 00115 void set_enabled(bool v) { _enabled = v; } 00116 bool enabled() const { return _enabled; } 00117 void set_locked(bool v) { _locked = v; } 00118 bool locked() const { return _locked; } 00119 logentries *logptr() const { return _log; } 00120 void zap() const { delete _log; } 00121 void set_iterator(const logentries::iterator& i) { _i = i; } 00122 void get_iterator(logentries::iterator& i) { i = _i; } 00123 int size() const { return _log->size(); } 00124 const string& comment() const {return _comment;} 00125 00126 private: 00127 const string _comment; // Textual description of this variable. 00128 bool _enabled; // True, if profiling is enabled. 00129 bool _locked; // True, if we are currently reading the log. 00130 logentries::iterator _i;// pointer into the log 00131 logentries *_log; 00132 }; 00133 00134 typedef map<string, ref_ptr<ProfileState> > profiles; 00135 00136 Profile(); 00137 00138 ~Profile(); 00139 00143 void create(const string& pname, const string& comment = "") 00144 throw(PVariableExists); 00145 00151 bool enabled(const string& pname) throw(PVariableUnknown) { 00152 // This is the most frequently called method hence make it 00153 // inline. As an optimisation if no profiling is enabled don't 00154 // perform any string maniplulation or lookups. 00155 00156 // If global profiling has not been enabled get out of here. 00157 if (0 == _profile_cnt) 00158 return false; 00159 00160 profiles::iterator i = _profiles.find(pname); 00161 // Catch any mispelt pnames. 00162 if (i == _profiles.end()) 00163 xorp_throw(PVariableUnknown, pname.c_str()); 00164 00165 return i->second->enabled(); 00166 } 00167 00171 void log(const string& pname, string comment) 00172 throw(PVariableUnknown,PVariableNotEnabled); 00173 00179 void enable(const string& pname) 00180 throw(PVariableUnknown,PVariableLocked); 00181 00186 void disable(const string& pname) throw(PVariableUnknown); 00187 00191 void lock_log(const string& pname) 00192 throw(PVariableUnknown,PVariableLocked); 00193 00200 bool read_log(const string& pname, ProfileLogEntry& entry) 00201 throw(PVariableUnknown,PVariableNotLocked); 00202 00206 void release_log(const string& pname) 00207 throw(PVariableUnknown,PVariableNotLocked); 00208 00212 void clear(const string& pname) throw(PVariableUnknown,PVariableLocked); 00213 00218 string get_list() const; 00219 00220 private: 00221 int _profile_cnt; // Number of variables that are enabled. 00222 profiles _profiles; 00223 }; 00224 00225 #ifdef PROFILE_UTILS_REQUIRED 00226 00230 class ProfileUtils { 00231 public: 00232 00233 static 00234 void 00235 transmit_log(const string& pname, XrlStdRouter *xrl_router, 00236 const string& instance_name, 00237 Profile *profile) 00238 { 00239 ProfileLogEntry ple; 00240 if (profile->read_log(pname, ple)) { 00241 TimeVal t = ple.time(); 00242 XrlProfileClientV0p1Client pc(xrl_router); 00243 pc.send_log(instance_name.c_str(), 00244 pname, t.sec(), t.usec(), ple.loginfo(), 00245 callback(ProfileUtils::transmit_callback, 00246 pname, xrl_router, instance_name, profile)); 00247 } else { 00248 // Unlock the log entry. 00249 profile->release_log(pname); 00250 ProfileUtils::transmit_finished(pname, xrl_router, instance_name); 00251 } 00252 } 00253 00254 static 00255 void 00256 transmit_callback(const XrlError& error, const string pname, 00257 XrlStdRouter *xrl_router, 00258 const string instance_name, 00259 Profile *profile) 00260 { 00261 if (XrlError::OKAY() != error) { 00262 XLOG_WARNING("%s", error.error_msg()); 00263 // Unlock the log entry. 00264 profile->release_log(pname); 00265 return; 00266 } 00267 ProfileUtils::transmit_log(pname, xrl_router, instance_name, profile); 00268 } 00269 00270 static 00271 void 00272 transmit_finished(const string& pname, XrlStdRouter *xrl_router, 00273 const string& instance_name) 00274 { 00275 debug_msg("pname = %s instance_name = %s\n", pname.c_str(), 00276 instance_name.c_str()); 00277 00278 XrlProfileClientV0p1Client pc(xrl_router); 00279 pc.send_finished(instance_name.c_str(), pname, 00280 callback(ProfileUtils::transmit_finished_callback, 00281 pname)); 00282 } 00283 00284 static 00285 void 00286 transmit_finished_callback(const XrlError& error, 00287 const string /*pname*/) 00288 { 00289 if (XrlError::OKAY() != error) 00290 XLOG_WARNING("%s", error.error_msg()); 00291 } 00292 00293 private: 00294 ProfileUtils(); // Don't allow instantiation 00295 ProfileUtils(const ProfileUtils&); 00296 }; 00297 #endif // PROFILE_UTILS_REQUIRED 00298 00299 // simple but fast profiling support 00300 #define SP_MAX_SAMPLES 128 00301 00302 namespace SP { 00303 typedef uint64_t SAMPLE; 00304 typedef SAMPLE (*SAMPLER)(void); 00305 00306 void set_sampler(SAMPLER sampler); 00307 void add_sample(const char* desc); 00308 void print_samples(); 00309 SAMPLE sample(); 00310 00311 SAMPLE sampler_time(); 00312 #if defined(__i386__) && defined(__GNUC__) 00313 #define __HAVE_TSC__ 00314 SAMPLE sampler_tsc(); 00315 #endif 00316 } // namespace SP 00317 00318 #endif // profile 00319 00320 #endif // __LIBXORP_PROFILE_HH__