Good work! Ack with comments inline, marked AndersW> below.

Some additional comments (you don't have to address all the comments in
this ticket but they could be considered for future improvements):

* Trace files seem to be dumped also when threads exit normally? Is it
dumped from some destructor of an object in thread local storage (I
think Hans hinted at this). Trace files shouldn't be dumped when no
error has occurred.

* In case a generated core dump is corrupted or otherwise not possible
to interpret with gdb, it could be useful if there is some easy to find
marker at the beginning of the circular trace buffer, which is possible
to find even without gdb by simply searching for a binary pattern.
Could you add such a marker (it could be a known constant integer which
is unlikely to appear anywhere else in the core dump - e.g. a randomly
generated number).

* I had originally imagined this feature to be an always-on light-
weight tracing (maybe just logging the function name at TRACE_ENTER and
TRACE_LEAVE, without any arguments) into a single circular memory buffer. In 
case of a crash you could use it to figure out how you got there by looking at 
the sequence of function calls. Possibly you could also call write() in the 
fatal signal handler to dump this raw memory area to disk, in case no core dump 
was generated. A question: does you implementation dump the trace buffers to 
disk in case of a crash? I couldn't find the connection with the fatal signal 
handler, but maybe it is done implicitly by the destructors? I just noted that 
rather than dumping a raw memory area to disk using the write() system call, 
the flushing of the trace buffer is rather complicated involving dereferencing 
pointers, and memory management (freeing instances of std::string). It may not 
work if the program crashed due to memory corruption.

regards,
Anders Widell


tis 2018-06-12 klockan 07:16 +1000 skrev Minh Chau:
> This ticket support the tracing buffer per thread. If enabled,
> each thread has it own buffer which the trace is written to.
> The thread trace buffers will be flushed to file if an abnormal
> end hits, i.e. LOG_ER is called.
> The thread trace file format: "daemon_name"_"proc_id"_"thread_id"
> is stored under /var/log/opensaf/. These file can be correlated
> in timing order by a "sort" command or could be by another saflog
> command.
> Main changes in this ticket
> . Rename LogTrace class to LogTraceClient
> . Move Log_Writer from dtm to base
> . Add LogTraceBuffer class, this class hold the trace buffer
> . Add thread_local instace of LogTraceBuffer, so that the instance
>   of LogTraceBuffer will be created/deleted whenever a new thread
>   is created or destroyed.
> . Add an instance of LogTraceClient for thread trace buffering.
> ---
>  src/amf/amfd/amfd.conf                     |   5 ++
>  src/base/Makefile.am                       |   4 +
>  src/base/daemon.c                          |   3 +
>  src/base/log_writer.cc                     | 135
> +++++++++++++++++++++++++++++
>  src/base/log_writer.h                      |  65 ++++++++++++++
>  src/base/logtrace.cc                       |  77 +++++++++++++---
>  src/base/logtrace.h                        |   6 ++
>  src/base/logtrace_buffer.cc                |  87 +++++++++++++++++++
>  src/base/logtrace_buffer.h                 |  52 +++++++++++
>  src/base/logtrace_client.cc                |  91 ++++++++++++++-----
>  src/base/logtrace_client.h                 |  50 ++++++++---
>  src/dtm/Makefile.am                        |   3 -
>  src/dtm/transport/log_server.h             |   2 +-
>  src/dtm/transport/log_writer.cc            | 117 -----------------
> --------
>  src/dtm/transport/log_writer.h             |  64 --------------
>  src/dtm/transport/tests/log_writer_test.cc |   2 +-
>  src/mds/mds_log.cc                         |  18 ++--


AndersW> Please split the single GIT commit into one commit per OpenSAF
component (subdirectory under src). The DTM commit should appear after
the base commit, since it depends on it.

>  17 files changed, 537 insertions(+), 244 deletions(-)
>  create mode 100644 src/base/log_writer.cc
>  create mode 100644 src/base/log_writer.h
>  create mode 100644 src/base/logtrace_buffer.cc
>  create mode 100644 src/base/logtrace_buffer.h
>  delete mode 100644 src/dtm/transport/log_writer.cc
>  delete mode 100644 src/dtm/transport/log_writer.h
> 
> diff --git a/src/amf/amfd/amfd.conf b/src/amf/amfd/amfd.conf
> index 9da3bec..5e20650 100644
> --- a/src/amf/amfd/amfd.conf
> +++ b/src/amf/amfd/amfd.conf
> @@ -24,3 +24,8 @@ export AVSV_HB_PERIOD=10000000000
>  # All logging will be recorded in a new node local log file
> $PKGLOGDIR/osaf.log.
>  # Uncomment the next line to enable this service to log to OpenSAF
> node local log file.
>  # export OSAF_LOCAL_NODE_LOG=1
> +
> +# THREAD_TRACE_BUFFER variable enables the tracing, writes the trace
> +# to thread based buffer in circular fashion. The trace buffers will
> +# be flushed to file if an abnormal end hits, i.e. LOG_ER is called
> +export THREAD_TRACE_BUFFER=1
> diff --git a/src/base/Makefile.am b/src/base/Makefile.am
> index 65f9219..a6c3178 100644
> --- a/src/base/Makefile.am
> +++ b/src/base/Makefile.am
> @@ -51,6 +51,8 @@ lib_libopensaf_core_la_SOURCES += \
>       src/base/log_message.cc \
>       src/base/logtrace.cc \
>       src/base/logtrace_client.cc \
> +     src/base/logtrace_buffer.cc \
> +     src/base/log_writer.cc \

AndersW> Keep the list of files sorted alphabetically.

