summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTad Marshall <tad@10gen.com>2011-11-23 15:14:39 -0500
committerEliot Horowitz <eliot@10gen.com>2011-12-22 11:57:34 -0500
commit8cd62bc27c3cec5eba8a763c0529637ff6a6f8c3 (patch)
tree13793c4106ee28361c8a1e8d6724d7ad3fdf05b2
parenta719914879ba9fa847bb9df596df956506054acf (diff)
downloadmongo-8cd62bc27c3cec5eba8a763c0529637ff6a6f8c3.tar.gz
SERVER-2612 -- support logRotate under windows
Add code to support the "logRotate" server command (e.g. "db.runCommand({logRotate:1})"). Windows does not support the "kill -SIGUSR1 <pid>" alternative that is available in Linux.
-rw-r--r--util/log.cpp66
1 files changed, 41 insertions, 25 deletions
diff --git a/util/log.cpp b/util/log.cpp
index 51f59be239b..0dc75eddf6e 100644
--- a/util/log.cpp
+++ b/util/log.cpp
@@ -25,12 +25,16 @@ using namespace std;
#ifdef _WIN32
# include <io.h>
+# include <fcntl.h>
#else
# include <cxxabi.h>
# include <sys/file.h>
#endif
-//#include "../db/jsobj.h"
+#ifdef _WIN32
+# define dup2 _dup2 // Microsoft headers use ISO C names
+# define fileno _fileno
+#endif
namespace mongo {
@@ -85,60 +89,72 @@ namespace mongo {
}
if ( _file ) {
-#ifdef _WIN32
- cout << "log rotation net yet supported on windows" << endl;
- return;
-#else
#ifdef POSIX_FADV_DONTNEED
posix_fadvise(fileno(_file), 0, 0, POSIX_FADV_DONTNEED);
#endif
- struct tm t;
- localtime_r( &_opened , &t );
-
+ // Rename the (open) existing log file to a timestamped name
stringstream ss;
- ss << _path << "." << terseCurrentTime(false);
+ ss << _path << "." << terseCurrentTime( false );
string s = ss.str();
rename( _path.c_str() , s.c_str() );
-#endif
}
-
- FILE* tmp = freopen(_path.c_str(), (_append ? "a" : "w"), stdout);
- if (!tmp) {
+ FILE* tmp = 0; // The new file using the original logpath name
+
+#if _WIN32
+ // We rename an open log file (above, on next rotation) and the trick to getting Windows to do that is
+ // to open the file with FILE_SHARE_DELETE. So, we can't use the freopen() call that non-Windows
+ // versions use because it would open the file without the FILE_SHARE_DELETE flag we need.
+ //
+ HANDLE newFileHandle = CreateFileA(
+ _path.c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if ( INVALID_HANDLE_VALUE != newFileHandle ) {
+ int newFileDescriptor = _open_osfhandle( reinterpret_cast<intptr_t>(newFileHandle), _O_APPEND );
+ tmp = _fdopen( newFileDescriptor, _append ? "a" : "w" );
+ }
+#else
+ tmp = freopen(_path.c_str(), _append ? "a" : "w", stdout);
+#endif
+ if ( !tmp ) {
cerr << "can't open: " << _path.c_str() << " for log file" << endl;
dbexit( EXIT_BADOPTIONS );
- assert(0);
+ assert( 0 );
}
-#ifdef _WIN32 // windows has these functions it just gives them a funny name
-# define dup2 _dup2
-# define fileno _fileno
-#endif
- // redirect stderr to log file
- dup2(fileno(tmp), 2);
+ // redirect stdout and stderr to log file
+ dup2( fileno( tmp ), 1 ); // stdout
+ dup2( fileno( tmp ), 2 ); // stderr
Logstream::setLogFile(tmp); // after this point no thread will be using old file
+#if _WIN32
+ if ( _file )
+ fclose( _file ); // In Windows, we still have the old file open, close it now
+#endif
+
#if 0 // enable to test redirection
cout << "written to cout" << endl;
cerr << "written to cerr" << endl;
log() << "written to log()" << endl;
#endif
- _file = tmp;
- _opened = time(0);
+ _file = tmp; // Save new file for next rotation
}
private:
-
bool _enabled;
string _path;
bool _append;
-
FILE * _file;
- time_t _opened;
} loggingManager;