diff --git a/src/leveldb/util/env_posix.cc b/src/leveldb/util/env_posix.cc index cfbe4f1f3..9879ceee9 100644 --- a/src/leveldb/util/env_posix.cc +++ b/src/leveldb/util/env_posix.cc @@ -783,6 +783,10 @@ class PosixEnv : public Env { } virtual Status NewLogger(const std::string& fname, Logger** result) { + *result = new EnhancePosixLogger(fname, &PosixEnv::gettid); + return Status::OK(); + + /* FILE* f = fopen(fname.c_str(), "w"); if (f == NULL) { *result = NULL; @@ -791,6 +795,7 @@ class PosixEnv : public Env { *result = new PosixLogger(f, &PosixEnv::gettid); return Status::OK(); } + */ } virtual void SetLogger(Logger* logger) { Logger::SetDefaultLogger(logger); diff --git a/src/leveldb/util/posix_logger.h b/src/leveldb/util/posix_logger.h index 2f06e1da7..78f7d08fb 100644 --- a/src/leveldb/util/posix_logger.h +++ b/src/leveldb/util/posix_logger.h @@ -12,11 +12,14 @@ #ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ #define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_ -#include #include #include #include +#include +#include #include "leveldb/env.h" +#include "port/port.h" +#include "util/mutexlock.h" namespace leveldb { @@ -101,6 +104,101 @@ class PosixLogger : public Logger { } }; +class EnhancePosixLogger : public Logger { + private: + port::Mutex mutex_; + std::string fname_; + uint64_t (*gettid_)(); // Return the thread id for the current thread + int64_t log_size_; + uint64_t log_count_; + int64_t cur_log_size_; + Logger* logger_; + std::set log_list_; + char* logbuf_; + public: + EnhancePosixLogger(const std::string& fname, uint64_t (*gettid)(), + int64_t log_size = 2000000000, int64_t log_count = 30) + : fname_(fname), + gettid_(gettid), + log_size_(log_size), + log_count_(log_count), + cur_log_size_(0), + logger_(NULL), + logbuf_(new char[30000]) {} + virtual ~EnhancePosixLogger() { + if (logger_) { + delete logger_; + } + delete[] logbuf_; + } + virtual void Logv(const char* format, va_list ap) { + TrySwitchLog(format, ap); + assert(logger_); + logger_->Logv(format, ap); + } + + private: + void TrySwitchLog(const char* format, va_list ap) { + // try switch log + MutexLock l(&mutex_); + if (logger_ == NULL || cur_log_size_ > log_size_) { + const uint64_t thread_id = (*gettid_)(); + char timebuf[64]; + char* p = timebuf; + + struct timeval now_tv; + gettimeofday(&now_tv, NULL); + const time_t seconds = now_tv.tv_sec; + struct tm t; + localtime_r(&seconds, &t); + p += snprintf(p, 64, +#ifdef OS_LINUX + "%04d-%02d-%02d-%02d:%02d:%02d:%06d.%llu", +#else + "%04d/%02d/%02d-%02d:%02d:%02d.%06d.%llx", +#endif + t.tm_year + 1900, + t.tm_mon + 1, + t.tm_mday, + t.tm_hour, + t.tm_min, + t.tm_sec, + static_cast(now_tv.tv_usec), + static_cast(thread_id)); + std::string logname(fname_ + "."); + logname.append(timebuf); + + Logger* slog = NULL; + FILE* f = fopen(logname.c_str(), "w"); + if (f) { + slog = new PosixLogger(f, gettid_); + if (logger_) { + delete logger_; + } + logger_ = slog; + cur_log_size_= 0; + log_list_.insert(logname); + + // try delete log + if (log_list_.size() > log_count_) { + std::set::iterator it = log_list_.begin(); + if (it != log_list_.end()) { + remove(it->c_str()); + } + } // evict oldest log + } // new log open suc + } + + char* pl = logbuf_; + char* limit = logbuf_ + 30000; + va_list backup_ap; + va_copy(backup_ap, ap); + pl += vsnprintf(pl, limit - pl, format, backup_ap); + va_end(backup_ap); + cur_log_size_ += (pl >= limit) ? 30000: (pl - logbuf_); + } +}; + } // namespace leveldb #endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_