summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2015-07-28 18:16:39 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2015-07-28 18:27:27 -0400
commitb66e993f1c742518d9b5e93b0d8a5f8255a4127c (patch)
tree55e6fed05333d2d37f34586726a342ed7f7dbc29 /src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp
parent314a22e93f283ab80e650618cbd3ed8babb8510f (diff)
downloadmongo-b66e993f1c742518d9b5e93b0d8a5f8255a4127c.tar.gz
SERVER-18579: Clang-Format - reformat code, no comment reflow
Diffstat (limited to 'src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp')
-rw-r--r--src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp486
1 files changed, 236 insertions, 250 deletions
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 a806bae91be..3d38d2cf723 100644
--- a/src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp
+++ b/src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp
@@ -45,322 +45,308 @@
namespace mongo {
- DurRecoveryUnit::DurRecoveryUnit()
- : _writeCount(0), _writeBytes(0), _mustRollback(false), _rollbackWritesDisabled(false) {
- }
-
- void DurRecoveryUnit::beginUnitOfWork(OperationContext* opCtx) {
- _startOfUncommittedChangesForLevel.push_back(Indexes(_changes.size(), _writeCount));
- }
+DurRecoveryUnit::DurRecoveryUnit()
+ : _writeCount(0), _writeBytes(0), _mustRollback(false), _rollbackWritesDisabled(false) {}
- void DurRecoveryUnit::commitUnitOfWork() {
- invariant(inAUnitOfWork());
- invariant(!_mustRollback);
-
- if (!inOutermostUnitOfWork()) {
- // If we are nested, make all changes for this level part of the containing UnitOfWork.
- // They will be added to the global damages list once the outermost UnitOfWork commits,
- // which it must now do.
- if (haveUncommittedChangesAtCurrentLevel()) {
- _startOfUncommittedChangesForLevel.back() =
- Indexes(_changes.size(), _writeCount);
- }
- return;
- }
+void DurRecoveryUnit::beginUnitOfWork(OperationContext* opCtx) {
+ _startOfUncommittedChangesForLevel.push_back(Indexes(_changes.size(), _writeCount));
+}
- commitChanges();
+void DurRecoveryUnit::commitUnitOfWork() {
+ invariant(inAUnitOfWork());
+ invariant(!_mustRollback);
- // global journal flush opportunity
- getDur().commitIfNeeded();
+ if (!inOutermostUnitOfWork()) {
+ // If we are nested, make all changes for this level part of the containing UnitOfWork.
+ // They will be added to the global damages list once the outermost UnitOfWork commits,
+ // which it must now do.
+ if (haveUncommittedChangesAtCurrentLevel()) {
+ _startOfUncommittedChangesForLevel.back() = Indexes(_changes.size(), _writeCount);
+ }
+ return;
}
- void DurRecoveryUnit::endUnitOfWork() {
- invariant(inAUnitOfWork());
+ commitChanges();
- if (haveUncommittedChangesAtCurrentLevel()) {
- _mustRollback = true;
- }
+ // global journal flush opportunity
+ getDur().commitIfNeeded();
+}
- // Reset back to default if this is the last unwind of the recovery unit. That way, it can
- // be reused for new operations.
- if (inOutermostUnitOfWork()) {
- rollbackChanges();
- _rollbackWritesDisabled = false;
- dassert(_changes.empty() && _initialWrites.empty() && _mergedWrites.empty());
- dassert( _preimageBuffer.empty() && !_writeCount && !_writeBytes && !_mustRollback);
- }
+void DurRecoveryUnit::endUnitOfWork() {
+ invariant(inAUnitOfWork());
- _startOfUncommittedChangesForLevel.pop_back();
+ if (haveUncommittedChangesAtCurrentLevel()) {
+ _mustRollback = true;
}
- void DurRecoveryUnit::commitAndRestart() {
- invariant( !inAUnitOfWork() );
- // no-op since we have no transaction
+ // Reset back to default if this is the last unwind of the recovery unit. That way, it can
+ // be reused for new operations.
+ if (inOutermostUnitOfWork()) {
+ rollbackChanges();
+ _rollbackWritesDisabled = false;
+ dassert(_changes.empty() && _initialWrites.empty() && _mergedWrites.empty());
+ dassert(_preimageBuffer.empty() && !_writeCount && !_writeBytes && !_mustRollback);
}
- void DurRecoveryUnit::commitChanges() {
- invariant(!_mustRollback);
- invariant(inOutermostUnitOfWork());
- invariant(_startOfUncommittedChangesForLevel.front().changeIndex == 0);
- invariant(_startOfUncommittedChangesForLevel.front().writeCount == 0);
+ _startOfUncommittedChangesForLevel.pop_back();
+}
- if (getDur().isDurable())
- markWritesForJournaling();
+void DurRecoveryUnit::commitAndRestart() {
+ invariant(!inAUnitOfWork());
+ // no-op since we have no transaction
+}
- try {
- for (Changes::const_iterator it = _changes.begin(), end = _changes.end();
- it != end; ++it) {
- (*it)->commit();
- }
- }
- catch (...) {
- std::terminate();
- }
+void DurRecoveryUnit::commitChanges() {
+ invariant(!_mustRollback);
+ invariant(inOutermostUnitOfWork());
+ invariant(_startOfUncommittedChangesForLevel.front().changeIndex == 0);
+ invariant(_startOfUncommittedChangesForLevel.front().writeCount == 0);
- resetChanges();
+ if (getDur().isDurable())
+ markWritesForJournaling();
+ try {
+ for (Changes::const_iterator it = _changes.begin(), end = _changes.end(); it != end; ++it) {
+ (*it)->commit();
+ }
+ } catch (...) {
+ std::terminate();
}
- void DurRecoveryUnit::markWritesForJournaling() {
- if (!_writeCount)
- return;
-
- typedef std::pair<void*, unsigned> Intent;
- std::vector<Intent> intents;
- const size_t numStoredWrites = _initialWrites.size() + _mergedWrites.size();
- intents.reserve(numStoredWrites);
-
- // Show very large units of work at LOG(1) level as they may hint at performance issues
- const int logLevel = (_writeCount > 100*1000 || _writeBytes > 50*1024*1024) ? 1 : 3;
-
- LOG(logLevel) << _writeCount << " writes (" << _writeBytes / 1024 << " kB) covered by "
- << numStoredWrites << " pre-images ("
- << _preimageBuffer.size() / 1024 << " kB) ";
-
- // orders the initial, unmerged writes, by address so we can coalesce overlapping and
- // adjacent writes
- std::sort(_initialWrites.begin(), _initialWrites.end());
-
- if (!_initialWrites.empty()) {
- intents.push_back(std::make_pair(_initialWrites.front().addr,
- _initialWrites.front().len));
- for (InitialWrites::iterator it = (_initialWrites.begin() + 1),
- end = _initialWrites.end();
- it != end;
- ++it) {
- Intent& lastIntent = intents.back();
- char* lastEnd = static_cast<char*>(lastIntent.first) + lastIntent.second;
- if (it->addr <= lastEnd) {
- // overlapping or adjacent, so extend.
- ptrdiff_t extendedLen = (it->end()) - static_cast<char*>(lastIntent.first);
- lastIntent.second = std::max(lastIntent.second, unsigned(extendedLen));
- }
- else {
- // not overlapping, so create a new intent
- intents.push_back(std::make_pair(it->addr, it->len));
- }
+ resetChanges();
+}
+
+void DurRecoveryUnit::markWritesForJournaling() {
+ if (!_writeCount)
+ return;
+
+ typedef std::pair<void*, unsigned> Intent;
+ std::vector<Intent> intents;
+ const size_t numStoredWrites = _initialWrites.size() + _mergedWrites.size();
+ intents.reserve(numStoredWrites);
+
+ // Show very large units of work at LOG(1) level as they may hint at performance issues
+ const int logLevel = (_writeCount > 100 * 1000 || _writeBytes > 50 * 1024 * 1024) ? 1 : 3;
+
+ LOG(logLevel) << _writeCount << " writes (" << _writeBytes / 1024 << " kB) covered by "
+ << numStoredWrites << " pre-images (" << _preimageBuffer.size() / 1024 << " kB) ";
+
+ // orders the initial, unmerged writes, by address so we can coalesce overlapping and
+ // adjacent writes
+ std::sort(_initialWrites.begin(), _initialWrites.end());
+
+ if (!_initialWrites.empty()) {
+ intents.push_back(std::make_pair(_initialWrites.front().addr, _initialWrites.front().len));
+ for (InitialWrites::iterator it = (_initialWrites.begin() + 1), end = _initialWrites.end();
+ it != end;
+ ++it) {
+ Intent& lastIntent = intents.back();
+ char* lastEnd = static_cast<char*>(lastIntent.first) + lastIntent.second;
+ if (it->addr <= lastEnd) {
+ // overlapping or adjacent, so extend.
+ ptrdiff_t extendedLen = (it->end()) - static_cast<char*>(lastIntent.first);
+ lastIntent.second = std::max(lastIntent.second, unsigned(extendedLen));
+ } else {
+ // not overlapping, so create a new intent
+ intents.push_back(std::make_pair(it->addr, it->len));
}
}
+ }
- MergedWrites::iterator it = _mergedWrites.begin();
- if (it != _mergedWrites.end()) {
- intents.push_back(std::make_pair(it->addr, it->len));
- while (++it != _mergedWrites.end()) {
- // Check the property that write intents are sorted and don't overlap.
- invariant(it->addr >= intents.back().first);
- Intent& lastIntent = intents.back();
- char* lastEnd = static_cast<char*>(lastIntent.first) + lastIntent.second;
- if (it->addr == lastEnd) {
- // adjacent, so extend.
- lastIntent.second += it->len;
- }
- else {
- // not overlapping, so create a new intent
- invariant(it->addr > lastEnd);
- intents.push_back(std::make_pair(it->addr, it->len));
- }
+ MergedWrites::iterator it = _mergedWrites.begin();
+ if (it != _mergedWrites.end()) {
+ intents.push_back(std::make_pair(it->addr, it->len));
+ while (++it != _mergedWrites.end()) {
+ // Check the property that write intents are sorted and don't overlap.
+ invariant(it->addr >= intents.back().first);
+ Intent& lastIntent = intents.back();
+ char* lastEnd = static_cast<char*>(lastIntent.first) + lastIntent.second;
+ if (it->addr == lastEnd) {
+ // adjacent, so extend.
+ lastIntent.second += it->len;
+ } else {
+ // not overlapping, so create a new intent
+ invariant(it->addr > lastEnd);
+ intents.push_back(std::make_pair(it->addr, it->len));
}
}
- LOG(logLevel) << _mergedWrites.size() << " pre-images " << "coalesced into "
- << intents.size() << " write intents";
-
- getDur().declareWriteIntents(intents);
- }
-
- void DurRecoveryUnit::resetChanges() {
- _writeCount = 0;
- _writeBytes = 0;
- _initialWrites.clear();
- _mergedWrites.clear();
- _changes.clear();
- _preimageBuffer.clear();
}
-
- void DurRecoveryUnit::rollbackChanges() {
- invariant(inOutermostUnitOfWork());
- invariant(!_startOfUncommittedChangesForLevel.back().changeIndex);
- invariant(!_startOfUncommittedChangesForLevel.back().writeCount);
-
- // First rollback disk writes, then Changes. This matches behavior in other storage engines
- // that either rollback a transaction or don't write a writebatch.
-
- if (_rollbackWritesDisabled) {
- LOG(2) << " ***** NOT ROLLING BACK " << _writeCount << " disk writes";
+ LOG(logLevel) << _mergedWrites.size() << " pre-images "
+ << "coalesced into " << intents.size() << " write intents";
+
+ getDur().declareWriteIntents(intents);
+}
+
+void DurRecoveryUnit::resetChanges() {
+ _writeCount = 0;
+ _writeBytes = 0;
+ _initialWrites.clear();
+ _mergedWrites.clear();
+ _changes.clear();
+ _preimageBuffer.clear();
+}
+
+void DurRecoveryUnit::rollbackChanges() {
+ invariant(inOutermostUnitOfWork());
+ invariant(!_startOfUncommittedChangesForLevel.back().changeIndex);
+ invariant(!_startOfUncommittedChangesForLevel.back().writeCount);
+
+ // First rollback disk writes, then Changes. This matches behavior in other storage engines
+ // that either rollback a transaction or don't write a writebatch.
+
+ if (_rollbackWritesDisabled) {
+ LOG(2) << " ***** NOT ROLLING BACK " << _writeCount << " disk writes";
+ } else {
+ LOG(2) << " ***** ROLLING BACK " << _writeCount << " disk writes";
+
+ // First roll back the merged writes. These have no overlap or ordering requirement
+ // other than needing to be rolled back before all _initialWrites.
+ for (MergedWrites::iterator it = _mergedWrites.begin(); it != _mergedWrites.end(); ++it) {
+ _preimageBuffer.copy(it->addr, it->len, it->offset);
}
- else {
- LOG(2) << " ***** ROLLING BACK " << _writeCount << " disk writes";
-
- // First roll back the merged writes. These have no overlap or ordering requirement
- // other than needing to be rolled back before all _initialWrites.
- for (MergedWrites::iterator it = _mergedWrites.begin();
- it != _mergedWrites.end();
- ++it) {
- _preimageBuffer.copy(it->addr, it->len, it->offset);
- }
- // Then roll back the initial writes in LIFO order, as these might have overlaps.
- for (InitialWrites::reverse_iterator rit = _initialWrites.rbegin();
- rit != _initialWrites.rend();
- ++rit) {
- _preimageBuffer.copy(rit->addr, rit->len, rit->offset);
- }
+ // Then roll back the initial writes in LIFO order, as these might have overlaps.
+ for (InitialWrites::reverse_iterator rit = _initialWrites.rbegin();
+ rit != _initialWrites.rend();
+ ++rit) {
+ _preimageBuffer.copy(rit->addr, rit->len, rit->offset);
}
+ }
- LOG(2) << " ***** ROLLING BACK " << (_changes.size()) << " custom changes";
+ LOG(2) << " ***** ROLLING BACK " << (_changes.size()) << " custom changes";
- try {
- for (int i = _changes.size() - 1; i >= 0; i--) {
- LOG(2) << "CUSTOM ROLLBACK " << demangleName(typeid(*_changes[i]));
- _changes[i]->rollback();
- }
- }
- catch (...) {
- std::terminate();
+ try {
+ for (int i = _changes.size() - 1; i >= 0; i--) {
+ LOG(2) << "CUSTOM ROLLBACK " << demangleName(typeid(*_changes[i]));
+ _changes[i]->rollback();
}
-
- resetChanges();
- _mustRollback = false;
+ } catch (...) {
+ std::terminate();
}
- bool DurRecoveryUnit::awaitCommit() {
- invariant(!inAUnitOfWork());
- return getDur().awaitCommit();
- }
+ resetChanges();
+ _mustRollback = false;
+}
- void DurRecoveryUnit::mergingWritingPtr(char* addr, size_t len) {
- // The invariant is that all writes are non-overlapping and non-empty. So, a single
- // writingPtr call may result in a number of new segments added. At this point, we cannot
- // in general merge adjacent writes, as that would require inefficient operations on the
- // preimage buffer.
+bool DurRecoveryUnit::awaitCommit() {
+ invariant(!inAUnitOfWork());
+ return getDur().awaitCommit();
+}
- MergedWrites::iterator coveringWrite = _mergedWrites.upper_bound(Write(addr, 0, 0));
+void DurRecoveryUnit::mergingWritingPtr(char* addr, size_t len) {
+ // The invariant is that all writes are non-overlapping and non-empty. So, a single
+ // writingPtr call may result in a number of new segments added. At this point, we cannot
+ // in general merge adjacent writes, as that would require inefficient operations on the
+ // preimage buffer.
- char* const end = addr + len;
- while (addr < end) {
- dassert(coveringWrite == _mergedWrites.end() || coveringWrite->end() > addr);
+ MergedWrites::iterator coveringWrite = _mergedWrites.upper_bound(Write(addr, 0, 0));
- // Determine whether addr[0] is already covered by a write or not.
- // If covered, adjust addr and len to exclude the covered run from addr[0] onwards.
+ char* const end = addr + len;
+ while (addr < end) {
+ dassert(coveringWrite == _mergedWrites.end() || coveringWrite->end() > addr);
- if (coveringWrite != _mergedWrites.end()) {
- char* const cwEnd = coveringWrite->end();
+ // Determine whether addr[0] is already covered by a write or not.
+ // If covered, adjust addr and len to exclude the covered run from addr[0] onwards.
- if (coveringWrite->addr <= addr) {
- // If the begin of the covering write at or before addr[0], addr[0] is covered.
- // While the existing pre-image will not generally be the same as the data
- // being written now, during rollback only the oldest pre-image matters.
+ if (coveringWrite != _mergedWrites.end()) {
+ char* const cwEnd = coveringWrite->end();
- if (end <= cwEnd) {
- break; // fully covered
- }
+ if (coveringWrite->addr <= addr) {
+ // If the begin of the covering write at or before addr[0], addr[0] is covered.
+ // While the existing pre-image will not generally be the same as the data
+ // being written now, during rollback only the oldest pre-image matters.
- addr = cwEnd;
- coveringWrite++;
- dassert(coveringWrite == _mergedWrites.end() || coveringWrite->addr >= cwEnd);
+ if (end <= cwEnd) {
+ break; // fully covered
}
- }
- dassert(coveringWrite == _mergedWrites.end() || coveringWrite->end() > addr);
- // If the next coveringWrite overlaps, adjust the end of the uncovered region.
- char* uncoveredEnd = end;
- if (coveringWrite != _mergedWrites.end() && coveringWrite->addr < end) {
- uncoveredEnd = coveringWrite->addr;
+ addr = cwEnd;
+ coveringWrite++;
+ dassert(coveringWrite == _mergedWrites.end() || coveringWrite->addr >= cwEnd);
}
+ }
+ dassert(coveringWrite == _mergedWrites.end() || coveringWrite->end() > addr);
- const size_t uncoveredLen = uncoveredEnd - addr;
- if (uncoveredLen) {
- // We are writing to a region that hasn't been declared previously.
- _mergedWrites.insert(Write(addr, uncoveredLen, _preimageBuffer.size()));
+ // If the next coveringWrite overlaps, adjust the end of the uncovered region.
+ char* uncoveredEnd = end;
+ if (coveringWrite != _mergedWrites.end() && coveringWrite->addr < end) {
+ uncoveredEnd = coveringWrite->addr;
+ }
- // Windows requires us to adjust the address space *before* we write to anything.
- privateViews.makeWritable(addr, uncoveredLen);
+ const size_t uncoveredLen = uncoveredEnd - addr;
+ if (uncoveredLen) {
+ // We are writing to a region that hasn't been declared previously.
+ _mergedWrites.insert(Write(addr, uncoveredLen, _preimageBuffer.size()));
- if (!_rollbackWritesDisabled) {
- _preimageBuffer.append(addr, uncoveredLen);
- }
- addr = uncoveredEnd;
+ // Windows requires us to adjust the address space *before* we write to anything.
+ privateViews.makeWritable(addr, uncoveredLen);
+
+ if (!_rollbackWritesDisabled) {
+ _preimageBuffer.append(addr, uncoveredLen);
}
+ addr = uncoveredEnd;
}
}
+}
- void* DurRecoveryUnit::writingPtr(void* addr, size_t len) {
- invariant(inAUnitOfWork());
+void* DurRecoveryUnit::writingPtr(void* addr, size_t len) {
+ invariant(inAUnitOfWork());
- if (len == 0) {
- return addr; // Don't need to do anything for empty ranges.
- }
+ if (len == 0) {
+ return addr; // Don't need to do anything for empty ranges.
+ }
- invariant(len < size_t(std::numeric_limits<int>::max()));
+ invariant(len < size_t(std::numeric_limits<int>::max()));
- _writeCount++;
- _writeBytes += len;
- char* const data = static_cast<char*>(addr);
+ _writeCount++;
+ _writeBytes += len;
+ char* const data = static_cast<char*>(addr);
- // The initial writes are stored in a faster, but less memory-efficient way. This will
- // typically be enough for simple operations, where the extra cost of incremental
- // coalescing and merging would be too much. For larger writes, more redundancy is
- // is expected, so the cost of checking for duplicates is offset by savings in copying
- // and allocating preimage buffers. Total memory use of the preimage buffer may be up to
- // kMaxUnmergedPreimageBytes larger than the amount memory covered by the write intents.
+// The initial writes are stored in a faster, but less memory-efficient way. This will
+// typically be enough for simple operations, where the extra cost of incremental
+// coalescing and merging would be too much. For larger writes, more redundancy is
+// is expected, so the cost of checking for duplicates is offset by savings in copying
+// and allocating preimage buffers. Total memory use of the preimage buffer may be up to
+// kMaxUnmergedPreimageBytes larger than the amount memory covered by the write intents.
#ifdef _DEBUG
- const size_t kMaxUnmergedPreimageBytes = 16*1024;
+ const size_t kMaxUnmergedPreimageBytes = 16 * 1024;
#else
- const size_t kMaxUnmergedPreimageBytes = 10*1024*1024;
+ const size_t kMaxUnmergedPreimageBytes = 10 * 1024 * 1024;
#endif
- if (_preimageBuffer.size() + len > kMaxUnmergedPreimageBytes) {
- mergingWritingPtr(data, len);
+ if (_preimageBuffer.size() + len > kMaxUnmergedPreimageBytes) {
+ mergingWritingPtr(data, len);
- // After a merged write, no more initial writes can occur or there would be an
- // ordering violation during rollback. So, ensure that the if-condition will be true
- // for any future write regardless of length. This is true now because
- // mergingWritingPtr also will store its first write in _preimageBuffer as well.
- invariant(_preimageBuffer.size() >= kMaxUnmergedPreimageBytes);
+ // After a merged write, no more initial writes can occur or there would be an
+ // ordering violation during rollback. So, ensure that the if-condition will be true
+ // for any future write regardless of length. This is true now because
+ // mergingWritingPtr also will store its first write in _preimageBuffer as well.
+ invariant(_preimageBuffer.size() >= kMaxUnmergedPreimageBytes);
- return addr;
- }
-
- // Windows requires us to adjust the address space *before* we write to anything.
- privateViews.makeWritable(data, len);
+ return addr;
+ }
- _initialWrites.push_back(Write(data, len, _preimageBuffer.size()));
+ // Windows requires us to adjust the address space *before* we write to anything.
+ privateViews.makeWritable(data, len);
- if (!_rollbackWritesDisabled) {
- _preimageBuffer.append(data, len);
- }
+ _initialWrites.push_back(Write(data, len, _preimageBuffer.size()));
- return addr;
+ if (!_rollbackWritesDisabled) {
+ _preimageBuffer.append(data, len);
}
- void DurRecoveryUnit::setRollbackWritesDisabled() {
- invariant(inOutermostUnitOfWork());
- _rollbackWritesDisabled = true;
- }
+ return addr;
+}
- void DurRecoveryUnit::registerChange(Change* change) {
- invariant(inAUnitOfWork());
- _changes.push_back(change);
- }
+void DurRecoveryUnit::setRollbackWritesDisabled() {
+ invariant(inOutermostUnitOfWork());
+ _rollbackWritesDisabled = true;
+}
+
+void DurRecoveryUnit::registerChange(Change* change) {
+ invariant(inAUnitOfWork());
+ _changes.push_back(change);
+}
} // namespace mongo