[Groonga-commit] groonga/grnxx at 0019e13 [master] Update grnxx::Logger.

Back to archive index

susumu.yata null+****@clear*****
Mon Jul 1 15:05:52 JST 2013


susumu.yata	2013-07-01 15:05:52 +0900 (Mon, 01 Jul 2013)

  New Revision: 0019e13bd8c0715ca38fb1c4bbfd4af60367043d
  https://github.com/groonga/grnxx/commit/0019e13bd8c0715ca38fb1c4bbfd4af60367043d

  Message:
    Update grnxx::Logger.

  Modified files:
    lib/grnxx/logger.cpp
    lib/grnxx/logger.hpp

  Modified: lib/grnxx/logger.cpp (+99 -84)
===================================================================
--- lib/grnxx/logger.cpp    2013-07-01 15:05:03 +0900 (3962978)
+++ lib/grnxx/logger.cpp    2013-07-01 15:05:52 +0900 (5c54760)
@@ -17,11 +17,13 @@
 */
 #include "grnxx/logger.hpp"
 
-#include <ctime>
+#include <cstring>
 #include <fstream>
 #include <iostream>
 #include <memory>
+#include <new>
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "grnxx/backtrace.hpp"
@@ -32,71 +34,13 @@ namespace grnxx {
 
 class LoggerSingleton {
  public:
-  static bool write(const StringBuilder &builder) {
-    initialize_once();
-    Lock lock(&mutex_);
-    if (!instance_) {
-      return false;
-    }
-    static constexpr LoggerFlags OUTPUT_FLAGS =
-        LOGGER_ENABLE_COUT | LOGGER_ENABLE_CERR | LOGGER_ENABLE_CLOG;
-    const LoggerFlags flags = Logger::flags();
-    if (!(flags & OUTPUT_FLAGS)) {
-      if (!instance_->file_ || !*instance_->file_) {
-        return false;
-      }
-    }
+  static bool write(const StringBuilder &builder);
 
-    if (instance_->file_ && *instance_->file_) {
-      instance_->file_->write(builder.c_str(), builder.length()) << std::endl;
-    }
-    if (flags & LOGGER_ENABLE_COUT) {
-      std::cout.write(builder.c_str(), builder.length()) << '\n';
-    }
-    if (flags & LOGGER_ENABLE_CERR) {
-      std::cerr.write(builder.c_str(), builder.length()) << '\n';
-    }
-    if (flags & LOGGER_ENABLE_CLOG) {
-      std::clog.write(builder.c_str(), builder.length()) << '\n';
-    }
-    return true;
-  }
-
-  static bool open(const char *path) {
-    if (!path) {
-      return false;
-    }
-    initialize_once();
-    Lock lock(&mutex_);
-    if (!instance_) {
-      return false;
-    }
-    try {
-      std::string path_dummy(path);
-      std::unique_ptr<std::ofstream> file_dummy(
-          new (std::nothrow) std::ofstream(path_dummy.c_str(),
-              std::ios::out | std::ios::app | std::ios::binary));
-      if (!file_dummy || !*file_dummy) {
-        return false;
-      }
-      instance_->path_.swap(path_dummy);
-      instance_->file_.swap(file_dummy);
-      return true;
-    } catch (...) {
-      return false;
-    }
-  }
-  static void close() {
-    initialize_once();
-    Lock lock(&mutex_);
-    if (instance_) {
-      instance_->file_.reset();
-      instance_->path_.clear();
-    }
-  }
+  static bool open(const char *path);
+  static void close();
 
  private:
-  std::string path_;
+  std::unique_ptr<char[]> path_;
   std::unique_ptr<std::ofstream> file_;
 
   // These variables may be used even after the instance termination.
@@ -127,23 +71,89 @@ class LoggerSingleton {
     initialized_ = true;
   }
 
-  LoggerSingleton(const LoggerSingleton &);
-  LoggerSingleton &operator=(const LoggerSingleton &);
+  LoggerSingleton(const LoggerSingleton &) = delete;
+  LoggerSingleton &operator=(const LoggerSingleton &) = delete;
 };
 
-volatile bool LoggerSingleton::initialized_ = false;
+volatile bool LoggerSingleton::initialized_           = false;
 LoggerSingleton * volatile LoggerSingleton::instance_ = nullptr;
 Mutex LoggerSingleton::mutex_(MUTEX_UNLOCKED);
 
-LoggerFlags Logger::flags_ = LOGGER_DEFAULT;
-int Logger::max_level_ = NOTICE_LOGGER;
+bool LoggerSingleton::write(const StringBuilder &builder) {
+  initialize_once();
+  Lock lock(&mutex_);
+  if (!instance_) {
+    return false;
+  }
+  static constexpr LoggerFlags OUTPUT_FLAGS =
+      LOGGER_ENABLE_COUT | LOGGER_ENABLE_CERR | LOGGER_ENABLE_CLOG;
+  const LoggerFlags flags = Logger::flags();
+  if (!(flags & OUTPUT_FLAGS)) {
+    if (!instance_->file_ || !*instance_->file_) {
+      return false;
+    }
+  }
+  if (instance_->file_ && *instance_->file_) {
+    instance_->file_->write(builder.c_str(), builder.length()) << std::endl;
+  }
+  if (flags & LOGGER_ENABLE_COUT) {
+    std::cout.write(builder.c_str(), builder.length()) << '\n';
+  }
+  if (flags & LOGGER_ENABLE_CERR) {
+    std::cerr.write(builder.c_str(), builder.length()) << '\n';
+  }
+  if (flags & LOGGER_ENABLE_CLOG) {
+    std::clog.write(builder.c_str(), builder.length()) << '\n';
+  }
+  return true;
+}
+
+bool LoggerSingleton::open(const char *path) {
+  if (!path) {
+    return false;
+  }
+  initialize_once();
+  Lock lock(&mutex_);
+  if (!instance_) {
+    return false;
+  }
+  try {
+    const size_t buf_size = std::strlen(path) + 1;
+    std::unique_ptr<char[]> path_clone(new (std::nothrow) char[buf_size]);
+    if (!path_clone) {
+      return false;
+    }
+    std::memcpy(path_clone.get(), path, buf_size);
+    std::unique_ptr<std::ofstream> file_dummy(
+        new (std::nothrow) std::ofstream(path_clone.get(),
+            std::ios::out | std::ios::app | std::ios::binary));
+    if (!file_dummy || !*file_dummy) {
+      return false;
+    }
+    instance_->path_ = std::move(path_clone);
+    instance_->file_.swap(file_dummy);
+    return true;
+  } catch (...) {
+    return false;
+  }
+}
+
+void LoggerSingleton::close() {
+  initialize_once();
+  Lock lock(&mutex_);
+  if (instance_) {
+    instance_->file_.reset();
+    instance_->path_.reset();
+  }
+}
+
+LoggerFlags Logger::flags_   = LOGGER_DEFAULT;
+int Logger::max_level_       = NOTICE_LOGGER;
 int Logger::backtrace_level_ = ERROR_LOGGER;
 
 Logger::Logger(const char *file, int line, const char *func, int level)
     : buf_(),
-      builder_(buf_, ((Logger::flags() & LOGGER_ENABLE_AUTO_RESIZE) ?
-                      STRING_BUILDER_AUTO_RESIZE : STRING_BUILDER_DEFAULT) |
-                     STRING_BUILDER_NOEXCEPT),
+      builder_(buf_, string_builder_flags()),
       file_(file),
       line_(line),
       func_(func),
@@ -153,13 +163,7 @@ Logger::Logger(const char *file, int line, const char *func, int level)
 
 Logger::~Logger() {
   if (level_ <= backtrace_level()) {
-    std::vector<std::string> backtrace;
-    if (grnxx::Backtrace::pretty_backtrace(1, &backtrace)) {
-      builder_ << new_line() << backtrace[0].c_str();
-      for (size_t i = 1; i < backtrace.size(); ++i) {
-        builder_ << ", " << backtrace[i].c_str();
-      }
-    }
+    builder_ << backtrace();
   }
   LoggerSingleton::write(builder_);
 }
@@ -176,7 +180,6 @@ void Logger::append_line_header() {
   if (!builder_) {
     return;
   }
-
   const LoggerFlags flags = Logger::flags();
   if (flags & LOGGER_WITH_DATE_TIME) {
     builder_ << SystemClock::now().local_time() << ": ";
@@ -199,16 +202,26 @@ void Logger::append_line_header() {
         break;
       }
       default: {
-        builder_ << "unknown (" << level_ << "): ";
+        builder_ << "n/a (" << level_ << "): ";
         break;
       }
     }
   }
 }
 
