Enable LevelDb to create a new log file if current log file is too large.

Summary: Enable LevelDb to create a new log file if current log file is too large.

Test Plan:
Write a script and manually check the generated info LOG.

Task ID: 1803577

Blame Rev:

Reviewers: dhruba, heyongqiang

Reviewed By: heyongqiang

CC: zshao

Differential Revision: https://reviews.facebook.net/D6003
main
Kai Liu 12 years ago
parent 3a91b78b23
commit d50f8eb603
  1. 40
      db/db_impl.cc
  2. 8
      include/leveldb/env.h
  3. 7
      include/leveldb/options.h
  4. 4
      util/options.cc
  5. 10
      util/posix_logger.h

@ -34,11 +34,40 @@
#include "util/logging.h" #include "util/logging.h"
#include "util/mutexlock.h" #include "util/mutexlock.h"
#include "util/build_version.h" #include "util/build_version.h"
#include "util/auto_split_logger.h"
namespace leveldb { namespace leveldb {
void dumpLeveldbBuildVersion(Logger * log); void dumpLeveldbBuildVersion(Logger * log);
static Status NewLogger(const std::string& dbname,
const std::string& db_log_dir,
Env* env,
size_t max_log_file_size,
Logger** logger) {
std::string db_absolute_path;
env->GetAbsolutePath(dbname, &db_absolute_path);
if (max_log_file_size > 0) { // need to auto split the log file?
AutoSplitLogger<Logger>* auto_split_logger =
new AutoSplitLogger<Logger>(env, dbname, db_log_dir, max_log_file_size);
Status s = auto_split_logger->GetStatus();
if (!s.ok()) {
delete auto_split_logger;
} else {
*logger = auto_split_logger;
}
return s;
} else {
// Open a log file in the same directory as the db
env->CreateDir(dbname); // In case it does not exist
std::string fname = InfoLogFileName(dbname, db_absolute_path, db_log_dir);
env->RenameFile(fname, OldInfoLogFileName(dbname, env->NowMicros(),
db_absolute_path, db_log_dir));
return env->NewLogger(fname, logger);
}
}
// Information kept for every waiting writer // Information kept for every waiting writer
struct DBImpl::Writer { struct DBImpl::Writer {
Status status; Status status;
@ -116,16 +145,9 @@ Options SanitizeOptions(const std::string& dbname,
ClipToRange(&result.max_open_files, 20, 50000); ClipToRange(&result.max_open_files, 20, 50000);
ClipToRange(&result.write_buffer_size, 64<<10, 1<<30); ClipToRange(&result.write_buffer_size, 64<<10, 1<<30);
ClipToRange(&result.block_size, 1<<10, 4<<20); ClipToRange(&result.block_size, 1<<10, 4<<20);
std::string db_absolute_path;
src.env->GetAbsolutePath(dbname, &db_absolute_path);
if (result.info_log == NULL) { if (result.info_log == NULL) {
// Open a log file in the same directory as the db Status s = NewLogger(dbname, result.db_log_dir, src.env,
src.env->CreateDir(dbname); // In case it does not exist result.max_log_file_size, &result.info_log);
src.env->RenameFile(InfoLogFileName(dbname, db_absolute_path,
result.db_log_dir), OldInfoLogFileName(dbname,src.env->NowMicros(),
db_absolute_path, result.db_log_dir));
Status s = src.env->NewLogger(InfoLogFileName(dbname, db_absolute_path,
result.db_log_dir), &result.info_log);
if (!s.ok()) { if (!s.ok()) {
// No place suitable for logging // No place suitable for logging
result.info_log = NULL; result.info_log = NULL;

@ -223,9 +223,9 @@ class WritableFile {
virtual Status Flush() = 0; virtual Status Flush() = 0;
virtual Status Sync() = 0; // sync data virtual Status Sync() = 0; // sync data
/* /*
* Sync data and/or metadata as well. * Sync data and/or metadata as well.
* By default, sync only metadata. * By default, sync only metadata.
* Override this method for environments where we need to sync * Override this method for environments where we need to sync
* metadata as well. * metadata as well.
*/ */
@ -249,11 +249,15 @@ class WritableFile {
// An interface for writing log messages. // An interface for writing log messages.
class Logger { class Logger {
public: public:
enum { DO_NOT_SUPPORT_GET_LOG_FILE_SIZE = -1 };
Logger() { } Logger() { }
virtual ~Logger(); virtual ~Logger();
// Write an entry to the log file with the specified format. // Write an entry to the log file with the specified format.
virtual void Logv(const char* format, va_list ap) = 0; virtual void Logv(const char* format, va_list ap) = 0;
virtual size_t GetLogFileSize() const {
return DO_NOT_SUPPORT_GET_LOG_FILE_SIZE;
}
private: private:
// No copying allowed // No copying allowed

@ -246,6 +246,13 @@ struct Options {
// every compaction run. // every compaction run.
uint64_t delete_obsolete_files_period_micros; uint64_t delete_obsolete_files_period_micros;
// Specify the maximal size of the info log file. If the log file
// is larger than `max_log_file_size`, a new info log file will
// be created.
// If max_log_file_size == 0, all logs will be written to one
// log file.
size_t max_log_file_size;
// Create an Options object with default values for all fields. // Create an Options object with default values for all fields.
Options(); Options();

@ -42,6 +42,7 @@ Options::Options()
db_stats_log_interval(1800), db_stats_log_interval(1800),
db_log_dir(""), db_log_dir(""),
disable_seek_compaction(false), disable_seek_compaction(false),
max_log_file_size(0),
delete_obsolete_files_period_micros(0) { delete_obsolete_files_period_micros(0) {
} }
@ -67,7 +68,8 @@ Options::Dump(
Log(log," Options.num_levels: %d", num_levels); Log(log," Options.num_levels: %d", num_levels);
Log(log," Options.disableDataSync: %d", disableDataSync); Log(log," Options.disableDataSync: %d", disableDataSync);
Log(log," Options.use_fsync: %d", use_fsync); Log(log," Options.use_fsync: %d", use_fsync);
Log(log," Options.db_stats_log_interval: %d", Log(log," Options.max_log_file_size: %d", max_log_file_size);
Log(log," Options.db_stats_log_interval: %d",
db_stats_log_interval); db_stats_log_interval);
Log(log," Options.level0_file_num_compaction_trigger: %d", Log(log," Options.level0_file_num_compaction_trigger: %d",
level0_file_num_compaction_trigger); level0_file_num_compaction_trigger);

@ -20,8 +20,11 @@ class PosixLogger : public Logger {
private: private:
FILE* file_; FILE* file_;
uint64_t (*gettid_)(); // Return the thread id for the current thread uint64_t (*gettid_)(); // Return the thread id for the current thread
size_t log_size_;
public: public:
PosixLogger(FILE* f, uint64_t (*gettid)()) : file_(f), gettid_(gettid) { } PosixLogger(FILE* f, uint64_t (*gettid)()) :
file_(f), gettid_(gettid), log_size_(0) { }
virtual ~PosixLogger() { virtual ~PosixLogger() {
fclose(file_); fclose(file_);
} }
@ -85,12 +88,17 @@ class PosixLogger : public Logger {
assert(p <= limit); assert(p <= limit);
fwrite(base, 1, p - base, file_); fwrite(base, 1, p - base, file_);
fflush(file_); fflush(file_);
log_size_ += (p - base);
if (base != buffer) { if (base != buffer) {
delete[] base; delete[] base;
} }
break; break;
} }
} }
size_t GetLogFileSize() const {
return log_size_;
}
}; };
} // namespace leveldb } // namespace leveldb

Loading…
Cancel
Save