xorp

profile.hh

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__
 All Classes Namespaces Functions Variables Typedefs Enumerations