Grid Community Toolkit  6.2.1653033972 (tag: v6.2.20220524)
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
globus_debug.h
Go to the documentation of this file.
1 /*
2  * Copyright 1999-2006 University of Chicago
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
22 #ifndef GLOBUS_DEBUG_H
23 #define GLOBUS_DEBUG_H
24 
25 #include "globus_common_include.h"
26 #include "globus_time.h"
27 
28 #ifdef __cplusplus
29 extern "C" {
30 #endif
31 
32 #ifdef BUILD_DEBUG
33 
34 typedef struct
35 {
36  unsigned levels;
37  unsigned timestamp_levels;
38  FILE * file;
39  globus_bool_t thread_ids;
40  globus_bool_t using_file;
41 } globus_debug_handle_t;
42 
43 void
44 globus_debug_init(
45  const char * env_name,
46  const char * level_names,
47  globus_debug_handle_t * handle);
48 
49 #define GlobusDebugThreadId() globus_thread_self()
50 
51 /* call in same file as module_activate func (before (de)activate funcs) */
52 #define GlobusDebugDefine(module_name) \
53  extern globus_debug_handle_t globus_i_##module_name##_debug_handle; \
54  void globus_i_##module_name##_debug_printf(const char * fmt, ...) \
55  { \
56  va_list ap; \
57  \
58  if(!globus_i_##module_name##_debug_handle.file) \
59  return; \
60  \
61  va_start(ap, fmt); \
62  if(globus_i_##module_name##_debug_handle.thread_ids) \
63  { \
64  char buf[4096]; /* XXX better not use a fmt bigger than this */ \
65  sprintf( \
66  buf, "%lu::%s", (unsigned long) globus_thread_self().dummy, fmt);\
67  vfprintf(globus_i_##module_name##_debug_handle.file, buf, ap); \
68  } \
69  else \
70  { \
71  vfprintf(globus_i_##module_name##_debug_handle.file, fmt, ap); \
72  } \
73  va_end(ap); \
74  } \
75  void globus_i_##module_name##_debug_time_printf(const char * fmt, ...) \
76  { \
77  va_list ap; \
78  char buf[4096]; /* XXX better not use a fmt bigger than this */ \
79  globus_abstime_t current_time; \
80  \
81  if(!globus_i_##module_name##_debug_handle.file) \
82  return; \
83  \
84  GlobusTimeAbstimeGetCurrent(current_time); \
85  va_start(ap, fmt); \
86  if(globus_i_##module_name##_debug_handle.thread_ids) \
87  { \
88  globus_thread_t __self = GlobusDebugThreadId(); \
89  sprintf(buf, "%lu:%lu.%.9lu::%s", \
90  (unsigned long) __self.dummy, \
91  (unsigned long) current_time.tv_sec, \
92  (unsigned long) current_time.tv_nsec, \
93  fmt); \
94  vfprintf(globus_i_##module_name##_debug_handle.file, buf, ap); \
95  } \
96  else \
97  { \
98  sprintf(buf, "%lu.%.9lu::%s", \
99  (unsigned long) current_time.tv_sec, \
100  (unsigned long) current_time.tv_nsec, \
101  fmt); \
102  vfprintf(globus_i_##module_name##_debug_handle.file, buf, ap); \
103  } \
104  va_end(ap); \
105  } \
106  void globus_i_##module_name##_debug_fwrite( \
107  const void *ptr, size_t size, size_t nmemb) \
108  { \
109  if(globus_i_##module_name##_debug_handle.file) \
110  fwrite(ptr, size, nmemb, \
111  globus_i_##module_name##_debug_handle.file); \
112  } \
113  globus_debug_handle_t globus_i_##module_name##_debug_handle
114 
115 /* call this in a header file (if needed externally) */
116 #define GlobusDebugDeclare(module_name) \
117  extern void globus_i_##module_name##_debug_printf(const char *, ...); \
118  extern void globus_i_##module_name##_debug_time_printf(const char *, ...);\
119  extern void globus_i_##module_name##_debug_fwrite( \
120  const void *ptr, size_t size, size_t nmemb); \
121  extern globus_debug_handle_t globus_i_##module_name##_debug_handle
122 
123 /* call this in module activate func
124  *
125  * 'levels' is a space separated list of level names that can be used in env
126  * they will map to a 2^i value (so, list them in same order as value)
127  *
128  * will look in env for {module_name}_DEBUG whose value is:
129  * <levels> [, [ [ # ] <file name>] [, <flags> [, <timestamp_levels>] ] ]
130  * where <levels> can be a single numeric or '|' separated level names
131  * <file name> is a debug output file... can be empty. stderr by default
132  * if a '#' precedes the filename, the file will be overwritten on each run
133  * otherwise, the default is to append to the existing (if one exists)
134  * <flags> 0 default (or any of the following to enable:
135  * 1 show thread ids
136  * 2 append pid to debug filename
137  * <timestamp_levels> similar to <levels>. specifies which levels to print
138  * timestamps with. default is none.
139  * Also, users can use the ALL level in their env setting to turn on
140  * all levels or precede the list of levels with '^' to enable all levels
141  * except those.
142  */
143 #define GlobusDebugInit(module_name, levels) \
144  globus_debug_init( \
145  #module_name "_DEBUG", \
146  #levels, \
147  &globus_i_##module_name##_debug_handle)
148 
149 /* call this in module deactivate func */
150 #define GlobusDebugDestroy(module_name) \
151  do \
152  { \
153  if(globus_i_##module_name##_debug_handle.using_file) \
154  { \
155  fclose(globus_i_##module_name##_debug_handle.file); \
156  } \
157  globus_i_##module_name##_debug_handle.file = GLOBUS_NULL; \
158  } while(0)
159 
160 /* use this to print a message unconditionally (message must be enclosed in
161  * parenthesis and contains a format and possibly var args
162  */
163 #define GlobusDebugMyPrintf(module_name, message) \
164  globus_i_##module_name##_debug_printf message
165 #define GlobusDebugMyTimePrintf(module_name, message) \
166  globus_i_##module_name##_debug_time_printf message
167 
168 #define GlobusDebugMyFwrite(module_name, buffer, size, count) \
169  globus_i_##module_name##_debug_fwrite((buffer), (size), (count))
170 
171 #define GlobusDebugMyFile(module_name) \
172  (globus_i_##module_name##_debug_handle.file)
173 
174 /* use this in an if() to debug enable blocks of code
175  * for example
176  *
177  * if(GlobusDebugTrue(MY_MODULE, VERIFICATION))
178  * {
179  * compute stats
180  * GlobusDebugMyPrintf(MY_MODULE, "Stats = %d\n", stats);
181  * }
182  */
183 #define GlobusDebugTrue(module_name, level) \
184  (globus_i_##module_name##_debug_handle.levels & (level))
185 
186 #define GlobusDebugTimeTrue(module_name, level) \
187  (globus_i_##module_name##_debug_handle.timestamp_levels & (level))
188 
189 /* most likely wrap this with your own macro,
190  * so you don't need to pass module_name all the time
191  * 'message' needs to be wrapped with parens and contains a format and
192  * possibly var args
193  */
194 #define GlobusDebugPrintf(module_name, level, message) \
195  do \
196  { \
197  if(GlobusDebugTrue(module_name, level)) \
198  { \
199  if(!GlobusDebugTimeTrue(module_name, level)) \
200  { \
201  GlobusDebugMyPrintf(module_name, message); \
202  } \
203  else \
204  { \
205  GlobusDebugMyTimePrintf(module_name, message); \
206  } \
207  } \
208  } while(0)
209 
210 #define GlobusDebugFwrite(module_name, level, buffer, size, count) \
211  do \
212  { \
213  if(GlobusDebugTrue(module_name, level)) \
214  { \
215  GlobusDebugMyFwrite(module_name, buffer, size, count); \
216  } \
217  } while(0)
218 
219 #else
220 
221 #define GlobusDebugThreadId() 0
222 #define GlobusDebugDeclare(module_name)
223 #define GlobusDebugDefine(module_name)
224 #define GlobusDebugInit(module_name, levels) do {} while(0)
225 #define GlobusDebugDestroy(module_name) do {} while(0)
226 #define GlobusDebugPrintf(module_name, level, message) do {} while(0)
227 #define GlobusDebugFwrite(module_name, level, buffer, size, count) \
228  do {} while(0)
229 #define GlobusDebugMyPrintf(module_name, message) do {} while(0)
230 #define GlobusDebugMyTimePrintf(module_name, message) do {} while(0)
231 #define GlobusDebugMyFwrite(module_name, buffer, size, count) do {} while(0)
232 #define GlobusDebugMyFile(module_name) (stderr)
233 #define GlobusDebugTrue(module_name, level) 0
234 #define GlobusDebugTimeTrue(module_name, level) 0
235 
236 #endif
237 
238 #ifdef __cplusplus
239 }
240 #endif
241 
242 #endif /* GLOBUS_DEBUG_H */
int globus_bool_t
Boolean type.
Definition: globus_types.h:93
Time Types and Macros.
Include System Headers.