• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

Diags.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /****************************************************************************
00025 
00026   Diags.h
00027 
00028   This file contains code to manipulate run-time diagnostics, and print
00029   warnings and errors at runtime.  Action tags and debugging tags are
00030   supported, allowing run-time conditionals affecting diagnostics.
00031 
00032 
00033  ****************************************************************************/
00034 
00035 #ifndef __DIAGS_H___
00036 #define __DIAGS_H___
00037 
00038 #include <stdarg.h>
00039 #include "ink_error.h"
00040 #include "ink_mutex.h"
00041 #include "Regex.h"
00042 #include "ink_apidefs.h"
00043 
00044 #define DIAGS_MAGIC 0x12345678
00045 
00046 class Diags;
00047 
00048 // extern int diags_on_for_plugins;
00049 typedef enum
00050 {
00051   DiagsTagType_Debug = 0,       // do not renumber --- used as array index
00052   DiagsTagType_Action = 1
00053 } DiagsTagType;
00054 
00055 struct DiagsModeOutput
00056 {
00057   bool to_stdout;
00058   bool to_stderr;
00059   bool to_syslog;
00060   bool to_diagslog;
00061 };
00062 
00063 typedef enum
00064 {                               // do not renumber --- used as array index
00065   DL_Diag = 0,                  // process does not die
00066   DL_Debug,                     // process does not die
00067   DL_Status,                    // process does not die
00068   DL_Note,                      // process does not die
00069   DL_Warning,                   // process does not die
00070   DL_Error,                     // process does not die
00071   DL_Fatal,                     // causes process termination
00072   DL_Alert,                     // causes process termination
00073   DL_Emergency,                 // causes process termination
00074   DL_Undefined                  // must be last, used for size!
00075 } DiagsLevel;
00076 
00077 #define DiagsLevel_Count DL_Undefined
00078 
00079 #define DiagsLevel_IsTerminal(_l) (((_l) >= DL_Fatal) && ((_l) < DL_Undefined))
00080 
00081 // Cleanup Function Prototype - Called before ink_fatal to
00082 //   cleanup process state
00083 typedef void (*DiagsCleanupFunc) ();
00084 
00085 struct DiagsConfigState
00086 {
00087   // this is static to eliminate many loads from the critical path
00088   static bool enabled[2];                       // one debug, one action
00089   DiagsModeOutput outputs[DiagsLevel_Count];    // where each level prints
00090 };
00091 
00092 
00093 //////////////////////////////////////////////////////////////////////////////
00094 //
00095 //      class SrcLoc
00096 //
00097 //      The SrcLoc class wraps up a source code location, including file
00098 //      name, function name, and line number, and contains a method to
00099 //      format the result into a string buffer.
00100 //
00101 //////////////////////////////////////////////////////////////////////////////
00102 
00103 #define DiagsMakeLocation() SrcLoc(__FILE__, __FUNCTION__, __LINE__)
00104 
00105 class SrcLoc
00106 {
00107 public:
00108   const char *file;
00109   const char *func;
00110   const int line;
00111 
00112   bool valid() const {
00113     return file && line;
00114   }
00115 
00116   SrcLoc(const char *_file, const char *_func, int _line)
00117     : file(_file), func(_func), line(_line) {
00118   }
00119 
00120   char * str(char *buf, int buflen) const;
00121 };
00122 
00123 
00124 //////////////////////////////////////////////////////////////////////////////
00125 //
00126 //      class Diags
00127 //
00128 //      The Diags class is used for global configuration of the run-time
00129 //      diagnostics system.  This class provides the following services:
00130 //
00131 //      * run-time notices, debugging, warnings, errors
00132 //      * debugging tags to selectively enable & disable diagnostics
00133 //      * action tags to selectively enable & disable code paths
00134 //      * configurable output to stdout, stderr, syslog, error logs
00135 //      * traffic_manager interface supporting on-the-fly reconfiguration
00136 //
00137 //////////////////////////////////////////////////////////////////////////////
00138 
00139 class Diags
00140 {
00141 public:
00142   Diags(const char *base_debug_tags, const char *base_action_tags, FILE * _diags_log_fp = NULL);
00143    ~Diags();
00144 
00145   FILE *diags_log_fp;
00146   const unsigned int magic;
00147   volatile DiagsConfigState config;
00148   int show_location;
00149   DiagsCleanupFunc cleanup_func;
00150   const char *prefix_str;
00151 
00152   ///////////////////////////
00153   // conditional debugging //
00154   ///////////////////////////
00155 
00156   bool on(DiagsTagType mode = DiagsTagType_Debug) const {
00157     return (config.enabled[mode]);
00158   }
00159 
00160   bool on(const char *tag, DiagsTagType mode = DiagsTagType_Debug) const {
00161     return (config.enabled[mode] && tag_activated(tag, mode));
00162   }
00163 
00164   /////////////////////////////////////
00165   // low-level tag inquiry functions //
00166   /////////////////////////////////////
00167 
00168   inkcoreapi bool tag_activated(const char *tag, DiagsTagType mode = DiagsTagType_Debug) const;
00169 
00170   /////////////////////////////
00171   // raw printing interfaces //
00172   /////////////////////////////
00173 
00174   const char *level_name(DiagsLevel dl) const;
00175 
00176   inkcoreapi void print_va(const char *tag, DiagsLevel dl,
00177                            const SrcLoc *loc, const char *format_string, va_list ap) const;
00178 
00179 
00180   //////////////////////////////
00181   // user printing interfaces //
00182   //////////////////////////////
00183 
00184   void print(const char *tag, DiagsLevel dl, const char *file, const char *func,
00185              const int line, const char *format_string, ...) const TS_PRINTFLIKE(7, 8)
00186   {
00187     va_list ap;
00188     va_start(ap, format_string);
00189     if (show_location) {
00190       SrcLoc lp(file, func, line);
00191       print_va(tag, dl, &lp, format_string, ap);
00192     } else {
00193       print_va(tag, dl, NULL, format_string, ap);
00194     }
00195     va_end(ap);
00196   }
00197 
00198   ///////////////////////////////////////////////////////////////////////
00199   // user diagnostic output interfaces --- enabled on or off based     //
00200   // on the value of the enable flag, and the state of the debug tags. //
00201   ///////////////////////////////////////////////////////////////////////
00202 
00203   void log_va(const char *tag, DiagsLevel dl, const SrcLoc * loc, const char *format_string, va_list ap)
00204   {
00205     if (!on(tag))
00206       return;
00207     print_va(tag, dl, loc, format_string, ap);
00208   }
00209 
00210   void log(const char *tag, DiagsLevel dl,
00211            const char *file, const char *func, const int line,
00212            const char *format_string, ...) const TS_PRINTFLIKE(7, 8);
00213 
00214   void error_va(DiagsLevel dl,
00215              const char *file, const char *func, const int line,
00216              const char *format_string, va_list ap) const;
00217 
00218   void
00219   error(DiagsLevel level,
00220                const char *file, const char *func, const int line,
00221                const char *format_string, ...) const TS_PRINTFLIKE(6, 7)
00222   {
00223     va_list ap;
00224     va_start(ap, format_string);
00225     error_va(level, file, func, line, format_string, ap);
00226     va_end(ap);
00227   }
00228 
00229   void dump(FILE * fp = stdout) const;
00230 
00231   void activate_taglist(const char *taglist, DiagsTagType mode = DiagsTagType_Debug);
00232 
00233   void deactivate_all(DiagsTagType mode = DiagsTagType_Debug);
00234 
00235   const char *base_debug_tags;        // internal copy of default debug tags
00236   const char *base_action_tags;       // internal copy of default action tags
00237 
00238 private:
00239   mutable ink_mutex tag_table_lock;   // prevents reconfig/read races
00240   DFA *activated_tags[2];             // 1 table for debug, 1 for action
00241 
00242   void lock() const
00243   {
00244     ink_mutex_acquire(&tag_table_lock);
00245   }
00246   void unlock() const
00247   {
00248     ink_mutex_release(&tag_table_lock);
00249   }
00250 };
00251 
00252 //////////////////////////////////////////////////////////////////////////
00253 //                                                                      //
00254 //      Macros                                                          //
00255 //                                                                      //
00256 //      The following are diagnostic macros that wrap up the compiler   //
00257 //      __FILE__, __FUNCTION__, and __LINE__ macros into closures       //
00258 //      and then invoke the closure on the remaining arguments.         //
00259 //                                                                      //
00260 //      This closure hack is done, because the cpp preprocessor doesn't //
00261 //      support manipulation and union of varargs parameters.           //
00262 //                                                                      //
00263 //////////////////////////////////////////////////////////////////////////
00264 
00265 #if !defined (__GNUC__)
00266 #ifndef __FUNCTION__
00267 #define __FUNCTION__ NULL
00268 #endif
00269 #endif
00270 
00271 extern inkcoreapi Diags *diags;
00272 
00273 #define DTA(l)    l,__FILE__,__FUNCTION__,__LINE__
00274 void dummy_debug(const char * tag, const char *fmt, ...) TS_PRINTFLIKE(2, 3);
00275 inline void
00276 dummy_debug(const char *tag, const char *fmt, ...)
00277 {
00278   (void)tag;
00279   (void)fmt;
00280 }
00281 
00282 #define Status(...)    diags->error(DTA(DL_Status), __VA_ARGS__)
00283 #define Note(...)      diags->error(DTA(DL_Note), __VA_ARGS__)
00284 #define Warning(...)   diags->error(DTA(DL_Warning), __VA_ARGS__)
00285 #define Error(...)     diags->error(DTA(DL_Error), __VA_ARGS__)
00286 #define Fatal(...)     diags->error(DTA(DL_Fatal), __VA_ARGS__)
00287 #define Alert(...)     diags->error(DTA(DL_Alert), __VA_ARGS__)
00288 #define Emergency(...) diags->error(DTA(DL_Emergency), __VA_ARGS__)
00289 
00290 #define StatusV(fmt, ap)    diags->error_va(DTA(DL_Status), fmt, ap)
00291 #define NoteV(fmt, ap)      diags->error_va(DTA(DL_Note), fmt, ap)
00292 #define WarningV(fmt, ap)   diags->error_va(DTA(DL_Warning), fmt, ap)
00293 #define ErrorV(fmt, ap)     diags->error_va(DTA(DL_Error), fmt, ap)
00294 #define FatalV(fmt, ap)     diags->error_va(DTA(DL_Fatal), fmt, ap)
00295 #define AlertV(fmt, ap)     diags->error_va(DTA(DL_Alert), fmt, ap)
00296 #define EmergencyV(fmt, ap) diags->error_va(DTA(DL_Emergency), fmt, ap)
00297 
00298 #ifdef TS_USE_DIAGS
00299 #define Diag(tag, ...)      if (unlikely(diags->on())) diags->log(tag, DTA(DL_Diag), __VA_ARGS__)
00300 #define Debug(tag, ...)     if (unlikely(diags->on())) diags->log(tag, DTA(DL_Debug), __VA_ARGS__)
00301 #define DiagSpecific(flag, tag, ...)  if (unlikely(diags->on())) flag ? diags->print(tag, DTA(DL_Diag), __VA_ARGS__) : \
00302                                                                    diags->log(tag, DTA(DL_Diag), __VA_ARGS__)
00303 #define DebugSpecific(flag, tag, ...)  if (unlikely(diags->on())) flag ? diags->print(tag, DTA(DL_Debug), __VA_ARGS__) : \
00304                                                                     diags->log(tag, DTA(DL_Debug), __VA_ARGS__)
00305 
00306 #define is_debug_tag_set(_t)     unlikely(diags->on(_t,DiagsTagType_Debug))
00307 #define is_action_tag_set(_t)    unlikely(diags->on(_t,DiagsTagType_Action))
00308 #define debug_tag_assert(_t,_a)  (is_debug_tag_set(_t) ? (ink_release_assert(_a), 0) : 0)
00309 #define action_tag_assert(_t,_a) (is_action_tag_set(_t) ? (ink_release_assert(_a), 0) : 0)
00310 #define is_diags_on(_t)          unlikely(diags->on(_t))
00311 
00312 #else // TS_USE_DIAGS
00313 
00314 #define Diag(tag, fmt, ...)      if (0) dummy_debug(tag, __VA_ARGS__)
00315 #define Debug(tag, fmt, ...)     if (0) dummy_debug(tag, __VA_ARGS__)
00316 #define DiagSpecific(flag, tag, ...)  if (0 && tag) dummy_debug(tag, __VA_ARGS__);
00317 #define DebugSpecific(flag, tag, ...)  if (0 && tag) dummy_debug(tag, __VA_ARGS__);
00318 
00319 
00320 #define is_debug_tag_set(_t)     0
00321 #define is_action_tag_set(_t)    0
00322 #define debug_tag_assert(_t,_a) /**/
00323 #define action_tag_assert(_t,_a) /**/
00324 #define is_diags_on(_t)          0
00325 
00326 #endif // TS_USE_DIAGS
00327 #endif  /*_Diags_h_*/

Generated by  doxygen 1.7.1