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