diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2014-06-04 18:17:42 -0400 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2014-06-04 18:17:42 -0400 |
commit | 64e3b85a7c8a4a6ea7c68f25ae27780c702cdfb5 (patch) | |
tree | 0143c273b63cfd4850d6f69cbd222ea3dec64d9d /src/mongo | |
parent | b0e11bb814f6554dfc791ba5a05e007f4d1efec9 (diff) | |
download | mongo-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.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp | 110 | ||||
-rw-r--r-- | src/mongo/db/storage/mmap_v1/dur_recovery_unit.h | 38 | ||||
-rw-r--r-- | src/mongo/db/storage/recovery_unit.h | 58 | ||||
-rw-r--r-- | src/mongo/db/storage/recovery_unit_noop.h | 7 | ||||
-rw-r--r-- | src/mongo/db/structure/catalog/namespace_index.cpp | 9 |
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 } } } |