summaryrefslogtreecommitdiff
path: root/ACE/ace/Log_Msg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/Log_Msg.cpp')
-rw-r--r--ACE/ace/Log_Msg.cpp2648
1 files changed, 2648 insertions, 0 deletions
diff --git a/ACE/ace/Log_Msg.cpp b/ACE/ace/Log_Msg.cpp
new file mode 100644
index 00000000000..0c77181410a
--- /dev/null
+++ b/ACE/ace/Log_Msg.cpp
@@ -0,0 +1,2648 @@
+// $Id$
+
+// We need this to get the status of ACE_NTRACE...
+#include "ace/config-all.h"
+
+// Turn off tracing for the duration of this file.
+#if defined (ACE_NTRACE)
+# undef ACE_NTRACE
+#endif /* ACE_NTRACE */
+#define ACE_NTRACE 1
+
+#include "ace/ACE.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Guard_T.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_sys_time.h"
+#include "ace/OS_NS_wchar.h"
+#include "ace/OS_NS_signal.h"
+#include "ace/OS_NS_unistd.h"
+
+#if !defined (ACE_MT_SAFE) || (ACE_MT_SAFE != 0)
+# include "ace/Object_Manager_Base.h"
+#endif /* ! ACE_MT_SAFE */
+
+#if !defined (ACE_LACKS_IOSTREAM_TOTALLY)
+// FUZZ: disable check_for_streams_include
+# include "ace/streams.h"
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+
+#if defined (ACE_HAS_TRACE)
+# include "ace/Trace.h"
+#endif /* ACE_HAS_TRACE */
+
+#include "ace/Log_Msg.h"
+#include "ace/Log_Msg_Callback.h"
+#include "ace/Log_Msg_IPC.h"
+#include "ace/Log_Msg_NT_Event_Log.h"
+#include "ace/Log_Msg_UNIX_Syslog.h"
+#include "ace/Log_Record.h"
+#include "ace/Recursive_Thread_Mutex.h"
+
+ACE_RCSID(ace, Log_Msg, "$Id$")
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+ACE_ALLOC_HOOK_DEFINE(ACE_Log_Msg)
+
+// only used here... dhinton
+#if defined (ACE_HAS_SYS_SIGLIST)
+# if !defined (_sys_siglist)
+# define _sys_siglist sys_siglist
+# endif /* !defined (sys_siglist) */
+//extern char **_sys_siglist;
+#endif /* ACE_HAS_SYS_SIGLIST */
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ int ACE_Log_Msg::key_created_ = 0;
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+
+static ACE_thread_key_t the_log_msg_tss_key = 0;
+
+ACE_thread_key_t *log_msg_tss_key (void)
+{
+ return &the_log_msg_tss_key;
+}
+
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#endif /* ACE_MT_SAFE */
+
+#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_PHARLAP)
+# define ACE_LOG_MSG_SYSLOG_BACKEND ACE_Log_Msg_NT_Event_Log
+#elif !defined (ACE_LACKS_UNIX_SYSLOG) && !defined (ACE_HAS_WINCE)
+# define ACE_LOG_MSG_SYSLOG_BACKEND ACE_Log_Msg_UNIX_Syslog
+#else
+# define ACE_LOG_MSG_SYSLOG_BACKEND ACE_Log_Msg_IPC
+#endif /* ! ACE_WIN32 */
+
+// When doing ACE_OS::s[n]printf() calls in log(), we need to update
+// the space remaining in the output buffer based on what's returned from
+// the output function. If we could rely on more modern compilers, this
+// would be in an unnamed namespace, but it's a macro instead.
+// count is a size_t, len is an int and assumed to be non-negative.
+#define ACE_UPDATE_COUNT(COUNT, LEN) \
+ do { if (static_cast<size_t> (LEN) > COUNT) COUNT = 0; \
+ else COUNT -= static_cast<size_t> (LEN); \
+ } while (0)
+
+/// Instance count for Log_Msg - used to know when dynamically
+/// allocated storage (program name and host name) can be safely
+/// deleted.
+int ACE_Log_Msg::instance_count_ = 0;
+
+/**
+ * @class ACE_Log_Msg_Manager
+ *
+ * @brief Synchronize output operations.
+ *
+ * Provides global point of contact for all ACE_Log_Msg instances
+ * in a process.
+ *
+ * For internal use by ACE, only!
+ */
+class ACE_Log_Msg_Manager
+{
+public:
+ static ACE_Log_Msg_Backend *log_backend_;
+ static ACE_Log_Msg_Backend *custom_backend_;
+
+ static u_long log_backend_flags_;
+
+ static int init_backend (const u_long *flags = 0);
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ static void close (void);
+
+ static ACE_Recursive_Thread_Mutex *get_lock (void);
+
+private:
+ static ACE_Recursive_Thread_Mutex *lock_;
+#endif /* ! ACE_MT_SAFE */
+};
+
+ACE_Log_Msg_Backend *ACE_Log_Msg_Manager::log_backend_ = 0;
+ACE_Log_Msg_Backend *ACE_Log_Msg_Manager::custom_backend_ = 0;
+
+u_long ACE_Log_Msg_Manager::log_backend_flags_ = 0;
+
+int ACE_Log_Msg_Manager::init_backend (const u_long *flags)
+{
+ // If flags have been supplied, and they are different from the flags
+ // we had last time, then we may have to re-create the backend as a
+ // different type.
+ if (flags)
+ {
+ // Sanity check for custom backend.
+ if (ACE_BIT_ENABLED (*flags, ACE_Log_Msg::CUSTOM) &&
+ ACE_Log_Msg_Manager::custom_backend_ == 0)
+ {
+ return -1;
+ }
+
+ if ((ACE_BIT_ENABLED (*flags, ACE_Log_Msg::SYSLOG)
+ && ACE_BIT_DISABLED (ACE_Log_Msg_Manager::log_backend_flags_, ACE_Log_Msg::SYSLOG))
+ || (ACE_BIT_DISABLED (*flags, ACE_Log_Msg::SYSLOG)
+ && ACE_BIT_ENABLED (ACE_Log_Msg_Manager::log_backend_flags_, ACE_Log_Msg::SYSLOG)))
+ {
+ delete ACE_Log_Msg_Manager::log_backend_;
+ ACE_Log_Msg_Manager::log_backend_ = 0;
+ }
+
+ ACE_Log_Msg_Manager::log_backend_flags_ = *flags;
+ }
+
+ if (ACE_Log_Msg_Manager::log_backend_ == 0)
+ {
+ ACE_NO_HEAP_CHECK;
+
+#if (defined (WIN32) || !defined (ACE_LACKS_UNIX_SYSLOG)) && !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_PHARLAP)
+ // Allocate the ACE_Log_Msg_Backend instance.
+ if (ACE_BIT_ENABLED (ACE_Log_Msg_Manager::log_backend_flags_, ACE_Log_Msg::SYSLOG))
+ ACE_NEW_RETURN (ACE_Log_Msg_Manager::log_backend_,
+ ACE_LOG_MSG_SYSLOG_BACKEND,
+ -1);
+ else
+#endif /* defined (WIN32) && !defined (ACE_HAS_WINCE) && !defined (ACE_HAS_PHARLAP) */
+ ACE_NEW_RETURN (ACE_Log_Msg_Manager::log_backend_,
+ ACE_Log_Msg_IPC,
+ -1);
+ }
+
+ return 0;
+}
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ACE_Recursive_Thread_Mutex *ACE_Log_Msg_Manager::lock_ = 0;
+
+ACE_Recursive_Thread_Mutex *
+ACE_Log_Msg_Manager::get_lock (void)
+{
+ // This function is called by the first thread to create an ACE_Log_Msg
+ // instance. It makes the call while holding a mutex, so we don't have
+ // to grab another one here.
+
+ if (ACE_Log_Msg_Manager::lock_ == 0)
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_NEW_RETURN (ACE_Log_Msg_Manager::lock_,
+ ACE_Recursive_Thread_Mutex,
+ 0);
+ }
+
+ if (init_backend () == -1)
+ return 0;
+
+ return ACE_Log_Msg_Manager::lock_;
+}
+
+void
+ACE_Log_Msg_Manager::close (void)
+{
+#if defined (ACE_HAS_STHREADS) && ! defined (ACE_HAS_TSS_EMULATION) && ! defined (ACE_HAS_EXCEPTIONS)
+ // Delete the (main thread's) Log_Msg instance. I think that this
+ // is only "necessary" if exception handling is not enabled.
+ // Without exception handling, main thread TSS destructors don't
+ // seem to be called. It's not really necessary anyways, because
+ // this one leak is harmless on Solaris.
+ delete ACE_Log_Msg::instance ();
+#endif /* ACE_HAS_STHREADS && ! TSS_EMULATION && ! ACE_HAS_EXCEPTIONS */
+
+ // Ugly, ugly, but don't know a better way.
+ delete ACE_Log_Msg_Manager::lock_;
+ ACE_Log_Msg_Manager::lock_ = 0;
+
+ delete ACE_Log_Msg_Manager::log_backend_;
+ ACE_Log_Msg_Manager::log_backend_ = 0;
+
+ // we are never responsible for custom backend
+ ACE_Log_Msg_Manager::custom_backend_ = 0;
+}
+
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+/* static */
+# if defined (ACE_HAS_THR_C_DEST)
+# define LOCAL_EXTERN_PREFIX extern "C"
+# else
+# define LOCAL_EXTERN_PREFIX
+# endif /* ACE_HAS_THR_C_DEST */
+LOCAL_EXTERN_PREFIX
+void
+ACE_TSS_CLEANUP_NAME (void *ptr)
+{
+#if !defined(ACE_USE_ONE_SHOT_AT_THREAD_EXIT)
+ // Delegate to thr_desc if this not has terminated
+ ACE_Log_Msg* log_msg = (ACE_Log_Msg*) ptr;
+ if (log_msg->thr_desc()!=0)
+ log_msg->thr_desc()->log_msg_cleanup(log_msg);
+ else
+#endif /* !ACE_USE_ONE_SHOT_AT_THREAD_EXIT */
+ delete (ACE_Log_Msg *) ptr;
+}
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#endif /* ! ACE_MT_SAFE */
+
+/* static */
+int
+ACE_Log_Msg::exists (void)
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+ ACE_Log_Msg *tss_log_msg = 0;
+
+ // Get the tss_log_msg from thread-specific storage.
+ return key_created_
+ && ACE_Thread::getspecific (*(log_msg_tss_key ()),
+ reinterpret_cast<void **> (&tss_log_msg)) != -1
+ && tss_log_msg;
+# else
+# error "Platform must support thread-specific storage if threads are used."
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#else /* ! ACE_MT_SAFE */
+ return 1;
+#endif /* ! ACE_MT_SAFE */
+}
+
+ACE_Log_Msg *
+ACE_Log_Msg::instance (void)
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION)
+ // TSS Singleton implementation.
+
+ if (key_created_ == 0)
+ {
+ ACE_thread_mutex_t *lock =
+ reinterpret_cast<ACE_thread_mutex_t *> (
+ ACE_OS_Object_Manager::preallocated_object
+ [ACE_OS_Object_Manager::ACE_LOG_MSG_INSTANCE_LOCK]);
+
+ if (1 == ACE_OS_Object_Manager::starting_up())
+ //This function is called before ACE_OS_Object_Manager is
+ //initialized. So the lock might not be valid. Assume it's
+ //single threaded and so don't need the lock.
+ ;
+ else
+ ACE_OS::thread_mutex_lock (lock);
+
+ if (key_created_ == 0)
+ {
+ // Allocate the Singleton lock.
+ ACE_Log_Msg_Manager::get_lock ();
+
+ {
+ ACE_NO_HEAP_CHECK;
+ if (ACE_Thread::keycreate (log_msg_tss_key (),
+ &ACE_TSS_CLEANUP_NAME) != 0)
+ {
+ if (1 == ACE_OS_Object_Manager::starting_up())
+ //This function is called before ACE_OS_Object_Manager is
+ //initialized. So the lock might not be valid. Assume it's
+ //single threaded and so don't need the lock.
+ ;
+ else
+ ACE_OS::thread_mutex_unlock (lock);
+ return 0; // Major problems, this should *never* happen!
+ }
+ }
+
+ key_created_ = 1;
+ }
+
+ if (1 == ACE_OS_Object_Manager::starting_up())
+ //This function is called before ACE_OS_Object_Manager is
+ //initialized. So the lock might not be valid. Assume it's
+ //single threaded and so don't need the lock.
+ ;
+ else
+ ACE_OS::thread_mutex_unlock (lock);
+ }
+
+ ACE_Log_Msg *tss_log_msg = 0;
+
+ // Get the tss_log_msg from thread-specific storage.
+ if (ACE_Thread::getspecific (*(log_msg_tss_key ()),
+ reinterpret_cast<void **> (&tss_log_msg)) == -1)
+ return 0; // This should not happen!
+
+ // Check to see if this is the first time in for this thread.
+ if (tss_log_msg == 0)
+ {
+ // Allocate memory off the heap and store it in a pointer in
+ // thread-specific storage (on the stack...). Stop heap
+ // checking, the memory will always be freed by the thread
+ // rundown because of the TSS callback set up when the key was
+ // created. This prevents from getting these blocks reported as
+ // memory leaks.
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_NEW_RETURN (tss_log_msg,
+ ACE_Log_Msg,
+ 0);
+ // Store the dynamically allocated pointer in thread-specific
+ // storage. It gets deleted via the ACE_TSS_cleanup function
+ // when the thread terminates.
+
+ if (ACE_Thread::setspecific (*(log_msg_tss_key()),
+ reinterpret_cast<void *> (tss_log_msg))
+ != 0)
+ return 0; // Major problems, this should *never* happen!
+ }
+ }
+
+ return tss_log_msg;
+# else
+# error "Platform must support thread-specific storage if threads are used."
+# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
+#else /* ! ACE_MT_SAFE */
+ // We don't have threads, we cannot call
+ // ACE_Log_Msg_Manager::get_lock () to initialize the logger
+ // callback, so instead we do it here.
+ if (ACE_Log_Msg_Manager::init_backend () == -1)
+ return 0;
+
+ // Singleton implementation.
+ static ACE_Cleanup_Adapter<ACE_Log_Msg> *log_msg = 0;
+ if (log_msg == 0)
+ {
+ ACE_NEW_RETURN (log_msg, ACE_Cleanup_Adapter<ACE_Log_Msg>, 0);
+ // Register the instance for destruction at program termination.
+ ACE_Object_Manager::at_exit (log_msg);
+ }
+
+ return &log_msg->object ();
+#endif /* ! ACE_MT_SAFE */
+}
+
+// Not inlined to help prevent having to include OS.h just to
+// get ACE_DEBUG, et al, macros.
+int
+ACE_Log_Msg::last_error_adapter (void)
+{
+ return ACE_OS::last_error ();
+}
+
+// Sets the flag in the default priority mask used to initialize
+// ACE_Log_Msg instances, as well as the current per-thread instance.
+
+void
+ACE_Log_Msg::enable_debug_messages (ACE_Log_Priority priority)
+{
+ ACE_SET_BITS (ACE_Log_Msg::default_priority_mask_, priority);
+ ACE_Log_Msg *i = ACE_Log_Msg::instance ();
+ i->priority_mask (i->priority_mask () | priority);
+}
+
+// Clears the flag in the default priority mask used to initialize
+// ACE_Log_Msg instances, as well as the current per-thread instance.
+
+void
+ACE_Log_Msg::disable_debug_messages (ACE_Log_Priority priority)
+{
+ ACE_CLR_BITS (ACE_Log_Msg::default_priority_mask_, priority);
+ ACE_Log_Msg *i = ACE_Log_Msg::instance ();
+ i->priority_mask (i->priority_mask () & ~priority);
+}
+
+const ACE_TCHAR *
+ACE_Log_Msg::program_name (void)
+{
+ return ACE_Log_Msg::program_name_;
+}
+
+/// Name of the local host.
+const ACE_TCHAR *ACE_Log_Msg::local_host_ = 0;
+
+/// Records the program name.
+const ACE_TCHAR *ACE_Log_Msg::program_name_ = 0;
+
+/// Default is to use stderr.
+u_long ACE_Log_Msg::flags_ = ACE_Log_Msg::STDERR;
+
+/// Process id of the current process.
+pid_t ACE_Log_Msg::pid_ = -1;
+
+/// Current offset of msg_[].
+long ACE_Log_Msg::msg_off_ = 0;
+
+/// Default per-thread priority mask
+/// By default, no priorities are enabled.
+u_long ACE_Log_Msg::default_priority_mask_ = 0;
+
+/// Default per-process priority mask
+/// By default, all priorities are enabled.
+u_long ACE_Log_Msg::process_priority_mask_ = LM_SHUTDOWN
+ | LM_TRACE
+ | LM_DEBUG
+ | LM_INFO
+ | LM_NOTICE
+ | LM_WARNING
+ | LM_STARTUP
+ | LM_ERROR
+ | LM_CRITICAL
+ | LM_ALERT
+ | LM_EMERGENCY;
+
+void
+ACE_Log_Msg::close (void)
+{
+ // This call needs to go here to avoid memory leaks.
+ ACE_MT (ACE_Log_Msg_Manager::close ());
+
+ // Please note that this will be called by a statement that is
+ // harded coded into the ACE_Object_Manager's shutdown sequence, in
+ // its destructor.
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) && \
+ (defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
+ defined (ACE_HAS_TSS_EMULATION))
+
+ if (key_created_ == 1)
+ {
+ ACE_thread_mutex_t *lock =
+ reinterpret_cast<ACE_thread_mutex_t *> (
+ ACE_OS_Object_Manager::preallocated_object
+ [ACE_OS_Object_Manager::ACE_LOG_MSG_INSTANCE_LOCK]);
+ ACE_OS::thread_mutex_lock (lock);
+
+ if (key_created_ == 1)
+ {
+ // The same as the ACE_TSS_Cleanup's own key doesn't get
+ // detached, the log_msg_tss_key_ won't get detached
+ // until ACE_TSS_Cleanup::free_all_keys_left, so it will
+ // be in the ACE_TSS_Cleanup::table_. However, there's
+ // no resource associated with it, so we don't need to
+ // keyfree it. The dynamic memory associated with it was
+ // already deleted by ACE_TSS_Cleanup::exit (), so we
+ // don't want to access it again.
+ key_created_ = 0;
+#ifdef ACE_HAS_BROKEN_THREAD_KEYFREE
+ // for some systems, e.g. LynxOS, we need to ensure that
+ // any registered thread destructor action for this thread
+ // is disabled. Otherwise in the event of a dynamic library
+ // unload of libACE, by a program not linked with libACE,
+ // ACE_TSS_cleanup will be invoked after libACE has been unloaded.
+
+ ACE_Log_Msg *tss_log_msg = 0;
+
+ // Get the tss_log_msg from thread-specific storage.
+ if ( ACE_Thread::getspecific (*(log_msg_tss_key ()),
+ ACE_reinterpret_cast (void **, &tss_log_msg)) != -1
+ && tss_log_msg)
+ {
+ // we haven't been cleaned up
+ ACE_TSS_cleanup(tss_log_msg);
+
+ if ( ACE_Thread::setspecific( (*log_msg_tss_key()),
+ (void *)NULL ) != 0 )
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("(%P|%t) ACE_Log_Msg::close failed to ACE_Thread::setspecific to NULL\n")));
+ }
+
+ }
+#endif /* ACE_HAS_BROKEN_THREAD_KEYFREE */
+ }
+
+ ACE_OS::thread_mutex_unlock (lock);
+ }
+#endif /* (ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION) && ACE_MT_SAFE */
+}
+
+void
+ACE_Log_Msg::sync_hook (const ACE_TCHAR *prg_name)
+{
+ ACE_LOG_MSG->sync (prg_name);
+}
+
+ACE_OS_Thread_Descriptor *
+ACE_Log_Msg::thr_desc_hook (void)
+{
+ return ACE_LOG_MSG->thr_desc ();
+}
+
+// Call after a fork to resynchronize the PID and PROGRAM_NAME
+// variables.
+void
+ACE_Log_Msg::sync (const ACE_TCHAR *prog_name)
+{
+ ACE_TRACE ("ACE_Log_Msg::sync");
+
+ if (prog_name)
+ {
+ // Must free if already allocated!!!
+ ACE_OS::free ((void *) ACE_Log_Msg::program_name_);
+
+ // Stop heap checking, block will be freed by the destructor when
+ // the last ACE_Log_Msg instance is deleted.
+ // Heap checking state will be restored when the block is left.
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_Log_Msg::program_name_ = ACE_OS::strdup (prog_name);
+ }
+ }
+
+ ACE_Log_Msg::pid_ = ACE_OS::getpid ();
+ ACE_Log_Msg::msg_off_ = 0;
+}
+
+u_long
+ACE_Log_Msg::flags (void)
+{
+ ACE_TRACE ("ACE_Log_Msg::flags");
+ u_long result;
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (), 0));
+
+ result = ACE_Log_Msg::flags_;
+ return result;
+}
+
+void
+ACE_Log_Msg::set_flags (u_long flgs)
+{
+ ACE_TRACE ("ACE_Log_Msg::set_flags");
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock ()));
+
+ ACE_SET_BITS (ACE_Log_Msg::flags_, flgs);
+}
+
+void
+ACE_Log_Msg::clr_flags (u_long flgs)
+{
+ ACE_TRACE ("ACE_Log_Msg::clr_flags");
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock ()));
+
+ ACE_CLR_BITS (ACE_Log_Msg::flags_, flgs);
+}
+
+int
+ACE_Log_Msg::acquire (void)
+{
+ ACE_TRACE ("ACE_Log_Msg::acquire");
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ return ACE_Log_Msg_Manager::get_lock ()->acquire ();
+#else /* ! ACE_MT_SAFE */
+ return 0;
+#endif /* ! ACE_MT_SAFE */
+}
+
+u_long
+ACE_Log_Msg::priority_mask (u_long n_mask, MASK_TYPE mask_type)
+{
+ u_long o_mask;
+
+ if (mask_type == THREAD)
+ {
+ o_mask = this->priority_mask_;
+ this->priority_mask_ = n_mask;
+ }
+ else
+ {
+ o_mask = ACE_Log_Msg::process_priority_mask_;
+ ACE_Log_Msg::process_priority_mask_ = n_mask;
+ }
+
+ return o_mask;
+}
+
+u_long
+ACE_Log_Msg::priority_mask (MASK_TYPE mask_type)
+{
+ return mask_type == THREAD
+ ? this->priority_mask_
+ : ACE_Log_Msg::process_priority_mask_;
+}
+
+int
+ACE_Log_Msg::log_priority_enabled (ACE_Log_Priority log_priority)
+{
+ return ACE_BIT_ENABLED (this->priority_mask_ |
+ ACE_Log_Msg::process_priority_mask_,
+ log_priority);
+}
+
+int
+ACE_Log_Msg::release (void)
+{
+ ACE_TRACE ("ACE_Log_Msg::release");
+
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+ return ACE_Log_Msg_Manager::get_lock ()->release ();
+#else /* ! ACE_MT_SAFE */
+ return 0;
+#endif /* ! ACE_MT_SAFE */
+}
+
+ACE_Log_Msg::ACE_Log_Msg (void)
+ : status_ (0),
+ errnum_ (0),
+ linenum_ (0),
+ msg_ (0),
+ restart_ (1), // Restart by default...
+ ostream_ (0),
+ msg_callback_ (0),
+ trace_depth_ (0),
+ trace_active_ (0),
+ tracing_enabled_ (1), // On by default?
+ delete_ostream_(0),
+ thr_desc_ (0),
+ priority_mask_ (default_priority_mask_),
+ timestamp_ (0)
+{
+ // ACE_TRACE ("ACE_Log_Msg::ACE_Log_Msg");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock ()));
+ ++instance_count_;
+
+ if (this->instance_count_ == 1)
+ ACE_Base_Thread_Adapter::set_log_msg_hooks (ACE_Log_Msg::init_hook,
+ ACE_Log_Msg::inherit_hook,
+ ACE_Log_Msg::close,
+ ACE_Log_Msg::sync_hook,
+ ACE_Log_Msg::thr_desc_hook);
+
+ this->conditional_values_.is_set_ = 0;
+
+ char *timestamp = ACE_OS::getenv ("ACE_LOG_TIMESTAMP");
+ if (timestamp != 0)
+ {
+ // If variable is set or is set to date tag so we print date and time.
+ if (ACE_OS::strcmp (timestamp, "TIME") == 0)
+ {
+ this->timestamp_ = 1;
+ }
+ else if (ACE_OS::strcmp (timestamp, "DATE") == 0)
+ {
+ this->timestamp_ = 2;
+ }
+ }
+
+ ACE_NEW_NORETURN (this->msg_, ACE_TCHAR[ACE_MAXLOGMSGLEN+1]);
+}
+
+ACE_Log_Msg::~ACE_Log_Msg (void)
+{
+#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+
+ int instance_count;
+
+ // Only hold the guard while updating the instance_count_.
+ // If ACE_Log_Msg_Manager::close () is called, the lock will
+ // be deleted.
+ {
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock ()));
+ instance_count = --instance_count_;
+ }
+ // Release the guard.
+
+#else /* ! ACE_MT_SAFE */
+ int instance_count = --instance_count_;
+#endif /* ! ACE_MT_SAFE */
+
+ // If this is the last instance then cleanup. Only the last
+ // thread to destroy its ACE_Log_Msg instance should execute
+ // this block.
+ if (instance_count == 0)
+ {
+ // Destroy the message queue instance.
+ if (ACE_Log_Msg_Manager::log_backend_ != 0)
+ ACE_Log_Msg_Manager::log_backend_->close ();
+
+ // Close down custom backend
+ if (ACE_Log_Msg_Manager::custom_backend_ != 0)
+ ACE_Log_Msg_Manager::custom_backend_->close ();
+
+# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
+# if defined (ACE_HAS_TSS_EMULATION)
+ ACE_Log_Msg_Manager::close ();
+# endif /* ACE_HAS_TSS_EMULATION */
+# endif /* ACE_MT_SAFE */
+
+ if (ACE_Log_Msg::program_name_)
+ {
+ ACE_OS::free ((void *) ACE_Log_Msg::program_name_);
+ ACE_Log_Msg::program_name_ = 0;
+ }
+
+ if (ACE_Log_Msg::local_host_)
+ {
+ ACE_OS::free ((void *) ACE_Log_Msg::local_host_);
+ ACE_Log_Msg::local_host_ = 0;
+ }
+ }
+
+ //
+ // do we need to close and clean up?
+ //
+ if (this->delete_ostream_ == 1)
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ {
+ ACE_OS::fclose (this->ostream_);
+ }
+#else
+ {
+ delete ostream_;
+ ostream_ = 0;
+ }
+#endif
+
+ delete[] this->msg_;
+}
+
+// Open the sender-side of the message queue.
+
+int
+ACE_Log_Msg::open (const ACE_TCHAR *prog_name,
+ u_long flags,
+ const ACE_TCHAR *logger_key)
+{
+ ACE_TRACE ("ACE_Log_Msg::open");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (), -1));
+
+ if (prog_name)
+ {
+ ACE_OS::free ((void *) ACE_Log_Msg::program_name_);
+
+ // Stop heap checking, block will be freed by the destructor.
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_ALLOCATOR_RETURN (ACE_Log_Msg::program_name_,
+ ACE_OS::strdup (prog_name),
+ -1);
+ }
+ }
+ else if (ACE_Log_Msg::program_name_ == 0)
+ {
+ // Stop heap checking, block will be freed by the destructor.
+ ACE_NO_HEAP_CHECK;
+ ACE_ALLOCATOR_RETURN (ACE_Log_Msg::program_name_,
+ ACE_OS::strdup (ACE_LIB_TEXT ("<unknown>")),
+ -1);
+ }
+
+ int status = 0;
+
+ // Be sure that there is a message_queue_, with multiple threads.
+ ACE_MT (ACE_Log_Msg_Manager::init_backend (&flags));
+
+ // Always close the current handle before doing anything else.
+ if (ACE_Log_Msg_Manager::log_backend_ != 0)
+ ACE_Log_Msg_Manager::log_backend_->reset ();
+
+ if (ACE_Log_Msg_Manager::custom_backend_ != 0)
+ ACE_Log_Msg_Manager::custom_backend_->reset ();
+
+ // Note that if we fail to open the message queue the default action
+ // is to use stderr (set via static initialization in the
+ // Log_Msg.cpp file).
+
+ if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER)
+ || ACE_BIT_ENABLED (flags, ACE_Log_Msg::SYSLOG))
+ {
+ // The SYSLOG backends (both NT and UNIX) can get along fine
+ // without the logger_key - they will default to prog_name if
+ // logger key is 0.
+ if (logger_key == 0 && ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER))
+ status = -1;
+ else
+ status = ACE_Log_Msg_Manager::log_backend_->open (logger_key);
+
+ if (status == -1)
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR);
+ else
+ {
+ if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::LOGGER))
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER);
+ if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::SYSLOG))
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG);
+ }
+ }
+ else if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER)
+ || ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG))
+ {
+ // If we are closing down logger, redirect logging to stderr.
+ ACE_CLR_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER);
+ ACE_CLR_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG);
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::STDERR);
+ }
+
+ if (ACE_BIT_ENABLED (flags, ACE_Log_Msg::CUSTOM))
+ {
+ status =
+ ACE_Log_Msg_Manager::custom_backend_->open (logger_key);
+
+ if (status != -1)
+ ACE_SET_BITS (ACE_Log_Msg::flags_, ACE_Log_Msg::CUSTOM);
+ }
+
+ // Remember, ACE_Log_Msg::STDERR bit is on by default...
+ if (status != -1
+ && ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::STDERR) == 0)
+ ACE_CLR_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::STDERR);
+
+ // VERBOSE takes precedence over VERBOSE_LITE...
+ if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::VERBOSE_LITE))
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::VERBOSE_LITE);
+ else if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::VERBOSE))
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::VERBOSE);
+
+ if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::OSTREAM))
+ {
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::OSTREAM);
+ // Only set this to cerr if it hasn't already been set.
+ if (this->msg_ostream () == 0)
+ this->msg_ostream (ACE_DEFAULT_LOG_STREAM);
+ }
+
+ if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::MSG_CALLBACK))
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::MSG_CALLBACK);
+
+ if (ACE_BIT_ENABLED (flags,
+ ACE_Log_Msg::SILENT))
+ ACE_SET_BITS (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT);
+
+ return status;
+}
+
+/**
+ * Valid Options (prefixed by '%', as in printf format strings) include:
+ * 'A': print an ACE_timer_t value
+ * 'a': exit the program at this point (var-argument is the exit status!)
+ * 'c': print a character
+ * 'C': print a character string
+ * 'i', 'd': print a decimal number
+ * 'I', indent according to nesting depth
+ * 'e', 'E', 'f', 'F', 'g', 'G': print a double
+ * 'l', print line number where an error occurred.
+ * 'M': print the name of the priority of the message.
+ * 'm': Return the message corresponding to errno value, e.g., as done by <strerror>
+ * 'N': print file name where the error occurred.
+ * 'n': print the name of the program (or "<unknown>" if not set)
+ * 'o': print as an octal number
+ * 'P': format the current process id
+ * 'p': format the appropriate errno message from sys_errlist, e.g., as done by <perror>
+ * 'Q': print out the uint64 number
+ * 'q': print out the int64 number
+ * '@': print a void* pointer (in hexadecimal)
+ * 'r': call the function pointed to by the corresponding argument
+ * 'R': print return status
+ * 'S': format the appropriate _sys_siglist entry corresponding to var-argument.
+ * 's': format a character string
+ * 'T': print timestamp in hour:minute:sec:usec format.
+ * 'D': print timestamp in month/day/year hour:minute:sec:usec format.
+ * 't': print thread id (1 if single-threaded)
+ * 'u': print as unsigned int
+ * 'x': print as a hex number
+ * 'X': print as a hex number
+ * 'w': print a wide character
+ * 'W': print out a wide character string.
+ * 'z': print an ACE_OS::WChar character
+ * 'Z': print an ACE_OS::WChar character string
+ * '%': format a single percent sign, '%'
+ */
+ssize_t
+ACE_Log_Msg::log (ACE_Log_Priority log_priority,
+ const ACE_TCHAR *format_str, ...)
+{
+ ACE_TRACE ("ACE_Log_Msg::log");
+
+ // Start of variable args section.
+ va_list argp;
+
+ va_start (argp, format_str);
+
+ ssize_t result = this->log (format_str,
+ log_priority,
+ argp);
+ va_end (argp);
+
+ return result;
+}
+
+#if defined (ACE_HAS_WCHAR)
+/**
+ * Since this is the ANTI_TCHAR version, we need to convert
+ * the format string over.
+ */
+ssize_t
+ACE_Log_Msg::log (ACE_Log_Priority log_priority,
+ const ACE_ANTI_TCHAR *format_str, ...)
+{
+ ACE_TRACE ("ACE_Log_Msg::log");
+
+ // Start of variable args section.
+ va_list argp;
+
+ va_start (argp, format_str);
+
+ ssize_t result = this->log (ACE_TEXT_ANTI_TO_TCHAR (format_str),
+ log_priority,
+ argp);
+ va_end (argp);
+
+ return result;
+}
+#endif /* ACE_HAS_WCHAR */
+
+ssize_t
+ACE_Log_Msg::log (const ACE_TCHAR *format_str,
+ ACE_Log_Priority log_priority,
+ va_list argp)
+{
+ ACE_TRACE ("ACE_Log_Msg::log");
+ // External decls.
+
+ typedef void (*PTF)(...);
+
+ // Check if there were any conditional values set.
+ int conditional_values = this->conditional_values_.is_set_;
+
+ // Reset conditional values.
+ this->conditional_values_.is_set_ = 0;
+
+ // Only print the message if <priority_mask_> hasn't been reset to
+ // exclude this logging priority.
+ if (this->log_priority_enabled (log_priority) == 0)
+ return 0;
+
+ // If conditional values were set and the log priority is correct,
+ // then the values are actually set.
+ if (conditional_values)
+ this->set (this->conditional_values_.file_,
+ this->conditional_values_.line_,
+ this->conditional_values_.op_status_,
+ this->conditional_values_.errnum_,
+ this->restart (),
+ this->msg_ostream (),
+ this->msg_callback ());
+
+ // Logging is supposed to be a benign activity (i.e., not interfer
+ // with normal application operations), so don't inadvertently smash
+ // errno!
+ ACE_Errno_Guard guard (errno);
+
+ ACE_Log_Record log_record (log_priority,
+ ACE_OS::gettimeofday (),
+ this->getpid ());
+ // bp is pointer to where to put next part of logged message.
+ // bspace is the number of characters remaining in msg_.
+ ACE_TCHAR *bp = const_cast<ACE_TCHAR *> (this->msg ());
+ size_t bspace = ACE_Log_Record::MAXLOGMSGLEN; // Leave room for Nul term.
+ if (this->msg_off_ <= ACE_Log_Record::MAXLOGMSGLEN)
+ bspace -= static_cast<size_t> (this->msg_off_);
+
+ // If this platform has snprintf() capability to prevent overrunning the
+ // output buffer, use it. To avoid adding a maintenance-hassle compile-
+ // time couple between here and OS.cpp, don't try to figure this out at
+ // compile time. Instead, do a quick check now; if we get a -1 return,
+ // the platform doesn't support the length-limiting capability.
+ ACE_TCHAR test[2];
+ int can_check = ACE_OS::snprintf (test, 1, ACE_LIB_TEXT ("x")) != -1;
+
+ int abort_prog = 0;
+ int exit_value = 0;
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::VERBOSE))
+ {
+ // Prepend the program name onto this message
+
+ if (ACE_Log_Msg::program_name_ != 0)
+ {
+ for (const ACE_TCHAR *s = ACE_Log_Msg::program_name_;
+ bspace > 1 && (*bp = *s) != '\0';
+ ++s, --bspace)
+ bp++;
+
+ *bp++ = '|';
+ --bspace;
+ }
+ }
+
+ if (timestamp_ > 0)
+ {
+ ACE_TCHAR day_and_time[35];
+ const ACE_TCHAR *s;
+ if (timestamp_ == 1)
+ {
+ // Print just the time
+ s = ACE::timestamp (day_and_time, sizeof day_and_time, 1);
+ }
+ else
+ {
+ // Print time and date
+ ACE::timestamp (day_and_time, sizeof day_and_time);
+ s = day_and_time;
+ }
+
+ for (; bspace > 1 && (*bp = *s) != '\0'; ++s, --bspace)
+ ++bp;
+
+ *bp++ = '|';
+ --bspace;
+ }
+
+ while (*format_str != '\0' && bspace > 0)
+ {
+ // Copy input to output until we encounter a %, however a
+ // % followed by another % is not a format specification.
+
+ if (*format_str != '%')
+ {
+ *bp++ = *format_str++;
+ --bspace;
+ }
+ else if (format_str[1] == '%') // An "escaped" '%' (just print one '%').
+ {
+ *bp++ = *format_str++; // Store first %
+ ++format_str; // but skip second %
+ --bspace;
+ }
+ else
+ {
+ // This is most likely a format specification that ends with
+ // one of the valid options described previously. To enable full
+ // use of all sprintf capabilities, save the format specifier
+ // from the '%' up to the format letter in a new char array.
+ // This allows the full sprintf capability for padding, field
+ // widths, alignment, etc. Any width/precision requiring a
+ // caller-supplied argument is extracted and placed as text
+ // into the format array. Lastly, we convert the caller-supplied
+ // format specifier from the ACE_Log_Msg-supported list to the
+ // equivalent sprintf specifier, and run the new format spec
+ // through sprintf, adding it to the bp string.
+
+ const ACE_TCHAR *abort_str = ACE_LIB_TEXT ("Aborting...");
+ const ACE_TCHAR *start_format = format_str;
+ ACE_TCHAR format[128]; // Converted format string
+ ACE_TCHAR *fp; // Current format pointer
+ int wp = 0; // Width/precision extracted from args
+ int done = 0;
+ int skip_nul_locate = 0;
+ int this_len = 0; // How many chars s[n]printf wrote
+
+ fp = format;
+ *fp++ = *format_str++; // Copy in the %
+
+ // Initialization to satisfy VC6
+ int tmp_indent = 0;
+ // Work through the format string to copy in the format
+ // from the caller. While it's going across, extract ints
+ // for '*' width/precision values from the argument list.
+ // When the real format specifier is located, change it to
+ // one recognized by sprintf, if needed, and do the sprintf
+ // call.
+
+ while (!done)
+ {
+ done = 1; // Unless a conversion spec changes it
+
+ switch (*format_str)
+ {
+ // The initial set of cases are the conversion
+ // specifiers. Copy them in to the format array.
+ // Note we don't use 'l', a normal conversion spec,
+ // as a conversion because it is a ACE_Log_Msg format
+ // specifier.
+ case '-':
+ case '+':
+ case '0':
+ case ' ':
+ case '#':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '.':
+ case 'L':
+ case 'h':
+ *fp++ = *format_str;
+ done = 0;
+ break;
+
+ case '*':
+ wp = va_arg (argp, int);
+ ACE_OS::sprintf (fp, ACE_LIB_TEXT ("%d"), wp);
+ fp += ACE_OS::strlen (fp);
+ done = 0;
+ break;
+
+ case 'A': // ACE_timer_t
+ {
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("f"));
+ double value = va_arg (argp, double);
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format, value);
+ else
+ this_len = ACE_OS::sprintf (bp, format, value);
+ ACE_UPDATE_COUNT (bspace, this_len);
+ }
+ break;
+
+ case 'a': // Abort program after handling all of format string.
+ abort_prog = 1;
+ exit_value = va_arg (argp, int);
+ ACE_OS::strsncpy (bp, abort_str, bspace);
+ if (bspace > ACE_OS::strlen (abort_str))
+ bspace -= ACE_OS::strlen (abort_str);
+ else
+ bspace = 0;
+ break;
+
+ case 'l': // Source file line number
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("d"));
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp,
+ bspace,
+ format,
+ this->linenum ());
+ else
+ this_len = ACE_OS::sprintf (bp, format, this->linenum ());
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'N': // Source file name
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+#else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format,
+ this->file () ?
+ ACE_TEXT_CHAR_TO_TCHAR (this->file ())
+ : ACE_LIB_TEXT ("<unknown file>"));
+ else
+ this_len = ACE_OS::sprintf (bp, format,
+ this->file () ?
+ ACE_TEXT_CHAR_TO_TCHAR (this->file ())
+ : ACE_LIB_TEXT ("<unknown file>"));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'n': // Program name
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format,
+ ACE_Log_Msg::program_name_ ?
+ ACE_Log_Msg::program_name_ :
+ ACE_LIB_TEXT ("<unknown>"));
+ else
+ this_len = ACE_OS::sprintf (bp, format,
+ ACE_Log_Msg::program_name_ ?
+ ACE_Log_Msg::program_name_ :
+ ACE_LIB_TEXT ("<unknown>"));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'P': // Process ID
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("d"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ static_cast<int> (this->getpid ()));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, static_cast<int> (this->getpid ()));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'p': // <errno> string, ala perror()
+ {
+ errno = 0;
+ char *msg;
+ msg = ACE_OS::strerror (ACE::map_errno (this->errnum ()));
+ // Windows can try to translate the errnum using
+ // system calls if strerror() doesn't get anything useful.
+#if defined (ACE_WIN32)
+ if (errno == 0)
+ {
+#endif
+
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls: %ls"));
+#else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s: %s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, ACE_TCHAR *),
+ ACE_TEXT_CHAR_TO_TCHAR (msg));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, ACE_TCHAR *),
+ ACE_TEXT_CHAR_TO_TCHAR (msg));
+#if defined (ACE_WIN32)
+ }
+ else
+ {
+ errno = ACE::map_errno (this->errnum ());
+ ACE_TCHAR *lpMsgBuf = 0;
+
+ // PharLap can't do FormatMessage, so try for socket
+ // error.
+# if !defined (ACE_HAS_PHARLAP)
+ ACE_TEXT_FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_MAX_WIDTH_MASK
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ errno,
+ MAKELANGID (LANG_NEUTRAL,
+ SUBLANG_DEFAULT),
+ // Default language
+ (ACE_TCHAR *) &lpMsgBuf,
+ 0,
+ 0);
+# endif /* ACE_HAS_PHARLAP */
+
+ // If we don't get a valid response from
+ // <FormatMessage>, we'll assume this is a
+ // WinSock error and so we'll try to convert
+ // it into a string. If this doesn't work it
+ // returns "unknown error" which is fine for
+ // our purposes.
+ if (lpMsgBuf == 0)
+ {
+ const ACE_TCHAR *message =
+ ACE::sock_error (errno);
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s: %s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ va_arg (argp, const ACE_TCHAR *),
+ message);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format,
+ va_arg (argp, const ACE_TCHAR *),
+ message);
+ }
+ else
+ {
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s: %s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ va_arg (argp, ACE_TCHAR *),
+ lpMsgBuf);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format,
+ va_arg (argp, ACE_TCHAR *),
+ lpMsgBuf);
+ // Free the buffer.
+ ::LocalFree (lpMsgBuf);
+ }
+ }
+#endif /* ACE_WIN32 */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'M': // Print the name of the priority of the message.
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+#else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ ACE_Log_Record::priority_name (log_priority));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format,
+ ACE_Log_Record::priority_name (log_priority));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'm': // Format the string assocated with the errno value.
+ {
+ errno = 0;
+ char *msg;
+ msg = ACE_OS::strerror (ACE::map_errno (this->errnum ()));
+ // Windows can try to translate the errnum using
+ // system calls if strerror() doesn't get anything useful.
+#if defined (ACE_WIN32)
+ if (errno == 0)
+ {
+#endif
+
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, ACE_TEXT_CHAR_TO_TCHAR (msg));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, ACE_TEXT_CHAR_TO_TCHAR (msg));
+#if defined (ACE_WIN32)
+ }
+ else
+ {
+ errno = ACE::map_errno (this->errnum ());
+ ACE_TCHAR *lpMsgBuf = 0;
+
+ // PharLap can't do FormatMessage, so try for socket
+ // error.
+# if !defined (ACE_HAS_PHARLAP)
+ ACE_TEXT_FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_MAX_WIDTH_MASK
+ | FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ errno,
+ MAKELANGID (LANG_NEUTRAL,
+ SUBLANG_DEFAULT),
+ // Default language
+ (ACE_TCHAR *) &lpMsgBuf,
+ 0,
+ 0);
+# endif /* ACE_HAS_PHARLAP */
+
+ // If we don't get a valid response from
+ // <FormatMessage>, we'll assume this is a
+ // WinSock error and so we'll try to convert
+ // it into a string. If this doesn't work it
+ // returns "unknown error" which is fine for
+ // our purposes.
+ if (lpMsgBuf == 0)
+ {
+ const ACE_TCHAR *message =
+ ACE::sock_error (errno);
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, message);
+ else
+ this_len = ACE_OS::sprintf (bp, format, message);
+ }
+ else
+ {
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, lpMsgBuf);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, lpMsgBuf);
+ // Free the buffer.
+ ::LocalFree (lpMsgBuf);
+ }
+ }
+#endif /* ACE_WIN32 */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'R': // Format the return status of the operation.
+ this->op_status (va_arg (argp, int));
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("d"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, this->op_status ());
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, this->op_status ());
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case '{': // Increment the trace_depth, then indent
+ skip_nul_locate = 1;
+ (void) this->inc ();
+ break;
+
+ case '}': // indent, then decrement trace_depth
+ skip_nul_locate = 1;
+ (void) this->dec ();
+ break;
+
+ case '$': // insert a newline, then indent the next line
+ // according to %I
+ *bp++ = '\n';
+ --bspace;
+ /* fallthrough */
+
+ case 'I': // Indent with nesting_depth*width spaces
+ // Caller can do %*I to override nesting indent, and
+ // if %*I was done, wp has the extracted width.
+#if defined (ACE_HAS_TRACE)
+ if (0 == wp)
+ wp = ACE_Trace::get_nesting_indent ();
+#else
+ if (0 == wp)
+ wp = 4;
+#endif /* ACE_HAS_TRACE */
+ wp *= this->trace_depth_;
+ if (static_cast<size_t> (wp) > bspace)
+ wp = static_cast<int> (bspace);
+ for (tmp_indent = wp;
+ tmp_indent;
+ --tmp_indent)
+ *bp++ = ' ';
+
+ *bp = '\0';
+ bspace -= static_cast<size_t> (wp);
+ skip_nul_locate = 1;
+ break;
+
+ case 'r': // Run (invoke) this subroutine.
+ {
+ long osave = ACE_Log_Msg::msg_off_;
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT) &&
+ bspace > 1)
+ {
+ *bp++ = '{';
+ --bspace;
+ }
+ ACE_Log_Msg::msg_off_ = bp - this->msg_;
+
+ (*va_arg (argp, PTF))();
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT) &&
+ bspace > (1 + ACE_OS::strlen (bp)))
+ {
+ bspace -= (ACE_OS::strlen (bp) + 1);
+ bp += ACE_OS::strlen (bp);
+ *bp++ = '}';
+ }
+ *bp = '\0';
+ skip_nul_locate = 1;
+ ACE_Log_Msg::msg_off_ = osave;
+ break;
+ }
+
+ case 'S': // format the string for with this signal number.
+ {
+ int sig = va_arg (argp, int);
+#if defined (ACE_HAS_SYS_SIGLIST)
+ if (sig >= 0 && sig < ACE_NSIG)
+ {
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, _sys_siglist[sig]);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, _sys_siglist[sig]);
+ }
+ else
+ {
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace,
+ ACE_LIB_TEXT("<unknown signal> %d"), sig);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, ACE_LIB_TEXT ("<unknown signal> %d"), sig);
+ }
+#else
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, ACE_LIB_TEXT ("signal %d"), sig);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, ACE_LIB_TEXT ("signal %d"), sig);
+#endif /* ACE_HAS_SYS_SIGLIST */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'D': // Format the timestamp in month/day/year
+ // hour:minute:sec:usec format.
+ {
+ ACE_TCHAR day_and_time[35];
+ ACE::timestamp (day_and_time,
+ sizeof day_and_time);
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+#else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+#endif
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, day_and_time);
+ else
+ this_len = ACE_OS::sprintf (bp, format, day_and_time);
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'T': // Format the timestamp in
+ // hour:minute:sec:usec format.
+ {
+ ACE_TCHAR day_and_time[35];
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ ACE::timestamp (day_and_time, sizeof day_and_time));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, ACE::timestamp (day_and_time,
+ sizeof day_and_time));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 't': // Format thread id.
+#if defined (ACE_WIN32)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format,
+ static_cast<unsigned> (ACE_Thread::self ()));
+ else
+ this_len =
+ ACE_OS::sprintf (bp,
+ format,
+ static_cast <unsigned> (ACE_Thread::self ()));
+#elif defined (ACE_AIX_VERS) && (ACE_AIX_VERS <= 402)
+ // AIX's pthread_t (ACE_hthread_t) is a pointer, and it's
+ // a little ugly to send that through a %u format. So,
+ // get the kernel thread ID (tid_t) via thread_self() and
+ // display that instead.
+ // This isn't conditionalized on ACE_HAS_THREAD_SELF because
+ // 1. AIX 4.2 doesn't have that def anymore (it messes up
+ // other things)
+ // 2. OSF/1 V3.2 has that def, and I'm not sure what affect
+ // this would have on that.
+ // -Steve Huston, 19-Aug-97
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, thread_self());
+ else
+ this_len = ACE_OS::sprintf (bp, format, thread_self());
+#elif defined (DIGITAL_UNIX)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ {
+ int id =
+# if defined (ACE_HAS_THREADS)
+ pthread_getselfseq_np ();
+# else
+ ACE_Thread::self ();
+# endif /* ACE_HAS_THREADS */
+
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format, id);
+ else
+ this_len = ACE_OS::sprintf (bp, format, id);
+ }
+#else
+ ACE_hthread_t t_id;
+ ACE_Thread::self (t_id);
+
+# if defined (ACE_MVS) || defined (ACE_TANDEM_T1248_PTHREADS)
+ // MVS's pthread_t is a struct... yuck. So use the ACE 5.0
+ // code for it.
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format, t_id);
+ else
+ this_len = ACE_OS::sprintf (bp, format, t_id);
+# else
+ // Yes, this is an ugly C-style cast, but the correct
+ // C++ cast is different depending on whether the t_id
+ // is an integral type or a pointer type. FreeBSD uses
+ // a pointer type, but doesn't have a _np function to
+ // get an integral type, like the OSes above.
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("lu"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, (unsigned long)t_id);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, (unsigned long)t_id);
+# endif /* ACE_MWS || ACE_TANDEM_T1248_PTHREADS */
+
+#endif /* ACE_WIN32 */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 's': // String
+ {
+#if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ wchar_t *str = va_arg (argp, wchar_t *);
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_TCHAR *str = va_arg (argp, ACE_TCHAR *);
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, str ? str : ACE_LIB_TEXT ("(null)"));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, str ? str : ACE_LIB_TEXT ("(null)"));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ }
+ break;
+
+ case 'C': // Char string, Unicode for Win32/WCHAR
+ {
+ ACE_TCHAR *cstr = va_arg (argp, ACE_TCHAR *);
+#if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("S"));
+#else /* ACE_WIN32 && ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, cstr ? cstr : ACE_LIB_TEXT ("(null)"));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, cstr ? cstr : ACE_LIB_TEXT ("(null)"));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ }
+ break;
+
+ case 'W':
+ {
+#if defined (ACE_WIN32)
+ ACE_TCHAR *wstr = va_arg (argp, ACE_TCHAR *);
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("S"));
+# endif /* ACE_USES_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, wstr ? wstr : ACE_LIB_TEXT ("(null)"));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, wstr ? wstr : ACE_LIB_TEXT ("(null)"));
+#elif defined (ACE_HAS_WCHAR)
+ wchar_t *wchar_str = va_arg (argp, wchar_t *);
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("S"));
+# else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+# endif /* HPUX */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, wchar_str);
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, wchar_str);
+#endif /* ACE_WIN32 / ACE_HAS_WCHAR */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ }
+ break;
+
+ case 'w': // Wide character
+#if defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("c"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("C"));
+# endif /* ACE_USES_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, int));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, int));
+#elif defined (ACE_USES_WCHAR)
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("C"));
+# else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("lc"));
+# endif /* HPUX */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, wint_t));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, wint_t));
+#else /* ACE_WIN32 */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, int));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, int));
+#endif /* ACE_WIN32 */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'z': // ACE_OS::WChar character
+ {
+ // On some platforms sizeof (wchar_t) can be 2
+ // on the others 4 ...
+ wchar_t wtchar =
+ static_cast<wchar_t> (va_arg (argp, int));
+#if defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("c"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("C"));
+# endif /* ACE_USES_WCHAR */
+#elif defined (ACE_USES_WCHAR)
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("C"));
+# else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("lc"));
+# endif /* HPUX */
+#else /* ACE_WIN32 */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("u"));
+#endif /* ACE_WIN32 */
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace, format, wtchar);
+ else
+ this_len = ACE_OS::sprintf (bp, format, wtchar);
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'Z': // ACE_OS::WChar character string
+ {
+ ACE_OS::WChar *wchar_str = va_arg (argp, ACE_OS::WChar*);
+ if (wchar_str == 0)
+ break;
+
+ wchar_t *wchar_t_str = 0;
+ if (sizeof (ACE_OS::WChar) != sizeof (wchar_t))
+ {
+ size_t len = ACE_OS::wslen (wchar_str) + 1;
+ ACE_NEW_NORETURN(wchar_t_str, wchar_t[len]);
+ if (wchar_t_str == 0)
+ break;
+
+ for (size_t i = 0; i < len; ++i)
+ {
+ wchar_t_str[i] = wchar_str[i];
+ }
+ }
+
+ if (wchar_t_str == 0)
+ {
+ wchar_t_str = reinterpret_cast<wchar_t*> (wchar_str);
+ }
+#if defined (ACE_WIN32)
+# if defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("s"));
+# else /* ACE_USES_WCHAR */
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("S"));
+# endif /* ACE_USES_WCHAR */
+#elif defined (ACE_HAS_WCHAR)
+# if defined (HPUX)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("S"));
+# else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("ls"));
+# endif /* HPUX */
+#endif /* ACE_WIN32 / ACE_HAS_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, wchar_t_str);
+ else
+ this_len = ACE_OS::sprintf (bp, format, wchar_t_str);
+ if(sizeof(ACE_OS::WChar) != sizeof(wchar_t))
+ {
+ delete wchar_t_str;
+ }
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+ }
+
+ case 'c':
+#if defined (ACE_WIN32) && defined (ACE_USES_WCHAR)
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("C"));
+#else
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("c"));
+#endif /* ACE_WIN32 && ACE_USES_WCHAR */
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, int));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, int));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'd': case 'i': case 'o':
+ case 'u': case 'x': case 'X':
+ fp[0] = *format_str;
+ fp[1] = '\0';
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, int));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, int));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'F': case 'f': case 'e': case 'E':
+ case 'g': case 'G':
+ fp[0] = *format_str;
+ fp[1] = '\0';
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, double));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, double));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'Q':
+#if defined (ACE_LACKS_LONGLONG_T) || defined (ACE_LACKS_UNSIGNEDLONGLONG_T)
+ {
+ // This relies on the ACE_U_LongLong storage layout.
+ ACE_UINT32 hi = va_arg (argp, ACE_UINT32);
+ ACE_UINT32 lo = va_arg (argp, ACE_UINT32);
+ if (hi > 0)
+ this_len = ACE_OS::sprintf (bp,
+ "0x%lx%0*lx",
+ hi,
+ 2 * sizeof lo,
+ lo);
+ else
+ this_len = ACE_OS::sprintf (bp, "0x%lx", lo);
+ }
+#else /* ! ACE_LACKS_LONGLONG_T */
+ {
+ const ACE_TCHAR *fmt = ACE_UINT64_FORMAT_SPECIFIER;
+ ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace,
+ format,
+ va_arg (argp, ACE_UINT64));
+ else
+ this_len = ACE_OS::sprintf (bp,
+ format,
+ va_arg (argp, ACE_UINT64));
+ }
+#endif /* ! ACE_LACKS_LONGLONG_T || ACE_LACKS_UNSIGNEDLONGLONG_T */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case 'q':
+ #if defined (ACE_LACKS_LONGLONG_T)
+ // No implementation available yet, no ACE_INT64 emulation
+ // available yet
+ #else /* ! ACE_LACKS_LONGLONG_T */
+ {
+ const ACE_TCHAR *fmt = ACE_INT64_FORMAT_SPECIFIER;
+ ACE_OS::strcpy (fp, &fmt[1]); // Skip leading %
+ if (can_check)
+ this_len = ACE_OS::snprintf (bp, bspace,
+ format,
+ va_arg (argp, ACE_INT64));
+ else
+ this_len = ACE_OS::sprintf (bp,
+ format,
+ va_arg (argp, ACE_INT64));
+ }
+ #endif /* ! ACE_LACKS_LONGLONG_T */
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ case '@':
+ ACE_OS::strcpy (fp, ACE_LIB_TEXT ("p"));
+ if (can_check)
+ this_len = ACE_OS::snprintf
+ (bp, bspace, format, va_arg (argp, void*));
+ else
+ this_len = ACE_OS::sprintf
+ (bp, format, va_arg (argp, void*));
+ ACE_UPDATE_COUNT (bspace, this_len);
+ break;
+
+ default:
+ // So, it's not a legit format specifier after all...
+ // Copy from the original % to where we are now, then
+ // continue with whatever comes next.
+ while (start_format != format_str && bspace > 0)
+ {
+ *bp++ = *start_format++;
+ --bspace;
+ }
+ if (bspace > 0)
+ {
+ *bp++ = *format_str;
+ --bspace;
+ }
+ break;
+ }
+
+ // Bump to the next char in the caller's format_str
+ ++format_str;
+ }
+
+ if (!skip_nul_locate)
+ while (*bp != '\0') // Locate end of bp.
+ ++bp;
+ }
+ }
+
+ *bp = '\0'; // Terminate bp, but don't auto-increment this!
+
+ ssize_t result = 0;
+
+ // Check that memory was not corrupted, if it corrupted we can't log anything
+ // anymore because all our members could be corrupted.
+ if (bp >= (this->msg_ + ACE_MAXLOGMSGLEN+1))
+ {
+ abort_prog = 1;
+ ACE_OS::fprintf (stderr,
+ "The following logged message is too long!\n");
+ }
+ else
+ {
+ // Copy the message from thread-specific storage into the transfer
+ // buffer (this can be optimized away by changing other code...).
+ log_record.msg_data (this->msg ());
+
+ // Write the <log_record> to the appropriate location.
+ result = this->log (log_record,
+ abort_prog);
+ }
+
+ if (abort_prog)
+ {
+ // Since we are now calling abort instead of exit, this value is
+ // not used.
+ ACE_UNUSED_ARG (exit_value);
+
+ // *Always* print a message to stderr if we're aborting. We
+ // don't use verbose, however, to avoid recursive aborts if
+ // something is hosed.
+ log_record.print (ACE_Log_Msg::local_host_, 0, stderr);
+ ACE_OS::abort ();
+ }
+
+ return result;
+}
+
+#if !defined (ACE_WIN32)
+/**
+ * @class ACE_Log_Msg_Sig_Guard
+ *
+ * @brief For use only by ACE_Log_Msg.
+ *
+ * Doesn't require the use of global variables or global
+ * functions in an application).
+ */
+class ACE_Log_Msg_Sig_Guard
+{
+private:
+ ACE_Log_Msg_Sig_Guard (void);
+ ~ACE_Log_Msg_Sig_Guard (void);
+
+ /// Original signal mask.
+ sigset_t omask_;
+
+ friend ssize_t ACE_Log_Msg::log (ACE_Log_Record &log_record,
+ int suppress_stderr);
+};
+
+ACE_Log_Msg_Sig_Guard::ACE_Log_Msg_Sig_Guard (void)
+{
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+ ACE_OS::sigemptyset (&this->omask_);
+
+# if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
+ ACE_OS::sigprocmask (SIG_BLOCK,
+ ACE_OS_Object_Manager::default_mask (),
+ &this->omask_);
+# else
+ ACE_OS::thr_sigsetmask (SIG_BLOCK,
+ ACE_OS_Object_Manager::default_mask (),
+ &this->omask_);
+# endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
+#endif /* ACE_LACKS_UNIX_SIGNALS */
+}
+
+ACE_Log_Msg_Sig_Guard::~ACE_Log_Msg_Sig_Guard (void)
+{
+#if !defined (ACE_LACKS_UNIX_SIGNALS)
+# if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
+ ACE_OS::sigprocmask (SIG_SETMASK,
+ &this->omask_,
+ 0);
+# else
+ ACE_OS::thr_sigsetmask (SIG_SETMASK,
+ &this->omask_,
+ 0);
+# endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
+#endif /* ! ACE_LACKS_UNIX_SIGNALS */
+}
+#endif /* ! ACE_WIN32 */
+
+ssize_t
+ACE_Log_Msg::log (ACE_Log_Record &log_record,
+ int suppress_stderr)
+{
+ ssize_t result = 0;
+
+ // Format the message and print it to stderr and/or ship it off to
+ // the log_client daemon, and/or print it to the ostream. Of
+ // course, only print the message if "SILENT" mode is disabled.
+ if (ACE_BIT_DISABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::SILENT))
+ {
+ int tracing = this->tracing_enabled ();
+ this->stop_tracing ();
+
+#if !defined (ACE_WIN32)
+ // Make this block signal-safe.
+ ACE_Log_Msg_Sig_Guard sb;
+#endif /* !ACE_WIN32 */
+
+ // Do the callback, if needed, before acquiring the lock
+ // to avoid holding the lock during the callback so we don't
+ // have deadlock if the callback uses the logger.
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::MSG_CALLBACK)
+ && this->msg_callback () != 0)
+ this->msg_callback ()->log (log_record);
+
+ // Make sure that the lock is held during all this.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (),
+ -1));
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::STDERR)
+ && !suppress_stderr) // This is taken care of by our caller.
+ log_record.print (ACE_Log_Msg::local_host_,
+ ACE_Log_Msg::flags_,
+ stderr);
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::CUSTOM) ||
+ ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG) ||
+ ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER))
+ {
+ // Be sure that there is a message_queue_, with multiple threads.
+ ACE_MT (ACE_Log_Msg_Manager::init_backend ());
+ }
+
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::LOGGER) ||
+ ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::SYSLOG))
+ {
+ result =
+ ACE_Log_Msg_Manager::log_backend_->log (log_record);
+ }
+
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_, ACE_Log_Msg::CUSTOM) &&
+ ACE_Log_Msg_Manager::custom_backend_ != 0)
+ {
+ result =
+ ACE_Log_Msg_Manager::custom_backend_->log (log_record);
+ }
+
+
+ // This must come last, after the other two print operations
+ // (see the <ACE_Log_Record::print> method for details).
+ if (ACE_BIT_ENABLED (ACE_Log_Msg::flags_,
+ ACE_Log_Msg::OSTREAM)
+ && this->msg_ostream () != 0)
+ log_record.print (ACE_Log_Msg::local_host_,
+ ACE_Log_Msg::flags_,
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ static_cast<FILE *> (this->msg_ostream ())
+#else /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+ *this->msg_ostream ()
+#endif /* ! ACE_LACKS_IOSTREAM_TOTALLY */
+ );
+
+ if (tracing)
+ this->start_tracing ();
+ }
+
+ return result;
+}
+
+// Calls log to do the actual print, but formats first.
+
+int
+ACE_Log_Msg::log_hexdump (ACE_Log_Priority log_priority,
+ const char *buffer,
+ size_t size,
+ const ACE_TCHAR *text)
+{
+ // Only print the message if <priority_mask_> hasn't been reset to
+ // exclude this logging priority.
+ if (this->log_priority_enabled (log_priority) == 0)
+ return 0;
+
+ ACE_TCHAR* buf = 0;
+ const size_t buf_sz =
+ ACE_Log_Record::MAXLOGMSGLEN - ACE_Log_Record::VERBOSE_LEN - 58;
+ ACE_NEW_RETURN (buf, ACE_TCHAR[buf_sz], -1);
+
+ ACE_TCHAR *msg_buf = 0;
+ const size_t text_sz = text ? ACE_OS::strlen(text) : 0;
+ ACE_NEW_RETURN (msg_buf,
+ ACE_TCHAR[text_sz + 58],
+ -1);
+
+ buf[0] = 0; // in case size = 0
+
+ const size_t len = ACE::format_hexdump
+ (buffer, size, buf, buf_sz / sizeof (ACE_TCHAR) - text_sz);
+
+ int sz = 0;
+
+ if (text)
+ sz = ACE_OS::sprintf (msg_buf,
+ ACE_LIB_TEXT ("%s - "),
+ text);
+
+ sz += ACE_OS::sprintf (msg_buf + sz,
+ ACE_LIB_TEXT ("HEXDUMP ")
+ ACE_SIZE_T_FORMAT_SPECIFIER
+ ACE_LIB_TEXT (" bytes"),
+ size);
+
+ if (len < size)
+ ACE_OS::sprintf (msg_buf + sz,
+ ACE_LIB_TEXT (" (showing first ")
+ ACE_SIZE_T_FORMAT_SPECIFIER
+ ACE_LIB_TEXT (" bytes)"),
+ len);
+
+ // Now print out the formatted buffer.
+ this->log (log_priority,
+ ACE_LIB_TEXT ("%s\n%s"),
+ msg_buf,
+ buf);
+
+ delete [] msg_buf;
+ delete [] buf;
+ return 0;
+}
+
+void
+ACE_Log_Msg::set (const char *filename,
+ int line,
+ int status,
+ int err,
+ int rs,
+ ACE_OSTREAM_TYPE *os,
+ ACE_Log_Msg_Callback *c)
+{
+ ACE_TRACE ("ACE_Log_Msg::set");
+ this->file (filename);
+ this->linenum (line);
+ this->op_status (status);
+ this->errnum (err);
+ this->restart (rs);
+ this->msg_ostream (os);
+ this->msg_callback (c);
+}
+
+void
+ACE_Log_Msg::conditional_set (const char *filename,
+ int line,
+ int status,
+ int err)
+{
+ this->conditional_values_.is_set_ = 1;
+ this->conditional_values_.file_ = filename;
+ this->conditional_values_.line_ = line;
+ this->conditional_values_.op_status_ = status;
+ this->conditional_values_.errnum_ = err;
+}
+
+void
+ACE_Log_Msg::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Log_Msg::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("status_ = %d\n"), this->status_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nerrnum_ = %d\n"), this->errnum_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nlinenum_ = %d\n"), this->linenum_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nfile_ = %C\n"), this->file_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmsg_ = %s\n"), this->msg_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nrestart_ = %d\n"), this->restart_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nostream_ = %@\n"), this->ostream_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmsg_callback_ = %@\n"),
+ this->msg_callback_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nprogram_name_ = %s\n"),
+ this->program_name_ ? this->program_name_
+ : ACE_LIB_TEXT ("<unknown>")));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nlocal_host_ = %s\n"),
+ this->local_host_ ? this->local_host_
+ : ACE_LIB_TEXT ("<unknown>")));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\npid_ = %d\n"), this->getpid ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nflags_ = 0x%x\n"), this->flags_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntrace_depth_ = %d\n"),
+ this->trace_depth_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntrace_active_ = %d\n"),
+ this->trace_active_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\ntracing_enabled_ = %d\n"),
+ this->tracing_enabled_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\npriority_mask_ = 0x%x\n"),
+ this->priority_mask_));
+ if (this->thr_desc_ != 0 && this->thr_desc_->state () != 0)
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nthr_state_ = %d\n"),
+ this->thr_desc_->state ()));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nmsg_off_ = %d\n"), this->msg_off_));
+
+ // Be sure that there is a message_queue_, with multiple threads.
+ ACE_MT (ACE_Log_Msg_Manager::init_backend ());
+
+ ACE_MT (ACE_Log_Msg_Manager::get_lock ()->dump ());
+ // Synchronize output operations.
+
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+void
+ACE_Log_Msg::op_status (int status)
+{
+ this->status_ = status;
+}
+
+int
+ACE_Log_Msg::op_status (void)
+{
+ return this->status_;
+}
+
+void
+ACE_Log_Msg::restart (int r)
+{
+ this->restart_ = r;
+}
+
+int
+ACE_Log_Msg::restart (void)
+{
+ return this->restart_;
+}
+
+int
+ACE_Log_Msg::errnum (void)
+{
+ return this->errnum_;
+}
+
+void
+ACE_Log_Msg::errnum (int e)
+{
+ this->errnum_ = e;
+}
+
+int
+ACE_Log_Msg::linenum (void)
+{
+ return this->linenum_;
+}
+
+void
+ACE_Log_Msg::linenum (int l)
+{
+ this->linenum_ = l;
+}
+
+int
+ACE_Log_Msg::inc (void)
+{
+ return this->trace_depth_++;
+}
+
+int
+ACE_Log_Msg::dec (void)
+{
+ return this->trace_depth_ == 0 ? 0 : --this->trace_depth_;
+}
+
+int
+ACE_Log_Msg::trace_depth (void)
+{
+ return this->trace_depth_;
+}
+
+void
+ACE_Log_Msg::trace_depth (int depth)
+{
+ this->trace_depth_ = depth;
+}
+
+int
+ACE_Log_Msg::trace_active (void)
+{
+ return this->trace_active_;
+}
+
+void
+ACE_Log_Msg::trace_active (int value)
+{
+ this->trace_active_ = value;
+}
+
+ACE_Thread_Descriptor *
+ACE_Log_Msg::thr_desc (void) const
+{
+ return this->thr_desc_;
+}
+
+void
+ACE_Log_Msg::thr_desc (ACE_Thread_Descriptor *td)
+{
+ this->thr_desc_ = td;
+
+ if (td != 0)
+ td->acquire_release ();
+}
+
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) && defined(ACE_LEGACY_MODE)
+ACE_SEH_EXCEPT_HANDLER
+ACE_Log_Msg::seh_except_selector (void)
+{
+ return ACE_OS_Object_Manager::seh_except_selector ();
+}
+
+ACE_SEH_EXCEPT_HANDLER
+ACE_Log_Msg::seh_except_selector (ACE_SEH_EXCEPT_HANDLER n)
+{
+ return ACE_OS_Object_Manager::seh_except_selector (n);
+}
+
+ACE_SEH_EXCEPT_HANDLER
+ACE_Log_Msg::seh_except_handler (void)
+{
+ return ACE_OS_Object_Manager::seh_except_handler ();
+}
+
+ACE_SEH_EXCEPT_HANDLER
+ACE_Log_Msg::seh_except_handler (ACE_SEH_EXCEPT_HANDLER n)
+{
+ return ACE_OS_Object_Manager::seh_except_handler (n);
+}
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS && ACE_LEGACY_MODE */
+
+// Enable the tracing facility on a per-thread basis.
+
+void
+ACE_Log_Msg::start_tracing (void)
+{
+ this->tracing_enabled_ = 1;
+}
+
+// Disable the tracing facility on a per-thread basis.
+
+void
+ACE_Log_Msg::stop_tracing (void)
+{
+ this->tracing_enabled_ = 0;
+}
+
+int
+ACE_Log_Msg::tracing_enabled (void)
+{
+ return this->tracing_enabled_;
+}
+
+const char *
+ACE_Log_Msg::file (void)
+{
+ return this->file_;
+}
+
+void
+ACE_Log_Msg::file (const char *s)
+{
+ ACE_OS::strsncpy (this->file_, s, sizeof this->file_);
+}
+
+const ACE_TCHAR *
+ACE_Log_Msg::msg (void)
+{
+ return this->msg_ + ACE_Log_Msg::msg_off_;
+}
+
+void
+ACE_Log_Msg::msg (const ACE_TCHAR *m)
+{
+ ACE_OS::strsncpy (this->msg_, m,
+ ((ACE_MAXLOGMSGLEN+1) / sizeof (ACE_TCHAR)));
+}
+
+ACE_Log_Msg_Callback *
+ACE_Log_Msg::msg_callback (void) const
+{
+ return this->msg_callback_;
+}
+
+ACE_Log_Msg_Callback *
+ACE_Log_Msg::msg_callback (ACE_Log_Msg_Callback *c)
+{
+ ACE_Log_Msg_Callback *old = this->msg_callback_;
+ this->msg_callback_ = c;
+ return old;
+}
+
+ACE_Log_Msg_Backend *
+ACE_Log_Msg::msg_backend (ACE_Log_Msg_Backend *b)
+{
+ ACE_TRACE ("ACE_Log_Msg::msg_backend");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (), 0));
+
+ ACE_Log_Msg_Backend *tmp = ACE_Log_Msg_Manager::custom_backend_;
+ ACE_Log_Msg_Manager::custom_backend_ = b;
+ return tmp;
+}
+
+ACE_Log_Msg_Backend *
+ACE_Log_Msg::msg_backend (void)
+{
+ ACE_TRACE ("ACE_Log_Msg::msg_backend");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Log_Msg_Manager::get_lock (), 0));
+
+ return ACE_Log_Msg_Manager::custom_backend_;
+}
+
+ACE_OSTREAM_TYPE *
+ACE_Log_Msg::msg_ostream (void) const
+{
+ return this->ostream_;
+}
+
+void
+ACE_Log_Msg::msg_ostream (ACE_OSTREAM_TYPE *m, int delete_ostream)
+{
+ if (this->ostream_ == m)
+ return;
+
+ if (this->delete_ostream_)
+ {
+#if defined (ACE_LACKS_IOSTREAM_TOTALLY)
+ ACE_OS::fclose (this->ostream_);
+#else
+ delete this->ostream_;
+#endif
+ }
+
+ this->delete_ostream_ = delete_ostream;
+ this->ostream_ = m;
+}
+
+void
+ACE_Log_Msg::msg_ostream (ACE_OSTREAM_TYPE *m)
+{
+ this->ostream_ = m;
+}
+
+void
+ACE_Log_Msg::local_host (const ACE_TCHAR *s)
+{
+ if (s)
+ {
+ ACE_OS::free ((void *) ACE_Log_Msg::local_host_);
+ {
+ ACE_NO_HEAP_CHECK;
+
+ ACE_ALLOCATOR (ACE_Log_Msg::local_host_, ACE_OS::strdup (s));
+ }
+ }
+}
+
+const ACE_TCHAR *
+ACE_Log_Msg::local_host (void) const
+{
+ return ACE_Log_Msg::local_host_;
+}
+
+pid_t
+ACE_Log_Msg::getpid (void) const
+{
+ if (ACE_Log_Msg::pid_ == -1)
+ ACE_Log_Msg::pid_ = ACE_OS::getpid ();
+
+ return ACE_Log_Msg::pid_;
+}
+
+int
+ACE_Log_Msg::log_priority_enabled (ACE_Log_Priority log_priority,
+ const char *,
+ ...)
+{
+ return this->log_priority_enabled (log_priority);
+}
+
+#if defined (ACE_USES_WCHAR)
+int
+ACE_Log_Msg::log_priority_enabled (ACE_Log_Priority log_priority,
+ const wchar_t *,
+ ...)
+{
+ return this->log_priority_enabled (log_priority);
+}
+#endif /* ACE_USES_WCHAR */
+
+// ****************************************************************
+
+void
+ACE_Log_Msg::init_hook (ACE_OS_Log_Msg_Attributes &attributes
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ , ACE_SEH_EXCEPT_HANDLER selector
+ , ACE_SEH_EXCEPT_HANDLER handler
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ )
+{
+# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ attributes.seh_except_selector_ = selector;
+ attributes.seh_except_handler_ = handler;
+# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+ if (ACE_Log_Msg::exists ())
+ {
+ ACE_Log_Msg *inherit_log = ACE_LOG_MSG;
+ attributes.ostream_ = inherit_log->msg_ostream ();
+ attributes.priority_mask_ = inherit_log->priority_mask ();
+ attributes.tracing_enabled_ = inherit_log->tracing_enabled ();
+ attributes.restart_ = inherit_log->restart ();
+ attributes.trace_depth_ = inherit_log->trace_depth ();
+ }
+}
+
+void
+ACE_Log_Msg::inherit_hook (ACE_OS_Thread_Descriptor *thr_desc,
+ ACE_OS_Log_Msg_Attributes &attributes)
+{
+#if !defined (ACE_THREADS_DONT_INHERIT_LOG_MSG) && \
+ !defined (ACE_HAS_MINIMAL_ACE_OS)
+ // Inherit the logging features if the parent thread has an
+ // <ACE_Log_Msg>. Note that all of the following operations occur
+ // within thread-specific storage.
+ ACE_Log_Msg *new_log = ACE_LOG_MSG;
+
+ // Note that we do not inherit the callback because this might have
+ // been allocated off of the stack of the original thread, in which
+ // case all hell would break loose...
+
+ if (attributes.ostream_)
+ {
+ new_log->msg_ostream (attributes.ostream_);
+ new_log->priority_mask (attributes.priority_mask_);
+
+ if (attributes.tracing_enabled_)
+ new_log->start_tracing ();
+
+ new_log->restart (attributes.restart_);
+ new_log->trace_depth (attributes.trace_depth_);
+ }
+
+ // @@ Now the TSS Log_Msg has been created, cache my thread
+ // descriptor in.
+
+ if (thr_desc != 0)
+ // This downcast is safe. We do it to avoid having to #include
+ // ace/Thread_Manager.h.
+ new_log->thr_desc (static_cast<ACE_Thread_Descriptor *> (thr_desc));
+ // Block the thread from proceeding until
+ // thread manager has thread descriptor ready.
+#endif /* ! ACE_THREADS_DONT_INHERIT_LOG_MSG && ! ACE_HAS_MINIMAL_ACE_OS */
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL