94 lines
3.1 KiB
C++
94 lines
3.1 KiB
C++
/*
|
|
* TesterWatchAndWaitWorkload.cpp
|
|
*
|
|
* This source file is part of the FoundationDB open source project
|
|
*
|
|
* Copyright 2013-2022 Apple Inc. and the FoundationDB project authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
#include "TesterApiWorkload.h"
|
|
#include "test/fdb_api.hpp"
|
|
|
|
namespace FdbApiTester {
|
|
|
|
using fdb::Key;
|
|
using fdb::Value;
|
|
|
|
class WatchAndWaitWorkload : public ApiWorkload {
|
|
public:
|
|
WatchAndWaitWorkload(const WorkloadConfig& config) : ApiWorkload(config) {}
|
|
int getMaxSelfBlockingFutures() override {
|
|
// One watch future running concurrently waits for a commit of a transaction which sets the value.
|
|
return 1;
|
|
}
|
|
|
|
private:
|
|
void randomOperation(TTaskFct cont) override {
|
|
// This test sets a key to an initial value, sets up a watch for that key, change the key's value to a different
|
|
// value, and waits for the watch to be triggered.
|
|
Key key(randomKeyName());
|
|
Value initialVal = randomValue();
|
|
auto newVal = randomValue();
|
|
// Ensure that newVal is different from initialVal, otherwise watch may not trigger.
|
|
while (initialVal == newVal) {
|
|
newVal = randomValue();
|
|
}
|
|
|
|
execTransaction(
|
|
[key, initialVal](auto ctx) {
|
|
// Set the key to initialVal.
|
|
ctx->tx().set(key, initialVal);
|
|
ctx->commit();
|
|
},
|
|
[this, key, newVal, cont]() {
|
|
execTransaction(
|
|
[key, newVal](auto ctx) {
|
|
// Check the value of the key.
|
|
auto f = ctx->tx().get(key, false);
|
|
ctx->continueAfter(f, [key, f, newVal, ctx] {
|
|
ASSERT(f.get().has_value());
|
|
if (f.get().value() == newVal) {
|
|
// If the key is already at newVal, finish successfully.
|
|
ctx->done();
|
|
} else {
|
|
// Otherwise, create a watch for the key.
|
|
auto watchF = ctx->tx().watch(key);
|
|
auto commitF = ctx->tx().commit();
|
|
|
|
ctx->continueAfterAll({ commitF, watchF }, [ctx] {
|
|
// Wait for the watch to report a change (to newVal).
|
|
ctx->done();
|
|
});
|
|
}
|
|
});
|
|
},
|
|
[this, cont]() { schedule(cont); });
|
|
schedule([this, key, newVal] {
|
|
execTransaction(
|
|
// Set the key to a newVal which is guaranteed to be different from initialVal, i.e.,
|
|
// must trigger the watch.
|
|
[key, newVal](auto ctx) {
|
|
ctx->tx().set(key, newVal);
|
|
ctx->commit();
|
|
},
|
|
[]() {});
|
|
});
|
|
});
|
|
}
|
|
};
|
|
|
|
WorkloadFactory<WatchAndWaitWorkload> WatchAndWaitWorkloadFactory("WatchAndWait");
|
|
|
|
} // namespace FdbApiTester
|