Skip to content

Commit 3315355

Browse files
Evgeni Dobranovevergreen
authored andcommitted
SERVER-38020 Log progress for record store and index traversal during collection validation
1 parent 13c2e61 commit 3315355

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

src/mongo/db/catalog/validate_adaptor.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "mongo/db/catalog/index_catalog.h"
3939
#include "mongo/db/catalog/index_consistency.h"
4040
#include "mongo/db/catalog/throttle_cursor.h"
41+
#include "mongo/db/curop.h"
4142
#include "mongo/db/index/index_access_method.h"
4243
#include "mongo/db/index/index_descriptor.h"
4344
#include "mongo/db/index/wildcard_access_method.h"
@@ -126,6 +127,7 @@ Status ValidateAdaptor::validateRecord(OperationContext* opCtx,
126127

127128
for (const auto& keyString : documentKeySet) {
128129
try {
130+
_totalIndexKeys++;
129131
_indexConsistency->addDocKey(opCtx, keyString, &indexInfo, recordId);
130132
} catch (...) {
131133
return exceptionToStatus();
@@ -146,6 +148,14 @@ void ValidateAdaptor::traverseIndex(OperationContext* opCtx,
146148

147149
bool isFirstEntry = true;
148150

151+
// The progress meter will be inactive after traversing the record store to allow the message
152+
// and the total to be set to different values.
153+
if (!_progress->isActive()) {
154+
const char* curopMessage = "Validate: scanning index entries";
155+
stdx::unique_lock<Client> lk(*opCtx->getClient());
156+
_progress.set(CurOp::get(opCtx)->setProgress_inlock(curopMessage, _totalIndexKeys));
157+
}
158+
149159
const KeyString::Version version =
150160
index->accessMethod()->getSortedDataInterface()->getKeyStringVersion();
151161
KeyString::Builder firstKeyString(
@@ -187,11 +197,13 @@ void ValidateAdaptor::traverseIndex(OperationContext* opCtx,
187197
if (descriptor->getIndexType() == IndexType::INDEX_WILDCARD &&
188198
indexEntry->loc == kWildcardMultikeyMetadataRecordId) {
189199
_indexConsistency->removeMultikeyMetadataPath(indexEntry->keyString, &indexInfo);
200+
_progress->hit();
190201
numKeys++;
191202
continue;
192203
}
193204

194205
_indexConsistency->addIndexKey(indexEntry->keyString, &indexInfo, indexEntry->loc);
206+
_progress->hit();
195207
numKeys++;
196208
isFirstEntry = false;
197209
prevIndexKeyStringValue = indexEntry->keyString;
@@ -220,12 +232,27 @@ void ValidateAdaptor::traverseRecordStore(OperationContext* opCtx,
220232
results->valid = true;
221233
RecordId prevRecordId;
222234

235+
// In case validation occurs twice and the progress meter persists after index traversal
236+
if (_progress.get() && _progress->isActive()) {
237+
_progress->finished();
238+
}
239+
240+
// Because the progress meter is intended as an approximation, it's sufficient to get the number
241+
// of records when we begin traversing, even if this number may deviate from the final number.
242+
const char* curopMessage = "Validate: scanning documents";
243+
const auto totalRecords = _validateState->getCollection()->getRecordStore()->numRecords(opCtx);
244+
{
245+
stdx::unique_lock<Client> lk(*opCtx->getClient());
246+
_progress.set(CurOp::get(opCtx)->setProgress_inlock(curopMessage, totalRecords));
247+
}
248+
223249
const std::unique_ptr<SeekableRecordThrottleCursor>& traverseRecordStoreCursor =
224250
_validateState->getTraverseRecordStoreCursor();
225251
for (auto record =
226252
traverseRecordStoreCursor->seekExact(opCtx, _validateState->getFirstRecordId());
227253
record;
228254
record = traverseRecordStoreCursor->next(opCtx)) {
255+
_progress->hit();
229256
++_numRecords;
230257
interruptIntervalNumBytes += record->data.size();
231258
if (_numRecords % kInterruptIntervalNumRecords == 0 ||
@@ -286,6 +313,8 @@ void ValidateAdaptor::traverseRecordStore(OperationContext* opCtx,
286313
opCtx, _numRecords, dataSizeTotal);
287314
}
288315

316+
_progress->finished();
317+
289318
output->appendNumber("nInvalidDocuments", nInvalid);
290319
output->appendNumber("nrecords", _numRecords);
291320
}

src/mongo/db/catalog/validate_adaptor.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#pragma once
3131

3232
#include "mongo/db/catalog/validate_state.h"
33+
#include "mongo/util/progress_meter.h"
3334

3435
namespace mongo {
3536

@@ -93,5 +94,12 @@ class ValidateAdaptor {
9394
// Saves the record count from the record store traversal to be used later to validate the index
9495
// entries count. Reset every time traverseRecordStore() is called.
9596
long long _numRecords = 0;
97+
98+
// For reporting progress during record store and index traversal.
99+
ProgressMeterHolder _progress;
100+
101+
// The total number of index keys is stored during the first validation phase, since this
102+
// count may change during a second phase.
103+
uint64_t _totalIndexKeys = 0;
96104
};
97105
} // namespace mongo

0 commit comments

Comments
 (0)