summaryrefslogtreecommitdiff
path: root/util/logfile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'util/logfile.cpp')
-rw-r--r--util/logfile.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/util/logfile.cpp b/util/logfile.cpp
new file mode 100644
index 0000000..0386a59
--- /dev/null
+++ b/util/logfile.cpp
@@ -0,0 +1,157 @@
+// @file logfile.cpp simple file log writing / journaling
+
+/**
+* Copyright (C) 2008 10gen Inc.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Affero General Public License, version 3,
+* as published by the Free Software Foundation.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Affero General Public License for more details.
+*
+* You should have received a copy of the GNU Affero General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "pch.h"
+#include "logfile.h"
+#include "text.h"
+#include "mongoutils/str.h"
+#include "unittest.h"
+
+using namespace mongoutils;
+
+namespace mongo {
+ struct LogfileTest : public UnitTest {
+ LogfileTest() { }
+ void run() {
+ if( 0 && debug ) {
+ try {
+ LogFile f("logfile_test");
+ void *p = malloc(16384);
+ char *buf = (char*) p;
+ buf += 4095;
+ buf = (char*) (((size_t)buf)&(~0xfff));
+ memset(buf, 'z', 8192);
+ buf[8190] = '\n';
+ buf[8191] = 'B';
+ buf[0] = 'A';
+ f.synchronousAppend(buf, 8192);
+ f.synchronousAppend(buf, 8192);
+ free(p);
+ }
+ catch(DBException& e ) {
+ log() << "logfile.cpp test failed : " << e.what() << endl;
+ throw;
+ }
+ }
+ }
+ } __test;
+}
+
+#if defined(_WIN32)
+
+namespace mongo {
+
+ LogFile::LogFile(string name) : _name(name) {
+ _fd = CreateFile(
+ toNativeString(name.c_str()).c_str(),
+ GENERIC_WRITE,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_ALWAYS,
+ FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
+ NULL);
+ if( _fd == INVALID_HANDLE_VALUE ) {
+ DWORD e = GetLastError();
+ uasserted(13518, str::stream() << "couldn't open file " << name << " for writing " << errnoWithDescription(e));
+ }
+ SetFilePointer(_fd, 0, 0, FILE_BEGIN);
+ }
+
+ LogFile::~LogFile() {
+ if( _fd != INVALID_HANDLE_VALUE )
+ CloseHandle(_fd);
+ }
+
+ void LogFile::synchronousAppend(const void *buf, size_t len) {
+ assert(_fd);
+ DWORD written;
+ if( !WriteFile(_fd, buf, len, &written, NULL) ) {
+ DWORD e = GetLastError();
+ if( e == 87 )
+ massert(13519, "error appending to file - misaligned direct write?", false);
+ else
+ uasserted(13517, str::stream() << "error appending to file " << errnoWithDescription(e));
+ }
+ else {
+ dassert( written == len );
+ }
+ }
+
+}
+
+#else
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+namespace mongo {
+
+ LogFile::LogFile(string name) : _name(name) {
+ _fd = open(name.c_str(),
+ O_CREAT
+ | O_WRONLY
+#if defined(O_DIRECT)
+ | O_DIRECT
+#endif
+#if defined(O_NOATIME)
+ | O_NOATIME
+#endif
+ ,
+ S_IRUSR | S_IWUSR);
+ if( _fd < 0 ) {
+ uasserted(13516, str::stream() << "couldn't open file " << name << " for writing " << errnoWithDescription());
+ }
+
+ }
+
+ LogFile::~LogFile() {
+ if( _fd >= 0 )
+ close(_fd);
+ _fd = -1;
+ }
+
+ void LogFile::synchronousAppend(const void *b, size_t len) {
+ const char *buf = (char *) b;
+ assert(_fd);
+ assert(((size_t)buf)%4096==0); // aligned
+ if( len % 4096 != 0 ) {
+ log() << len << ' ' << len % 4096 << endl;
+ assert(false);
+ }
+ ssize_t written = write(_fd, buf, len);
+ if( written != (ssize_t) len ) {
+ log() << "write fails written:" << written << " len:" << len << " buf:" << buf << ' ' << errnoWithDescription() << endl;
+ uasserted(13515, str::stream() << "error appending to file " << _fd << ' ' << errnoWithDescription());
+ }
+
+ if(
+#if defined(__linux__)
+ fdatasync(_fd) < 0
+#else
+ fsync(_fd)
+#endif
+ ) {
+ uasserted(13514, str::stream() << "error appending to file on fsync " << ' ' << errnoWithDescription());
+ }
+
+ }
+
+}
+
+#endif