>       src/base/mutex.cc \
>       src/base/ncs_main_pub.c \
>       src/base/ncs_sprr.c \
> @@ -101,6 +103,8 @@ noinst_HEADERS += \
>       src/base/log_message.h \
>       src/base/logtrace.h \
>       src/base/logtrace_client.h \
> +     src/base/logtrace_buffer.h \
> +     src/base/log_writer.h \
>       src/base/macros.h \
>       src/base/mutex.h \
>       src/base/ncs_edu.h \
> diff --git a/src/base/daemon.c b/src/base/daemon.c
> index 361dd8d..ad052bf 100644
> --- a/src/base/daemon.c
> +++ b/src/base/daemon.c
> @@ -549,6 +549,9 @@ void daemon_exit(void)
>       unlink(fifo_file);
>       unlink(__pidfile);
>  
> +     /* flush the logtrace */
> +     logtrace_exit_daemon();
> +
>       _Exit(0);
>  }
>  
> diff --git a/src/base/log_writer.cc b/src/base/log_writer.cc
> new file mode 100644
> index 0000000..eb079d6
> --- /dev/null
> +++ b/src/base/log_writer.cc
> @@ -0,0 +1,135 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + * Copyright Ericsson AB 2017 - All Rights Reserved.
> + *
> + * This program is distributed in the hope that it will be useful,
> but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> + * under the GNU Lesser General Public License Version 2.1, February
> 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for
> full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "base/log_writer.h"
> +#include <fcntl.h>
> +#include <sys/stat.h>
> +#include <unistd.h>
> +#include <stdio.h>
> +#include <cerrno>
> +#include <cstdio>
> +#include <cstring>
> +#include "base/getenv.h"
> +#include "osaf/configmake.h"
> +
> +LogWriter::LogWriter(const std::string& log_name, size_t
> max_backups,
> +                                                  size_t
> max_file_size)
> +    : log_file_{base::GetEnv<std::string>("pkglogdir", PKGLOGDIR) +
> "/" +
> +                log_name},
> +      fd_{-1},
> +      current_file_size_{0},
> +      current_buffer_size_{0},
> +      max_backups_{max_backups},
> +      max_file_size_{max_file_size},
> +      buffer_{new char[kBufferSize]} {}
> +
> +LogWriter::~LogWriter() {
> +  Flush();
> +  Close();
> +  delete[] buffer_;
> +}
> +
> +std::string LogWriter::log_file(size_t backup) const {
> +  std::string file_name = log_file_;
> +  if (backup != 0) {
> +    file_name += std::string(".") + std::to_string(backup);
> +  }
> +  return file_name;
> +}
> +
> +void LogWriter::Open() {
> +  if (fd_ < 0) {
> +    int fd;
> +    do {
> +      fd = open(log_file(0).c_str(), O_WRONLY | O_CLOEXEC | O_CREAT,
> +                S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH |
> S_IWOTH);
> +    } while (fd == -1 && errno == EINTR);
> +    if (fd >= 0) {
> +      off_t seek_result = lseek(fd, 0, SEEK_END);
> +      if (seek_result >= 0) current_file_size_ = seek_result;
> +      fd_ = fd;
> +    }
> +  }
> +}
> +
> +void LogWriter::Close() {
> +  int fd = fd_;
> +  if (fd >= 0) {
> +    close(fd);
> +    fd_ = -1;
> +    current_file_size_ = 0;
> +  }
> +}
> +
> +void LogWriter::RotateLog() {
> +  Close();
> +  unlink(log_file(max_backups_).c_str());
> +  for (size_t i = max_backups_; i != 0; --i) {
> +    std::string backup_name = log_file(i);
> +    std::string previous_backup = log_file(i - 1);
> +    if (rename(previous_backup.c_str(), backup_name.c_str()) != 0) {
> +      unlink(previous_backup.c_str());
> +    }
> +  }
> +}
> +
> +void LogWriter::Write(const char* bytes, size_t size) {
> +  size_t bytes_written = 0;
> +  size_t bytes_chunk = 0;
> +  while (bytes_written < size) {
> +    if ((size - bytes_written) > (kBufferSize -
> current_buffer_size_)) {
> +      bytes_chunk = kBufferSize - current_buffer_size_;
> +    } else {
> +      bytes_chunk = size - bytes_written;
> +    }
> +    memcpy(current_buffer_position(), bytes + bytes_written,
> bytes_chunk);
> +    bytes_written += bytes_chunk;
> +    current_buffer_size_ += bytes_chunk;
> +    if (current_buffer_size_ >= kBufferSize ||
> +        current_buffer_size_ >= max_file_size_) Flush();
> +  }
> +}
> +
> +void LogWriter::Write(size_t size) {
> +  current_buffer_size_ += size;
> +  if (current_buffer_size_ > kBufferSize - kMaxMessageSize ||
> +      current_buffer_size_ >= max_file_size_) Flush();
> +}
> +
> +void LogWriter::Flush() {
> +  size_t size = current_buffer_size_;
> +  current_buffer_size_ = 0;
> +  if (size == 0) return;
> +  if (fd_ < 0) Open();
> +  if (fd_ < 0) return;
> +  if (current_file_size_ >= max_file_size_) {
> +    RotateLog();
> +    if (fd_ < 0) Open();
> +    if (fd_ < 0) return;
> +  }
> +  size_t bytes_written = 0;
> +  while (bytes_written < size) {
> +    ssize_t result = write(fd_, buffer_ + bytes_written, size -
> bytes_written);
> +    if (result < 0) {
> +      if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
> continue;
> +      break;
> +    }
> +    bytes_written += result;
> +  }
> +  current_file_size_ += bytes_written;
> +}
> diff --git a/src/base/log_writer.h b/src/base/log_writer.h
> new file mode 100644
> index 0000000..9fddd52
> --- /dev/null
> +++ b/src/base/log_writer.h
> @@ -0,0 +1,65 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * (C) Copyright 2016 The OpenSAF Foundation
> + * Copyright Ericsson AB 2017 - All Rights Reserved.
> + *
> + * This program is distributed in the hope that it will be useful,
> but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> + * under the GNU Lesser General Public License Version 2.1, February
> 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for
> full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef BASE_LOG_WRITER_H_
> +#define BASE_LOG_WRITER_H_
> +
> +#include <cstddef>
> +#include <string>
> +#include "base/macros.h"
> +
> +// This class is responsible for writing MDS log messages to disk,
> and rotating
> +// the log file when it exceeds the maximum file size limit.
> +class LogWriter {
> + public:
> +  constexpr static const size_t kMaxMessageSize = 2 * size_t{1024};
> +
> +  LogWriter(const std::string& log_name, size_t max_backups,
> +                                          size_t max_file_size);
> +  virtual ~LogWriter();
> +
> +  char* current_buffer_position() { return buffer_ +
> current_buffer_size_; }
> +  bool empty() const { return current_buffer_size_ == 0; }
> +
> +  // Write @a size bytes of log message data in the memory pointed
> to by @a
> +  // buffer to the MDS log file. After the log message has been
> written, the
> +  // file will be rotated if necessary. This method performs
> blocking file I/O.
> +  void Write(size_t size);
> +  void Write(const char* bytes, size_t size);
> +  void Flush();
> +
> + private:
> +  constexpr static const size_t kBufferSize = 128 * size_t{1024};
> +  void Open();
> +  void Close();
> +  void RotateLog();
> +
> +  std::string log_file(size_t backup) const;
> +
> +  const std::string log_file_;
> +  int fd_;
> +  size_t current_file_size_;
> +  size_t current_buffer_size_;
> +  size_t max_backups_;
> +  size_t max_file_size_;
> +  char* buffer_;
> +
> +  DELETE_COPY_AND_MOVE_OPERATORS(LogWriter);
> +};
> +
> +#endif  // BASE_LOG_WRITER_H_
> diff --git a/src/base/logtrace.cc b/src/base/logtrace.cc
> index b54f14e..3dff86b 100644
> --- a/src/base/logtrace.cc
> +++ b/src/base/logtrace.cc
> @@ -29,6 +29,7 @@
>  #include <unistd.h>
>  #include "base/getenv.h"
>  #include "base/logtrace_client.h"
> +#include "base/logtrace_buffer.h"
>  #include "base/ncsgl_defs.h"
>  
>  namespace global {
> @@ -41,13 +42,21 @@ char *msg_id;
>  int logmask;
>  const char* osaf_log_file = "osaf.log";
>  bool enable_osaf_log = false;
> +bool enable_thread_trace_buffer = false;
>  
>  }  // namespace global
>  
> -TraceLog* gl_trace = nullptr;
> -TraceLog* gl_osaflog = nullptr;
> +// legacy tracing, trace is written by osaftransportd
> +LogTraceClient* gl_remote_trace = nullptr;
> +// direct osaf services logging to a configured file
> +LogTraceClient* gl_remote_osaflog = nullptr;
> +// local thread trace buffering
> +LogTraceClient* gl_local_thread_trace = nullptr;
> +
>  std::once_flag init_flag;
>  
> +thread_local LogTraceBuffer gl_thread_buffer{gl_local_thread_trace,
> 10240};
> +
>  static pid_t gettid() { return syscall(SYS_gettid); }
>  
>  /**
> @@ -84,14 +93,28 @@ static void sighup_handler(int sig) {
>  void trace_output(const char *file, unsigned line, unsigned
> priority,
>                       unsigned category, const char *format, va_list
> ap) {
>    char preamble[288];
> +  const char* entry = nullptr;
>  
>    assert(priority <= LOG_DEBUG && category < CAT_MAX);
>  
>    if (strncmp(file, "src/", 4) == 0) file += 4;
>    snprintf(preamble, sizeof(preamble), "%d:%s:%u %s %s", gettid(),
> file, line,
>             global::prefix_name[priority + category], format);
> -  TraceLog::Log(gl_trace,
> static_cast<base::LogMessage::Severity>(priority),
> -      preamble, ap);
> +  // legacy trace
> +  if (is_logtrace_enabled(category)) {
> +    entry = LogTraceClient::Log(gl_remote_trace,
> +        static_cast<base::LogMessage::Severity>(priority), preamble,
> ap);
> +  }
> +  // thread trace
> +  if (global::enable_thread_trace_buffer == true) {
> +    // reuse @entry if legacy trace is enabled
> +    if (!entry) {
> +      entry = gl_local_thread_trace->CreateLogEntry(
> +          static_cast<base::LogMessage::Severity>(priority),
> +          preamble, ap);
> +    }
> +    gl_thread_buffer.WriteToBuffer(entry);
> +  }
>  }
>  
>  void log_output(const char *file, unsigned line, unsigned priority,
> @@ -103,8 +126,15 @@ void log_output(const char *file, unsigned line,
> unsigned priority,
>    if (strncmp(file, "src/", 4) == 0) file += 4;
>    snprintf(preamble, sizeof(preamble), "%d:%s:%u %s %s", gettid(),
> file, line,
>             global::prefix_name[priority + category], format);
> -  TraceLog::Log(gl_osaflog,
> static_cast<base::LogMessage::Severity>(priority),
> -      preamble, ap);
> +  LogTraceClient::Log(gl_remote_osaflog,
> +      static_cast<base::LogMessage::Severity>(priority), preamble,
> ap);
> +  // Flush the thread buffer for logging error or lower
> +  if (global::enable_thread_trace_buffer == true &&
> gl_local_thread_trace &&
> +      static_cast<base::LogMessage::Severity>(priority) <=
> +      base::LogMessage::Severity::kErr) {
> +    gl_thread_buffer.RequestFlush();
> +    gl_thread_buffer.FlushBuffer();
> +  }
>  }
>  
>  void logtrace_log(const char *file, unsigned line, int priority,
> @@ -154,7 +184,8 @@ void logtrace_trace(const char *file, unsigned
> line, unsigned category,
>                      const char *format, ...) {
>    va_list ap;
>  
> -  if (is_logtrace_enabled(category) == false) return;
> +  if (is_logtrace_enabled(category) == false &&
> +      global::enable_thread_trace_buffer == false) return;
>  
>    va_start(ap, format);
>    trace_output(file, line, LOG_DEBUG, category, format, ap);
> @@ -177,14 +208,27 @@ static void logtrace_init_interal(const char
> *pathname, unsigned mask,
>  
>    result = global::msg_id != nullptr;
>  
> +  // Initialize various type of logging instances based on
> +  // environment variables
>    if (result && mask != 0) {
> -    if (!gl_trace) gl_trace = new TraceLog();
> -    result = gl_trace->Init(global::msg_id, TraceLog::kBlocking);
> +    if (!gl_remote_trace) {
> +      gl_remote_trace = new LogTraceClient(global::msg_id,
> +          LogTraceClient::kRemoteBlocking);
> +    }
> +  }
> +  if (base::GetEnv("THREAD_TRACE_BUFFER", uint32_t{0}) == 1) {
> +    global::enable_thread_trace_buffer = true;
> +    if (!gl_local_thread_trace) {
> +      gl_local_thread_trace = new LogTraceClient(global::msg_id,
> +          LogTraceClient::kLocalBuffer);
> +    }
>    }
>    if (base::GetEnv("OSAF_LOCAL_NODE_LOG", uint32_t{0}) == 1) {
>      global::enable_osaf_log = true;
> -    if (!gl_osaflog) gl_osaflog = new TraceLog();
> -    result = gl_osaflog->Init(global::osaf_log_file,
> TraceLog::kBlocking);
> +    if (!gl_remote_osaflog) {
> +      gl_remote_osaflog = new LogTraceClient(global::osaf_log_file,
> +          LogTraceClient::kRemoteBlocking);
> +    }
>    }
>    if (result) {
>      syslog(LOG_INFO, "logtrace: trace enabled to file '%s',
> mask=0x%x",
> @@ -204,6 +248,11 @@ int logtrace_init(const char *, const char
> *pathname, unsigned mask) {
>    return result;
>  }
>  
> +int logtrace_exit_daemon() {
> +  if (gl_local_thread_trace) gl_local_thread_trace-
> >FlushExternalBuffer();
> +  return 0;
> +}
> +
>  int logtrace_init_daemon(const char *ident, const char *pathname,
>                           unsigned tracemask, int logmask) {
>    if (signal(SIGUSR2, sigusr2_handler) == SIG_ERR) {
> @@ -231,8 +280,10 @@ int trace_category_set(unsigned mask) {
>    if (global::category_mask == 0) {
>      syslog(LOG_INFO, "logtrace: trace disabled");
>    } else {
> -    if (!gl_trace) gl_trace = new TraceLog();
> -    gl_trace->Init(global::msg_id, TraceLog::kBlocking);
> +    if (!gl_remote_trace) {
> +      gl_remote_trace = new LogTraceClient(global::msg_id,
> +        LogTraceClient::kRemoteBlocking);
> +    }
>      syslog(LOG_INFO, "logtrace: trace enabled to file %s,
> mask=0x%x",
>             global::msg_id, global::category_mask);
>    }
> diff --git a/src/base/logtrace.h b/src/base/logtrace.h
> index 9b20da8..5d2d667 100644
> --- a/src/base/logtrace.h
> +++ b/src/base/logtrace.h
> @@ -96,6 +96,12 @@ extern int logtrace_init(const char *ident, const
> char *pathname,
>  extern int logtrace_init_daemon(const char *ident, const char
> *pathname,
>                                  unsigned tracemask, int logmask);
>  
> +/*
> + * logtrace_exit_daemon
> + * This should be called when a daemon exit
> + */
> +extern int logtrace_exit_daemon();
> +
>  /**
>   * trace_category_set - Set the mask used for trace filtering.
>   *
> diff --git a/src/base/logtrace_buffer.cc
> b/src/base/logtrace_buffer.cc
> new file mode 100644
> index 0000000..59099b2
> --- /dev/null
> +++ b/src/base/logtrace_buffer.cc
> @@ -0,0 +1,87 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * Copyright Ericsson AB 2018 - All Rights Reserved.
> + *
> + * This program is distributed in the hope that it will be useful,
> but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> + * under the GNU Lesser General Public License Version 2.1, February
> 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for
> full
> + * licensing terms.
> + *
> + */
> +
> +#include "base/logtrace_buffer.h"
> +#include <fcntl.h>
> +#include <sys/stat.h>
> +#include <sys/syscall.h>
> +#include <unistd.h>
> +#include <cerrno>
> +#include <cstdio>
> +#include <cstdint>
> +#include <cstdlib>
> +#include <thread>
> +
> +LogTraceBuffer::LogTraceBuffer(LogTraceClient* owner, size_t
> buffer_size) :
> +  owner_(owner),
> +  buffer_size_(buffer_size) {
> +  std::string log_file_name;
> +  index_ = 0;
> +  flush_required_ = false;
> +  tid_ = syscall(SYS_gettid);
> +  vector_.resize(buffer_size_);
> +  if (owner_) {
> +    owner_->AddExternalBuffer(tid_, this);
> +    log_file_name = std::string(owner_->app_name()) + "_" + owner_-
> >proc_id()
> +        + "_" + std::to_string(tid_);
> +  } else {
> +    log_file_name = std::string(getpid() + "_" +
> std::to_string(tid_));
> +  }
> +  log_writer_ = new LogWriter{log_file_name, 10, 10 * 1024 * 1024};
> +}
> +
> +LogTraceBuffer::~LogTraceBuffer() {
> +  if (owner_) {
> +    owner_->RemoveExternalBuffer(tid_);
> +  }
> +  FlushBuffer();
> +  delete log_writer_;
> +}
> +
> +void LogTraceBuffer::WriteToBuffer(std::string trace) {
> +  vector_[index_] = trace;
> +  // add break line char
> +  if (trace.at(trace.length() - 1) != '\n')
> +    vector_[index_] += "\n";
> +
> +  if (index_++ == buffer_size_) index_ = 0;
> +  if (flush_required_) FlushBuffer();
> +}
> +void LogTraceBuffer::RequestFlush() {
> +  flush_required_ = true;
> +  if (owner_) owner_->RequestFlushExternalBuffer();
> +}
> +
> +bool LogTraceBuffer::FlushBuffer() {
> +  size_t i;
> +  // flushing the right half first
> +  for (i = index_ ; i < buffer_size_ ; i++) {
> +    if (vector_[i].length() > 0) {
> +      log_writer_->Write(vector_[i].c_str(), vector_[i].length());
> +      vector_[i] = "";
> +    }
> +  }
> +  // flushing the left half second
> +  for (i = 0 ; i < index_ ; i++) {
> +    if (vector_[i].length() > 0) {
> +      log_writer_->Write(vector_[i].c_str(), vector_[i].length());
> +      vector_[i] = "";
> +    }
> +  }
> +  log_writer_->Flush();
> +  flush_required_ = false;
> +  return true;
> +}
> +
> diff --git a/src/base/logtrace_buffer.h b/src/base/logtrace_buffer.h
> new file mode 100644
> index 0000000..535932a
> --- /dev/null
> +++ b/src/base/logtrace_buffer.h
> @@ -0,0 +1,52 @@
> +/*      -*- OpenSAF  -*-
> + *
> + * Copyright Ericsson AB 2018 - All Rights Reserved.
> + *
> + * This program is distributed in the hope that it will be useful,
> but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> + * under the GNU Lesser General Public License Version 2.1, February
> 1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for
> full
> + * licensing terms.
> + *
> + */
> +
> +#ifndef BASE_LOGTRACE_BUFFER_H_
> +#define BASE_LOGTRACE_BUFFER_H_
> +
> +#include <vector>
> +#include <string>
> +#include <list>
> +#include "base/buffer.h"
> +#include "base/conf.h"
> +#include "base/macros.h"
> +#include "base/logtrace_client.h"
> +#include "base/log_writer.h"
> +
> +class LogTraceClient;
> +// A class implements a buffer which is written in circular fashion
> +// This buffer is attached to its owner which is a LogTraceClient
> +
> +class LogTraceBuffer {
> + public:
> +  explicit LogTraceBuffer(LogTraceClient* owner, size_t
> buffer_size);

AndersW> explicit is not needed here, remove it.

> +  ~LogTraceBuffer();
> +  void WriteToBuffer(std::string trace);
> +  bool FlushBuffer();
> +  void RequestFlush();
> +  void SetFlush(const bool flush) { flush_required_ = flush; }
> + private:
> +  LogTraceClient* owner_;
> +  const size_t buffer_size_;
> +  size_t index_;
> +  int64_t tid_;
> +  std::vector<std::string> vector_;
> +  LogWriter* log_writer_;
> +  bool flush_required_;
> +  DELETE_COPY_AND_MOVE_OPERATORS(LogTraceBuffer);
> +};
> +
> +
> +#endif  // BASE_LOGTRACE_BUFFER_H_
> diff --git a/src/base/logtrace_client.cc
> b/src/base/logtrace_client.cc
> index a9d82e2..e22112a 100644
> --- a/src/base/logtrace_client.cc
> +++ b/src/base/logtrace_client.cc
> @@ -16,32 +16,35 @@
>  #include "base/logtrace_client.h"
>  #include <limits.h>
>  #include <unistd.h>
> -#include <cstring>
> +#include <utility>
> +#include <string>
>  #include "base/getenv.h"
>  #include "base/ncsgl_defs.h"
>  #include "base/osaf_utility.h"
>  #include "dtm/common/osaflog_protocol.h"
>  
> -TraceLog::TraceLog()
> +
> +LogTraceClient::LogTraceClient(const char *msg_id, WriteMode mode)
>      : sequence_id_{1}, buffer_{} {
> -  mutex_ = nullptr;
> +  log_mutex_ = nullptr;
> +  ext_buffer_mutex_ = nullptr;
>    log_socket_ = nullptr;
> +  Init(msg_id, mode);
>  }
>  
> -TraceLog::~TraceLog() {
> -  if (mutex_) delete mutex_;
> +LogTraceClient::~LogTraceClient() {
> +  if (log_mutex_) delete log_mutex_;
> +  if (ext_buffer_mutex_) delete ext_buffer_mutex_;
>    if (log_socket_) delete log_socket_;
>  }
>  
> -bool TraceLog::Init(const char *msg_id, WriteMode mode) {
> +bool LogTraceClient::Init(const char *msg_id, WriteMode mode) {
>    char app_name[NAME_MAX];
>    char pid_path[PATH_MAX];
>    uint32_t process_id;
>    char *token, *saveptr;
>    char *pid_name = nullptr;
>  
> -  if (log_socket_ != nullptr && mutex_ != nullptr) return true;
> -
>    memset(app_name, 0, NAME_MAX);
>    memset(pid_path, 0, PATH_MAX);
>    process_id = getpid();
> @@ -74,28 +77,46 @@ bool TraceLog::Init(const char *msg_id, WriteMode
> mode) {
>    app_name_ = base::LogMessage::AppName(app_name);
>    proc_id_ = base::LogMessage::ProcId{std::to_string(process_id)};
>    msg_id_ = base::LogMessage::MsgId{msg_id};
> -  log_socket_ = new
> base::UnixClientSocket{Osaflog::kServerSocketPath,
> -    static_cast<base::UnixSocket::Mode>(mode)};
> -  mutex_ = new base::Mutex{};
>  
> +  if (mode == kRemoteBlocking || mode == kRemoteNonblocking) {
> +    log_socket_ = new
> base::UnixClientSocket{Osaflog::kServerSocketPath,
> +      static_cast<base::UnixSocket::Mode>(mode)};
> +  }
> +  log_mutex_ = new base::Mutex{};
> +  ext_buffer_mutex_ = new base::Mutex{};
>    return true;
>  }
>  
> -void TraceLog::Log(TraceLog* tracelog, base::LogMessage::Severity
> severity,
> -      const char *fmt, va_list ap) {
> -  if (tracelog != nullptr) tracelog->Log(severity, fmt, ap);
> +const char* LogTraceClient::Log(LogTraceClient* tracelog,
> +    base::LogMessage::Severity severity, const char *fmt, va_list
> ap) {
> +  if (tracelog != nullptr) return tracelog->Log(severity, fmt, ap);
> +  return nullptr;
>  }
>  
> -void TraceLog::Log(base::LogMessage::Severity severity, const char
> *fmt,
> -                   va_list ap) {
> -  if (log_socket_ != nullptr && mutex_ != nullptr) {
> -    LogInternal(severity, fmt, ap);
> +const char* LogTraceClient::Log(base::LogMessage::Severity severity,
> +    const char *fmt, va_list ap) {
> +  if (log_socket_ != nullptr && log_mutex_ != nullptr) {
> +    return LogInternal(severity, fmt, ap);
>    }
> +  return nullptr;
> +}
> +
> +const char* LogTraceClient::LogInternal(base::LogMessage::Severity
> severity,
> +    const char *fmt, va_list ap) {
> +  base::Lock lock(*log_mutex_);
> +  CreateLogEntryInternal(severity, fmt, ap);
> +  log_socket_->Send(buffer_.data(), buffer_.size());
> +  return buffer_.data();
>  }
>  
> -void TraceLog::LogInternal(base::LogMessage::Severity severity,
> const char *fmt,
> -                           va_list ap) {
> -  base::Lock lock(*mutex_);
> +const char*
> LogTraceClient::CreateLogEntry(base::LogMessage::Severity severity,
> +    const char *fmt, va_list ap) {
> +  base::Lock lock(*log_mutex_);
> +  return CreateLogEntryInternal(severity, fmt, ap);
> +}
> +
> +const char* LogTraceClient::CreateLogEntryInternal(
> +    base::LogMessage::Severity severity, const char *fmt, va_list
> ap) {
>    uint32_t id = sequence_id_;
>    sequence_id_ = id < kMaxSequenceId ? id + 1 : 1;
>    buffer_.clear();
> @@ -106,5 +127,31 @@ void
> TraceLog::LogInternal(base::LogMessage::Severity severity, const char
> *fmt,
>          {base::LogMessage::Parameter{base::LogMessage::SdName{"seque
> nceId"},
>                                       std::to_string(id)}}}},
>        fmt, ap, &buffer_);
> -  log_socket_->Send(buffer_.data(), buffer_.size());
> +  return buffer_.data();
> +}
> +
> +void LogTraceClient::AddExternalBuffer(int64_t tid, LogTraceBuffer*
> buffer) {
> +  base::Lock lock(*ext_buffer_mutex_);
> +  ext_buffer_map_.insert(std::pair<int64_t, LogTraceBuffer*>(tid,
> buffer));
>  }
> +
> +void LogTraceClient::RemoveExternalBuffer(int64_t tid) {
> +  base::Lock lock(*ext_buffer_mutex_);
> +  ext_buffer_map_.erase(tid);
> +}
> +
> +void LogTraceClient::RequestFlushExternalBuffer() {
> +  base::Lock lock(*ext_buffer_mutex_);
> +  for (auto &buff : ext_buffer_map_) {
> +    buff.second->SetFlush(true);
> +  }
> +}
> +
> +bool LogTraceClient::FlushExternalBuffer() {
> +  base::Lock lock(*ext_buffer_mutex_);
> +  for (auto &buff : ext_buffer_map_) {
> +    buff.second->FlushBuffer();
> +  }
> +  return true;
> +}
> +
> diff --git a/src/base/logtrace_client.h b/src/base/logtrace_client.h
> index 21c7d2e..5b165e5 100644
> --- a/src/base/logtrace_client.h
> +++ b/src/base/logtrace_client.h
> @@ -16,32 +16,50 @@
>  #ifndef BASE_LOGTRACE_CLIENT_H_
>  #define BASE_LOGTRACE_CLIENT_H_
>  
> +#include <map>
>  #include "base/log_message.h"
> -#include "base/unix_client_socket.h"
>  #include "base/buffer.h"
>  #include "base/conf.h"
> +#include "base/logtrace_buffer.h"
>  #include "base/macros.h"
>  #include "base/mutex.h"
> +#include "base/unix_client_socket.h"
>  
>  // A class implements trace/log client that communicates to the log
> server
>  // running in osaftransportd.
> -class TraceLog {
> +class LogTraceBuffer;
> +
> +class LogTraceClient {
>   public:
>    enum WriteMode {
> -    kBlocking = base::UnixSocket::Mode::kBlocking,
> -    kNonblocking = base::UnixSocket::Mode::kNonblocking,
> +    kRemoteBlocking = base::UnixSocket::Mode::kBlocking,
> +    kRemoteNonblocking = base::UnixSocket::Mode::kNonblocking,
> +    kLocalBuffer
>    };
> -  bool Init(const char *msg_id, WriteMode mode);
> -  static void Log(TraceLog* tracelog, base::LogMessage::Severity
> severity,
> -      const char *fmt, va_list ap);
> -  void Log(base::LogMessage::Severity severity, const char *fmt,
> +  LogTraceClient(const char *msg_id, WriteMode mode);
> +  ~LogTraceClient();
> +
> +  static const char* Log(LogTraceClient* tracelog,
> +      base::LogMessage::Severity severity, const char *fmt, va_list
> ap);
> +  const char* Log(base::LogMessage::Severity severity, const char
> *fmt,
>                    va_list ap);
> -  TraceLog();
> -  ~TraceLog();
> +  const char* CreateLogEntry(base::LogMessage::Severity severity,
> +      const char *fmt, va_list ap);
> +  void AddExternalBuffer(int64_t tid, LogTraceBuffer* buffer);
> +  void RemoveExternalBuffer(int64_t tid);
> +  void RequestFlushExternalBuffer();
> +
> +  const char* app_name() const { return app_name_.data(); }
> +  const char* proc_id() const { return proc_id_.data(); }
> +
> +  bool FlushExternalBuffer();
>  
>   private:
> -  void LogInternal(base::LogMessage::Severity severity, const char
> *fmt,
> -                     va_list ap);
> +  bool Init(const char *msg_id, WriteMode mode);
> +  const char* LogInternal(base::LogMessage::Severity severity, const
> char *fmt,
> +      va_list ap);
> +  const char* CreateLogEntryInternal(base::LogMessage::Severity
> severity,
> +      const char *fmt, va_list ap);
>    static constexpr const uint32_t kMaxSequenceId =
> uint32_t{0x7fffffff};
>    base::LogMessage::HostName fqdn_{""};
>    base::LogMessage::AppName app_name_{""};
> @@ -50,8 +68,12 @@ class TraceLog {
>    uint32_t sequence_id_;
>    base::UnixClientSocket* log_socket_;
>    base::Buffer<512> buffer_;
> -  base::Mutex* mutex_;
> -  DELETE_COPY_AND_MOVE_OPERATORS(TraceLog);
> +  base::Mutex* log_mutex_;
> +
> +  std::map<int64_t, LogTraceBuffer*> ext_buffer_map_;
> +  base::Mutex* ext_buffer_mutex_;
> +
> +  DELETE_COPY_AND_MOVE_OPERATORS(LogTraceClient);
>  };
>  
>  #endif  // BASE_LOGTRACE_CLIENT_H_
> diff --git a/src/dtm/Makefile.am b/src/dtm/Makefile.am
> index f925e51..847f6d6 100644
> --- a/src/dtm/Makefile.am
> +++ b/src/dtm/Makefile.am
> @@ -31,7 +31,6 @@ noinst_HEADERS += \
>       src/dtm/dtmnd/dtm_node.h \
>       src/dtm/dtmnd/multicast.h \
>       src/dtm/transport/log_server.h \
> -     src/dtm/transport/log_writer.h \
>       src/dtm/transport/tests/mock_logtrace.h \
>       src/dtm/transport/tests/mock_osaf_poll.h \
>       src/dtm/transport/transport_monitor.h
> @@ -67,7 +66,6 @@ bin_osaftransportd_CPPFLAGS = \
>  
>  bin_osaftransportd_SOURCES = \
>       src/dtm/transport/log_server.cc \
> -     src/dtm/transport/log_writer.cc \
>       src/dtm/transport/main.cc \
>       src/dtm/transport/transport_monitor.cc
>  
> @@ -107,7 +105,6 @@ bin_transport_test_CPPFLAGS = \
>  bin_transport_test_LDFLAGS = \
>       $(AM_LDFLAGS) \
>       src/base/lib_libopensaf_core_la-getenv.lo \
> -     src/dtm/transport/bin_osaftransportd-log_writer.o \
>       src/dtm/transport/bin_osaftransportd-transport_monitor.o
>  
>  bin_transport_test_SOURCES = \
> diff --git a/src/dtm/transport/log_server.h
> b/src/dtm/transport/log_server.h
> index 793465d..bbc3af8 100644
> --- a/src/dtm/transport/log_server.h
> +++ b/src/dtm/transport/log_server.h
> @@ -26,7 +26,7 @@
>  #include "base/macros.h"
>  #include "base/unix_server_socket.h"
>  #include "dtm/common/osaflog_protocol.h"
> -#include "dtm/transport/log_writer.h"
> +#include "base/log_writer.h"
>  
>  // This class implements a loop that receives log messages over a
> UNIX socket
>  // and sends them to a LogWriter instance.
> diff --git a/src/dtm/transport/log_writer.cc
> b/src/dtm/transport/log_writer.cc
> deleted file mode 100644
> index 0195c25..0000000
> --- a/src/dtm/transport/log_writer.cc
> +++ /dev/null
> @@ -1,117 +0,0 @@
> -/*      -*- OpenSAF  -*-
> - *
> - * (C) Copyright 2016 The OpenSAF Foundation
> - * Copyright Ericsson AB 2017 - All Rights Reserved.
> - *
> - * This program is distributed in the hope that it will be useful,
> but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> - * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> - * under the GNU Lesser General Public License Version 2.1, February
> 1999.
> - * The complete license can be accessed from the following location:
> - * http://opensource.org/licenses/lgpl-license.php
> - * See the Copying file included with the OpenSAF distribution for
> full
> - * licensing terms.
> - *
> - * Author(s): Ericsson AB
> - *
> - */
> -
> -#include <fcntl.h>
> -#include <sys/stat.h>
> -#include <unistd.h>
> -#include <cerrno>
> -#include <cstdio>
> -#include "base/getenv.h"
> -#include "osaf/configmake.h"
> -#include "dtm/transport/log_writer.h"
> -#include "dtm/transport/log_server.h"
> -
> -LogWriter::LogWriter(const std::string& log_name, size_t
> max_backups,
> -                                                  size_t
> max_file_size)
> -    : log_file_{base::GetEnv<std::string>("pkglogdir", PKGLOGDIR) +
> "/" +
> -                log_name},
> -      fd_{-1},
> -      current_file_size_{0},
> -      current_buffer_size_{0},
> -      max_backups_{max_backups},
> -      max_file_size_{max_file_size},
> -      buffer_{new char[kBufferSize]} {}
> -
> -LogWriter::~LogWriter() {
> -  Flush();
> -  Close();
> -  delete[] buffer_;
> -}
> -
> -std::string LogWriter::log_file(size_t backup) const {
> -  std::string file_name = log_file_;
> -  if (backup != 0) {
> -    file_name += std::string(".") + std::to_string(backup);
> -  }
> -  return file_name;
> -}
> -
> -void LogWriter::Open() {
> -  if (fd_ < 0) {
> -    int fd;
> -    do {
> -      fd = open(log_file(0).c_str(), O_WRONLY | O_CLOEXEC | O_CREAT,
> -                S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH |
> S_IWOTH);
> -    } while (fd == -1 && errno == EINTR);
> -    if (fd >= 0) {
> -      off_t seek_result = lseek(fd, 0, SEEK_END);
> -      if (seek_result >= 0) current_file_size_ = seek_result;
> -      fd_ = fd;
> -    }
> -  }
> -}
> -
> -void LogWriter::Close() {
> -  int fd = fd_;
> -  if (fd >= 0) {
> -    close(fd);
> -    fd_ = -1;
> -    current_file_size_ = 0;
> -  }
> -}
> -
> -void LogWriter::RotateLog() {
> -  Close();
> -  unlink(log_file(max_backups_).c_str());
> -  for (size_t i = max_backups_; i != 0; --i) {
> -    std::string backup_name = log_file(i);
> -    std::string previous_backup = log_file(i - 1);
> -    if (rename(previous_backup.c_str(), backup_name.c_str()) != 0) {
> -      unlink(previous_backup.c_str());
> -    }
> -  }
> -}
> -
> -void LogWriter::Write(size_t size) {
> -  current_buffer_size_ += size;
> -  if (current_buffer_size_ > kBufferSize - kMaxMessageSize ||
> -      current_buffer_size_ >= max_file_size_) Flush();
> -}
> -
> -void LogWriter::Flush() {
> -  size_t size = current_buffer_size_;
> -  current_buffer_size_ = 0;
> -  if (size == 0) return;
> -  if (fd_ < 0) Open();
> -  if (fd_ < 0) return;
> -  if (current_file_size_ >= max_file_size_) {
> -    RotateLog();
> -    if (fd_ < 0) Open();
> -    if (fd_ < 0) return;
> -  }
> -  size_t bytes_written = 0;
> -  while (bytes_written < size) {
> -    ssize_t result = write(fd_, buffer_ + bytes_written, size -
> bytes_written);
> -    if (result < 0) {
> -      if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
> continue;
> -      break;
> -    }
> -    bytes_written += result;
> -  }
> -  current_file_size_ += bytes_written;
> -}
> diff --git a/src/dtm/transport/log_writer.h
> b/src/dtm/transport/log_writer.h
> deleted file mode 100644
> index e70f9c2..0000000
> --- a/src/dtm/transport/log_writer.h
> +++ /dev/null
> @@ -1,64 +0,0 @@
> -/*      -*- OpenSAF  -*-
> - *
> - * (C) Copyright 2016 The OpenSAF Foundation
> - * Copyright Ericsson AB 2017 - All Rights Reserved.
> - *
> - * This program is distributed in the hope that it will be useful,
> but
> - * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> - * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> - * under the GNU Lesser General Public License Version 2.1, February
> 1999.
> - * The complete license can be accessed from the following location:
> - * http://opensource.org/licenses/lgpl-license.php
> - * See the Copying file included with the OpenSAF distribution for
> full
> - * licensing terms.
> - *
> - * Author(s): Ericsson AB
> - *
> - */
> -
> -#ifndef DTM_TRANSPORT_LOG_WRITER_H_
> -#define DTM_TRANSPORT_LOG_WRITER_H_
> -
> -#include <cstddef>
> -#include <string>
> -#include "base/macros.h"
> -
> -// This class is responsible for writing MDS log messages to disk,
> and rotating
> -// the log file when it exceeds the maximum file size limit.
> -class LogWriter {
> - public:
> -  constexpr static const size_t kMaxMessageSize = 2 * size_t{1024};
> -
> -  LogWriter(const std::string& log_name, size_t max_backups,
> -                                          size_t max_file_size);
> -  virtual ~LogWriter();
> -
> -  char* current_buffer_position() { return buffer_ +
> current_buffer_size_; }
> -  bool empty() const { return current_buffer_size_ == 0; }
> -
> -  // Write @a size bytes of log message data in the memory pointed
> to by @a
> -  // buffer to the MDS log file. After the log message has been
> written, the
> -  // file will be rotated if necessary. This method performs
> blocking file I/O.
> -  void Write(size_t size);
> -  void Flush();
> -
> - private:
> -  constexpr static const size_t kBufferSize = 128 * size_t{1024};
> -  void Open();
> -  void Close();
> -  void RotateLog();
> -
> -  std::string log_file(size_t backup) const;
> -
> -  const std::string log_file_;
> -  int fd_;
> -  size_t current_file_size_;
> -  size_t current_buffer_size_;
> -  size_t max_backups_;
> -  size_t max_file_size_;
> -  char* buffer_;
> -
> -  DELETE_COPY_AND_MOVE_OPERATORS(LogWriter);
> -};
> -
> -#endif  // DTM_TRANSPORT_LOG_WRITER_H_
> diff --git a/src/dtm/transport/tests/log_writer_test.cc
> b/src/dtm/transport/tests/log_writer_test.cc
> index e96831e..93bf21c 100644
> --- a/src/dtm/transport/tests/log_writer_test.cc
> +++ b/src/dtm/transport/tests/log_writer_test.cc
> @@ -17,7 +17,7 @@
>  #include <cstring>
>  #include <fstream>
>  #include <string>
> -#include "dtm/transport/log_writer.h"
> +#include "base/log_writer.h"
>  #include "gtest/gtest.h"
>  
>  class LogWriterTest : public ::testing::Test {
> diff --git a/src/mds/mds_log.cc b/src/mds/mds_log.cc
> index 24bc398..5350a22 100644
> --- a/src/mds/mds_log.cc
> +++ b/src/mds/mds_log.cc
> @@ -29,7 +29,7 @@
>  #include "mds/mds_papi.h"
>  
>  int gl_mds_log_level = 3;
> -TraceLog* gl_mds_log = nullptr;
> +LogTraceClient* gl_mds_log = nullptr;
>  
>  /*******************************************************************
> ************
>   * Funtion Name   :    mds_log_init
> @@ -40,9 +40,9 @@ TraceLog* gl_mds_log = nullptr;
>   *
>  
> *********************************************************************
> **********/
>  uint32_t mds_log_init(const char *) {
> -  if (!gl_mds_log) gl_mds_log = new TraceLog();
> -  if (!gl_mds_log->Init("mds.log", TraceLog::kNonblocking)) {
> -    return NCSCC_RC_FAILURE;
> +  if (!gl_mds_log) {
> +    gl_mds_log = new LogTraceClient("mds.log",
> +        LogTraceClient::kRemoteNonblocking);
>    }
>    tzset();
>    log_mds_notify("BEGIN MDS LOGGING| ARCHW=%x|64bit=%zu\n",
> MDS_SELF_ARCHWORD,
> @@ -62,7 +62,7 @@ void log_mds_critical(const char *fmt, ...) {
>    if (gl_mds_log_level < NCSMDS_LC_CRITICAL) return;
>    va_list ap;
>    va_start(ap, fmt);
> -  TraceLog::Log(gl_mds_log, base::LogMessage::Severity::kCrit, fmt,
> ap);
> +  LogTraceClient::Log(gl_mds_log, base::LogMessage::Severity::kCrit,
> fmt, ap);
>    va_end(ap);
>  }
>  
> @@ -78,7 +78,7 @@ void log_mds_err(const char *fmt, ...) {
>    if (gl_mds_log_level < NCSMDS_LC_ERR) return;
>    va_list ap;
>    va_start(ap, fmt);
> -  TraceLog::Log(gl_mds_log, base::LogMessage::Severity::kErr, fmt,
> ap);
> +  LogTraceClient::Log(gl_mds_log, base::LogMessage::Severity::kErr,
> fmt, ap);
>    va_end(ap);
>  }
>  
> @@ -94,7 +94,7 @@ void log_mds_notify(const char *fmt, ...) {
>    if (gl_mds_log_level < NCSMDS_LC_NOTIFY) return;
>    va_list ap;
>    va_start(ap, fmt);
> -  TraceLog::Log(gl_mds_log, base::LogMessage::Severity::kNotice,
> fmt, ap);
> +  LogTraceClient::Log(gl_mds_log,
> base::LogMessage::Severity::kNotice, fmt, ap);
>    va_end(ap);
>  }
>  
> @@ -110,7 +110,7 @@ void log_mds_info(const char *fmt, ...) {
>    if (gl_mds_log_level < NCSMDS_LC_INFO) return;
>    va_list ap;
>    va_start(ap, fmt);
> -  TraceLog::Log(gl_mds_log, base::LogMessage::Severity::kInfo, fmt,
> ap);
> +  LogTraceClient::Log(gl_mds_log, base::LogMessage::Severity::kInfo,
> fmt, ap);
>    va_end(ap);
>  }
>  
> @@ -127,6 +127,6 @@ void log_mds_dbg(const char *fmt, ...) {
>    if (gl_mds_log_level < NCSMDS_LC_DBG) return;
>    va_list ap;
>    va_start(ap, fmt);
> -  TraceLog::Log(gl_mds_log, base::LogMessage::Severity::kDebug, fmt,
> ap);
> +  LogTraceClient::Log(gl_mds_log,
> base::LogMessage::Severity::kDebug, fmt, ap);
>    va_end(ap);
>  }
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to