summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Kuehne <ian.kuehne@mongodb.com>2017-08-24 15:00:34 -0400
committerIan Kuehne <ian.kuehne@mongodb.com>2017-08-25 08:19:57 -0400
commita7a647f3b640ec4135a0d0a932b43af7307874d7 (patch)
treef00f7f8418d3c6d5445923fab64630ab3a4d7865
parenta44b50d7e47082084800dd7550ddaa5d7c1af266 (diff)
downloadmongo-a7a647f3b640ec4135a0d0a932b43af7307874d7.tar.gz
SERVER-30806 Add options for limiting dbCheck rate
-rw-r--r--src/mongo/db/commands/dbcheck.cpp29
-rw-r--r--src/mongo/db/repl/dbcheck.idl3
2 files changed, 30 insertions, 2 deletions
diff --git a/src/mongo/db/commands/dbcheck.cpp b/src/mongo/db/commands/dbcheck.cpp
index 5fbce23eefb..c39484cd031 100644
--- a/src/mongo/db/commands/dbcheck.cpp
+++ b/src/mongo/db/commands/dbcheck.cpp
@@ -58,6 +58,7 @@ struct DbCheckCollectionInfo {
BSONKey end;
int64_t maxCount;
int64_t maxSize;
+ int64_t maxRate;
};
/**
@@ -77,7 +78,8 @@ std::unique_ptr<DbCheckRun> singleCollectionRun(OperationContext* opCtx,
auto end = invocation.getMaxKey();
auto maxCount = invocation.getMaxCount();
auto maxSize = invocation.getMaxSize();
- auto info = DbCheckCollectionInfo{nss, start, end, maxCount, maxSize};
+ auto maxRate = invocation.getMaxCountPerSecond();
+ auto info = DbCheckCollectionInfo{nss, start, end, maxCount, maxSize, maxRate};
auto result = stdx::make_unique<DbCheckRun>();
result->push_back(info);
return result;
@@ -94,9 +96,10 @@ std::unique_ptr<DbCheckRun> fullDatabaseRun(OperationContext* opCtx,
uassert(ErrorCodes::NamespaceNotFound, "Database " + dbName + " not found", agd.getDb());
int64_t max = std::numeric_limits<int64_t>::max();
+ auto rate = invocation.getMaxCountPerSecond();
for (Collection* coll : *db) {
- DbCheckCollectionInfo info{coll->ns(), BSONKey::min(), BSONKey::max(), max, max};
+ DbCheckCollectionInfo info{coll->ns(), BSONKey::min(), BSONKey::max(), max, max, rate};
result->push_back(info);
}
@@ -178,7 +181,20 @@ private:
int64_t totalBytesSeen = 0;
int64_t totalDocsSeen = 0;
+ // Limit the rate of the check.
+ using Clock = stdx::chrono::system_clock;
+ using TimePoint = stdx::chrono::time_point<Clock>;
+ TimePoint lastStart = Clock::now();
+ int64_t docsInCurrentInterval = 0;
+
do {
+ using namespace std::literals::chrono_literals;
+
+ if (Clock::now() - lastStart > 1s) {
+ lastStart = Clock::now();
+ docsInCurrentInterval = 0;
+ }
+
auto result = _runBatch(info, start, kBatchDocs, kBatchBytes);
if (_done) {
@@ -212,12 +228,21 @@ private:
// Update our running totals.
totalDocsSeen += stats.nDocs;
totalBytesSeen += stats.nBytes;
+ docsInCurrentInterval += stats.nDocs;
// Check if we've exceeded any limits.
bool reachedLast = stats.lastKey >= info.end;
bool tooManyDocs = totalDocsSeen >= info.maxCount;
bool tooManyBytes = totalBytesSeen >= info.maxSize;
reachedEnd = reachedLast || tooManyDocs || tooManyBytes;
+
+ if (docsInCurrentInterval > info.maxRate && info.maxRate > 0) {
+ // If an extremely low max rate has been set (substantially smaller than the batch
+ // size) we might want to sleep for multiple seconds between batches.
+ int64_t timesExceeded = docsInCurrentInterval / info.maxRate;
+
+ stdx::this_thread::sleep_for(timesExceeded * 1s - (Clock::now() - lastStart));
+ }
} while (!reachedEnd);
}
diff --git a/src/mongo/db/repl/dbcheck.idl b/src/mongo/db/repl/dbcheck.idl
index 93262bf0555..357e02b5b46 100644
--- a/src/mongo/db/repl/dbcheck.idl
+++ b/src/mongo/db/repl/dbcheck.idl
@@ -90,6 +90,9 @@ structs:
maxKey:
type: _id_key
cpp_name: maxKey
+ maxRate:
+ type: safeInt64
+ optional: true
DbCheckOplogCollection:
description: "Oplog entry for dbCheck collection metadata"