summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2014-06-04 18:17:42 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2014-06-04 18:17:42 -0400
commit64e3b85a7c8a4a6ea7c68f25ae27780c702cdfb5 (patch)
tree0143c273b63cfd4850d6f69cbd222ea3dec64d9d /src/mongo
parentb0e11bb814f6554dfc791ba5a05e007f4d1efec9 (diff)
downloadmongo-64e3b85a7c8a4a6ea7c68f25ae27780c702cdfb5.tar.gz
Revert "SERVER-13951 First phase of rollback implementation"
Broke Windows Compile This reverts commit 8b0d5c879339e16f06829ebb4265e54b1a356b2a.
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/storage/data_file.cpp8
-rw-r--r--src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp110
-rw-r--r--src/mongo/db/storage/mmap_v1/dur_recovery_unit.h38
-rw-r--r--src/mongo/db/storage/recovery_unit.h58
-rw-r--r--src/mongo/db/storage/recovery_unit_noop.h7
-rw-r--r--src/mongo/db/structure/catalog/namespace_index.cpp9
6 files changed, 22 insertions, 208 deletions
diff --git a/src/mongo/db/storage/data_file.cpp b/src/mongo/db/storage/data_file.cpp
index 915484aa0e3..8630e767d3b 100644
--- a/src/mongo/db/storage/data_file.cpp
+++ b/src/mongo/db/storage/data_file.cpp
@@ -199,13 +199,9 @@ namespace mongo {
}
}
- // The writes done in this function must not be rolled back. If the containing
- // UnitOfWork rolls back it should roll back to the state *after* these writes. This
- // will leave the file empty, but available for future use. That is why we go directly
- // to the global dur dirty list rather than going through the OperationContext.
- getDur().createdFile(filename, filelength);
+ txn->recoveryUnit()->createdFile(filename, filelength);
verify( HeaderSize == 8192 );
- DataFileHeader *h = getDur().writing(this);
+ DataFileHeader *h = txn->recoveryUnit()->writing(this);
h->fileLength = filelength;
h->version = PDFILE_VERSION;
h->versionMinor = PDFILE_VERSION_MINOR_22_AND_OLDER; // All dbs start like this
diff --git a/src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp b/src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp
index c0970763eb4..20f61fd1c3e 100644
--- a/src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp
+++ b/src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp
@@ -30,111 +30,17 @@
#include "mongo/db/storage/mmap_v1/dur.h"
-// Remove once we are ready to enable
-#define ROLLBACK_ENABLED false
-
namespace mongo {
DurRecoveryUnit::DurRecoveryUnit() {
_hasWrittenSinceCheckpoint = false;
}
- void DurRecoveryUnit::beginUnitOfWork() {
-#if ROLLBACK_ENABLED
- _nestingLevel++;
-#endif
- }
-
- void DurRecoveryUnit::commitUnitOfWork() {
-#if ROLLBACK_ENABLED
- invariant(_state != MUST_ROLLBACK);
- invariant(_nestingLevel > 0);
-
- if (_nestingLevel != 1) {
- // If we are nested, punt to outer UnitOfWork. These changes will only be pushed to the
- // global damages list when the outer UnitOfWork commits (which it must now do).
- if (haveUncommitedChanges())
- _state = MUST_COMMIT;
- return;
- }
-
- publishChanges();
-#endif
-
- // global journal flush
- getDur().commitIfNeeded();
- }
-
- void DurRecoveryUnit::endUnitOfWork() {
-#if ROLLBACK_ENABLED
- invariant(_nestingLevel > 0);
-
- if (--_nestingLevel != 0) {
- // If we are nested, punt to outer UnitOfWork. These changes will only be rolled back
- // when the outer UnitOfWork rolls back (which it must now do).
- if (haveUncommitedChanges()) {
- invariant(_state != MUST_COMMIT);
- _state = MUST_ROLLBACK;
- }
- return;
- }
-
- rollbackChanges();
-#endif
- }
-
- void DurRecoveryUnit::publishChanges() {
- invariant(_state != MUST_ROLLBACK);
-
- if (getDur().isDurable()) {
- for (Changes::iterator it=_changes.begin(), end=_changes.end(); it != end; ++it) {
- // TODO don't go through getDur() interface.
- getDur().writingPtr(it->base, it->preimage.size());
- }
- }
-
- reset();
- }
-
- void DurRecoveryUnit::rollbackChanges() {
- invariant(_state != MUST_COMMIT);
-
- for (Changes::reverse_iterator it=_changes.rbegin(), end=_changes.rend(); it != end; ++it) {
- // TODO need to add these pages to our "dirty count" somehow.
- it->preimage.copy(it->base, it->preimage.size());
- }
-
- reset();
- }
-
- void DurRecoveryUnit::recordPreimage(char* data, size_t len) {
- invariant(len > 0);
-
- Change change;
- change.base = data;
- change.preimage.assign(data, len);
- _changes.push_back(change);
- }
-
- void DurRecoveryUnit::reset() {
- _state = NORMAL;
- _changes.clear();
- }
-
bool DurRecoveryUnit::awaitCommit() {
-#if ROLLBACK_ENABLED
- invariant(_state != MUST_ROLLBACK);
- publishChanges();
- _state = NORMAL;
-#endif
return getDur().awaitCommit();
}
bool DurRecoveryUnit::commitIfNeeded(bool force) {
-#if ROLLBACK_ENABLED
- invariant(_state != MUST_ROLLBACK);
- publishChanges();
-#endif
_hasWrittenSinceCheckpoint = false;
return getDur().commitIfNeeded(force);
}
@@ -144,23 +50,15 @@ namespace mongo {
}
void* DurRecoveryUnit::writingPtr(void* data, size_t len) {
-#if ROLLBACK_ENABLED
- invariant(_nestingLevel >= 1);
- invariant(_state != MUST_ROLLBACK);
- recordPreimage(static_cast<char*>(data), len);
- _hasWrittenSinceCheckpoint = true;
- return data;
-#else
_hasWrittenSinceCheckpoint = true;
return getDur().writingPtr(data, len);
-#endif
+ }
+
+ void DurRecoveryUnit::createdFile(const std::string& filename, unsigned long long len) {
+ getDur().createdFile(filename, len);
}
void DurRecoveryUnit::syncDataAndTruncateJournal() {
-#if ROLLBACK_ENABLED
- invariant(_state != MUST_ROLLBACK);
- publishChanges();
-#endif
return getDur().syncDataAndTruncateJournal();
}
diff --git a/src/mongo/db/storage/mmap_v1/dur_recovery_unit.h b/src/mongo/db/storage/mmap_v1/dur_recovery_unit.h
index 8ff208e9056..3715ba4468e 100644
--- a/src/mongo/db/storage/mmap_v1/dur_recovery_unit.h
+++ b/src/mongo/db/storage/mmap_v1/dur_recovery_unit.h
@@ -27,10 +27,8 @@
*/
#include <string>
-#include <vector>
#include "mongo/db/storage/recovery_unit.h"
-#include "mongo/platform/compiler.h"
#pragma once
@@ -45,10 +43,6 @@ namespace mongo {
virtual ~DurRecoveryUnit() { }
- virtual void beginUnitOfWork();
- virtual void commitUnitOfWork();
- virtual void endUnitOfWork();
-
virtual bool awaitCommit();
virtual bool commitIfNeeded(bool force = false);
@@ -57,39 +51,11 @@ namespace mongo {
virtual void* writingPtr(void* data, size_t len);
+ virtual void createdFile(const std::string& filename, unsigned long long len);
+
virtual void syncDataAndTruncateJournal();
private:
- void recordPreimage(char* data, size_t len);
- void publishChanges();
- void rollbackChanges();
- void reset();
- bool haveUncommitedChanges() { return !_changes.empty(); }
-
- // State is only used for invariant checking today. It should be deleted once we get rid of
- // nesting.
- enum State {
- NORMAL, // anything is allowed
- MUST_COMMIT, // can't rollback
- MUST_ROLLBACK, // can't do anything else
- };
- State _state;
-
- // How many begins haven't had a matching end. TODO remove the need for this.
- int _nestingLevel;
-
- struct Change {
- char* base;
- std::string preimage; // TODO consider storing out-of-line
- };
-
- // Changes are ordered from oldest to newest. Overlapping and duplicate regions are allowed,
- // since rollback undoes changes in reverse order.
- // TODO compare performance against a data-structure that coalesces overlapping/adjacent
- // changes.
- typedef std::vector<Change> Changes;
- Changes _changes;
-
// XXX: this will be meaningful once killCurrentOp doesn't examine this bool's evil sibling
// in client.h. This requires killCurrentOp to go through OperationContext...
bool _hasWrittenSinceCheckpoint;
diff --git a/src/mongo/db/storage/recovery_unit.h b/src/mongo/db/storage/recovery_unit.h
index bf479cd94fe..f089c6180b8 100644
--- a/src/mongo/db/storage/recovery_unit.h
+++ b/src/mongo/db/storage/recovery_unit.h
@@ -29,7 +29,6 @@
#pragma once
#include <stdlib.h>
-#include <string>
#include "mongo/base/disallow_copying.h"
@@ -45,36 +44,6 @@ namespace mongo {
virtual ~RecoveryUnit() { }
/**
- * These should be called through WriteUnitOfWork rather than directly.
- *
- * begin and end mark the begining and end of a unit of work. Each call to begin must be
- * matched with exactly one call to end. commit can be called any number of times between
- * begin and end but must not be called outside. When end() is called, all changes since the
- * last commit (if any) will be rolled back.
- *
- * If UnitsOfWork nest (ie begin is called twice before a call to end), the prior paragraph
- * describes the behavior of the outermost UnitOfWork. Inner UnitsOfWork neither commit nor
- * rollback on their own but rely on the outermost to do it. If an inner UnitOfWork commits
- * any changes, it is illegal for an outer unit to rollback. If an inner UnitOfWork
- * rollsback any changes, it is illegal for an outer UnitOfWork to do anything other than
- * rollback.
- *
- * The goal is not to fully support nested transaction, instead we want to allow delaying
- * commit on a unit if it is part of a larger atomic unit.
- *
- * TODO see if we can get rid of nested UnitsOfWork.
- */
- virtual void beginUnitOfWork() = 0;
- virtual void commitUnitOfWork() = 0;
- virtual void endUnitOfWork() = 0;
-
- // WARNING: "commit" in functions below refers to a global journal flush which implicitly
- // commits the current UnitOfWork as well. They are actually stronger than commitUnitOfWork
- // as they can commit even if the UnitOfWork is nested. That is because we have already
- // verified that the db will be left in a valid state at these commit points.
- // TODO clean up the naming and semantics.
-
- /**
* XXX: document
*/
virtual bool awaitCommit() = 0;
@@ -87,21 +56,25 @@ namespace mongo {
virtual bool commitIfNeeded(bool force = false) = 0;
/**
- * Returns true if a global commit of the journal is needed but does not commit.
+ * Returns true if a commit is needed but does not commit.
*/
virtual bool isCommitNeeded() const = 0;
-
- //
- // The remaining methods probably belong on DurRecoveryUnit rather than on the interface.
- //
-
/**
* Declare that the data at [x, x + len) is being written.
*/
virtual void* writingPtr(void* data, size_t len) = 0;
/**
+ * Declare that a file has been created
+ *
+ * Normally writes are applied only after journaling, for safety. But here the file
+ * is created first, and the journal will just replay the creation if the create didn't
+ * happen because of crashing.
+ */
+ virtual void createdFile(const std::string& filename, unsigned long long len) = 0;
+
+ /**
* Commits pending changes, flushes all changes to main data files, then removes the
* journal.
*
@@ -137,15 +110,4 @@ namespace mongo {
RecoveryUnit() { }
};
- class WriteUnitOfWork {
- MONGO_DISALLOW_COPYING(WriteUnitOfWork);
- public:
- WriteUnitOfWork(RecoveryUnit* ru) : _ru(ru) { _ru->beginUnitOfWork(); }
- ~WriteUnitOfWork(){ _ru->endUnitOfWork(); }
-
- void commit() { _ru->commitUnitOfWork(); }
-
- RecoveryUnit* const _ru;
- };
-
} // namespace mongo
diff --git a/src/mongo/db/storage/recovery_unit_noop.h b/src/mongo/db/storage/recovery_unit_noop.h
index 7afd07005e0..d808c4d261c 100644
--- a/src/mongo/db/storage/recovery_unit_noop.h
+++ b/src/mongo/db/storage/recovery_unit_noop.h
@@ -32,11 +32,6 @@ namespace mongo {
class RecoveryUnitNoop : public RecoveryUnit {
public:
- // TODO implement rollback
- virtual void beginUnitOfWork() {}
- virtual void commitUnitOfWork() {}
- virtual void endUnitOfWork() {}
-
virtual bool commitIfNeeded(bool force = false) {
return false;
}
@@ -53,6 +48,8 @@ namespace mongo {
return data;
}
+ virtual void createdFile(const std::string& filename, unsigned long long len) { }
+
virtual void syncDataAndTruncateJournal() { }
};
diff --git a/src/mongo/db/structure/catalog/namespace_index.cpp b/src/mongo/db/structure/catalog/namespace_index.cpp
index e4ce0bdca27..f4f66ec3569 100644
--- a/src/mongo/db/structure/catalog/namespace_index.cpp
+++ b/src/mongo/db/structure/catalog/namespace_index.cpp
@@ -166,12 +166,7 @@ namespace mongo {
maybeMkdir();
unsigned long long l = storageGlobalParams.lenForNewNsFiles;
if ( _f.create(pathString, l, true) ) {
- // The writes done in this function must not be rolled back. If the containing
- // UnitOfWork rolls back it should roll back to the state *after* these writes. This
- // will leave the file empty, but available for future use. That is why we go
- // directly to the global dur dirty list rather than going through the
- // OperationContext.
- getDur().createdFile(pathString, l); // always a new file
+ txn->recoveryUnit()->createdFile(pathString, l); // always a new file
len = l;
verify(len == storageGlobalParams.lenForNewNsFiles);
p = _f.getView();
@@ -180,7 +175,7 @@ namespace mongo {
// we do this so the durability system isn't mad at us for
// only initiating file and not doing a write
// grep for 17388
- getDur().writingPtr( p, 5 ); // throw away
+ txn->recoveryUnit()->writingPtr( p, 5 ); // throw away
}
}
}