+StringBuilderFlags Logger::string_builder_flags() {
+  StringBuilderFlags flags = STRING_BUILDER_NOEXCEPT;
+  if (Logger::flags() & LOGGER_ENABLE_AUTO_RESIZE) {
+    flags |= STRING_BUILDER_AUTO_RESIZE;
+  }
+  return flags;
+}
+
 StringBuilder &operator<<(StringBuilder &builder, const Logger::NewLine &) {
+  if (!builder) {
+    return builder;
+  }
   builder << '\n';
-
   Logger * const logger = reinterpret_cast<Logger *>(
       (reinterpret_cast<char *>(&builder) - LOGGER_BUF_SIZE));
   logger->append_line_header();
@@ -216,11 +229,13 @@ StringBuilder &operator<<(StringBuilder &builder, const Logger::NewLine &) {
 }
 
 StringBuilder &operator<<(StringBuilder &builder, const Logger::Backtrace &) {
+  if (!builder) {
+    return builder;
+  }
   std::vector<std::string> backtrace;
   if (Backtrace::pretty_backtrace(1, &backtrace)) {
-    builder << backtrace[0].c_str();
-    for (size_t i = 1; i < backtrace.size(); ++i) {
-      builder << ", " << backtrace[i].c_str();
+    for (size_t i = 0; i < backtrace.size(); ++i) {
+      builder << Logger::new_line() << backtrace[i].c_str();
     }
   }
   return builder;

  Modified: lib/grnxx/logger.hpp (+28 -13)
===================================================================
--- lib/grnxx/logger.hpp    2013-07-01 15:05:03 +0900 (642a46f)
+++ lib/grnxx/logger.hpp    2013-07-01 15:05:52 +0900 (e34f772)
@@ -24,39 +24,49 @@
 #include "grnxx/string_builder.hpp"
 #include "grnxx/types.hpp"
 
-#define GRNXX_ERROR()   GRNXX_LOGGER(::grnxx::ERROR_LOGGER)
-#define GRNXX_WARNING() GRNXX_LOGGER(::grnxx::WARNING_LOGGER)
-#define GRNXX_NOTICE()  GRNXX_LOGGER(::grnxx::NOTICE_LOGGER)
+#define GRNXX_ERROR()   GRNXX_LOGGER(grnxx::ERROR_LOGGER)
+#define GRNXX_WARNING() GRNXX_LOGGER(grnxx::WARNING_LOGGER)
+#define GRNXX_NOTICE()  GRNXX_LOGGER(grnxx::NOTICE_LOGGER)
 
 #define GRNXX_LOGGER(level)\
-  ((level) > ::grnxx::Logger::max_level()) ? (void)0 :\
-  ::grnxx::Logger::Voidify() &\
-  ::grnxx::Logger(__FILE__, __LINE__, __func__, (level)).builder()
+  ((level) > grnxx::Logger::max_level()) ? (void)0 :\
+  grnxx::Logger::Voidify() &\
+  grnxx::Logger(__FILE__, __LINE__, __func__, (level)).builder()
 
 namespace grnxx {
 
 constexpr size_t LOGGER_BUF_SIZE = 4096;
 
 enum LoggerLevel {
-  ERROR_LOGGER   = 0x0000,
-  WARNING_LOGGER = 0x0001,
-  NOTICE_LOGGER  = 0x0002
+  ERROR_LOGGER   = 0,
+  WARNING_LOGGER = 1,
+  NOTICE_LOGGER  = 2
 };
 
 class Logger;
 typedef FlagsImpl<Logger> LoggerFlags;
 
+// Use the default settings.
 constexpr LoggerFlags LOGGER_DEFAULT        = LoggerFlags::define(0x0000);
 
+// Logging with data and time.
 constexpr LoggerFlags LOGGER_WITH_DATE_TIME = LoggerFlags::define(0x0001);
+// Logging with __FILE__, __LINE__, and __func__.
 constexpr LoggerFlags LOGGER_WITH_LOCATION  = LoggerFlags::define(0x0002);
+// Logging with LoggerLevel.
 constexpr LoggerFlags LOGGER_WITH_LEVEL     = LoggerFlags::define(0x0004);
+// Enable all the LOGGER_WITH_* flags.
 constexpr LoggerFlags LOGGER_WITH_ALL       = LoggerFlags::define(0x0007);
 
+// Logging to the standard output.
 constexpr LoggerFlags LOGGER_ENABLE_COUT    = LoggerFlags::define(0x0100);
+// Logging to the standard error.
 constexpr LoggerFlags LOGGER_ENABLE_CERR    = LoggerFlags::define(0x0200);
+// Logging to the standard log.
 constexpr LoggerFlags LOGGER_ENABLE_CLOG    = LoggerFlags::define(0x0400);
 
+// Dynamically allocate memory when LOGGER_BUF_SIZE is not enough to store a
+// logging message.
 constexpr LoggerFlags LOGGER_ENABLE_AUTO_RESIZE = LoggerFlags::define(0x1000);
 
 class Logger {
@@ -64,7 +74,9 @@ class Logger {
   Logger(const char *file, int line, const char *func, int level);
   ~Logger();
 
+  // Open or create a file to which logs are written.
   static bool open(const char *path);
+  // Close a file opened with open().
   static void close();
 
   static LoggerFlags flags() {
@@ -97,8 +109,9 @@ class Logger {
     return Backtrace();
   }
 
-  class Voidify {
-   public:
+  // Use an operator&() to voidify StringBuilder.
+  // The operators & and << are both left-to-right and << is prior to &.
+  struct Voidify {
     void operator&(StringBuilder &) const {}
   };
 
@@ -120,8 +133,10 @@ class Logger {
   static int max_level_;
   static int backtrace_level_;
 
-  Logger(const Logger &);
-  Logger &operator=(const Logger &);
+  static StringBuilderFlags string_builder_flags();
+
+  Logger(const Logger &) = delete;
+  Logger &operator=(const Logger &) = delete;
 };
 
 // These operators must not be called with a regular (non-logger) builder.
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index