From 502d41f1503d7d65e91a47b6d6ba9faf1c0471dd Mon Sep 17 00:00:00 2001 From: Tomas Kolda Date: Wed, 27 Jan 2016 13:36:22 +0100 Subject: [PATCH 1/3] Making use of GetSystemTimePreciseAsFileTime dynamic to not break compatibility with Windows 7. The issue with rotated logs was fixed other way. --- db/auto_roll_logger.cc | 13 ++++++++-- port/win/env_win.cc | 59 ++++++++++++++++++++++++++++-------------- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/db/auto_roll_logger.cc b/db/auto_roll_logger.cc index cf92f34c8..c984b4810 100644 --- a/db/auto_roll_logger.cc +++ b/db/auto_roll_logger.cc @@ -32,8 +32,17 @@ Status AutoRollLogger::ResetLogger() { } void AutoRollLogger::RollLogFile() { - std::string old_fname = OldInfoLogFileName( - dbname_, env_->NowMicros(), db_absolute_path_, db_log_dir_); + uint64_t now = env_->NowMicros(); + std::string old_fname; + // Try to check target name only 10 times at most + for (int i = 0; i < 10; i++) { + old_fname = OldInfoLogFileName( + dbname_, now, db_absolute_path_, db_log_dir_); + if (!env_->FileExists(old_fname).ok()) { + break; + } + now++; + }; env_->RenameFile(log_fname_, old_fname); } diff --git a/port/win/env_win.cc b/port/win/env_win.cc index 50059a98f..87a25569c 100644 --- a/port/win/env_win.cc +++ b/port/win/env_win.cc @@ -1138,6 +1138,8 @@ void WinthreadCall(const char* label, std::error_code result) { } } +typedef VOID(WINAPI * FnGetSystemTimePreciseAsFileTime)(LPFILETIME); + class WinEnv : public Env { public: WinEnv(); @@ -1676,25 +1678,29 @@ class WinEnv : public Env { } virtual uint64_t NowMicros() override { - // all std::chrono clocks on windows proved to return - // values that may repeat that is not good enough for some uses. - const int64_t c_UnixEpochStartTicks = 116444736000000000i64; - const int64_t c_FtToMicroSec = 10; - - // This interface needs to return system time and not - // just any microseconds because it is often used as an argument - // to TimedWait() on condition variable - FILETIME ftSystemTime; - GetSystemTimePreciseAsFileTime(&ftSystemTime); - - LARGE_INTEGER li; - li.LowPart = ftSystemTime.dwLowDateTime; - li.HighPart = ftSystemTime.dwHighDateTime; - // Subtract unix epoch start - li.QuadPart -= c_UnixEpochStartTicks; - // Convert to microsecs - li.QuadPart /= c_FtToMicroSec; - return li.QuadPart; + if (GetSystemTimePreciseAsFileTime_ != NULL) { + // all std::chrono clocks on windows proved to return + // values that may repeat that is not good enough for some uses. + const int64_t c_UnixEpochStartTicks = 116444736000000000i64; + const int64_t c_FtToMicroSec = 10; + + // This interface needs to return system time and not + // just any microseconds because it is often used as an argument + // to TimedWait() on condition variable + FILETIME ftSystemTime; + GetSystemTimePreciseAsFileTime_(&ftSystemTime); + + LARGE_INTEGER li; + li.LowPart = ftSystemTime.dwLowDateTime; + li.HighPart = ftSystemTime.dwHighDateTime; + // Subtract unix epoch start + li.QuadPart -= c_UnixEpochStartTicks; + // Convert to microsecs + li.QuadPart /= c_FtToMicroSec; + return li.QuadPart; + } + using namespace std::chrono; + return duration_cast(system_clock::now().time_since_epoch()).count(); } virtual uint64_t NowNanos() override { @@ -2104,8 +2110,13 @@ class WinEnv : public Env { std::vector thread_pools_; mutable std::mutex mu_; std::vector threads_to_join_; + static FnGetSystemTimePreciseAsFileTime GetSystemTimePreciseAsFileTime_; + static bool GetSystemTimePreciseAsFileTimeInitialized_; }; +FnGetSystemTimePreciseAsFileTime WinEnv::GetSystemTimePreciseAsFileTime_ = NULL; +bool WinEnv::GetSystemTimePreciseAsFileTimeInitialized_ = false; + WinEnv::WinEnv() : checkedDiskForMmap_(false), forceMmapOff(false), @@ -2113,6 +2124,16 @@ WinEnv::WinEnv() allocation_granularity_(page_size_), perf_counter_frequency_(0), thread_pools_(Priority::TOTAL) { + + if (!GetSystemTimePreciseAsFileTimeInitialized_) { + HMODULE module = GetModuleHandle("kernel32.dll"); + if (module != NULL) { + GetSystemTimePreciseAsFileTime_ = (FnGetSystemTimePreciseAsFileTime)GetProcAddress( + module, "GetSystemTimePreciseAsFileTime"); + } + GetSystemTimePreciseAsFileTimeInitialized_ = true; + } + SYSTEM_INFO sinfo; GetSystemInfo(&sinfo); From 57a95a700155345c658936a3b2ca492f36192691 Mon Sep 17 00:00:00 2001 From: Tomas Kolda Date: Wed, 27 Jan 2016 21:00:42 +0100 Subject: [PATCH 2/3] Making use of GetSystemTimePreciseAsFileTime dynamic - code review fixes --- db/auto_roll_logger.cc | 4 +++- port/win/env_win.cc | 20 +++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/db/auto_roll_logger.cc b/db/auto_roll_logger.cc index c984b4810..b8ba14c83 100644 --- a/db/auto_roll_logger.cc +++ b/db/auto_roll_logger.cc @@ -32,9 +32,11 @@ Status AutoRollLogger::ResetLogger() { } void AutoRollLogger::RollLogFile() { + // This function is called when log is rotating. Two rotations + // can happen quickly (NowMicro returns same value). To not overwrite + // previous log file we increment by one micro second and try again. uint64_t now = env_->NowMicros(); std::string old_fname; - // Try to check target name only 10 times at most for (int i = 0; i < 10; i++) { old_fname = OldInfoLogFileName( dbname_, now, db_absolute_path_, db_log_dir_); diff --git a/port/win/env_win.cc b/port/win/env_win.cc index 87a25569c..1ae0b1932 100644 --- a/port/win/env_win.cc +++ b/port/win/env_win.cc @@ -2110,28 +2110,22 @@ class WinEnv : public Env { std::vector thread_pools_; mutable std::mutex mu_; std::vector threads_to_join_; - static FnGetSystemTimePreciseAsFileTime GetSystemTimePreciseAsFileTime_; - static bool GetSystemTimePreciseAsFileTimeInitialized_; + FnGetSystemTimePreciseAsFileTime GetSystemTimePreciseAsFileTime_; }; -FnGetSystemTimePreciseAsFileTime WinEnv::GetSystemTimePreciseAsFileTime_ = NULL; -bool WinEnv::GetSystemTimePreciseAsFileTimeInitialized_ = false; - WinEnv::WinEnv() : checkedDiskForMmap_(false), forceMmapOff(false), page_size_(4 * 1012), allocation_granularity_(page_size_), perf_counter_frequency_(0), - thread_pools_(Priority::TOTAL) { + thread_pools_(Priority::TOTAL), + GetSystemTimePreciseAsFileTime_(NULL) { - if (!GetSystemTimePreciseAsFileTimeInitialized_) { - HMODULE module = GetModuleHandle("kernel32.dll"); - if (module != NULL) { - GetSystemTimePreciseAsFileTime_ = (FnGetSystemTimePreciseAsFileTime)GetProcAddress( - module, "GetSystemTimePreciseAsFileTime"); - } - GetSystemTimePreciseAsFileTimeInitialized_ = true; + HMODULE module = GetModuleHandle("kernel32.dll"); + if (module != NULL) { + GetSystemTimePreciseAsFileTime_ = (FnGetSystemTimePreciseAsFileTime)GetProcAddress( + module, "GetSystemTimePreciseAsFileTime"); } SYSTEM_INFO sinfo; From a62c519bb6129bce4f2300cb07c305ad6c0c945b Mon Sep 17 00:00:00 2001 From: Tomas Kolda Date: Tue, 2 Feb 2016 10:33:49 +0100 Subject: [PATCH 3/3] RollLogFile tries to find non conflicting file until there is no conflict. --- db/auto_roll_logger.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/db/auto_roll_logger.cc b/db/auto_roll_logger.cc index b8ba14c83..2349bd0c0 100644 --- a/db/auto_roll_logger.cc +++ b/db/auto_roll_logger.cc @@ -37,14 +37,11 @@ void AutoRollLogger::RollLogFile() { // previous log file we increment by one micro second and try again. uint64_t now = env_->NowMicros(); std::string old_fname; - for (int i = 0; i < 10; i++) { + do { old_fname = OldInfoLogFileName( dbname_, now, db_absolute_path_, db_log_dir_); - if (!env_->FileExists(old_fname).ok()) { - break; - } now++; - }; + } while (env_->FileExists(old_fname).ok()); env_->RenameFile(log_fname_, old_fname); }