summaryrefslogtreecommitdiff
path: root/db
diff options
context:
space:
mode:
authordwight <dwight@10gen.com>2010-12-17 07:59:45 -0500
committerdwight <dwight@10gen.com>2010-12-17 08:00:06 -0500
commit4efaae056697c024920bfe387cf31d6ec37c749f (patch)
treebadfbff27a1a0c94788235f473cd3681cee7b9a7 /db
parent28904fa7ae991355a1043da387328ad98bb0ac84 (diff)
downloadmongo-4efaae056697c024920bfe387cf31d6ec37c749f.tar.gz
dur optimizing seeting context to local database as that will be super common case
Diffstat (limited to 'db')
-rw-r--r--db/dur.cpp17
-rw-r--r--db/dur.h62
-rw-r--r--db/dur_journalformat.h23
-rw-r--r--db/dur_recover.cpp41
-rw-r--r--db/mongommf.cpp4
5 files changed, 91 insertions, 56 deletions
diff --git a/db/dur.cpp b/db/dur.cpp
index 906b4030272..278e9e8b993 100644
--- a/db/dur.cpp
+++ b/db/dur.cpp
@@ -194,6 +194,8 @@ namespace mongo {
}
#endif
+ RelativePath local = RelativePath::fromRelativePath("local");
+
/** we will build an output buffer ourself and then use O_DIRECT
we could be in read lock for this
caller handles locking
@@ -239,18 +241,21 @@ namespace mongo {
mmf->willNeedRemap() = true;
}
i->w_ptr = ((char*)mmf->view_write()) + ofs;
- if( mmf->relativePath() != lastFilePath ) {
+ JEntry e;
+ e.len = i->len;
+ assert( ofs <= 0x80000000 );
+ e.ofs = (unsigned) ofs;
+ e.setFileNo( mmf->fileSuffixNo() );
+ if( mmf->relativePath() == local ) {
+ e.setLocalDbContextBit();
+ }
+ else if( mmf->relativePath() != lastFilePath ) {
lastFilePath = mmf->relativePath();
//assert( !str::startsWith(lastFilePath, dbpath) ); // dbpath should be stripped this is a relative path
JDbContext c;
bb.appendStruct(c);
bb.appendStr(lastFilePath.toString());
}
- JEntry e;
- e.len = i->len;
- assert( ofs <= 0x80000000 );
- e.ofs = (unsigned) ofs;
- e.fileNo = mmf->fileSuffixNo();
bb.appendStruct(e);
bb.appendBuf(i->p, i->len);
}
diff --git a/db/dur.h b/db/dur.h
index 54741a43940..2f4ca6ca2b2 100644
--- a/db/dur.h
+++ b/db/dur.h
@@ -11,36 +11,13 @@ namespace mongo {
class DurableInterface : boost::noncopyable {
public:
- virtual ~DurableInterface() {
- log() << "ERROR warning ~DurableInterface not intended to be called" << endl;
- }
+ virtual ~DurableInterface() { log() << "ERROR warning ~DurableInterface not intended to be called" << endl; }
/** Call during startup so durability module can initialize
throws if fatal error
*/
virtual void startup() = 0;
- /** Wait for acknowledgement of the next group commit.
- @return true if --dur is on. There will be delay.
- @return false if --dur is off.
- */
- virtual bool awaitCommit() = 0;
-
- /** Commit immediately.
-
- Generally, you do not want to do this often, as highly granular committing may affect
- performance.
-
- Does not return until the commit is complete.
-
- You must be at least read locked when you call this. Ideally, you are not write locked
- and then read operations can occur concurrently.
-
- @return true if --dur is on.
- @return false if --dur is off. (in which case there is action)
- */
- virtual bool commitNow() = 0;
-
/** Declare that a file has been created
Normally writes are applied only after journalling, for safety. But here the file
is created first, and the journal will just replay the creation if the create didn't
@@ -77,21 +54,39 @@ namespace mongo {
*/
virtual void* writingAtOffset(void *buf, unsigned ofs, unsigned len) = 0;
+ /** Wait for acknowledgement of the next group commit.
+ @return true if --dur is on. There will be delay.
+ @return false if --dur is off.
+ */
+ virtual bool awaitCommit() = 0;
+
+ /** Commit immediately.
+
+ Generally, you do not want to do this often, as highly granular committing may affect
+ performance.
+
+ Does not return until the commit is complete.
+
+ You must be at least read locked when you call this. Ideally, you are not write locked
+ and then read operations can occur concurrently.
+
+ @return true if --dur is on.
+ @return false if --dur is off. (in which case there is action)
+ */
+ virtual bool commitNow() = 0;
+
#if defined(_DEBUG)
virtual void debugCheckLastDeclaredWrite() = 0;
#endif
- /// END OF VIRTUAL FUNCTIONS
-
- inline DiskLoc& writingDiskLoc(DiskLoc& d) {
- return *((DiskLoc*) writingPtr(&d, sizeof(d)));
- }
+ /** Declare write intent for a DiskLoc. @see DiskLoc::writing() */
+ inline DiskLoc& writingDiskLoc(DiskLoc& d) { return *((DiskLoc*) writingPtr(&d, sizeof(d))); }
- inline int& writingInt(int& d) {
- return *((int*) writingPtr(&d, sizeof(d)));
- }
+ /** Declare write intent for an int */
+ inline int& writingInt(int& d) { return *((int*) writingPtr(&d, sizeof(d))); }
/** "assume i've already indicated write intent, let me write"
+ redeclaration is fine too, but this is faster.
*/
template <typename T>
inline
@@ -169,6 +164,9 @@ namespace mongo {
#endif
};
+ /** puts DurableImpl into effect. call druing startup if --dur specified. */
+ void enableDurability();
+
} // namespace dur
inline dur::DurableInterface& getDur() { return dur::DurableInterface::getDur(); }
diff --git a/db/dur_journalformat.h b/db/dur_journalformat.h
index 9259daa2dba..6f6d6d2f5d3 100644
--- a/db/dur_journalformat.h
+++ b/db/dur_journalformat.h
@@ -36,7 +36,7 @@ namespace mongo {
// x4142 is asci--readable if you look at the file with head/less -- thus the starting values were near
// that. simply incrementing the version # is safe on a fwd basis.
- enum { CurrentVersion = 0x4142 };
+ enum { CurrentVersion = 0x4143 };
unsigned short _version;
// these are just for diagnostic ease (make header more useful as plain text)
@@ -61,23 +61,36 @@ namespace mongo {
unsigned len; // length in bytes of the whole section
};
- /** an individual operation within section. Either the entire section should be applied, or nothing. */
+ /** an individual write operation within a group commit section. Either the entire section should
+ be applied, or nothing. (We check the md5 for the whole section before doing anything on recovery.)
+ */
struct JEntry {
enum OpCodes {
OpCode_Footer = 0xffffffff,
OpCode_DbContext = 0xfffffffe,
OpCode_FileCreated = 0xfffffffd,
OpCode_DropDb = 0xfffffffc,
- OpCode_Min = 0xfffff000 // higher than max len: OpCode_Min + sizeof(JHeader) > 2^32
+ OpCode_Min = 0xfffff000
};
union {
unsigned len;
OpCodes opcode;
};
- unsigned ofs; // offset in file
- int fileNo;
+ unsigned ofs; // offset in file
+
+ enum {
+ DotNsSuffix = 0x7fffffff, // ".ns" file
+ LocalDbBit = 0x80000000 // assuming "local" db instead of using the JDbContext
+ };
+ int _fileNo; // high bit is set to indicate it should be the <dbpath>/local database
// char data[] follows
+
+ int getFileNo() const { return _fileNo & (~LocalDbBit); }
+ void setFileNo(int f) { _fileNo = f; }
+ void setLocalDbContextBit() { _fileNo |= LocalDbBit; }
+ bool isLocalDbContext() const { return _fileNo & LocalDbBit; }
+ void clearLocalDbContextBit() { _fileNo = getFileNo(); }
};
/** group commit section footer. md5 is a key field. */
diff --git a/db/dur_recover.cpp b/db/dur_recover.cpp
index 687722bf7cb..586fa6f7a39 100644
--- a/db/dur_recover.cpp
+++ b/db/dur_recover.cpp
@@ -41,10 +41,18 @@ namespace mongo {
struct FullyQualifiedJournalEntry {
bool isBasicWrite() const { return dbName != 0; }
- const char *dbName; // pointer into mmaped Journal file
+ // relative path of database for the operation.
+ // might be a pointer into mmaped Journal file
+ const char *dbName;
+
+
+ // local db sentinel is already parsed out here into dbName
JEntry e;
- const char *srcData; // pointer into mmaped Journal file
+ // pointer into mmaped Journal file
+ const char *srcData;
+
+ // if not a simple JEntry, the operation
shared_ptr<DurOp> op;
};
@@ -98,7 +106,7 @@ namespace mongo {
* throws on premature end of section.
*/
bool next(FullyQualifiedJournalEntry& e) {
- if( !_sectHead ) {
+ if( !_sectHead ) {
_sectHead = static_cast<const JSectHeader*>(_br.pos());
_br.skip(sizeof(JSectHeader));
}
@@ -106,6 +114,8 @@ namespace mongo {
unsigned lenOrOpCode;
_br.read(lenOrOpCode);
if( lenOrOpCode >= JEntry::OpCode_Min ) {
+ // not a "basic write"
+
if( lenOrOpCode == JEntry::OpCode_Footer ) {
const char* pos = (const char*) _br.pos();
pos -= sizeof(lenOrOpCode); // rewind to include OpCode
@@ -139,17 +149,20 @@ namespace mongo {
const unsigned len = strnlen(_lastDbName, limit);
massert(13533, "problem processing journal file during recovery", _lastDbName[len] == '\0');
_br.skip(len+1); // skip '\0' too
-
_br.read(lenOrOpCode);
}
}
- // now do JEntry
+ // JEntry - a basic write
assert( lenOrOpCode && lenOrOpCode < JEntry::OpCode_Min );
e.dbName = _lastDbName;
e.e.len = lenOrOpCode;
_br.read(e.e.ofs);
- _br.read(e.e.fileNo);
+ _br.read(e.e._fileNo);
+ if( e.e.isLocalDbContext() ) {
+ e.dbName = "local";
+ e.e.clearLocalDbContextBit();
+ }
e.srcData = (const char *) _br.skip(lenOrOpCode);
return true;
}
@@ -197,7 +210,8 @@ namespace mongo {
{
stringstream ss;
ss << dbName << '.';
- if( fileNo < 0 )
+ assert( fileNo >= 0 );
+ if( fileNo == JEntry::DotNsSuffix )
ss << "ns";
else
ss << fileNo;
@@ -252,13 +266,16 @@ namespace mongo {
if( fqe.isBasicWrite() ) {
if( dump ) {
stringstream ss;
- ss << " BASICWRITE " << setw(20) << fqe.dbName << '.'
- << setw(2) << fqe.e.fileNo << ' ' << setw(6) << fqe.e.len
- << ' ' << hex << setw(8) << (size_t) fqe.srcData << dec << " " << hexdump(fqe.srcData, fqe.e.len);
+ ss << " BASICWRITE " << setw(20) << fqe.dbName << '.';
+ if( fqe.e._fileNo == JEntry::DotNsSuffix )
+ ss << "ns";
+ else
+ ss << setw(2) << fqe.e._fileNo;
+ ss << ' ' << setw(6) << fqe.e.len << ' ' << hex << setw(8) << (size_t) fqe.srcData << dec << " " << hexdump(fqe.srcData, fqe.e.len);
log() << ss.str() << endl;
}
if( apply ) {
- void *p = ptr(fqe.dbName, fqe.e.fileNo, fqe.e.ofs);
+ void *p = ptr(fqe.dbName, fqe.e._fileNo, fqe.e.ofs);
memcpy(p, fqe.srcData, fqe.e.len);
}
} else {
@@ -333,7 +350,7 @@ namespace mongo {
close();
if( cmdLine.durOptions & CmdLine::DurScanOnly ) {
- uasserted(13545, str::stream() << "--durOptions " << (int) CmdLine::DurScanOnly << " specified, terminating");
+ uasserted(13545, str::stream() << "--durOptions " << (int) CmdLine::DurScanOnly << " (scan only) specified");
}
log() << "recover cleaning up" << endl;
diff --git a/db/mongommf.cpp b/db/mongommf.cpp
index 3be78702e35..120460909b5 100644
--- a/db/mongommf.cpp
+++ b/db/mongommf.cpp
@@ -24,6 +24,7 @@
#include "cmdline.h"
#include "mongommf.h"
#include "dur.h"
+#include "dur_journalformat.h"
#include "../util/mongoutils/str.h"
using namespace mongoutils;
@@ -151,13 +152,14 @@ namespace mongo {
extern string dbpath;
+ // here so that it is precomputed...
void MongoMMF::setPath(string f) {
string suffix;
string prefix;
bool ok = str::rSplitOn(f, '.', prefix, suffix);
uassert(13520, str::stream() << "MongoMMF only supports filenames in a certain format " << f, ok);
if( suffix == "ns" )
- _fileSuffixNo = -1;
+ _fileSuffixNo = dur::JEntry::DotNsSuffix;
else
_fileSuffixNo = (int) str::toUnsigned(suffix);