Fix WinEnv::NowMicrosec

* std::chrono does not provide enough granularity for microsecs and periodically emits
    duplicates
  * the bug is manifested in log rotation logic where we get duplicate
   log file names and loose previous log content
  * msvc does not imlement COW on std::strings adjusted the test to use
    refs in the loops as auto does not retain ref info
  * adjust auto_log rotation test with Windows specific command to remove
    a folder. The test previously worked because we have unix utils installed
    in house but this may not be the case for everyone.
main
Dmitri Smirnov 10 years ago
parent fe09a6dae3
commit 555ca3e7b7
  1. 13
      port/win/env_win.cc
  2. 2
      util/auto_roll_logger.cc
  3. 27
      util/auto_roll_logger_test.cc

@ -1976,9 +1976,16 @@ class WinEnv : public Env {
}
virtual uint64_t NowMicros() override {
using namespace std::chrono;
return duration_cast<microseconds>(system_clock::now().time_since_epoch())
.count();
// all std::chrono clocks on windows have the same resolution that is only
// On Windows 8 and Windows 2012 Server
// GetSystemTimePreciseAsFileTime(&current_time) can be used
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
// Convert to nanoseconds first to avoid loss of precision
// and divide by frequency
li.QuadPart *= std::micro::den;
li.QuadPart /= perf_counter_frequency_;
return li.QuadPart;
}
virtual uint64_t NowNanos() override {

@ -91,7 +91,7 @@ void AutoRollLogger::Logv(const char* format, va_list ap) {
void AutoRollLogger::WriteHeaderInfo() {
mutex_.AssertHeld();
for (auto header : headers_) {
for (auto& header : headers_) {
LogInternal("%s", header.c_str());
}
}

@ -23,7 +23,17 @@ namespace rocksdb {
class AutoRollLoggerTest : public testing::Test {
public:
static void InitTestDb() {
string deleteCmd = "rm -rf " + kTestDir;
#ifdef OS_WIN
// Replace all slashes in the path so windows CompSpec does not
// become confused
std::string testDir(kTestDir);
std::replace_if(testDir.begin(), testDir.end(),
[](char ch) { return ch == '/'; },
'\\');
std::string deleteCmd = "if exist " + testDir + " rd /s /q " + testDir;
#else
std::string deleteCmd = "rm -rf " + kTestDir;
#endif
ASSERT_TRUE(system(deleteCmd.c_str()) == 0);
Env::Default()->CreateDir(kTestDir);
}
@ -296,17 +306,18 @@ TEST_F(AutoRollLoggerTest, InfoLogLevel) {
// Test the logger Header function for roll over logs
// We expect the new logs creates as roll over to carry the headers specified
static list<string> GetOldFileNames(const string& path) {
static std::vector<string> GetOldFileNames(const string& path) {
std::vector<string> ret;
const string dirname = path.substr(/*start=*/ 0, path.find_last_of("/"));
const string fname = path.substr(path.find_last_of("/") + 1);
vector<string> children;
std::vector<string> children;
Env::Default()->GetChildren(dirname, &children);
// We know that the old log files are named [path]<something>
// Return all entities that match the pattern
list<string> ret;
for (auto child : children) {
for (auto& child : children) {
if (fname != child && child.find(fname) == 0) {
ret.push_back(dirname + "/" + child);
}
@ -360,7 +371,7 @@ TEST_F(AutoRollLoggerTest, LogHeaderTest) {
}
}
const string& newfname = logger.TEST_log_fname().c_str();
const string newfname = logger.TEST_log_fname();
// Log enough data to cause a roll over
int i = 0;
@ -376,11 +387,11 @@ TEST_F(AutoRollLoggerTest, LogHeaderTest) {
// Flush the log for the latest file
LogFlush(&logger);
const list<string> oldfiles = GetOldFileNames(newfname);
const auto oldfiles = GetOldFileNames(newfname);
ASSERT_EQ(oldfiles.size(), (size_t) 2);
for (auto oldfname : oldfiles) {
for (auto& oldfname : oldfiles) {
// verify that the files rolled over
ASSERT_NE(oldfname, newfname);
// verify that the old log contains all the header logs

Loading…
Cancel
Save