diff options
author | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2015-07-28 18:16:39 -0400 |
---|---|---|
committer | Mark Benvenuto <mark.benvenuto@mongodb.com> | 2015-07-28 18:27:27 -0400 |
commit | b66e993f1c742518d9b5e93b0d8a5f8255a4127c (patch) | |
tree | 55e6fed05333d2d37f34586726a342ed7f7dbc29 /src/mongo/db/storage/mmap_v1/dur_recovery_unit.cpp | |
parent | 314a22e93f283ab80e650618cbd3ed8babb8510f (diff) | |
download | mongo-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.cpp | 486 |
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 |