Merge pull request #2309 from mitza-oci/warnings
[ACE_TAO.git] / ACE / ace / Log_Msg.cpp
blob570711e99dc11afaf53d03faea1d3832931fdb6d
1 // We need this to get the status of ACE_NTRACE...
2 #include "ace/config-all.h"
4 // Turn off tracing for the duration of this file.
5 #if defined (ACE_NTRACE)
6 # undef ACE_NTRACE
7 #endif /* ACE_NTRACE */
8 #define ACE_NTRACE 1
10 #include "ace/ACE.h"
11 #include "ace/Thread_Manager.h"
12 #include "ace/Guard_T.h"
13 #include "ace/OS_NS_stdio.h"
14 #include "ace/OS_NS_errno.h"
15 #include "ace/OS_NS_sys_time.h"
16 #include "ace/OS_NS_string.h"
17 #include "ace/OS_NS_wchar.h"
18 #include "ace/OS_NS_signal.h"
19 #include "ace/os_include/os_typeinfo.h"
21 #if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE != 0)
22 # include "ace/Object_Manager.h"
23 #endif /* ! ACE_MT_SAFE */
25 #if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
26 // FUZZ: disable check_for_streams_include
27 # include "ace/streams.h"
28 #endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
30 #if defined (ACE_HAS_TRACE)
31 # include "ace/Trace.h"
32 #endif /* ACE_HAS_TRACE */
34 #include "ace/Log_Msg.h"
35 #include "ace/Log_Msg_Callback.h"
36 #include "ace/Log_Msg_IPC.h"
37 #include "ace/Log_Msg_NT_Event_Log.h"
38 #include "ace/Log_Msg_UNIX_Syslog.h"
39 #include "ace/Log_Record.h"
40 #include "ace/Recursive_Thread_Mutex.h"
41 #include "ace/Stack_Trace.h"
42 #include "ace/Atomic_Op.h"
44 #include <algorithm>
46 #if !defined (__ACE_INLINE__)
47 #include "ace/Log_Msg.inl"
48 #endif /* __ACE_INLINE__ */
50 #ifdef ACE_ANDROID
51 # include "ace/Log_Msg_Android_Logcat.h"
52 #endif
54 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
56 ACE_ALLOC_HOOK_DEFINE(ACE_Log_Msg)
58 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
59 bool ACE_Log_Msg::key_created_ = 0;
60 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
61 defined (ACE_HAS_TSS_EMULATION)
63 static ACE_thread_key_t the_log_msg_tss_key;
65 ACE_thread_key_t *log_msg_tss_key ()
67 return &the_log_msg_tss_key;
70 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
71 #else
72 static ACE_Cleanup_Adapter<ACE_Log_Msg>* log_msg_cleanup = 0;
73 class ACE_Msg_Log_Cleanup: public ACE_Cleanup_Adapter<ACE_Log_Msg>
75 public:
76 virtual ~ACE_Msg_Log_Cleanup () {
77 if (this == log_msg_cleanup)
78 log_msg_cleanup = 0;
81 #endif /* ACE_MT_SAFE */
83 #if defined (ACE_WIN32)
84 # define ACE_LOG_MSG_SYSLOG_BACKEND ACE_Log_Msg_NT_Event_Log
85 #elif defined (ACE_ANDROID)
86 # define ACE_LOG_MSG_SYSLOG_BACKEND ACE_Log_Msg_Android_Logcat
87 #elif !defined (ACE_LACKS_UNIX_SYSLOG)
88 # define ACE_LOG_MSG_SYSLOG_BACKEND ACE_Log_Msg_UNIX_Syslog
89 #endif
91 // When doing ACE_OS::s[n]printf() calls in log(), we need to update
92 // the space remaining in the output buffer based on what's returned from
93 // the output function. If we could rely on more modern compilers, this
94 // would be in an unnamed namespace, but it's a macro instead.
95 // count is a size_t, len is an int and assumed to be non-negative.
96 #define ACE_UPDATE_COUNT(COUNT, LEN) \
97 do { if (static_cast<size_t> (LEN) > COUNT) COUNT = 0; \
98 else COUNT -= static_cast<size_t> (LEN); \
99 } while (0)
101 /// Instance count for Log_Msg - used to know when dynamically
102 /// allocated storage (program name and host name) can be safely
103 /// deleted.
104 int ACE_Log_Msg::instance_count_ = 0;
107 * @class ACE_Log_Msg_Manager
109 * @brief Synchronize output operations.
111 * Provides global point of contact for all ACE_Log_Msg instances
112 * in a process.
114 * For internal use by ACE, only!
116 class ACE_Log_Msg_Manager
118 public:
119 static ACE_Log_Msg_Backend *log_backend_;
120 static ACE_Log_Msg_Backend *custom_backend_;
122 static u_long log_backend_flags_;
124 static int init_backend (const u_long *flags = 0);
126 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
127 //FUZZ: disable check_for_lack_ACE_OS
128 static void close () ACE_GCC_DESTRUCTOR_ATTRIBUTE;
129 //FUZZ: enable check_for_lack_ACE_OS
131 static ACE_Recursive_Thread_Mutex *get_lock ();
133 private:
134 static ACE_Recursive_Thread_Mutex *lock_;
135 #endif /* ! ACE_MT_SAFE */
138 ACE_Log_Msg_Backend *ACE_Log_Msg_Manager::log_backend_ = 0;
139 ACE_Log_Msg_Backend *ACE_Log_Msg_Manager::custom_backend_ = 0;
141 #ifndef ACE_DEFAULT_LOG_BACKEND_FLAGS
142 # ifdef ACE_ANDROID
143 # define ACE_DEFAULT_LOG_BACKEND_FLAGS ACE_Log_Msg::SYSLOG
144 # else
145 # define ACE_DEFAULT_LOG_BACKEND_FLAGS 0
146 # endif
147 #endif
149 u_long ACE_Log_Msg_Manager::log_backend_flags_ = ACE_DEFAULT_LOG_BACKEND_FLAGS;
151 int ACE_Log_Msg_Manager::init_backend (const u_long *flags)
153 // If flags have been supplied, and they are different from the flags
154 // we had last time, then we may have to re-create the backend as a
155 // different type.
156 if (flags)
158 // Sanity check for custom backend.
159 if (ACE_BIT_ENABLED (*flags, ACE_Log_Msg::CUSTOM) &&
160 ACE_Log_Msg_Manager::custom_backend_ == 0)
162 return -1;
165 if ((ACE_BIT_ENABLED (*flags, ACE_Log_Msg::SYSLOG)
166 && ACE_BIT_DISABLED (ACE_Log_Msg_Manager::log_backend_flags_, ACE_Log_Msg::SYSLOG))
167 || (ACE_BIT_DISABLED (*flags, ACE_Log_Msg::SYSLOG)
168 && ACE_BIT_ENABLED (ACE_Log_Msg_Manager::log_backend_flags_, ACE_Log_Msg::SYSLOG)))
170 delete ACE_Log_Msg_Manager::log_backend_;
171 ACE_Log_Msg_Manager::log_backend_ = 0;
174 ACE_Log_Msg_Manager::log_backend_flags_ = *flags;
177 if (ACE_Log_Msg_Manager::log_backend_ == 0)
179 #ifdef ACE_LOG_MSG_SYSLOG_BACKEND
180 // Allocate the ACE_Log_Msg_Backend instance.
181 if (ACE_BIT_ENABLED (ACE_Log_Msg_Manager::log_backend_flags_, ACE_Log_Msg::SYSLOG))
182 ACE_NEW_RETURN (ACE_Log_Msg_Manager::log_backend_,
183 ACE_LOG_MSG_SYSLOG_BACKEND,
184 -1);
185 else
186 #endif
187 ACE_NEW_RETURN (ACE_Log_Msg_Manager::log_backend_,
188 ACE_Log_Msg_IPC,
189 -1);
192 return 0;
195 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
196 ACE_Recursive_Thread_Mutex *ACE_Log_Msg_Manager::lock_ = 0;
198 ACE_Recursive_Thread_Mutex *
199 ACE_Log_Msg_Manager::get_lock ()
201 // This function is called by the first thread to create an ACE_Log_Msg
202 // instance. It makes the call while holding a mutex, so we don't have
203 // to grab another one here.
204 if (ACE_Log_Msg_Manager::lock_ == 0)
206 ACE_NEW_RETURN (ACE_Log_Msg_Manager::lock_,
207 ACE_Recursive_Thread_Mutex,
211 if (init_backend () == -1)
212 return 0;
214 return ACE_Log_Msg_Manager::lock_;
217 void
218 ACE_Log_Msg_Manager::close ()
220 // Ugly, ugly, but don't know a better way.
221 delete ACE_Log_Msg_Manager::lock_;
222 ACE_Log_Msg_Manager::lock_ = 0;
224 delete ACE_Log_Msg_Manager::log_backend_;
225 ACE_Log_Msg_Manager::log_backend_ = 0;
227 // we are never responsible for custom backend
228 ACE_Log_Msg_Manager::custom_backend_ = 0;
231 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
232 defined (ACE_HAS_TSS_EMULATION)
233 /* static */
234 # if defined (ACE_HAS_THR_C_DEST)
235 # define LOCAL_EXTERN_PREFIX extern "C"
236 # else
237 # define LOCAL_EXTERN_PREFIX
238 # endif /* ACE_HAS_THR_C_DEST */
239 LOCAL_EXTERN_PREFIX
240 void
241 ACE_TSS_CLEANUP_NAME (void *ptr)
243 if (ptr != 0)
245 // Delegate to thr_desc if this not has terminated
246 ACE_Log_Msg *log_msg = (ACE_Log_Msg *) ptr;
247 if (log_msg->thr_desc () != 0)
248 log_msg->thr_desc ()->log_msg_cleanup (log_msg);
249 else
250 delete log_msg;
253 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
254 #endif /* ! ACE_MT_SAFE */
256 /* static */
258 ACE_Log_Msg::exists ()
260 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
261 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
262 defined (ACE_HAS_TSS_EMULATION)
263 void *tss_log_msg = 0; // The actual type is ACE_Log_Msg*, but we need this
264 // void to keep G++ from complaining.
266 // Get the tss_log_msg from thread-specific storage.
267 return ACE_Log_Msg::key_created_
268 && ACE_Thread::getspecific (*(log_msg_tss_key ()), &tss_log_msg) != -1
269 && tss_log_msg != 0;
270 # else
271 # error "Platform must support thread-specific storage if threads are used."
272 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
273 #else /* ! ACE_MT_SAFE */
274 return 1;
275 #endif /* ! ACE_MT_SAFE */
278 ACE_Log_Msg *
279 ACE_Log_Msg::instance ()
281 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
282 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
283 defined (ACE_HAS_TSS_EMULATION)
284 // TSS Singleton implementation.
286 if (!ACE_Log_Msg::key_created_)
288 ACE_thread_mutex_t *lock =
289 reinterpret_cast<ACE_thread_mutex_t *> (
290 ACE_OS_Object_Manager::preallocated_object
291 [ACE_OS_Object_Manager::ACE_LOG_MSG_INSTANCE_LOCK]);
293 if (1 == ACE_OS_Object_Manager::starting_up())
294 //This function is called before ACE_OS_Object_Manager is
295 //initialized. So the lock might not be valid. Assume it's
296 //single threaded and so don't need the lock.
298 else
299 ACE_OS::thread_mutex_lock (lock);
301 if (!ACE_Log_Msg::key_created_)
303 // Allocate the Singleton lock.
304 ACE_Log_Msg_Manager::get_lock ();
306 if (ACE_Thread::keycreate (log_msg_tss_key (),
307 &ACE_TSS_CLEANUP_NAME) != 0)
309 if (1 == ACE_OS_Object_Manager::starting_up())
310 //This function is called before ACE_OS_Object_Manager is
311 //initialized. So the lock might not be valid. Assume it's
312 //single threaded and so don't need the lock.
314 else
315 ACE_OS::thread_mutex_unlock (lock);
316 return 0; // Major problems, this should *never* happen!
319 ACE_Log_Msg::key_created_ = true;
322 if (1 == ACE_OS_Object_Manager::starting_up())
323 //This function is called before ACE_OS_Object_Manager is
324 //initialized. So the lock might not be valid. Assume it's
325 //single threaded and so don't need the lock.
327 else
328 ACE_OS::thread_mutex_unlock (lock);
331 ACE_Log_Msg *tss_log_msg = 0;
332 void *temp = 0;
334 // Get the tss_log_msg from thread-specific storage.
335 if (ACE_Thread::getspecific (*(log_msg_tss_key ()), &temp) == -1)
336 return 0; // This should not happen!
338 tss_log_msg = static_cast <ACE_Log_Msg *> (temp);
340 // Check to see if this is the first time in for this thread.
341 if (tss_log_msg == 0)
343 // Allocate memory off the heap and store it in a pointer in
344 // thread-specific storage (on the stack...). The memory will
345 // always be freed by the thread rundown because of the TSS
346 // callback set up when the key was created.
347 ACE_NEW_RETURN (tss_log_msg,
348 ACE_Log_Msg,
350 // Store the dynamically allocated pointer in thread-specific
351 // storage. It gets deleted via the ACE_TSS_cleanup function
352 // when the thread terminates.
354 if (ACE_Thread::setspecific (*(log_msg_tss_key()),
355 reinterpret_cast<void *> (tss_log_msg))
356 != 0)
357 return 0; // Major problems, this should *never* happen!
360 return tss_log_msg;
361 # else
362 # error "Platform must support thread-specific storage if threads are used."
363 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
364 #else /* ! ACE_MT_SAFE */
365 // We don't have threads, we cannot call
366 // ACE_Log_Msg_Manager::get_lock () to initialize the logger
367 // callback, so instead we do it here.
368 if (ACE_Log_Msg_Manager::init_backend () == -1)
369 return 0;
371 // Singleton implementation.
373 if (log_msg_cleanup == 0)
375 ACE_NEW_RETURN (log_msg_cleanup, ACE_Msg_Log_Cleanup, 0);
376 // Register the instance for destruction at program termination.
377 ACE_Object_Manager::at_exit (log_msg_cleanup,
379 typeid (*log_msg_cleanup).name ());
382 return &log_msg_cleanup->object ();
383 #endif /* ! ACE_MT_SAFE */
386 // Not inlined to help prevent having to include OS.h just to
387 // get ACELIB_DEBUG, et al, macros.
389 ACE_Log_Msg::last_error_adapter ()
391 return ACE_OS::last_error ();
394 // Sets the flag in the default priority mask used to initialize
395 // ACE_Log_Msg instances, as well as the current per-thread instance.
397 void
398 ACE_Log_Msg::enable_debug_messages (ACE_Log_Priority priority)
400 ACE_SET_BITS (ACE_Log_Msg::default_priority_mask_, priority);
401 ACE_Log_Msg *i = ACE_Log_Msg::instance ();
402 i->priority_mask (i->priority_mask () | priority);
405 // Clears the flag in the default priority mask used to initialize
406 // ACE_Log_Msg instances, as well as the current per-thread instance.
408 void
409 ACE_Log_Msg::disable_debug_messages (ACE_Log_Priority priority)
411 ACE_CLR_BITS (ACE_Log_Msg::default_priority_mask_, priority);
412 ACE_Log_Msg *i = ACE_Log_Msg::instance ();
413 i->priority_mask (i->priority_mask () & ~priority);
416 const ACE_TCHAR *
417 ACE_Log_Msg::program_name ()
419 return ACE_Log_Msg::program_name_;
422 /// Name of the local host.
423 const ACE_TCHAR *ACE_Log_Msg::local_host_ = 0;
425 /// Records the program name.
426 const ACE_TCHAR *ACE_Log_Msg::program_name_ = 0;
428 /// Default is to use stderr.
429 u_long ACE_Log_Msg::flags_ = ACE_DEFAULT_LOG_FLAGS;
431 /// Current offset of msg_[].
432 ptrdiff_t ACE_Log_Msg::msg_off_ = 0;
434 /// Default per-thread priority mask
435 /// By default, no priorities are enabled.
436 u_long ACE_Log_Msg::default_priority_mask_ = 0;
438 /// Default per-process priority mask
439 /// By default, all priorities are enabled.
440 u_long ACE_Log_Msg::process_priority_mask_ = LM_SHUTDOWN
441 | LM_TRACE
442 | LM_DEBUG
443 | LM_INFO
444 | LM_NOTICE
445 | LM_WARNING
446 | LM_STARTUP
447 | LM_ERROR
448 | LM_CRITICAL
449 | LM_ALERT
450 | LM_EMERGENCY;
452 void
453 ACE_Log_Msg::close ()
455 // This call needs to go here to avoid memory leaks.
456 ACE_MT (ACE_Log_Msg_Manager::close ());
458 // Please note that this will be called by a statement that is
459 // harded coded into the ACE_Object_Manager's shutdown sequence, in
460 // its destructor.
462 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) && \
463 (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
464 defined (ACE_HAS_TSS_EMULATION))
466 if (ACE_Log_Msg::key_created_)
468 ACE_thread_mutex_t *lock =
469 reinterpret_cast<ACE_thread_mutex_t *>
470 (ACE_OS_Object_Manager::preallocated_object
471 [ACE_OS_Object_Manager::ACE_LOG_MSG_INSTANCE_LOCK]);
472 if (lock)
473 ACE_OS::thread_mutex_lock (lock);
475 if (ACE_Log_Msg::key_created_)
477 // Clean up this ACE_Log_Msg instance and reset the TSS to
478 // prevent any future cleanup attempts via TSS mechanisms at
479 // thread exit. Otherwise in the event of a dynamic library
480 // unload of libACE, by a program not linked with libACE,
481 // ACE_TSS_cleanup will be invoked after libACE has been unloaded.
482 // See Bugzilla 2980 for lots of details.
483 void *temp = 0;
485 // Get the tss_log_msg from thread-specific storage.
486 if (ACE_Thread::getspecific (*(log_msg_tss_key ()), &temp) != -1
487 && temp)
489 ACE_Log_Msg *tss_log_msg = static_cast <ACE_Log_Msg *> (temp);
490 // we haven't been cleaned up
491 ACE_TSS_CLEANUP_NAME(tss_log_msg);
492 if (ACE_Thread::setspecific(*(log_msg_tss_key()),
493 reinterpret_cast <void *>(0)) != 0)
494 ACE_OS::printf ("ACE_Log_Msg::close failed to ACE_Thread::setspecific to 0\n");
497 // The key is not needed any longer; ACE_Log_Msg is closing
498 // and will need to be reopened if this process wishes to use
499 // logging again. So delete the key.
500 ACE_Thread::keyfree (*(log_msg_tss_key()));
501 ACE_Log_Msg::key_created_ = false;
504 if (lock)
505 ACE_OS::thread_mutex_unlock (lock);
507 #endif /* (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION) && ACE_MT_SAFE */
510 void
511 ACE_Log_Msg::sync_hook (const ACE_TCHAR *prg_name)
513 ACE_LOG_MSG->sync (prg_name);
516 ACE_OS_Thread_Descriptor *
517 ACE_Log_Msg::thr_desc_hook ()
519 return ACE_LOG_MSG->thr_desc ();
522 // Call after a fork to resynchronize the PID and PROGRAM_NAME
523 // variables.
524 void
525 ACE_Log_Msg::sync (const ACE_TCHAR *prog_name)
527 ACE_TRACE ("ACE_Log_Msg::sync");
529 if (prog_name)
531 // Must free if already allocated!!!
532 #if defined (ACE_HAS_ALLOC_HOOKS)
533 ACE_Allocator::instance()->free ((void *) ACE_Log_Msg::program_name_);
534 #else
535 ACE_OS::free ((void *) ACE_Log_Msg::program_name_);
536 #endif /* ACE_HAS_ALLOC_HOOKS */
538 ACE_Log_Msg::program_name_ = ACE_OS::strdup (prog_name);
541 ACE_Log_Msg::msg_off_ = 0;
544 u_long
545 ACE_Log_Msg::flags ()
547 ACE_TRACE ("ACE_Log_Msg::flags");
548 u_long result;
549 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
550 *ACE_Log_Msg_Manager::get_lock (), 0));
552 result = ACE_Log_Msg::flags_;
553 return result;
556 void
557 ACE_Log_Msg::set_flags (u_long flgs)
559 ACE_TRACE ("ACE_Log_Msg::set_flags");
560 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
561 *ACE_Log_Msg_Manager::get_lock ()));
563 ACE_SET_BITS (ACE_Log_Msg::flags_, flgs);
566 void
567 ACE_Log_Msg::clr_flags (u_long flgs)
569 ACE_TRACE ("ACE_Log_Msg::clr_flags");
570 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
571 *ACE_Log_Msg_Manager::get_lock ()));
573 ACE_CLR_BITS (ACE_Log_Msg::flags_, flgs);
577 ACE_Log_Msg::acquire ()
579 ACE_TRACE ("ACE_Log_Msg::acquire");
580 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
581 return ACE_Log_Msg_Manager::get_lock ()->acquire ();
582 #else /* ! ACE_MT_SAFE */
583 return 0;
584 #endif /* ! ACE_MT_SAFE */
587 u_long
588 ACE_Log_Msg::priority_mask (u_long n_mask, MASK_TYPE mask_type)
590 u_long o_mask;
592 if (mask_type == THREAD)
594 o_mask = this->priority_mask_;
595 this->priority_mask_ = n_mask;
597 else
599 o_mask = ACE_Log_Msg::process_priority_mask_;
600 ACE_Log_Msg::process_priority_mask_ = n_mask;
603 return o_mask;
607 ACE_Log_Msg::release ()
609 ACE_TRACE ("ACE_Log_Msg::release");
611 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
612 return ACE_Log_Msg_Manager::get_lock ()->release ();
613 #else /* ! ACE_MT_SAFE */
614 return 0;
615 #endif /* ! ACE_MT_SAFE */
618 ACE_Log_Msg::ACE_Log_Msg ()
619 : status_ (0),
620 errnum_ (0),
621 linenum_ (0),
622 msg_ (0),
623 restart_ (1), // Restart by default...
624 ostream_ (0),
625 ostream_refcount_ (0),
626 msg_callback_ (0),
627 trace_depth_ (0),
628 trace_active_ (false),
629 tracing_enabled_ (true), // On by default?
630 thr_desc_ (0),
631 priority_mask_ (default_priority_mask_),
632 timestamp_ (0)
634 // ACE_TRACE ("ACE_Log_Msg::ACE_Log_Msg");
636 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
637 *ACE_Log_Msg_Manager::get_lock ()));
638 ++instance_count_;
640 if (this->instance_count_ == 1)
641 ACE_Base_Thread_Adapter::set_log_msg_hooks (ACE_Log_Msg::init_hook,
642 ACE_Log_Msg::inherit_hook,
643 ACE_Log_Msg::close,
644 ACE_Log_Msg::sync_hook,
645 ACE_Log_Msg::thr_desc_hook);
647 this->conditional_values_.is_set_ = false;
649 char *timestamp = ACE_OS::getenv ("ACE_LOG_TIMESTAMP");
650 if (timestamp != 0)
652 // If variable is set or is set to date tag so we print date and time.
653 if (ACE_OS::strcmp (timestamp, "TIME") == 0)
655 this->timestamp_ = 1;
657 else if (ACE_OS::strcmp (timestamp, "DATE") == 0)
659 this->timestamp_ = 2;
663 #if defined (ACE_HAS_ALLOC_HOOKS)
664 ACE_ALLOCATOR_NORETURN (this->msg_, static_cast<ACE_TCHAR *>(ACE_Allocator::instance()->malloc(sizeof(ACE_TCHAR) * (ACE_MAXLOGMSGLEN+1))));
665 #else
666 ACE_NEW_NORETURN (this->msg_, ACE_TCHAR[ACE_MAXLOGMSGLEN+1]);
667 #endif /* ACE_HAS_ALLOC_HOOKS */
670 ACE_Log_Msg::~ACE_Log_Msg ()
672 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
674 int instance_count = 0;
676 // Only hold the guard while updating the instance_count_.
677 // If ACE_Log_Msg_Manager::close () is called, the lock will
678 // be deleted.
680 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
681 *ACE_Log_Msg_Manager::get_lock ()));
682 instance_count = --instance_count_;
684 // Release the guard.
686 #else /* ! ACE_MT_SAFE */
687 int instance_count = --instance_count_;
688 #endif /* ! ACE_MT_SAFE */
690 // If this is the last instance then cleanup. Only the last
691 // thread to destroy its ACE_Log_Msg instance should execute
692 // this block.
693 if (instance_count == 0)
695 // Destroy the message queue instance.
696 if (ACE_Log_Msg_Manager::log_backend_ != 0)
697 ACE_Log_Msg_Manager::log_backend_->close ();
699 // Close down custom backend
700 if (ACE_Log_Msg_Manager::custom_backend_ != 0)
701 ACE_Log_Msg_Manager::custom_backend_->close ();
703 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
704 # if defined (ACE_HAS_TSS_EMULATION)
705 ACE_Log_Msg_Manager::close ();
706 # endif /* ACE_HAS_TSS_EMULATION */
707 # endif /* ACE_MT_SAFE */
709 if (ACE_Log_Msg::program_name_)
711 #if defined (ACE_HAS_ALLOC_HOOKS)
712 ACE_Allocator::instance()->free ((void *) ACE_Log_Msg::program_name_);
713 #else
714 ACE_OS::free ((void *) ACE_Log_Msg::program_name_);
715 #endif /* ACE_HAS_ALLOC_HOOKS */
716 ACE_Log_Msg::program_name_ = 0;
719 if (ACE_Log_Msg::local_host_)
721 #if defined (ACE_HAS_ALLOC_HOOKS)
722 ACE_Allocator::instance()->free ((void *) ACE_Log_Msg::local_host_);
723 #else
724 ACE_OS::free ((void *) ACE_Log_Msg::local_host_);
725 #endif /* ACE_HAS_ALLOC_HOOKS */
726 ACE_Log_Msg::local_host_ = 0;
730 this->cleanup_ostream ();
732 #if defined (ACE_HAS_ALLOC_HOOKS)
733 ACE_Allocator::instance()->free(this->msg_);
734 #else
735 delete[] this->msg_;
736 #endif /* ACE_HAS_ALLOC_HOOKS */
739 void
740 ACE_Log_Msg::cleanup_ostream ()
742 if (this->ostream_refcount_)
744 if (--*this->ostream_refcount_ == 0)
746 #if defined (ACE_HAS_ALLOC_HOOKS)
747 this->ostream_refcount_->~Atomic_ULong();
748 ACE_Allocator::instance()->free(this->ostream_refcount_);
749 #else
750 delete this->ostream_refcount_;
751 #endif /* ACE_HAS_ALLOC_HOOKS */
752 #if defined (ACE_LACKS_IOSTREAM_TOTALLY)
753 ACE_OS::fclose (this->ostream_);
754 #else
755 delete this->ostream_;
756 this->ostream_ = 0;
757 #endif
759 this->ostream_refcount_ = 0;
763 // Open the sender-side of the message queue.
765 ACE_Log_Msg::open (const ACE_TCHAR *prog_name,
766 u_long flags,
767 const ACE_TCHAR *logger_key)
769 ACE_TRACE ("ACE_Log_Msg::open");
770 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
771 *ACE_Log_Msg_Manager::get_lock (), -1));
773 if (prog_name)
775 #if defined(ACE_HAS_ALLOC_HOOKS)
776 ACE_Allocator::instance()->free ((void *) ACE_Log_Msg::program_name_);
777 #else
778 ACE_OS::free ((void *) ACE_Log_Msg::program_name_);
779 #endif /* ACE_HAS_ALLOC_HOOKS */
781 ACE_ALLOCATOR_RETURN (ACE_Log_Msg::program_name_,
782 ACE_OS::strdup (prog_name),
783 -1);
785 else if (ACE_Log_Msg::program_name_ == 0)
787 ACE_ALLOCATOR_RETURN (ACE_Log_Msg::program_name_,
788 ACE_OS::strdup (ACE_TEXT ("<unknown>")),
789 -1);
792 int status = 0;
794 // Be sure that there is a message_queue_, with multiple threads.
795 ACE_MT (ACE_Log_Msg_Manager::init_backend (&flags));
797 // Always close the current handle before doing anything else.
798 if (ACE_Log_Msg_Manager::log_backend_ != 0)
799 ACE_Log_Msg_Manager::log_backend_->reset ();
801 if (ACE_Log_Msg_Manager::custom_backend_ != 0)
802 ACE_Log_Msg_Manager::custom_backend_->reset ();
804 // Note that if we fail to open the message queue the default action
805 // is to use stderr (set via static initialization in the
806 // Log_Msg.cpp file).
808 if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER)
809 || ACE_BIT_ENABLED (flags, ACE_Log_Msg::SYSLOG))
811 // The SYSLOG backends (both NT and UNIX) can get along fine
812 // without the logger_key - they will default to prog_name if
813 // logger key is 0.
814 if (logger_key == 0 && ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER))
815 status = -1;
816 else
817 status = ACE_Log_Msg_Manager::log_backend_->open (logger_key);
819 if (status == -1)
820 ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR);
821 else
823 if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER))
824 ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER);
825 if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::SYSLOG))
826 ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG);
829 else if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER)
830 || ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG))
832 // If we are closing down logger, redirect logging to stderr.
833 ACE_CLR_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER);
834 ACE_CLR_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG);
835 ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR);
838 if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::CUSTOM))
840 status =
841 ACE_Log_Msg_Manager::custom_backend_->open (logger_key);
843 if (status != -1)
844 ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::CUSTOM);
847 // Remember, ACE_Log_Msg::STDERR bit is on by default...
848 if (status != -1
849 && ACE_BIT_ENABLED (flags,
850 ACE_Log_Msg::STDERR) == 0)
851 ACE_CLR_BITS (ACE_Log_Msg::flags_,
852 ACE_Log_Msg::STDERR);
854 // VERBOSE takes precedence over VERBOSE_LITE...
855 if (ACE_BIT_ENABLED (flags,
856 ACE_Log_Msg::VERBOSE_LITE))
857 ACE_SET_BITS (ACE_Log_Msg::flags_,
858 ACE_Log_Msg::VERBOSE_LITE);
859 else if (ACE_BIT_ENABLED (flags,
860 ACE_Log_Msg::VERBOSE))
861 ACE_SET_BITS (ACE_Log_Msg::flags_,
862 ACE_Log_Msg::VERBOSE);
864 if (ACE_BIT_ENABLED (flags,
865 ACE_Log_Msg::OSTREAM))
867 ACE_SET_BITS (ACE_Log_Msg::flags_,
868 ACE_Log_Msg::OSTREAM);
869 // Only set this to cerr if it hasn't already been set.
870 if (this->msg_ostream () == 0)
871 this->msg_ostream (ACE_DEFAULT_LOG_STREAM);
874 if (ACE_BIT_ENABLED (flags,
875 ACE_Log_Msg::MSG_CALLBACK))
876 ACE_SET_BITS (ACE_Log_Msg::flags_,
877 ACE_Log_Msg::MSG_CALLBACK);
879 if (ACE_BIT_ENABLED (flags,
880 ACE_Log_Msg::SILENT))
881 ACE_SET_BITS (ACE_Log_Msg::flags_,
882 ACE_Log_Msg::SILENT);
884 return status;
887 #ifndef ACE_LACKS_VA_FUNCTIONS
889 * Valid Options (prefixed by '%', as in printf format strings) include:
890 * 'A': print an ACE_timer_t value
891 * 'a': exit the program at this point (var-argument is the exit status!)
892 * 'b': print a ssize_t value
893 * 'B': print a size_t value
894 * 'c': print a character
895 * 'C': print a character string
896 * 'i', 'd': print a decimal number
897 * 'I', indent according to nesting depth
898 * 'e', 'E', 'f', 'F', 'g', 'G': print a double
899 * 'l', print line number where an error occurred.
900 * 'M': print the name of the priority of the message.
901 * 'm': Return the message corresponding to errno value, e.g., as done by <strerror>
902 * 'N': print file name where the error occurred.
903 * 'n': print the name of the program (or "<unknown>" if not set)
904 * 'o': print as an octal number
905 * 'P': format the current process id
906 * 'p': format the appropriate errno message from sys_errlist, e.g., as done by <perror>
907 * 'Q': print out the uint64 number
908 * 'q': print out the int64 number
909 * '@': print a void* pointer (in hexadecimal)
910 * 'r': call the function pointed to by the corresponding argument
911 * 'R': print return status
912 * 'S': print out the appropriate signal message corresponding
913 * to var-argument, e.g., as done by strsignal()
914 * 's': format a character string
915 * 'T': print timestamp in hour:minute:sec:usec format.
916 * 'D': print timestamp in month/day/year hour:minute:sec:usec format.
917 * 't': print thread id (1 if single-threaded)
918 * 'u': print as unsigned int
919 * 'x': print as a hex number
920 * 'X': print as a hex number
921 * 'w': print a wide character
922 * 'W': print out a wide character string.
923 * 'z': print an ACE_OS::WChar character
924 * 'Z': print an ACE_OS::WChar character string
925 * ':': print a time_t value as an integral number
926 * '%': format a single percent sign, '%'
928 ssize_t
929 ACE_Log_Msg::log (ACE_Log_Priority log_priority,
930 const ACE_TCHAR *format_str, ...)
932 ACE_TRACE ("ACE_Log_Msg::log");
933 // Start of variable args section.
934 va_list argp;
936 va_start (argp, format_str);
938 ssize_t const result = this->log (format_str,
939 log_priority,
940 argp);
941 va_end (argp);
943 return result;
946 #if defined (ACE_HAS_WCHAR)
948 * Since this is the ANTI_TCHAR version, we need to convert
949 * the format string over.
951 ssize_t
952 ACE_Log_Msg::log (ACE_Log_Priority log_priority,
953 const ACE_ANTI_TCHAR *format_str, ...)
955 ACE_TRACE ("ACE_Log_Msg::log");
957 // Start of variable args section.
958 va_list argp;
960 va_start (argp, format_str);
962 ssize_t const result = this->log (ACE_TEXT_ANTI_TO_TCHAR (format_str),
963 log_priority,
964 argp);
965 va_end (argp);
967 return result;
969 #endif /* ACE_HAS_WCHAR */
971 #endif /* ACE_LACKS_VA_FUNCTIONS */
973 #if defined ACE_HAS_STRERROR_R && defined ACE_LACKS_STRERROR
974 #define ACE_LOG_MSG_USE_STRERROR_R
975 #endif
977 ssize_t
978 ACE_Log_Msg::log (const ACE_TCHAR *format_str,
979 ACE_Log_Priority log_priority,
980 va_list argp,
981 ACE_Log_Category_TSS* category)
983 ACE_TRACE ("ACE_Log_Msg::log");
984 #if defined (ACE_LACKS_VA_FUNCTIONS)
985 ACE_UNUSED_ARG (log_priority);
986 ACE_UNUSED_ARG (format_str);
987 ACE_UNUSED_ARG (argp);
988 ACE_UNUSED_ARG (category);
989 ACE_NOTSUP_RETURN (-1);
990 #else
991 // External decls.
993 using PointerToFunction = void (*)(...);
995 // Check if there were any conditional values set.
996 bool const conditional_values = this->conditional_values_.is_set_;
998 // Reset conditional values.
999 this->conditional_values_.is_set_ = false;
1001 // Only print the message if <priority_mask_> hasn't been reset to
1002 // exclude this logging priority.
1003 if (this->log_priority_enabled (log_priority) == 0)
1004 return 0;
1006 // If conditional values were set and the log priority is correct,
1007 // then the values are actually set.
1008 if (conditional_values)
1009 this->set (this->conditional_values_.file_,
1010 this->conditional_values_.line_,
1011 this->conditional_values_.op_status_,
1012 this->conditional_values_.errnum_,
1013 this->restart (),
1014 this->msg_ostream (),
1015 this->msg_callback ());
1017 // Logging is supposed to be a benign activity (i.e., not interfer
1018 // with normal application operations), so don't inadvertently smash
1019 // errno!
1020 ACE_Errno_Guard guard (errno);
1022 ACE_Log_Record log_record (log_priority,
1023 ACE_OS::gettimeofday (),
1024 this->getpid ());
1026 log_record.category(category);
1028 // bp is pointer to where to put next part of logged message.
1029 // bspace is the number of characters remaining in msg_.
1030 ACE_TCHAR *bp = const_cast<ACE_TCHAR *> (this->msg ());
1031 size_t bspace = ACE_MAXLOGMSGLEN; // Leave room for Nul term.
1032 if (this->msg_off_ <= ACE_Log_Record::MAXLOGMSGLEN)
1033 bspace -= static_cast<size_t> (this->msg_off_);
1035 // If this platform has snprintf() capability to prevent overrunning the
1036 // output buffer, use it. To avoid adding a maintenance-hassle compile-
1037 // time couple between here and OS.cpp, don't try to figure this out at
1038 // compile time. Instead, do a quick check now; if we get a -1 return,
1039 // the platform doesn't support the length-limiting capability.
1040 ACE_TCHAR test[2];
1041 bool can_check = ACE_OS::snprintf (test, 1, ACE_TEXT ("x")) != -1;
1043 bool abort_prog = false;
1044 int exit_value = 0;
1046 // Retrieve the flags in a local variable on the stack, it is
1047 // accessed by multiple threads and within this operation we
1048 // check it several times, so this way we only lock once
1049 u_long flags = this->flags ();
1051 if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::VERBOSE))
1053 // Prepend the program name onto this message
1054 if (ACE_Log_Msg::program_name_ != 0)
1056 for (const ACE_TCHAR *s = ACE_Log_Msg::program_name_;
1057 bspace > 1 && (*bp = *s) != '\0';
1058 ++s, --bspace)
1059 bp++;
1061 *bp++ = '|';
1062 --bspace;
1066 if (timestamp_ > 0)
1068 ACE_TCHAR day_and_time[27];
1069 const ACE_TCHAR *s = 0;
1070 if (timestamp_ == 1)
1072 // Print just the time
1073 s = ACE::timestamp (day_and_time,
1074 sizeof (day_and_time) / sizeof (ACE_TCHAR),
1075 true);
1077 else
1079 // Print time and date
1080 ACE::timestamp (day_and_time,
1081 sizeof (day_and_time) / sizeof (ACE_TCHAR));
1082 s = day_and_time;
1085 for (; bspace > 1 && (*bp = *s) != '\0'; ++s, --bspace)
1086 ++bp;
1088 *bp++ = '|';
1089 --bspace;
1092 while (*format_str != '\0' && bspace > 0)
1094 // Copy input to output until we encounter a %, however a
1095 // % followed by another % is not a format specification.
1097 if (*format_str != '%')
1099 *bp++ = *format_str++;
1100 --bspace;
1102 else if (format_str[1] == '%') // An "escaped" '%' (just print one '%').
1104 *bp++ = *format_str++; // Store first %
1105 ++format_str; // but skip second %
1106 --bspace;
1108 else
1110 // This is most likely a format specification that ends with
1111 // one of the valid options described previously. To enable full
1112 // use of all sprintf capabilities, save the format specifier
1113 // from the '%' up to the format letter in a new char array.
1114 // This allows the full sprintf capability for padding, field
1115 // widths, alignment, etc. Any width/precision requiring a
1116 // caller-supplied argument is extracted and placed as text
1117 // into the format array. Lastly, we convert the caller-supplied
1118 // format specifier from the ACE_Log_Msg-supported list to the
1119 // equivalent sprintf specifier, and run the new format spec
1120 // through sprintf, adding it to the bp string.
1122 const ACE_TCHAR *abort_str = ACE_TEXT ("Aborting...");
1123 const ACE_TCHAR *start_format = format_str;
1124 size_t fspace = 128;
1125 ACE_TCHAR format[128]; // Converted format string
1126 ACE_OS::memset (format, '\0', 128); // Set this string to known values.
1127 ACE_TCHAR *fp = 0; // Current format pointer
1128 int wp = 0; // Width/precision extracted from args
1129 bool done = false;
1130 bool skip_nul_locate = false;
1131 int this_len = 0; // How many chars s[n]printf wrote
1133 #ifdef ACE_LOG_MSG_USE_STRERROR_R
1134 char strerror_buf[128]; // always narrow chars
1135 ACE_OS::strcpy (strerror_buf, "strerror_r failed");
1136 #endif
1138 fp = format;
1139 *fp++ = *format_str++; // Copy in the %
1140 --fspace;
1142 // Initialization to satisfy VC6
1143 int tmp_indent = 0;
1144 // Work through the format string to copy in the format
1145 // from the caller. While it's going across, extract ints
1146 // for '*' width/precision values from the argument list.
1147 // When the real format specifier is located, change it to
1148 // one recognized by sprintf, if needed, and do the sprintf
1149 // call.
1151 while (!done)
1153 done = true; // Unless a conversion spec changes it
1155 switch (*format_str)
1157 // The initial set of cases are the conversion
1158 // specifiers. Copy them in to the format array.
1159 // Note we don't use 'l', a normal conversion spec,
1160 // as a conversion because it is a ACE_Log_Msg format
1161 // specifier.
1162 case '-':
1163 case '+':
1164 case '0':
1165 case ' ':
1166 case '#':
1167 case '1':
1168 case '2':
1169 case '3':
1170 case '4':
1171 case '5':
1172 case '6':
1173 case '7':
1174 case '8':
1175 case '9':
1176 case '.':
1177 case 'h':
1178 *fp++ = *format_str;
1179 --fspace;
1180 done = false;
1181 break;
1182 case 'L':
1183 *fp++ = 'l';
1184 done = false;
1185 break;
1187 case '*':
1188 wp = va_arg (argp, int);
1189 if (can_check)
1190 this_len = ACE_OS::snprintf (fp, fspace,
1191 ACE_TEXT ("%d"), wp);
1192 else
1193 this_len = ACE_OS::sprintf (fp, ACE_TEXT ("%d"), wp);
1194 ACE_UPDATE_COUNT (fspace, this_len);
1195 fp += ACE_OS::strlen (fp);
1196 done = false;
1197 break;
1199 case 'A': // ACE_timer_t
1201 ACE_OS::strcpy (fp, ACE_TEXT ("f"));
1202 --fspace;
1203 double const value = va_arg (argp, double);
1204 if (can_check)
1205 this_len = ACE_OS::snprintf (bp, bspace, format, value);
1206 else
1207 this_len = ACE_OS::sprintf (bp, format, value);
1208 ACE_UPDATE_COUNT (bspace, this_len);
1210 break;
1212 case 'a': // Abort program after handling all of format string.
1213 abort_prog = true;
1214 exit_value = va_arg (argp, int);
1215 ACE_OS::strsncpy (bp, abort_str, bspace);
1216 if (bspace > ACE_OS::strlen (abort_str))
1217 bspace -= ACE_OS::strlen (abort_str);
1218 else
1219 bspace = 0;
1220 break;
1222 case 'l': // Source file line number
1223 ACE_OS::strcpy (fp, ACE_TEXT ("d"));
1224 if (can_check)
1225 this_len = ACE_OS::snprintf (bp,
1226 bspace,
1227 format,
1228 this->linenum ());
1229 else
1230 this_len = ACE_OS::sprintf (bp, format, this->linenum ());
1231 ACE_UPDATE_COUNT (bspace, this_len);
1232 break;
1234 case 'N': // Source file name
1235 ACE_OS::strcpy (fp, ACE_TEXT_PRIs);
1236 if (can_check)
1237 this_len = ACE_OS::snprintf (bp, bspace, format,
1238 this->file () ?
1239 ACE_TEXT_CHAR_TO_TCHAR (this->file ())
1240 : ACE_TEXT ("<unknown file>"));
1241 else
1242 this_len = ACE_OS::sprintf (bp, format,
1243 this->file () ?
1244 ACE_TEXT_CHAR_TO_TCHAR (this->file ())
1245 : ACE_TEXT ("<unknown file>"));
1246 ACE_UPDATE_COUNT (bspace, this_len);
1247 break;
1249 case 'n': // Program name
1250 ACE_OS::strcpy (fp, ACE_TEXT_PRIs);
1251 if (can_check)
1252 this_len = ACE_OS::snprintf (bp, bspace, format,
1253 ACE_Log_Msg::program_name_ ?
1254 ACE_Log_Msg::program_name_ :
1255 ACE_TEXT ("<unknown>"));
1256 else
1257 this_len = ACE_OS::sprintf (bp, format,
1258 ACE_Log_Msg::program_name_ ?
1259 ACE_Log_Msg::program_name_ :
1260 ACE_TEXT ("<unknown>"));
1261 ACE_UPDATE_COUNT (bspace, this_len);
1262 break;
1264 case 'P': // Process ID
1265 ACE_OS::strcpy (fp, ACE_TEXT ("d"));
1266 if (can_check)
1267 this_len = ACE_OS::snprintf
1268 (bp, bspace, format,
1269 static_cast<int> (this->getpid ()));
1270 else
1271 this_len = ACE_OS::sprintf
1272 (bp, format, static_cast<int> (this->getpid ()));
1273 ACE_UPDATE_COUNT (bspace, this_len);
1274 break;
1276 case 'p': // <errno> string, ala perror()
1278 errno = 0;
1279 const int mapped = ACE::map_errno (this->errnum ());
1280 #ifdef ACE_LOG_MSG_USE_STRERROR_R
1281 char *msg = ACE_OS::strerror_r (mapped, strerror_buf,
1282 sizeof strerror_buf);
1283 #else
1284 char *msg = ACE_OS::strerror (mapped);
1285 #endif
1286 // Windows can try to translate the errnum using
1287 // system calls if strerror() doesn't get anything useful.
1288 #if defined (ACE_WIN32)
1289 if (errno == 0)
1291 #endif
1293 #if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
1294 ACE_OS::strcpy (fp, ACE_TEXT ("ls: %ls"));
1295 wchar_t *str = va_arg (argp, wchar_t *);
1296 #else
1297 ACE_OS::strcpy (fp, ACE_TEXT ("s: %s"));
1298 ACE_TCHAR *str = va_arg (argp, ACE_TCHAR *);
1299 #endif
1300 if (can_check)
1301 this_len = ACE_OS::snprintf
1302 (bp, bspace, format,
1303 str ? str : ACE_TEXT ("(null)"),
1304 ACE_TEXT_CHAR_TO_TCHAR (msg));
1305 else
1306 this_len = ACE_OS::sprintf
1307 (bp, format,
1308 str ? str : ACE_TEXT ("(null)"),
1309 ACE_TEXT_CHAR_TO_TCHAR (msg));
1310 #if defined (ACE_WIN32)
1312 else
1314 errno = ACE::map_errno (this->errnum ());
1315 ACE_TCHAR *lpMsgBuf = 0;
1316 ACE_TEXT_FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
1317 | FORMAT_MESSAGE_MAX_WIDTH_MASK
1318 | FORMAT_MESSAGE_FROM_SYSTEM,
1320 errno,
1321 MAKELANGID (LANG_NEUTRAL,
1322 SUBLANG_DEFAULT),
1323 // Default language
1324 (ACE_TCHAR *) &lpMsgBuf,
1328 // If we don't get a valid response from
1329 // <FormatMessage>, we'll assume this is a
1330 // WinSock error and so we'll try to convert
1331 // it into a string. If this doesn't work it
1332 // returns "unknown error" which is fine for
1333 // our purposes.
1334 ACE_TCHAR *str = va_arg (argp, ACE_TCHAR *);
1335 if (lpMsgBuf == 0)
1337 const ACE_TCHAR *message =
1338 ACE::sock_error (errno);
1339 ACE_OS::strcpy (fp, ACE_TEXT ("s: %s"));
1340 if (can_check)
1341 this_len = ACE_OS::snprintf
1342 (bp, bspace, format,
1343 str ? str : ACE_TEXT ("(null)"),
1344 message);
1345 else
1346 this_len = ACE_OS::sprintf
1347 (bp, format,
1348 str ? str : ACE_TEXT ("(null)"),
1349 message);
1351 else
1353 ACE_OS::strcpy (fp, ACE_TEXT ("s: %s"));
1354 if (can_check)
1355 this_len = ACE_OS::snprintf
1356 (bp, bspace, format,
1357 str ? str : ACE_TEXT ("(null)"),
1358 lpMsgBuf);
1359 else
1360 this_len = ACE_OS::sprintf
1361 (bp, format,
1362 str ? str : ACE_TEXT ("(null)"),
1363 lpMsgBuf);
1364 // Free the buffer.
1365 ::LocalFree (lpMsgBuf);
1368 #endif /* ACE_WIN32 */
1369 ACE_UPDATE_COUNT (bspace, this_len);
1370 break;
1373 case 'M': // Print the name of the priority of the message.
1375 // Look at the format precision specifier. .1 is interpreted
1376 // as a single character printout, otherwise we print the name of
1377 // the priority.
1379 // So, did we find a .1 specifier? Do we need to override it?
1380 if (format[1] == ACE_TEXT('.') &&
1381 format[2] == ACE_TEXT('1'))
1383 // Yup.
1384 // Print a single character signifying the severity of the message
1385 fp = format;
1386 fp++;
1388 # if defined (ACE_USES_WCHAR)
1390 # if defined (ACE_WIN32) // Windows uses 'c' for a wide character
1391 ACE_OS::strcpy (fp, ACE_TEXT ("c"));
1392 # else // Other platforms behave differently
1393 ACE_OS::strcpy (fp, ACE_TEXT ("lc"));
1394 # endif
1396 # else /* ACE_USES_WCHAR */
1398 // Non-unicode builds simply use a standard character format specifier
1399 ACE_OS::strcpy (fp, ACE_TEXT ("c"));
1401 # endif /* ACE_USES_WCHAR */
1403 // Below is an optimized (binary search based)
1404 // version of the following simple piece of code:
1406 // log_priority == LM_SHUTDOWN ? 'S' : // Shutdown
1407 // log_priority == LM_TRACE ? 'T' : // Trace
1408 // log_priority == LM_DEBUG ? 'D' : // Debug
1409 // log_priority == LM_INFO ? 'I' : // Info
1410 // log_priority == LM_NOTICE ? 'N' : // Notice
1411 // log_priority == LM_WARNING ? 'W' : // Warning
1412 // log_priority == LM_STARTUP ? 'U' : // Startup
1413 // log_priority == LM_ERROR ? 'E' : // Error
1414 // log_priority == LM_CRITICAL ? 'C' : // Critical
1415 // log_priority == LM_ALERT ? 'A' : // Alert
1416 // log_priority == LM_EMERGENCY ? '!' : // Emergency
1417 // '?' // Unknown
1419 if (can_check)
1421 this_len = ACE_OS::snprintf
1422 (bp, bspace, format,
1423 #if !defined (ACE_USES_WCHAR) || defined (ACE_WIN32)
1424 (int)
1425 #else
1426 (wint_t)
1427 #endif
1428 (log_priority <= LM_WARNING) ?
1429 (log_priority <= LM_DEBUG) ?
1430 (log_priority <= LM_TRACE) ?
1431 (log_priority == LM_SHUTDOWN) ?
1432 ACE_TEXT('S') : ACE_TEXT('T') : ACE_TEXT('D') :
1433 (log_priority <= LM_NOTICE) ?
1434 (log_priority == LM_INFO) ?
1435 ACE_TEXT('I') : ACE_TEXT('N') : ACE_TEXT('W') :
1436 (log_priority <= LM_CRITICAL) ?
1437 (log_priority <= LM_ERROR) ?
1438 (log_priority == LM_STARTUP) ?
1439 ACE_TEXT('U') : ACE_TEXT('E') : ACE_TEXT('C') :
1440 (log_priority <= LM_EMERGENCY) ?
1441 (log_priority == LM_ALERT) ?
1442 ACE_TEXT('A') : ACE_TEXT('!') : ACE_TEXT('?'));
1444 else
1446 this_len = ACE_OS::sprintf
1447 (bp, format,
1448 #if !defined (ACE_USES_WCHAR) || defined (ACE_WIN32)
1449 (int)
1450 #else
1451 (wint_t)
1452 #endif
1453 (log_priority <= LM_WARNING) ?
1454 (log_priority <= LM_DEBUG) ?
1455 (log_priority <= LM_TRACE) ?
1456 (log_priority == LM_SHUTDOWN) ?
1457 ACE_TEXT('S') : ACE_TEXT('T') : ACE_TEXT('D') :
1458 (log_priority <= LM_NOTICE) ?
1459 (log_priority == LM_INFO) ?
1460 ACE_TEXT('I') : ACE_TEXT('N') : ACE_TEXT('W') :
1461 (log_priority <= LM_CRITICAL) ?
1462 (log_priority <= LM_ERROR) ?
1463 (log_priority == LM_STARTUP) ?
1464 ACE_TEXT('U') : ACE_TEXT('E') : ACE_TEXT('C') :
1465 (log_priority <= LM_EMERGENCY) ?
1466 (log_priority == LM_ALERT) ?
1467 ACE_TEXT('A') : ACE_TEXT('!') : ACE_TEXT('?'));
1470 ACE_UPDATE_COUNT (bspace, this_len);
1472 else
1474 // Nope, print out standard priority_name() string
1476 ACE_OS::strcpy (fp, ACE_TEXT_PRIs);
1477 if (can_check)
1478 this_len = ACE_OS::snprintf
1479 (bp, bspace, format,
1480 ACE_Log_Record::priority_name (log_priority));
1481 else
1482 this_len = ACE_OS::sprintf
1483 (bp, format,
1484 ACE_Log_Record::priority_name (log_priority));
1485 ACE_UPDATE_COUNT (bspace, this_len);
1487 break;
1489 case 'm': // Format the string assocated with the errno value.
1491 errno = 0;
1492 const int mapped = ACE::map_errno (this->errnum ());
1493 #ifdef ACE_LOG_MSG_USE_STRERROR_R
1494 char *msg = ACE_OS::strerror_r (mapped, strerror_buf,
1495 sizeof strerror_buf);
1496 #else
1497 char *msg = ACE_OS::strerror (mapped);
1498 #endif
1499 // Windows can try to translate the errnum using
1500 // system calls if strerror() doesn't get anything useful.
1501 #if defined (ACE_WIN32)
1502 if (errno == 0)
1504 #endif
1506 ACE_OS::strcpy (fp, ACE_TEXT_PRIs);
1507 if (can_check)
1508 this_len = ACE_OS::snprintf
1509 (bp, bspace, format, ACE_TEXT_CHAR_TO_TCHAR (msg));
1510 else
1511 this_len = ACE_OS::sprintf
1512 (bp, format, ACE_TEXT_CHAR_TO_TCHAR (msg));
1513 #if defined (ACE_WIN32)
1515 else
1517 errno = ACE::map_errno (this->errnum ());
1518 ACE_TCHAR *lpMsgBuf = 0;
1519 ACE_TEXT_FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
1520 | FORMAT_MESSAGE_MAX_WIDTH_MASK
1521 | FORMAT_MESSAGE_FROM_SYSTEM,
1523 errno,
1524 MAKELANGID (LANG_NEUTRAL,
1525 SUBLANG_DEFAULT),
1526 // Default language
1527 (ACE_TCHAR *) &lpMsgBuf,
1531 // If we don't get a valid response from
1532 // <FormatMessage>, we'll assume this is a
1533 // WinSock error and so we'll try to convert
1534 // it into a string. If this doesn't work it
1535 // returns "unknown error" which is fine for
1536 // our purposes.
1537 if (lpMsgBuf == 0)
1539 const ACE_TCHAR *message =
1540 ACE::sock_error (errno);
1541 ACE_OS::strcpy (fp, ACE_TEXT ("s"));
1542 if (can_check)
1543 this_len = ACE_OS::snprintf
1544 (bp, bspace, format, message);
1545 else
1546 this_len = ACE_OS::sprintf (bp, format, message);
1548 else
1550 ACE_OS::strcpy (fp, ACE_TEXT ("s"));
1551 if (can_check)
1552 this_len = ACE_OS::snprintf
1553 (bp, bspace, format, lpMsgBuf);
1554 else
1555 this_len = ACE_OS::sprintf
1556 (bp, format, lpMsgBuf);
1557 // Free the buffer.
1558 ::LocalFree (lpMsgBuf);
1561 #endif /* ACE_WIN32 */
1562 ACE_UPDATE_COUNT (bspace, this_len);
1563 break;
1566 case 'R': // Format the return status of the operation.
1567 this->op_status (va_arg (argp, int));
1568 ACE_OS::strcpy (fp, ACE_TEXT ("d"));
1569 if (can_check)
1570 this_len = ACE_OS::snprintf
1571 (bp, bspace, format, this->op_status ());
1572 else
1573 this_len = ACE_OS::sprintf
1574 (bp, format, this->op_status ());
1575 ACE_UPDATE_COUNT (bspace, this_len);
1576 break;
1578 case '{': // Increment the trace_depth, then indent
1579 skip_nul_locate = true;
1580 (void) this->inc ();
1581 break;
1583 case '}': // indent, then decrement trace_depth
1584 skip_nul_locate = true;
1585 (void) this->dec ();
1586 break;
1588 case '$': // insert a newline, then indent the next line
1589 // according to %I
1590 *bp++ = '\n';
1591 --bspace;
1592 ACE_FALLTHROUGH;
1594 case 'I': // Indent with nesting_depth*width spaces
1595 // Caller can do %*I to override nesting indent, and
1596 // if %*I was done, wp has the extracted width.
1597 #if defined (ACE_HAS_TRACE)
1598 if (0 == wp)
1599 wp = ACE_Trace::get_nesting_indent ();
1600 #else
1601 if (0 == wp)
1602 wp = 4;
1603 #endif /* ACE_HAS_TRACE */
1604 wp *= this->trace_depth_;
1605 if (static_cast<size_t> (wp) > bspace)
1606 wp = static_cast<int> (bspace);
1607 for (tmp_indent = wp;
1608 tmp_indent;
1609 --tmp_indent)
1610 *bp++ = ' ';
1612 *bp = '\0';
1613 bspace -= static_cast<size_t> (wp);
1614 skip_nul_locate = true;
1615 break;
1617 case 'r': // Run (invoke) this subroutine.
1619 ptrdiff_t const osave = ACE_Log_Msg::msg_off_;
1621 if (ACE_BIT_ENABLED (flags,
1622 ACE_Log_Msg::SILENT) &&
1623 bspace > 1)
1625 *bp++ = '{';
1626 --bspace;
1628 ACE_Log_Msg::msg_off_ = bp - this->msg_;
1630 (*va_arg (argp, PointerToFunction))();
1632 if (ACE_BIT_ENABLED (flags,
1633 ACE_Log_Msg::SILENT) &&
1634 bspace > (1 + ACE_OS::strlen (bp)))
1636 bspace -= (ACE_OS::strlen (bp) + 1);
1637 bp += ACE_OS::strlen (bp);
1638 *bp++ = '}';
1640 *bp = '\0';
1641 skip_nul_locate = true;
1642 ACE_Log_Msg::msg_off_ = osave;
1643 break;
1646 case 'S': // format the string for with this signal number.
1648 const int sig = va_arg (argp, int);
1649 ACE_OS::strcpy (fp, ACE_TEXT ("s"));
1650 if (can_check)
1651 this_len = ACE_OS::snprintf
1652 (bp, bspace, format, ACE_OS::strsignal(sig));
1653 else
1654 this_len = ACE_OS::sprintf
1655 (bp, format, ACE_OS::strsignal(sig));
1656 ACE_UPDATE_COUNT (bspace, this_len);
1657 break;
1660 case 'D': // Format the timestamp in format:
1661 // yyyy-mm-dd hour:minute:sec.usec
1662 // This is a maximum of 27 characters
1663 // including terminator.
1665 ACE_TCHAR day_and_time[27];
1666 // Did we find the flag indicating a time value argument
1667 if (format[1] == ACE_TEXT('#'))
1669 ACE_Time_Value* time_value = va_arg (argp, ACE_Time_Value*);
1670 ACE::timestamp (*time_value,
1671 day_and_time,
1672 sizeof (day_and_time) / sizeof (ACE_TCHAR),
1673 true);
1675 else
1677 ACE::timestamp (day_and_time,
1678 sizeof (day_and_time) / sizeof (ACE_TCHAR),
1679 true);
1681 ACE_OS::strcpy (fp, ACE_TEXT_PRIs);
1682 if (can_check)
1683 this_len = ACE_OS::snprintf
1684 (bp, bspace, format, day_and_time);
1685 else
1686 this_len = ACE_OS::sprintf (bp, format, day_and_time);
1687 ACE_UPDATE_COUNT (bspace, this_len);
1688 break;
1691 case 'T': // Format the timestamp in
1692 // hour:minute:sec.usec format.
1694 ACE_TCHAR day_and_time[27];
1695 ACE_OS::strcpy (fp, ACE_TEXT_PRIs);
1696 // Did we find the flag indicating a time value argument
1697 if (format[1] == ACE_TEXT('#'))
1699 ACE_Time_Value* time_value = va_arg (argp, ACE_Time_Value*);
1700 if (can_check)
1701 this_len = ACE_OS::snprintf
1702 (bp, bspace, format,
1703 ACE::timestamp (*time_value,
1704 day_and_time,
1705 sizeof day_and_time / sizeof (ACE_TCHAR),
1706 true));
1707 else
1708 this_len = ACE_OS::sprintf
1709 (bp, format, ACE::timestamp (*time_value,
1710 day_and_time,
1711 sizeof day_and_time / sizeof (ACE_TCHAR),
1712 true));
1714 else
1716 if (can_check)
1717 this_len = ACE_OS::snprintf
1718 (bp, bspace, format,
1719 ACE::timestamp (day_and_time, sizeof day_and_time / sizeof (ACE_TCHAR), true));
1720 else
1721 this_len = ACE_OS::sprintf
1722 (bp, format, ACE::timestamp (day_and_time,
1723 sizeof day_and_time / sizeof (ACE_TCHAR), true));
1725 ACE_UPDATE_COUNT (bspace, this_len);
1726 break;
1729 case 't': // Format thread id.
1730 #if defined (ACE_WIN32)
1731 ACE_OS::strcpy (fp, ACE_TEXT ("u"));
1732 if (can_check)
1733 this_len = ACE_OS::snprintf
1734 (bp, bspace, format,
1735 static_cast<unsigned> (ACE_Thread::self ()));
1736 else
1737 this_len =
1738 ACE_OS::sprintf (bp,
1739 format,
1740 static_cast <unsigned> (ACE_Thread::self ()));
1741 #else
1743 # ifdef ACE_HAS_GETTID
1744 # define ACE_LOG_MSG_GET_THREAD_ID ACE_OS::thr_gettid
1745 # define ACE_LOG_MSG_GET_THREAD_ID_BUFFER_SIZE 12
1746 # else
1747 # define ACE_LOG_MSG_GET_THREAD_ID ACE_OS::thr_id
1748 # define ACE_LOG_MSG_GET_THREAD_ID_BUFFER_SIZE 32
1749 # endif
1751 # if defined ACE_USES_WCHAR
1753 char tid_buf[ACE_LOG_MSG_GET_THREAD_ID_BUFFER_SIZE] = {};
1754 ACE_LOG_MSG_GET_THREAD_ID (tid_buf, sizeof tid_buf);
1755 this_len = ACE_OS::strlen (tid_buf);
1756 ACE_OS::strncpy (bp, ACE_TEXT_CHAR_TO_TCHAR (tid_buf),
1757 bspace);
1759 # else
1760 this_len = ACE_LOG_MSG_GET_THREAD_ID (bp, bspace);
1761 # endif /* ACE_USES_WCHAR */
1762 #endif /* ACE_WIN32 */
1763 ACE_UPDATE_COUNT (bspace, this_len);
1764 break;
1766 case 's': // String
1768 #if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
1769 wchar_t *str = va_arg (argp, wchar_t *);
1770 #else /* ACE_WIN32 && ACE_USES_WCHAR */
1771 ACE_TCHAR *str = va_arg (argp, ACE_TCHAR *);
1772 #endif /* ACE_WIN32 && ACE_USES_WCHAR */
1773 ACE_OS::strcpy (fp, ACE_TEXT_PRIs);
1774 if (can_check)
1775 this_len = ACE_OS::snprintf
1776 (bp, bspace, format, str ? str : ACE_TEXT ("(null)"));
1777 else
1778 this_len = ACE_OS::sprintf
1779 (bp, format, str ? str : ACE_TEXT ("(null)"));
1780 ACE_UPDATE_COUNT (bspace, this_len);
1782 break;
1784 case 'C': // Narrow-char string
1786 char *cstr = va_arg (argp, char *);
1787 #if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
1788 ACE_OS::strcpy (fp, ACE_TEXT ("S"));
1789 #else /* ACE_WIN32 && ACE_USES_WCHAR */
1790 ACE_OS::strcpy (fp, ACE_TEXT ("s"));
1791 #endif /* ACE_WIN32 && ACE_USES_WCHAR */
1792 if (can_check)
1793 this_len = ACE_OS::snprintf
1794 (bp, bspace, format, cstr ? cstr : "(null)");
1795 else
1796 this_len = ACE_OS::sprintf
1797 (bp, format, cstr ? cstr : "(null)");
1798 ACE_UPDATE_COUNT (bspace, this_len);
1800 break;
1802 case 'W':
1804 #if defined (ACE_HAS_WCHAR)
1805 wchar_t *wchar_str = va_arg (argp, wchar_t *);
1806 # if defined (ACE_WIN32)
1807 # if defined (ACE_USES_WCHAR)
1808 ACE_OS::strcpy (fp, ACE_TEXT ("s"));
1809 # else /* ACE_USES_WCHAR */
1810 ACE_OS::strcpy (fp, ACE_TEXT ("S"));
1811 # endif /* ACE_USES_WCHAR */
1812 # else
1813 ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
1814 # endif /* ACE_HAS_WCHAR */
1815 if (can_check)
1816 this_len = ACE_OS::snprintf
1817 (bp, bspace, format, wchar_str ? wchar_str : ACE_TEXT_WIDE("(null)"));
1818 else
1819 this_len = ACE_OS::sprintf
1820 (bp, format, wchar_str ? wchar_str : ACE_TEXT_WIDE("(null)"));
1821 #endif /* ACE_HAS_WCHAR */
1822 ACE_UPDATE_COUNT (bspace, this_len);
1824 break;
1826 case 'w': // Wide character
1827 #if defined (ACE_WIN32)
1828 # if defined (ACE_USES_WCHAR)
1829 ACE_OS::strcpy (fp, ACE_TEXT ("c"));
1830 # else /* ACE_USES_WCHAR */
1831 ACE_OS::strcpy (fp, ACE_TEXT ("C"));
1832 # endif /* ACE_USES_WCHAR */
1833 if (can_check)
1834 this_len = ACE_OS::snprintf
1835 (bp, bspace, format, va_arg (argp, int));
1836 else
1837 this_len = ACE_OS::sprintf
1838 (bp, format, va_arg (argp, int));
1839 #elif defined (ACE_USES_WCHAR)
1840 ACE_OS::strcpy (fp, ACE_TEXT ("lc"));
1841 if (can_check)
1842 this_len = ACE_OS::snprintf
1843 (bp, bspace, format, va_arg (argp, wint_t));
1844 else
1845 this_len = ACE_OS::sprintf
1846 (bp, format, va_arg (argp, wint_t));
1847 #else /* ACE_WIN32 */
1848 ACE_OS::strcpy (fp, ACE_TEXT ("u"));
1849 if (can_check)
1850 this_len = ACE_OS::snprintf
1851 (bp, bspace, format, va_arg (argp, int));
1852 else
1853 this_len = ACE_OS::sprintf
1854 (bp, format, va_arg (argp, int));
1855 #endif /* ACE_WIN32 */
1856 ACE_UPDATE_COUNT (bspace, this_len);
1857 break;
1859 case 'z': // ACE_OS::WChar character
1861 // On some platforms sizeof (wchar_t) can be 2
1862 // on the others 4 ...
1863 wchar_t wtchar =
1864 static_cast<wchar_t> (va_arg (argp, int));
1865 #if defined (ACE_WIN32)
1866 # if defined (ACE_USES_WCHAR)
1867 ACE_OS::strcpy (fp, ACE_TEXT ("c"));
1868 # else /* ACE_USES_WCHAR */
1869 ACE_OS::strcpy (fp, ACE_TEXT ("C"));
1870 # endif /* ACE_USES_WCHAR */
1871 #elif defined (ACE_USES_WCHAR)
1872 ACE_OS::strcpy (fp, ACE_TEXT ("lc"));
1873 #else /* ACE_WIN32 */
1874 ACE_OS::strcpy (fp, ACE_TEXT ("u"));
1875 #endif /* ACE_WIN32 */
1876 if (can_check)
1877 this_len = ACE_OS::snprintf (bp, bspace, format, wtchar);
1878 else
1879 this_len = ACE_OS::sprintf (bp, format, wtchar);
1880 ACE_UPDATE_COUNT (bspace, this_len);
1881 break;
1884 case 'Z': // ACE_OS::WChar character string
1886 ACE_OS::WChar *wchar_str = va_arg (argp, ACE_OS::WChar*);
1887 if (wchar_str == 0)
1888 break;
1890 wchar_t *wchar_t_str = 0;
1891 if (sizeof (ACE_OS::WChar) != sizeof (wchar_t))
1893 size_t len = ACE_OS::wslen (wchar_str) + 1;
1894 ACE_NEW_NORETURN(wchar_t_str, wchar_t[len]);
1895 if (wchar_t_str == 0)
1896 break;
1898 for (size_t i = 0; i < len; ++i)
1900 wchar_t_str[i] = wchar_str[i];
1904 if (wchar_t_str == 0)
1906 wchar_t_str = reinterpret_cast<wchar_t*> (wchar_str);
1908 #if defined (ACE_WIN32)
1909 # if defined (ACE_USES_WCHAR)
1910 ACE_OS::strcpy (fp, ACE_TEXT ("s"));
1911 # else /* ACE_USES_WCHAR */
1912 ACE_OS::strcpy (fp, ACE_TEXT ("S"));
1913 # endif /* ACE_USES_WCHAR */
1914 #elif defined (ACE_HAS_WCHAR)
1915 ACE_OS::strcpy (fp, ACE_TEXT ("ls"));
1916 #endif /* ACE_WIN32 / ACE_HAS_WCHAR */
1917 if (can_check)
1918 this_len = ACE_OS::snprintf
1919 (bp, bspace, format, wchar_t_str);
1920 else
1921 this_len = ACE_OS::sprintf (bp, format, wchar_t_str);
1922 if(sizeof(ACE_OS::WChar) != sizeof(wchar_t))
1924 delete [] wchar_t_str;
1926 ACE_UPDATE_COUNT (bspace, this_len);
1927 break;
1930 case 'c':
1931 #if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
1932 ACE_OS::strcpy (fp, ACE_TEXT ("C"));
1933 #else
1934 ACE_OS::strcpy (fp, ACE_TEXT ("c"));
1935 #endif /* ACE_WIN32 && ACE_USES_WCHAR */
1936 if (can_check)
1937 this_len = ACE_OS::snprintf
1938 (bp, bspace, format, va_arg (argp, int));
1939 else
1940 this_len = ACE_OS::sprintf
1941 (bp, format, va_arg (argp, int));
1942 ACE_UPDATE_COUNT (bspace, this_len);
1943 break;
1945 case 'd': case 'i': case 'o':
1946 case 'u': case 'x': case 'X':
1947 fp[0] = *format_str;
1948 fp[1] = '\0';
1949 if (can_check)
1950 this_len = ACE_OS::snprintf
1951 (bp, bspace, format, va_arg (argp, int));
1952 else
1953 this_len = ACE_OS::sprintf
1954 (bp, format, va_arg (argp, int));
1955 ACE_UPDATE_COUNT (bspace, this_len);
1956 break;
1958 case 'F': case 'f': case 'e': case 'E':
1959 case 'g': case 'G':
1960 fp[0] = *format_str;
1961 fp[1] = '\0';
1962 if (can_check)
1963 this_len = ACE_OS::snprintf
1964 (bp, bspace, format, va_arg (argp, double));
1965 else
1966 this_len = ACE_OS::sprintf
1967 (bp, format, va_arg (argp, double));
1968 ACE_UPDATE_COUNT (bspace, this_len);
1969 break;
1971 case 'Q':
1973 const ACE_TCHAR *fmt = ACE_UINT64_FORMAT_SPECIFIER;
1974 ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
1975 if (can_check)
1976 this_len = ACE_OS::snprintf (bp, bspace,
1977 format,
1978 va_arg (argp, ACE_UINT64));
1979 else
1980 this_len = ACE_OS::sprintf (bp,
1981 format,
1982 va_arg (argp, ACE_UINT64));
1984 ACE_UPDATE_COUNT (bspace, this_len);
1985 break;
1987 case 'q':
1989 const ACE_TCHAR *fmt = ACE_INT64_FORMAT_SPECIFIER;
1990 ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
1991 if (can_check)
1992 this_len = ACE_OS::snprintf (bp, bspace,
1993 format,
1994 va_arg (argp, ACE_INT64));
1995 else
1996 this_len = ACE_OS::sprintf (bp,
1997 format,
1998 va_arg (argp, ACE_INT64));
2000 ACE_UPDATE_COUNT (bspace, this_len);
2001 break;
2003 case 'b':
2005 const ACE_TCHAR *fmt = ACE_SSIZE_T_FORMAT_SPECIFIER;
2006 ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
2008 if (can_check)
2009 this_len = ACE_OS::snprintf (bp, bspace,
2010 format,
2011 va_arg (argp, ssize_t));
2012 else
2013 this_len = ACE_OS::sprintf (bp,
2014 format,
2015 va_arg (argp, ssize_t));
2016 ACE_UPDATE_COUNT (bspace, this_len);
2017 break;
2019 case 'B':
2021 const ACE_TCHAR *fmt = ACE_SIZE_T_FORMAT_SPECIFIER;
2022 ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
2024 if (can_check)
2025 this_len = ACE_OS::snprintf (bp, bspace,
2026 format,
2027 va_arg (argp, size_t));
2028 else
2029 this_len = ACE_OS::sprintf (bp,
2030 format,
2031 va_arg (argp, size_t));
2032 ACE_UPDATE_COUNT (bspace, this_len);
2033 break;
2035 case ':':
2037 // Assume a 32 bit time_t and change if needed.
2038 const ACE_TCHAR *fmt = ACE_TEXT ("%d");
2039 if (sizeof (time_t) == 8)
2040 fmt = ACE_INT64_FORMAT_SPECIFIER;
2042 ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
2044 if (can_check)
2045 this_len = ACE_OS::snprintf (bp, bspace,
2046 format,
2047 va_arg (argp, time_t));
2048 else
2049 this_len = ACE_OS::sprintf (bp,
2050 format,
2051 va_arg (argp, time_t));
2052 ACE_UPDATE_COUNT (bspace, this_len);
2053 break;
2055 case '@':
2056 ACE_OS::strcpy (fp, ACE_TEXT ("p"));
2057 if (can_check)
2058 this_len = ACE_OS::snprintf
2059 (bp, bspace, format, va_arg (argp, void*));
2060 else
2061 this_len = ACE_OS::sprintf
2062 (bp, format, va_arg (argp, void*));
2063 ACE_UPDATE_COUNT (bspace, this_len);
2064 break;
2066 case '?':
2067 // Stack trace up to this point
2069 // skip the frame that we're currently in
2070 ACE_Stack_Trace t(2);
2071 #if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
2072 ACE_OS::strcpy (fp, ACE_TEXT ("S"));
2073 #else /* ACE_WIN32 && ACE_USES_WCHAR */
2074 ACE_OS::strcpy (fp, ACE_TEXT ("s"));
2075 #endif /* ACE_WIN32 && ACE_USES_WCHAR */
2076 if (can_check)
2077 this_len = ACE_OS::snprintf
2078 (bp, bspace, format, t.c_str ());
2079 else
2080 this_len = ACE_OS::sprintf
2081 (bp, format, t.c_str ());
2082 ACE_UPDATE_COUNT (bspace, this_len);
2083 break;
2087 default:
2088 // So, it's not a legit format specifier after all...
2089 // Copy from the original % to where we are now, then
2090 // continue with whatever comes next.
2091 while (start_format != format_str && bspace > 0)
2093 *bp++ = *start_format++;
2094 --bspace;
2096 if (bspace > 0)
2098 *bp++ = *format_str;
2099 --bspace;
2101 break;
2104 // Bump to the next char in the caller's format_str
2105 ++format_str;
2108 if (!skip_nul_locate)
2109 while (*bp != '\0') // Locate end of bp.
2110 ++bp;
2114 *bp = '\0'; // Terminate bp, but don't auto-increment this!
2116 ssize_t result = 0;
2118 // Check that memory was not corrupted, if it corrupted we can't log anything
2119 // anymore because all our members could be corrupted.
2120 if (bp >= (this->msg_ + ACE_MAXLOGMSGLEN+1))
2122 abort_prog = true;
2123 ACE_OS::fprintf (stderr,
2124 "The following logged message is too long!\n");
2126 else
2128 // Copy the message from thread-specific storage into the transfer
2129 // buffer (this can be optimized away by changing other code...).
2130 log_record.msg_data (this->msg ());
2132 // Write the <log_record> to the appropriate location.
2133 result = this->log (log_record,
2134 abort_prog);
2137 if (abort_prog)
2139 // Since we are now calling abort instead of exit, this value is
2140 // not used.
2141 ACE_UNUSED_ARG (exit_value);
2143 // *Always* print a message to stderr if we're aborting. We
2144 // don't use verbose, however, to avoid recursive aborts if
2145 // something is hosed.
2146 log_record.print (ACE_Log_Msg::local_host_, 0, stderr);
2147 ACE_OS::abort ();
2150 return result;
2151 #endif /* ACE_LACKS_VA_FUNCTIONS */
2154 #ifdef ACE_LACKS_VA_FUNCTIONS
2155 ACE_Log_Formatter operator, (ACE_Log_Priority prio, const char *fmt)
2157 return ACE_Log_Formatter (prio, fmt);
2160 ACE_Log_Formatter::ACE_Log_Formatter (ACE_Log_Priority prio, const char *fmt)
2161 : saved_errno_ (errno)
2162 , priority_ (prio)
2163 , format_ (fmt)
2164 , logger_ (ACE_LOG_MSG)
2165 , abort_ (ABRT_NONE)
2166 , in_prog_ (' ')
2167 , last_star_ (0)
2169 const bool conditional_values = this->logger_->conditional_values_.is_set_;
2170 this->logger_->conditional_values_.is_set_ = false;
2172 this->enabled_ = this->logger_->log_priority_enabled (prio);
2173 if (!this->enabled_) return;
2175 if (conditional_values)
2176 this->logger_->set (this->logger_->conditional_values_.file_,
2177 this->logger_->conditional_values_.line_,
2178 this->logger_->conditional_values_.op_status_,
2179 this->logger_->conditional_values_.errnum_,
2180 this->logger_->restart (),
2181 this->logger_->msg_ostream (),
2182 this->logger_->msg_callback ());
2183 this->bp_ = this->logger_->msg_ + ACE_Log_Msg::msg_off_;
2184 this->bspace_ = ACE_Log_Record::MAXLOGMSGLEN;
2185 if (ACE_Log_Msg::msg_off_ <= ACE_Log_Record::MAXLOGMSGLEN)
2186 this->bspace_ -= static_cast<size_t> (ACE_Log_Msg::msg_off_);
2188 if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::VERBOSE)
2189 && ACE_Log_Msg::program_name_ != 0)
2191 const int n = ACE_OS::snprintf (this->bp_, this->bspace_, "%s|",
2192 ACE_Log_Msg::program_name_);
2193 ACE_UPDATE_COUNT (this->bspace_, n);
2194 this->bp_ += n;
2197 if (this->logger_->timestamp_)
2199 ACE_TCHAR day_and_time[27];
2200 const bool time_only = this->logger_->timestamp_ == 1;
2201 const ACE_TCHAR *const time =
2202 ACE::timestamp (day_and_time,
2203 sizeof day_and_time / sizeof (ACE_TCHAR),
2204 time_only);
2205 const int n = ACE_OS::snprintf (this->bp_, this->bspace_, "%s|",
2206 time_only ? time : day_and_time);
2207 ACE_UPDATE_COUNT (this->bspace_, n);
2208 this->bp_ += n;
2212 int ACE_Log_Formatter::copy_trunc (const char *str, int limit)
2214 const int n = std::min (static_cast<int> (this->bspace_), limit);
2215 ACE_OS::memcpy (this->bp_, str, n);
2216 ACE_UPDATE_COUNT (this->bspace_, n);
2217 this->bp_ += n;
2218 return n;
2221 void ACE_Log_Formatter::prepare_format ()
2223 const char in_progress = this->in_prog_;
2224 this->in_prog_ = ' ';
2225 switch (in_progress)
2227 case '*':
2228 if (!this->process_conversion ()) return;
2229 break;
2230 case 'p':
2232 // continuation of the '%p' format after the user's message
2233 const int mapped = ACE::map_errno (this->logger_->errnum ());
2234 #ifdef ACE_LOG_MSG_USE_STRERROR_R
2235 char strerror_buf[128]; // always narrow chars
2236 ACE_OS::strcpy (strerror_buf, "strerror_r failed");
2237 const char *const msg = ACE_OS::strerror_r (mapped, strerror_buf,
2238 sizeof strerror_buf);
2239 #else
2240 const char *const msg = ACE_OS::strerror (mapped);
2241 #endif
2242 this->copy_trunc (": ", 2);
2243 this->copy_trunc (msg, ACE_OS::strlen (msg));
2244 break;
2246 case 'r':
2247 if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SILENT))
2249 const size_t len = ACE_OS::strlen (this->bp_);
2250 this->bspace_ -= len + 1;
2251 this->bp_ += len;
2252 this->copy_trunc ("}", 1);
2254 *this->bp_ = 0;
2255 ACE_Log_Msg::msg_off_ = this->offset_;
2256 break;
2259 *this->fmt_out_ = 0;
2261 while (const char *const pct = ACE_OS::strchr (this->format_, '%'))
2263 const bool escaped = pct[1] == '%';
2264 this->format_ += 1 + this->copy_trunc (this->format_,
2265 pct - this->format_ + escaped);
2266 if (!this->bspace_) return;
2267 if (!escaped)
2269 ACE_OS::strcpy (this->fmt_out_, "%");
2270 this->fp_ = this->fmt_out_ + 1;
2271 this->last_star_ = 0;
2272 if (!this->process_conversion ()) return;
2276 this->copy_trunc (this->format_, ACE_OS::strlen (this->format_));
2279 bool ACE_Log_Formatter::process_conversion ()
2281 const size_t n = ACE_OS::strspn (this->format_, "-+ #0123456789.Lh");
2282 const size_t fspace = sizeof this->fmt_out_ - (this->fp_ - this->fmt_out_);
2283 if (n >= fspace || !this->format_[n]) return true;
2285 // when copying to fmt_out_, convert L (used by ACE) to l (used by std)
2286 for (size_t i = 0; i < n; ++i)
2287 if (this->format_[i] == 'L') this->fp_[i] = 'l';
2288 else this->fp_[i] = this->format_[i];
2290 this->fp_ += n;
2291 *this->fp_ = 0;
2292 this->in_prog_ = this->format_[n];
2293 const char *const format_start = this->format_;
2294 this->format_ += n + (this->in_prog_ ? 1 : 0);
2295 int len;
2297 switch (this->in_prog_)
2299 // the following formatters (here through '?') take no argument
2300 // from the "varags" list so they will end up returning true (keep parsing)
2301 case '$':
2302 this->copy_trunc ("\n", 1);
2303 ACE_FALLTHROUGH;
2304 case 'I':
2305 len = std::min (static_cast<int> (this->bspace_),
2306 this->logger_->trace_depth_ *
2307 (this->last_star_ ? this->last_star_ :
2308 #ifdef ACE_HAS_TRACE
2309 ACE_Trace::get_nesting_indent ()));
2310 #else
2311 4));
2312 #endif
2313 ACE_OS::memset (this->bp_, ' ', len);
2314 ACE_UPDATE_COUNT (this->bspace_, len);
2315 this->bp_ += len;
2316 break;
2318 case 'l':
2319 ACE_OS::strcpy (this->fp_, "d");
2320 len = ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_,
2321 this->logger_->linenum ());
2322 ACE_UPDATE_COUNT (this->bspace_, len);
2323 this->bp_ += len;
2324 break;
2326 case 'm':
2328 const int mapped = ACE::map_errno (this->logger_->errnum ());
2329 #ifdef ACE_LOG_MSG_USE_STRERROR_R
2330 char strerror_buf[128]; // always narrow chars
2331 ACE_OS::strcpy (strerror_buf, "strerror_r failed");
2332 const char *const msg = ACE_OS::strerror_r (mapped, strerror_buf,
2333 sizeof strerror_buf);
2334 #else
2335 const char *const msg = ACE_OS::strerror (mapped);
2336 #endif
2337 ACE_OS::strcpy (this->fp_, "s");
2338 len = ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_, msg);
2339 ACE_UPDATE_COUNT (this->bspace_, len);
2340 this->bp_ += len;
2342 break;
2344 case 'M':
2346 const char *const pri = ACE_Log_Record::priority_name (this->priority_);
2348 // special case for %.1M: unique 1-char abbreviation for log priority
2349 if (this->fp_ == this->fmt_out_ + 3 &&
2350 this->fmt_out_[1] == '.' && this->fmt_out_[2] == '1')
2352 const char abbrev =
2353 this->priority_ == LM_STARTUP ? 'U' :
2354 this->priority_ == LM_EMERGENCY ? '!' :
2355 (ACE_OS::strlen (pri) < 4) ? '?' : pri[3];
2356 this->copy_trunc (&abbrev, 1);
2358 else
2360 ACE_OS::strcpy (this->fp_, "s");
2361 len = ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_,
2362 pri);
2363 ACE_UPDATE_COUNT (this->bspace_, len);
2364 this->bp_ += len;
2367 break;
2369 case 'n':
2370 ACE_OS::strcpy (this->fp_, "s");
2371 len = ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_,
2372 ACE_Log_Msg::program_name_ ?
2373 ACE_Log_Msg::program_name_ : "<unknown>");
2374 ACE_UPDATE_COUNT (this->bspace_, len);
2375 this->bp_ += len;
2376 break;
2378 case 'N':
2379 ACE_OS::strcpy (this->fp_, "s");
2380 len = ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_,
2381 this->logger_->file () ?
2382 this->logger_->file () : "<unknown file>");
2383 ACE_UPDATE_COUNT (this->bspace_, len);
2384 this->bp_ += len;
2385 break;
2387 case 'P':
2388 ACE_OS::strcpy (this->fp_, "d");
2389 len = ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_,
2390 static_cast<int> (this->logger_->getpid ()));
2391 ACE_UPDATE_COUNT (this->bspace_, len);
2392 this->bp_ += len;
2393 break;
2395 case 't':
2396 ACE_OS::strcpy (this->fp_, "u");
2397 len = ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_,
2398 ACE_OS::thr_self ());
2399 ACE_UPDATE_COUNT (this->bspace_, len);
2400 this->bp_ += len;
2401 break;
2403 // %D and %T with # in the conversion spec do take an arg (ACE_Time_Value*)
2404 case 'D': case 'T':
2405 ACE_OS::strcpy (this->fp_, "s");
2406 if (ACE_OS::memchr (this->fmt_out_, '#', this->fp_ - this->fmt_out_))
2407 return false;
2409 char day_and_time[27];
2410 const char *const time =
2411 ACE::timestamp (day_and_time, sizeof day_and_time, true);
2412 len = ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_,
2413 this->in_prog_ == 'T' ? time : day_and_time);
2414 ACE_UPDATE_COUNT (this->bspace_, len);
2415 this->bp_ += len;
2417 break;
2419 case '{':
2420 this->logger_->inc ();
2421 break;
2422 case '}':
2423 this->logger_->dec ();
2424 break;
2426 case '?':
2428 ACE_Stack_Trace trc(3); // 3 stack frames between here and user code
2429 ACE_OS::strcpy (this->fp_, "s");
2430 len = ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_,
2431 trc.c_str ());
2432 ACE_UPDATE_COUNT (this->bspace_, len);
2433 this->bp_ += len;
2435 break;
2437 case '*':
2438 // * requires an argument from the "varags" but doesn't complete
2439 // the current conversion specification (for example, %*s):
2440 return false;
2442 // these require an argument from the "varags" list:
2443 case 'a':
2444 this->abort_ = ABRT_NEED_ARG;
2445 this->copy_trunc ("Aborting...", 11);
2446 return false;
2447 case 'A': // ACE_timer_t is a typedef for double on all platforms
2448 ACE_OS::strcpy (this->fp_, "f");
2449 return false;
2451 case 'b':
2452 ACE_OS::strcpy (this->fp_, ACE_SSIZE_T_FORMAT_SPECIFIER + 1); // skip %
2453 return false;
2454 case 'B':
2455 ACE_OS::strcpy (this->fp_, ACE_SIZE_T_FORMAT_SPECIFIER + 1); // skip %
2456 return false;
2458 case 'C': case 'p': case 'S':
2459 ACE_OS::strcpy (this->fp_, "s");
2460 // the remaining parts of case 'p' are handled in prepare_format
2461 return false;
2463 case 'q':
2464 ACE_OS::strcpy (this->fp_, ACE_INT64_FORMAT_SPECIFIER + 1); // skip %
2465 return false;
2466 case 'Q':
2467 ACE_OS::strcpy (this->fp_, ACE_UINT64_FORMAT_SPECIFIER + 1); // skip %
2468 return false;
2470 case 'r':
2471 this->offset_ = ACE_Log_Msg::msg_off_;
2472 if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SILENT))
2473 this->copy_trunc ("{", 1);
2474 ACE_Log_Msg::msg_off_ = this->bp_ - this->logger_->msg_;
2475 return false;
2477 case 'R':
2478 ACE_OS::strcpy (this->fp_, "d");
2479 return false;
2481 case 'w': case 'z':
2482 ACE_OS::strcpy (this->fp_, "u");
2483 return false;
2484 case 'W':
2485 ACE_OS::strcpy (this->fp_, "ls");
2486 return false;
2487 case 'Z':
2488 #if (defined ACE_WIN32 && !defined ACE_USES_WCHAR)
2489 ACE_OS::strcpy (this->fp_, "S");
2490 #elif defined ACE_WIN32
2491 ACE_OS::strcpy (this->fp_, "s");
2492 #else
2493 ACE_OS::strcpy (this->fp_, "ls");
2494 #endif
2495 return false;
2497 case '@':
2498 ACE_OS::strcpy (this->fp_, "p");
2499 return false;
2500 case ':':
2501 if (sizeof (time_t) == 8)
2502 ACE_OS::strcpy (this->fp_, ACE_INT64_FORMAT_SPECIFIER + 1); // skip %
2503 else
2504 ACE_OS::strcpy (this->fp_, "d");
2505 return false;
2507 case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': // <- ints
2508 case 'e': case 'E': case 'f': case 'F': case 'g': case 'G': // <- doubles
2509 case 'c': case 's': // <- char / const char*
2510 *this->fp_++ = this->in_prog_;
2511 *this->fp_ = 0;
2512 return false;
2514 default:
2515 // not actually a format specifier: copy verbatim to output
2516 this->copy_trunc (format_start - 1 /* start at % */, n + 2);
2517 this->in_prog_ = ' ';
2518 break;
2520 return true;
2523 void ACE_Log_Formatter::insert_pct_S (int sig)
2525 const int n = ACE_OS::snprintf (this->bp_, this->bspace_,
2526 this->fmt_out_, ACE_OS::strsignal (sig));
2527 ACE_UPDATE_COUNT (this->bspace_, n);
2528 this->bp_ += n;
2531 template <typename ArgT>
2532 void ACE_Log_Formatter::insert_arg (ArgT arg, bool allow_star)
2534 if (!this->enabled_) return;
2536 this->prepare_format ();
2538 const int intArg = static_cast<int> (arg);
2539 switch (this->in_prog_)
2541 case 'R':
2542 this->logger_->op_status (intArg);
2543 break;
2544 case 'S':
2545 this->insert_pct_S (intArg);
2546 return;
2547 case '*':
2548 if (allow_star)
2550 this->last_star_ = intArg;
2551 this->fp_ +=
2552 ACE_OS::snprintf (this->fp_,
2553 sizeof fmt_out_ - (this->fp_ - this->fmt_out_),
2554 "%d", intArg);
2555 return;
2557 break;
2560 insert_arg_i (arg);
2563 template <typename ArgT>
2564 void ACE_Log_Formatter::insert_arg (ArgT *arg)
2566 if (!this->enabled_) return;
2568 this->prepare_format ();
2570 insert_arg_i (arg);
2573 template <typename ArgT>
2574 void ACE_Log_Formatter::insert_arg_i (ArgT arg)
2576 if (this->abort_ == ABRT_NEED_ARG)
2578 // arg is ignored
2579 this->abort_ = ABRT_AFTER_FORMAT;
2581 else if (*this->fmt_out_)
2583 const int n = ACE_OS::snprintf (this->bp_, this->bspace_,
2584 this->fmt_out_, arg);
2585 ACE_UPDATE_COUNT (this->bspace_, n);
2586 this->bp_ += n;
2590 ACE_Log_Formatter &ACE_Log_Formatter::operator, (int pct_adiRS)
2592 this->insert_arg (pct_adiRS, true);
2593 return *this;
2596 ACE_Log_Formatter &ACE_Log_Formatter::operator, (unsigned int pct_ouxX)
2598 this->insert_arg (pct_ouxX, true);
2599 return *this;
2602 ACE_Log_Formatter &ACE_Log_Formatter::operator, (double pct_AeEfFgG)
2604 this->insert_arg (pct_AeEfFgG);
2605 return *this;
2608 ACE_Log_Formatter &ACE_Log_Formatter::operator, (long double pct_AeEfFgG)
2610 this->insert_arg (pct_AeEfFgG);
2611 return *this;
2614 ACE_Log_Formatter &ACE_Log_Formatter::operator, (char pct_c)
2616 this->insert_arg (pct_c);
2617 return *this;
2620 ACE_Log_Formatter &ACE_Log_Formatter::operator, (const char *pct_Cps)
2622 this->insert_arg (pct_Cps ? pct_Cps : "(null)");
2623 return *this;
2626 ACE_Log_Formatter &ACE_Log_Formatter::operator, (ACE_INT64 pct_q)
2628 this->insert_arg (pct_q);
2629 return *this;
2632 ACE_Log_Formatter &ACE_Log_Formatter::operator, (ACE_UINT64 pct_Q)
2634 this->insert_arg (pct_Q);
2635 return *this;
2638 ACE_Log_Formatter &ACE_Log_Formatter::operator, (void (*pct_r) ())
2640 if (this->enabled_)
2642 this->prepare_format ();
2643 pct_r ();
2645 return *this;
2648 ACE_Log_Formatter &ACE_Log_Formatter::operator, (ACE_WCHAR_T pct_wz)
2650 this->insert_arg (pct_wz);
2651 return *this;
2654 ACE_Log_Formatter &ACE_Log_Formatter::operator, (const ACE_WCHAR_T *pct_WZ)
2656 this->insert_arg (pct_WZ ? pct_WZ : (const ACE_WCHAR_T *) L"(null)");
2657 return *this;
2660 ACE_Log_Formatter &ACE_Log_Formatter::operator, (const void *pct_at)
2662 this->insert_arg (pct_at);
2663 return *this;
2666 ACE_Log_Formatter &ACE_Log_Formatter::operator, (const ACE_Time_Value *pct_DT)
2668 if (!this->enabled_) return *this;
2670 this->prepare_format ();
2672 char day_and_time[27];
2673 const char *const time =
2674 ACE::timestamp (*pct_DT, day_and_time, sizeof day_and_time, true);
2675 const int len =
2676 ACE_OS::snprintf (this->bp_, this->bspace_, this->fmt_out_,
2677 this->in_prog_ == 'T' ? time : day_and_time);
2678 ACE_UPDATE_COUNT (this->bspace_, len);
2679 this->bp_ += len;
2681 return *this;
2684 #if ACE_SIZEOF_LONG == 4
2685 ACE_Log_Formatter &ACE_Log_Formatter::operator, (long pct_Lmodifier)
2687 this->insert_arg (pct_Lmodifier, true);
2688 return *this;
2691 ACE_Log_Formatter &ACE_Log_Formatter::operator, (unsigned long pct_Lmodifier)
2693 this->insert_arg (pct_Lmodifier, true);
2694 return *this;
2696 #endif
2698 bool ACE_Log_Formatter::to_record (ACE_Log_Record &record)
2700 if (!this->enabled_) return false;
2702 this->prepare_format ();
2703 if (this->bspace_) *this->bp_ = 0;
2705 record.priority (this->priority_);
2706 record.time_stamp (ACE_OS::gettimeofday ());
2707 record.pid (this->logger_->getpid ());
2708 record.msg_data (this->logger_->msg ());
2709 return true;
2712 ssize_t ACE_Log_Msg::log (const ACE_Log_Formatter &formatter)
2714 ACE_Log_Record record;
2715 if (const_cast<ACE_Log_Formatter &> (formatter).to_record (record))
2717 const ssize_t result = this->log (record, formatter.abort ());
2718 if (formatter.abort ())
2720 #ifndef ACE_LACKS_STDERR
2721 record.print (local_host_, 0, stderr);
2722 #endif
2723 ACE_OS::abort ();
2725 errno = formatter.saved_errno ();
2726 return result;
2728 return 0;
2731 #endif /* ACE_LACKS_VA_FUNCTIONS */
2734 #if !defined (ACE_WIN32)
2736 * @class ACE_Log_Msg_Sig_Guard
2738 * @brief For use only by ACE_Log_Msg.
2740 * Doesn't require the use of global variables or global
2741 * functions in an application).
2743 class ACE_Log_Msg_Sig_Guard
2745 private:
2746 ACE_Log_Msg_Sig_Guard ();
2747 ~ACE_Log_Msg_Sig_Guard ();
2749 /// Original signal mask.
2750 sigset_t omask_;
2752 friend ssize_t ACE_Log_Msg::log (ACE_Log_Record &log_record,
2753 int suppress_stderr);
2756 ACE_Log_Msg_Sig_Guard::ACE_Log_Msg_Sig_Guard ()
2758 #if !defined (ACE_LACKS_UNIX_SIGNALS)
2759 ACE_OS::sigemptyset (&this->omask_);
2761 # if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
2762 ACE_OS::sigprocmask (SIG_BLOCK,
2763 ACE_OS_Object_Manager::default_mask (),
2764 &this->omask_);
2765 # else
2766 ACE_OS::thr_sigsetmask (SIG_BLOCK,
2767 ACE_OS_Object_Manager::default_mask (),
2768 &this->omask_);
2769 # endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
2770 #endif /* ACE_LACKS_UNIX_SIGNALS */
2773 ACE_Log_Msg_Sig_Guard::~ACE_Log_Msg_Sig_Guard ()
2775 #if !defined (ACE_LACKS_UNIX_SIGNALS)
2776 # if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
2777 ACE_OS::sigprocmask (SIG_SETMASK,
2778 &this->omask_,
2780 # else
2781 ACE_OS::thr_sigsetmask (SIG_SETMASK,
2782 &this->omask_,
2784 # endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
2785 #endif /* ! ACE_LACKS_UNIX_SIGNALS */
2787 #endif /* ! ACE_WIN32 */
2789 ssize_t
2790 ACE_Log_Msg::log (ACE_Log_Record &log_record,
2791 int suppress_stderr)
2793 ssize_t result = 0;
2795 // Retrieve the flags in a local variable on the stack, it is
2796 // accessed by multiple threads and within this operation we
2797 // check it several times, so this way we only lock once
2798 u_long flags = this->flags ();
2800 // Format the message and print it to stderr and/or ship it off to
2801 // the log_client daemon, and/or print it to the ostream. Of
2802 // course, only print the message if "SILENT" mode is disabled.
2803 if (ACE_BIT_DISABLED (flags, ACE_Log_Msg::SILENT))
2805 bool tracing = this->tracing_enabled ();
2806 this->stop_tracing ();
2808 #if !defined (ACE_WIN32)
2809 // Make this block signal-safe.
2810 ACE_Log_Msg_Sig_Guard sb;
2811 #endif /* !ACE_WIN32 */
2813 // Do the callback, if needed, before acquiring the lock
2814 // to avoid holding the lock during the callback so we don't
2815 // have deadlock if the callback uses the logger.
2816 if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::MSG_CALLBACK)
2817 && this->msg_callback () != 0)
2819 this->msg_callback ()->log (log_record);
2822 // Make sure that the lock is held during all this.
2823 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
2824 *ACE_Log_Msg_Manager::get_lock (),
2825 -1));
2827 #if !defined ACE_LACKS_STDERR || defined ACE_FACE_DEV
2828 if (ACE_BIT_ENABLED (flags,
2829 ACE_Log_Msg::STDERR)
2830 && !suppress_stderr) // This is taken care of by our caller.
2831 log_record.print (ACE_Log_Msg::local_host_,
2832 flags,
2833 stderr);
2834 #else
2835 ACE_UNUSED_ARG (suppress_stderr);
2836 #endif
2838 if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::CUSTOM) ||
2839 ACE_BIT_ENABLED (flags, ACE_Log_Msg::SYSLOG) ||
2840 ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER))
2842 // Be sure that there is a message_queue_, with multiple threads.
2843 ACE_MT (ACE_Log_Msg_Manager::init_backend ());
2846 if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER) ||
2847 ACE_BIT_ENABLED (flags, ACE_Log_Msg::SYSLOG))
2849 result =
2850 ACE_Log_Msg_Manager::log_backend_->log (log_record);
2853 if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::CUSTOM) &&
2854 ACE_Log_Msg_Manager::custom_backend_ != 0)
2856 result =
2857 ACE_Log_Msg_Manager::custom_backend_->log (log_record);
2860 // This must come last, after the other two print operations
2861 // (see the <ACE_Log_Record::print> method for details).
2862 if (ACE_BIT_ENABLED (flags,
2863 ACE_Log_Msg::OSTREAM)
2864 && this->msg_ostream () != 0)
2865 log_record.print (ACE_Log_Msg::local_host_,
2866 flags,
2867 #if defined (ACE_LACKS_IOSTREAM_TOTALLY)
2868 static_cast<FILE *> (this->msg_ostream ())
2869 #else /* ! ACE_LACKS_IOSTREAM_TOTALLY */
2870 *this->msg_ostream ()
2871 #endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
2874 if (tracing)
2875 this->start_tracing ();
2878 return result;
2881 // Calls log to do the actual print, but formats first.
2884 ACE_Log_Msg::log_hexdump (ACE_Log_Priority log_priority,
2885 const char *buffer,
2886 size_t size,
2887 const ACE_TCHAR *text,
2888 ACE_Log_Category_TSS* category)
2890 // Only print the message if <priority_mask_> hasn't been reset to
2891 // exclude this logging priority.
2892 if (this->log_priority_enabled (log_priority) == 0)
2893 return 0;
2895 size_t text_sz = 0;
2896 if (text)
2897 text_sz = ACE_OS::strlen (text);
2899 size_t const total_buffer_size =
2900 ACE_Log_Record::MAXLOGMSGLEN - ACE_Log_Record::VERBOSE_LEN + text_sz;
2902 ACE_Array<ACE_TCHAR> msg_buf(total_buffer_size);
2903 if (msg_buf.size() == 0)
2904 return -1;
2906 ACE_TCHAR* end_ptr = &msg_buf[0] + total_buffer_size;
2907 ACE_TCHAR* wr_ptr = &msg_buf[0];
2908 msg_buf[0] = 0; // in case size = 0
2910 if (text)
2911 wr_ptr += ACE_OS::snprintf (wr_ptr,
2912 end_ptr - wr_ptr,
2913 ACE_TEXT ("%") ACE_TEXT_PRIs ACE_TEXT (" - "),
2914 text);
2916 wr_ptr += ACE_OS::snprintf (wr_ptr,
2917 end_ptr - wr_ptr,
2918 ACE_TEXT ("HEXDUMP ")
2919 ACE_SIZE_T_FORMAT_SPECIFIER
2920 ACE_TEXT (" bytes"),
2921 size);
2923 // estimate how many bytes can be output
2924 // We can fit 16 bytes output in text mode per line, 4 chars per byte;
2925 // i.e. we need 68 bytes of buffer per line.
2926 size_t hexdump_size = (end_ptr - wr_ptr -58)/68*16;
2928 if (hexdump_size < size)
2930 wr_ptr += ACE_OS::snprintf (wr_ptr,
2931 end_ptr - wr_ptr,
2932 ACE_TEXT (" (showing first ")
2933 ACE_SIZE_T_FORMAT_SPECIFIER
2934 ACE_TEXT (" bytes)"),
2935 hexdump_size);
2936 size = hexdump_size;
2939 *wr_ptr++ = '\n';
2940 ACE::format_hexdump(buffer, size, wr_ptr, end_ptr - wr_ptr);
2942 // Now print out the formatted buffer.
2943 ACE_Log_Record log_record (log_priority,
2944 ACE_OS::gettimeofday (),
2945 this->getpid ());
2947 log_record.category(category);
2948 log_record.msg_data(&msg_buf[0]);
2950 this->log (log_record, false);
2951 return 0;
2954 void
2955 ACE_Log_Msg::set (const char *file,
2956 int line,
2957 int op_status,
2958 int errnum,
2959 bool restart,
2960 ACE_OSTREAM_TYPE *os,
2961 ACE_Log_Msg_Callback *c)
2963 ACE_TRACE ("ACE_Log_Msg::set");
2964 this->file (file);
2965 this->linenum (line);
2966 this->op_status (op_status);
2967 this->errnum (errnum);
2968 this->restart (restart);
2969 this->msg_ostream (os);
2970 this->msg_callback (c);
2973 void
2974 ACE_Log_Msg::conditional_set (const char *filename,
2975 int line,
2976 int status,
2977 int err)
2979 this->conditional_values_.is_set_ = true;
2980 this->conditional_values_.file_ = filename;
2981 this->conditional_values_.line_ = line;
2982 this->conditional_values_.op_status_ = status;
2983 this->conditional_values_.errnum_ = err;
2986 void
2987 ACE_Log_Msg::dump () const
2989 #if defined (ACE_HAS_DUMP)
2990 ACE_TRACE ("ACE_Log_Msg::dump");
2992 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
2993 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("status_ = %d\n"), this->status_));
2994 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nerrnum_ = %d\n"), this->errnum_));
2995 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nlinenum_ = %d\n"), this->linenum_));
2996 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nfile_ = %C\n"), this->file_));
2997 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmsg_ = %s\n"), this->msg_));
2998 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nrestart_ = %d\n"), this->restart_));
2999 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nostream_ = %@\n"), this->ostream_));
3000 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmsg_callback_ = %@\n"),
3001 this->msg_callback_));
3002 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nprogram_name_ = %s\n"),
3003 this->program_name_ ? this->program_name_
3004 : ACE_TEXT ("<unknown>")));
3005 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nlocal_host_ = %s\n"),
3006 this->local_host_ ? this->local_host_
3007 : ACE_TEXT ("<unknown>")));
3008 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nflags_ = 0x%x\n"), this->flags_));
3009 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntrace_depth_ = %d\n"),
3010 this->trace_depth_));
3011 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntrace_active_ = %d\n"),
3012 this->trace_active_));
3013 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntracing_enabled_ = %d\n"),
3014 this->tracing_enabled_));
3015 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\npriority_mask_ = 0x%x\n"),
3016 this->priority_mask_));
3017 if (this->thr_desc_ != 0 && this->thr_desc_->state () != 0)
3018 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nthr_state_ = %d\n"),
3019 this->thr_desc_->state ()));
3020 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("\nmsg_off_ = %d\n"), this->msg_off_));
3022 // Be sure that there is a message_queue_, with multiple threads.
3023 ACE_MT (ACE_Log_Msg_Manager::init_backend ());
3025 ACE_MT (ACE_Log_Msg_Manager::get_lock ()->dump ());
3026 // Synchronize output operations.
3028 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
3029 #endif /* ACE_HAS_DUMP */
3032 void
3033 ACE_Log_Msg::thr_desc (ACE_Thread_Descriptor *td)
3035 this->thr_desc_ = td;
3037 if (td != 0)
3038 td->acquire_release ();
3041 ACE_Log_Msg_Backend *
3042 ACE_Log_Msg::msg_backend (ACE_Log_Msg_Backend *b)
3044 ACE_TRACE ("ACE_Log_Msg::msg_backend");
3045 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
3046 *ACE_Log_Msg_Manager::get_lock (), 0));
3048 ACE_Log_Msg_Backend *tmp = ACE_Log_Msg_Manager::custom_backend_;
3049 ACE_Log_Msg_Manager::custom_backend_ = b;
3050 return tmp;
3053 ACE_Log_Msg_Backend *
3054 ACE_Log_Msg::msg_backend ()
3056 ACE_TRACE ("ACE_Log_Msg::msg_backend");
3057 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
3058 *ACE_Log_Msg_Manager::get_lock (), 0));
3060 return ACE_Log_Msg_Manager::custom_backend_;
3063 void
3064 ACE_Log_Msg::msg_ostream (ACE_OSTREAM_TYPE *m, bool delete_ostream)
3066 if (this->ostream_ == m)
3068 // Same stream, allow user to change the delete_ostream "flag"
3069 if (delete_ostream && !this->ostream_refcount_)
3071 #if defined (ACE_HAS_ALLOC_HOOKS)
3072 ACE_NEW_MALLOC (this->ostream_refcount_, static_cast<Atomic_ULong*>(ACE_Allocator::instance()->malloc(sizeof(Atomic_ULong))), Atomic_ULong (1));
3073 #else
3074 ACE_NEW (this->ostream_refcount_, Atomic_ULong (1));
3075 #endif /* ACE_HAS_ALLOC_HOOKS */
3077 else if (!delete_ostream && this->ostream_refcount_)
3079 if (--*this->ostream_refcount_ == 0)
3081 #if defined (ACE_HAS_ALLOC_HOOKS)
3082 this->ostream_refcount_->~Atomic_ULong();
3083 ACE_Allocator::instance()->free(this->ostream_refcount_);
3084 #else
3085 delete this->ostream_refcount_;
3086 #endif /* ACE_HAS_ALLOC_HOOKS */
3088 this->ostream_refcount_ = 0;
3090 // The other two cases are no-ops, the user has requested the same
3091 // state that's already present.
3092 return;
3095 this->cleanup_ostream ();
3097 if (delete_ostream)
3099 #if defined (ACE_HAS_ALLOC_HOOKS)
3100 ACE_NEW_MALLOC (this->ostream_refcount_, static_cast<Atomic_ULong*>(ACE_Allocator::instance()->malloc(sizeof(Atomic_ULong))), Atomic_ULong (1));
3101 #else
3102 ACE_NEW (this->ostream_refcount_, Atomic_ULong (1));
3103 #endif /* ACE_HAS_ALLOC_HOOKS */
3106 this->ostream_ = m;
3109 void
3110 ACE_Log_Msg::local_host (const ACE_TCHAR *s)
3112 if (s)
3114 #if defined (ACE_HAS_ALLOC_HOOKS)
3115 ACE_Allocator::instance()->free ((void *) ACE_Log_Msg::local_host_);
3116 #else
3117 ACE_OS::free ((void *) ACE_Log_Msg::local_host_);
3118 #endif /* ACE_HAS_ALLOC_HOOKS */
3120 ACE_ALLOCATOR (ACE_Log_Msg::local_host_, ACE_OS::strdup (s));
3124 #ifndef ACE_LACKS_VA_FUNCTIONS
3126 ACE_Log_Msg::log_priority_enabled (ACE_Log_Priority log_priority,
3127 const char *,
3128 ...)
3130 return this->log_priority_enabled (log_priority);
3133 #if defined (ACE_USES_WCHAR)
3135 ACE_Log_Msg::log_priority_enabled (ACE_Log_Priority log_priority,
3136 const wchar_t *,
3137 ...)
3139 return this->log_priority_enabled (log_priority);
3141 #endif /* ACE_USES_WCHAR */
3143 #endif /* ACE_LACKS_VA_FUNCTIONS */
3145 // ****************************************************************
3147 void
3148 ACE_Log_Msg::init_hook (ACE_OS_Log_Msg_Attributes &attributes
3149 # if defined (ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS)
3150 , ACE_SEH_EXCEPT_HANDLER selector
3151 , ACE_SEH_EXCEPT_HANDLER handler
3152 # endif /* ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS */
3155 # if defined (ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS)
3156 attributes.seh_except_selector_ = selector;
3157 attributes.seh_except_handler_ = handler;
3158 # endif /* ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS */
3159 if (ACE_Log_Msg::exists ())
3161 ACE_Log_Msg *inherit_log = ACE_LOG_MSG;
3162 attributes.ostream_ = inherit_log->msg_ostream ();
3163 if (attributes.ostream_ && inherit_log->ostream_refcount_)
3165 ++*inherit_log->ostream_refcount_;
3166 attributes.ostream_refcount_ = inherit_log->ostream_refcount_;
3168 else
3170 attributes.ostream_refcount_ = 0;
3172 attributes.priority_mask_ = inherit_log->priority_mask ();
3173 attributes.tracing_enabled_ = inherit_log->tracing_enabled ();
3174 attributes.restart_ = inherit_log->restart ();
3175 attributes.trace_depth_ = inherit_log->trace_depth ();
3179 void
3180 ACE_Log_Msg::inherit_hook (ACE_OS_Thread_Descriptor *thr_desc,
3181 ACE_OS_Log_Msg_Attributes &attributes)
3183 #if !defined (ACE_THREADS_DONT_INHERIT_LOG_MSG) && \
3184 !defined (ACE_HAS_MINIMAL_ACE_OS)
3185 // Inherit the logging features if the parent thread has an
3186 // ACE_Log_Msg. Note that all of the following operations occur
3187 // within thread-specific storage.
3188 ACE_Log_Msg *new_log = ACE_LOG_MSG;
3190 // Note that we do not inherit the callback because this might have
3191 // been allocated off of the stack of the original thread, in which
3192 // case all hell would break loose...
3194 if (attributes.ostream_)
3196 new_log->ostream_ = attributes.ostream_;
3197 new_log->ostream_refcount_ =
3198 static_cast<Atomic_ULong *> (attributes.ostream_refcount_);
3200 new_log->priority_mask (attributes.priority_mask_);
3202 if (attributes.tracing_enabled_)
3203 new_log->start_tracing ();
3205 new_log->restart (attributes.restart_);
3206 new_log->trace_depth (attributes.trace_depth_);
3209 // @@ Now the TSS Log_Msg has been created, cache my thread
3210 // descriptor in.
3212 if (thr_desc != 0)
3213 // This downcast is safe. We do it to avoid having to #include
3214 // ace/Thread_Manager.h.
3215 new_log->thr_desc (static_cast<ACE_Thread_Descriptor *> (thr_desc));
3216 // Block the thread from proceeding until
3217 // thread manager has thread descriptor ready.
3218 #endif /* ! ACE_THREADS_DONT_INHERIT_LOG_MSG && ! ACE_HAS_MINIMAL_ACE_OS */
3221 ACE_END_VERSIONED_NAMESPACE_DECL