summaryrefslogtreecommitdiff
path: root/src/mongo/util/fail_point.cpp
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2017-09-11 11:13:08 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2017-09-14 07:46:46 -0400
commitb0abd3f0b318e61837c2853a21b0ffde0bf8639f (patch)
treecc6ae8ca405766d44799c93667990bf7a8da25ed /src/mongo/util/fail_point.cpp
parentb15fb2303c5c9ef72b64061c4b931bf7d39cdfab (diff)
downloadmongo-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.cpp37
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;