diff options
author | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2017-09-11 11:13:08 -0400 |
---|---|---|
committer | Kaloian Manassiev <kaloian.manassiev@mongodb.com> | 2017-09-14 07:46:46 -0400 |
commit | b0abd3f0b318e61837c2853a21b0ffde0bf8639f (patch) | |
tree | cc6ae8ca405766d44799c93667990bf7a8da25ed /src/mongo/util/fail_point.cpp | |
parent | b15fb2303c5c9ef72b64061c4b931bf7d39cdfab (diff) | |
download | mongo-b0abd3f0b318e61837c2853a21b0ffde0bf8639f.tar.gz |
SERVER-29606 Add a 'skip' failpoint option
This option allows the failpoint's effect to be skipped for up to a
certain amount of checks.
Diffstat (limited to 'src/mongo/util/fail_point.cpp')
-rw-r--r-- | src/mongo/util/fail_point.cpp | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/src/mongo/util/fail_point.cpp b/src/mongo/util/fail_point.cpp index 8f85ba18f17..75be5f48231 100644 --- a/src/mongo/util/fail_point.cpp +++ b/src/mongo/util/fail_point.cpp @@ -76,7 +76,7 @@ void FailPoint::setThreadPRNGSeed(int32_t seed) { FailPointPRNG::current()->resetSeed(seed); } -FailPoint::FailPoint() : _fpInfo(0), _mode(off), _timesOrPeriod(0) {} +FailPoint::FailPoint() = default; void FailPoint::shouldFailCloseBlock() { _fpInfo.subtractAndFetch(1); @@ -151,24 +151,28 @@ FailPoint::RetCode FailPoint::slowShouldFailOpenBlock() { switch (_mode) { case alwaysOn: return slowOn; - case random: { const AtomicInt32::WordType maxActivationValue = _timesOrPeriod.load(); - if (FailPointPRNG::current()->nextPositiveInt32() < maxActivationValue) { + if (FailPointPRNG::current()->nextPositiveInt32() < maxActivationValue) return slowOn; - } + return slowOff; } case nTimes: { - AtomicInt32::WordType newVal = _timesOrPeriod.subtractAndFetch(1); - - if (newVal <= 0) { + if (_timesOrPeriod.subtractAndFetch(1) <= 0) disableFailPoint(); - } return slowOn; } + case skip: { + // Ensure that once the skip counter reaches within some delta from 0 we don't continue + // decrementing it unboundedly because at some point it will roll over and become + // positive again + if (_timesOrPeriod.load() <= 0 || _timesOrPeriod.subtractAndFetch(1) < 0) + return slowOn; + return slowOff; + } default: error() << "FailPoint Mode not supported: " << static_cast<int>(_mode); fassertFailed(16444); @@ -212,6 +216,23 @@ StatusWith<std::tuple<FailPoint::Mode, FailPoint::ValType, BSONObj>> FailPoint:: return {ErrorCodes::BadValue, "'times' option to 'mode' is too large"}; } val = static_cast<int>(longVal); + } else if (modeObj.hasField("skip")) { + mode = FailPoint::skip; + + long long longVal; + auto status = bsonExtractIntegerField(modeObj, "skip", &longVal); + if (!status.isOK()) { + return status; + } + + if (longVal < 0) { + return {ErrorCodes::BadValue, "'skip' option to 'mode' must be positive"}; + } + + if (longVal > std::numeric_limits<int>::max()) { + return {ErrorCodes::BadValue, "'skip' option to 'mode' is too large"}; + } + val = static_cast<int>(longVal); } else if (modeObj.hasField("activationProbability")) { mode = FailPoint::random; |