3 //=============================================================================
7 * @author Huang-Ming Huang <huangh@ociweb.com>
9 //=============================================================================
11 #ifndef ACE_LOG_CATEGORY_H
12 #define ACE_LOG_CATEGORY_H
14 #include /**/ "ace/pre.h"
16 #include "ace/Log_Priority.h"
17 #include "ace/Log_Msg.h"
18 #include "ace/Thread_Mutex.h"
20 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
22 #if defined (ACE_NLOGGING)
23 #if !defined (ACELIB_HEX_DUMP)
24 # define ACELIB_HEX_DUMP(X) do {} while (0)
26 #if !defined (ACELIB_RETURN)
27 # define ACELIB_RETURN(Y) do { return (Y); } while (0)
29 #if !defined (ACELIB_ERROR_RETURN)
30 # define ACELIB_ERROR_RETURN(X, Y) return (Y)
32 #if !defined (ACELIB_ERROR_BREAK)
33 # define ACELIB_ERROR_BREAK(X) { break; }
35 #if !defined (ACELIB_ERROR)
36 # define ACELIB_ERROR(X) do {} while (0)
38 #if !defined (ACELIB_DEBUG)
39 # define ACELIB_DEBUG(X) do {} while (0)
41 #if !defined (ACELIB_ERROR_INIT)
42 # define ACELIB_ERROR_INIT(VALUE, FLAGS)
45 #if !defined (ACELIB_HEX_DUMP)
46 #define ACELIB_HEX_DUMP(X) \
48 int const __ace_error = ACE_Log_Msg::last_error_adapter (); \
49 ACE_Log_Category_TSS *ace___ = ACE_Log_Category::ace_lib().per_thr_obj(); \
50 if (ace___ == 0) break;\
51 ace___->conditional_set (__FILE__, __LINE__, 0, __ace_error); \
52 ace___->log_hexdump X; \
55 #if !defined (ACELIB_RETURN)
56 #define ACELIB_RETURN(Y) \
58 int const __ace_error = ACE_Log_Msg::last_error_adapter (); \
59 ACE_Log_Msg *ace___ = ACE_Log_Msg::instance(); \
60 ace___->set (__FILE__, __LINE__, Y, __ace_error, ace___->restart (), \
61 ace___->msg_ostream (), ace___->msg_callback ()); \
65 #if !defined (ACELIB_ERROR_RETURN)
66 # ifdef ACE_LACKS_VA_FUNCTIONS
67 # define ACELIB_ERROR_RETURN(X, Y) \
69 int const __ace_error = ACE_Log_Msg::last_error_adapter (); \
70 ACE_Log_Category_TSS *ace___ = ACE_Log_Category::ace_lib().per_thr_obj(); \
71 if (ace___ == 0) return Y;\
72 ace___->conditional_set (__FILE__, __LINE__, Y, __ace_error); \
76 # else /* ACE_LACKS_VA_FUNCTIONS */
77 # define ACELIB_ERROR_RETURN(X, Y) \
79 int const __ace_error = ACE_Log_Msg::last_error_adapter (); \
80 ACE_Log_Category_TSS *ace___ = ACE_Log_Category::ace_lib().per_thr_obj(); \
81 if (ace___ == 0) return Y;\
82 ace___->conditional_set (__FILE__, __LINE__, Y, __ace_error); \
86 # endif /* ACE_LACKS_VA_FUNCTIONS */
88 #if !defined (ACELIB_ERROR)
89 # ifdef ACE_LACKS_VA_FUNCTIONS
90 # define ACELIB_ERROR(X) \
92 int const __ace_error = ACE_Log_Msg::last_error_adapter (); \
93 ACE_Log_Category_TSS *ace___ = ACE_Log_Category::ace_lib().per_thr_obj(); \
94 if (ace___ == 0) break;\
95 ace___->conditional_set (__FILE__, __LINE__, -1, __ace_error); \
98 # else /* ACE_LACKS_VA_FUNCTIONS */
99 # define ACELIB_ERROR(X) \
101 int const __ace_error = ACE_Log_Msg::last_error_adapter (); \
102 ACE_Log_Category_TSS *ace___ = ACE_Log_Category::ace_lib().per_thr_obj(); \
103 if (ace___ == 0) break;\
104 ace___->conditional_set (__FILE__, __LINE__, -1, __ace_error); \
107 # endif /* ACE_LACKS_VA_FUNCTIONS */
109 #if !defined (ACELIB_DEBUG)
110 # ifdef ACE_LACKS_VA_FUNCTIONS
111 # define ACELIB_DEBUG(X) \
113 int const __ace_error = ACE_Log_Msg::last_error_adapter (); \
114 ACE_Log_Category_TSS *ace___ = ACE_Log_Category::ace_lib().per_thr_obj(); \
115 if (ace___ == 0) break;\
116 ace___->conditional_set (__FILE__, __LINE__, 0, __ace_error); \
119 # else /* ACE_LACKS_VA_FUNCTIONS */
120 # define ACELIB_DEBUG(X) \
122 int const __ace_error = ACE_Log_Msg::last_error_adapter (); \
123 ACE_Log_Category_TSS *ace___ = ACE_Log_Category::ace_lib().per_thr_obj(); \
124 if (ace___ == 0) break;\
125 ace___->conditional_set (__FILE__, __LINE__, 0, __ace_error); \
128 # endif /* ACE_LACKS_VA_FUNCTIONS */
130 #if !defined (ACELIB_ERROR_BREAK)
131 #define ACELIB_ERROR_BREAK(X) { ACELIB_ERROR (X); break; }
133 #endif /* ACE_NLOGGING */
137 class ACE_Log_Category
;
141 * @class ACE_Log_Category_TSS
143 * @brief The thread specific object for a ACE_Log_Categy object.
145 * @see ACE_Log_Categy
147 class ACE_Export ACE_Log_Category_TSS
150 ACE_Log_Category_TSS(ACE_Log_Category
* category
, ACE_Log_Msg
* logger
);
152 const char* name() const;
153 unsigned int id() const;
155 ACE_Log_Msg
* logger();
156 /// Get the current ACE_Log_Priority mask.
157 u_long
priority_mask () const;
159 /// Set the ACE_Log_Priority mask, returns original mask.
160 u_long
priority_mask (u_long
);
161 /// Return true if the requested priority is enabled.
162 int log_priority_enabled (ACE_Log_Priority log_priority
);
165 * Set the line number, file name, operational status, error number,
166 * restart flag, ostream, and the callback object. This combines
167 * all the other set methods into a single method.
169 void set (const char *file
,
174 /// These values are only actually set if the requested priority is
176 void conditional_set (const char *file
,
181 #if !defined (ACE_LACKS_VA_FUNCTIONS)
182 ssize_t
log (ACE_Log_Priority priority
, const ACE_TCHAR
*format
, ...);
184 #if defined (ACE_HAS_WCHAR)
185 ssize_t
log (ACE_Log_Priority priority
, const ACE_ANTI_TCHAR
*format
, ...);
186 #endif /* ACE_HAS_WCHAR */
187 #else /* ACE_LACKS_VA_FUNCTIONS */
188 friend class ACE_Log_Formatter
;
190 ssize_t
log (const ACE_Log_Formatter
&formatter
);
191 #endif /* ACE_LACKS_VA_FUNCTIONS */
193 ssize_t
log (const ACE_TCHAR
*format
,
194 ACE_Log_Priority priority
,
197 ssize_t
log (ACE_Log_Record
&log_record
,
198 int suppress_stderr
= 0);
201 * Method to log hex dump. This is useful for debugging. Calls
202 * log() to do the actual print, but formats first to make the chars
205 int log_hexdump (ACE_Log_Priority log_priority
,
208 const ACE_TCHAR
*text
= 0);
210 ACE_ALLOC_HOOK_DECLARE
;
213 friend class ACE_Log_Category
;
214 ACE_Log_Category
* category_
;
215 ACE_Log_Msg
* logger_
;
216 u_long priority_mask_
;
220 * @class ACE_Log_Category
222 * @brief Provides a categorized message logging
225 * This class added another level of abstraction to
226 * @c ACE_Log_Msg to separate log messages into different
227 * categories. Logs in different categories can be independently
228 * enabled or disabled. However, they will all be affected by the
229 * priority_mask setting in ACE_Log_Msg. That is to say, if a
230 * given priority level is disabled using @c ACE_Log_Msg::priority_mask(),
231 * all messages of that priority level logged via any @c ACE_Log_Category
232 * object would also be disabled regardless of the @c priority_mask
233 * setting in the @c ACE_Log_Category object.
235 * Each category can have a name which
236 * is fixed at construction. The name is not used for
237 * formatting the messages. However, it can be used by a
238 * message backend object for identification and reformat
241 * To log a message into a category. Create a new @c ACE_Log_Category
242 * and then use @c per_thr_obj() for logging. For example,
245 * ACE_Log_Category test_category("Test");
246 * test_category.per_thr_obj()->log(LM_DEBUG, "Log into the Test category.");
248 * // set the process wide priority mask
249 * test_category.priority_mask(LM_DEBUG|LM_ERROR);
251 * // set the thread specific priority mask
252 * test_category.per_thr_obj()->priority_mask(LM_DEBUG);
255 class ACE_Export ACE_Log_Category
259 * Initialize the logger with a name.
261 * Notice that ACE_Log_Category does not
262 * deep copy the passed \a name; therefore,
263 * you must keep the lifetime of \a name
264 * longer than the newly create ACE_Log_Category
265 * object. The rational for the design is to avoid
266 * static initialization problem when the ACE_Log_Category
267 * is created in static storage.
269 ACE_Log_Category(const char* name
);
272 unsigned int id() const;
273 const char* name() const;
275 ACE_Log_Category_TSS
* per_thr_obj();
277 /// Get the process ACE_Log_Priority mask.
278 u_long
priority_mask () const;
280 /// Set the process ACE_Log_Priority mask, returns original mask.
281 u_long
priority_mask (u_long
);
283 static ACE_Log_Category
& ace_lib();
286 friend class ACE_Log_Category_TSS
;
289 ACE_Log_Category(const ACE_Log_Category
&);
290 ACE_Log_Category
& operator = (const ACE_Log_Category
&);
294 u_long priority_mask_
;
296 /// we couldn't directly use ACE_TSS because it would
297 /// create circular dependency
298 #if defined (ACE_HAS_THREADS)
299 /// Avoid race conditions during initialization.
300 ACE_Thread_Mutex keylock_
;
301 /// "First time in" flag.
302 /// Key for the thread-specific error data.
303 ACE_thread_key_t key_
;
304 #else // defined (ACE_HAS_THREADS)
305 ACE_Log_Category_TSS per_thr_obj_
;
306 #endif // defined (ACE_HAS_THREADS)
309 ACE_END_VERSIONED_NAMESPACE_DECL
311 #if defined (__ACE_INLINE__)
312 #include "ace/Log_Category.inl"
313 #endif /* __ACE_INLINE__ */
315 #include /**/ "ace/post.h"
316 #endif /* ACE_LOG_CATEGORY_H */