2017-05-26 04:48:44 +08:00
|
|
|
/*
|
|
|
|
* FileSystem.actor.cpp
|
|
|
|
*
|
|
|
|
* This source file is part of the FoundationDB open source project
|
|
|
|
*
|
|
|
|
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* 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
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2018-02-22 02:25:11 +08:00
|
|
|
*
|
2017-05-26 04:48:44 +08:00
|
|
|
* 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 "fdbrpc/ContinuousSample.h"
|
2019-02-18 07:41:16 +08:00
|
|
|
#include "fdbclient/NativeAPI.actor.h"
|
2019-02-18 11:25:16 +08:00
|
|
|
#include "fdbserver/TesterInterface.actor.h"
|
2019-02-18 11:18:30 +08:00
|
|
|
#include "fdbserver/workloads/workloads.actor.h"
|
2021-03-11 02:06:03 +08:00
|
|
|
#include "flow/actorcompiler.h" // This must be the last #include.
|
2017-05-26 04:48:44 +08:00
|
|
|
|
|
|
|
struct FileSystemWorkload : TestWorkload {
|
|
|
|
int actorCount, writeActorCount, fileCount, pathMinChars, pathCharRange, serverCount, userIDCount;
|
|
|
|
double testDuration, transactionsPerSecond, deletedFilesRatio;
|
|
|
|
bool discardEdgeMeasurements, performingWrites, loggingQueries;
|
|
|
|
std::string operationName;
|
|
|
|
|
|
|
|
vector<Future<Void>> clients;
|
|
|
|
PerfIntCounter queries, writes;
|
|
|
|
ContinuousSample<double> latencies;
|
|
|
|
ContinuousSample<double> writeLatencies;
|
|
|
|
|
|
|
|
class FileSystemOp {
|
|
|
|
public:
|
2021-03-11 02:06:03 +08:00
|
|
|
virtual Future<Optional<Version>> run(FileSystemWorkload* self, Transaction* tr) = 0;
|
|
|
|
virtual const char* name() = 0;
|
2017-05-26 04:48:44 +08:00
|
|
|
virtual ~FileSystemOp() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
FileSystemWorkload(WorkloadContext const& wcx)
|
2021-03-11 02:06:03 +08:00
|
|
|
: TestWorkload(wcx), latencies(2500), writeLatencies(1000), queries("Queries"), writes("Latency") {
|
|
|
|
testDuration = getOption(options, LiteralStringRef("testDuration"), 10.0);
|
|
|
|
transactionsPerSecond = getOption(options, LiteralStringRef("transactionsPerSecond"), 5000.0) / clientCount;
|
|
|
|
double allowedLatency = getOption(options, LiteralStringRef("allowedLatency"), 0.250);
|
2017-05-26 04:48:44 +08:00
|
|
|
actorCount = transactionsPerSecond * allowedLatency;
|
2021-03-11 02:06:03 +08:00
|
|
|
fileCount = getOption(options, LiteralStringRef("fileCount"), 100000);
|
|
|
|
pathMinChars = std::max(getOption(options, LiteralStringRef("pathMinChars"), 32), 8);
|
|
|
|
pathCharRange =
|
|
|
|
std::max(getOption(options, LiteralStringRef("pathMaxChars"), 128), pathMinChars) - pathMinChars;
|
|
|
|
discardEdgeMeasurements = getOption(options, LiteralStringRef("discardEdgeMeasurements"), true);
|
|
|
|
deletedFilesRatio = getOption(options, LiteralStringRef("deletedFilesRatio"), 0.01);
|
|
|
|
serverCount = getOption(options, LiteralStringRef("serverCount"), 32);
|
|
|
|
userIDCount = getOption(options, LiteralStringRef("userIDCount"), std::max(100, fileCount / 3000));
|
|
|
|
operationName =
|
|
|
|
getOption(options, LiteralStringRef("operationName"), LiteralStringRef("modificationQuery")).toString();
|
|
|
|
performingWrites = getOption(options, LiteralStringRef("performingWrites"), false);
|
|
|
|
writeActorCount = getOption(options, LiteralStringRef("writeActorCount"), 4);
|
|
|
|
loggingQueries = getOption(options, LiteralStringRef("loggingQueries"), false);
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
2020-10-05 13:29:07 +08:00
|
|
|
std::string description() const override { return "ReadWrite"; }
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2020-10-05 13:29:07 +08:00
|
|
|
Future<Void> setup(Database const& cx) override { return nodeSetup(cx, this); }
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2020-10-05 13:29:07 +08:00
|
|
|
Future<Void> start(Database const& cx) override { return _start(cx, this); }
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2020-10-05 13:29:07 +08:00
|
|
|
Future<bool> check(Database const& cx) override {
|
2017-05-26 04:48:44 +08:00
|
|
|
clients.clear();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-10-05 13:29:07 +08:00
|
|
|
void getMetrics(vector<PerfMetric>& m) override {
|
2017-05-26 04:48:44 +08:00
|
|
|
double duration = testDuration * (discardEdgeMeasurements ? 0.75 : 1.0);
|
2021-03-11 02:06:03 +08:00
|
|
|
m.push_back(PerfMetric("Measured Duration", duration, true));
|
|
|
|
m.push_back(PerfMetric("Transactions/sec", queries.getValue() / duration, false));
|
|
|
|
m.push_back(PerfMetric("Writes/sec", writes.getValue() / duration, false));
|
|
|
|
m.push_back(PerfMetric("Mean Latency (ms)", 1000 * latencies.mean(), true));
|
|
|
|
m.push_back(PerfMetric("Median Latency (ms, averaged)", 1000 * latencies.median(), true));
|
|
|
|
m.push_back(PerfMetric("90% Latency (ms, averaged)", 1000 * latencies.percentile(0.90), true));
|
|
|
|
m.push_back(PerfMetric("98% Latency (ms, averaged)", 1000 * latencies.percentile(0.98), true));
|
|
|
|
m.push_back(PerfMetric("Median Write Latency (ms, averaged)", 1000 * writeLatencies.median(), true));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
Key keyForFileID(uint64_t id) { return StringRef(format("/files/id/%016llx", id)); }
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
void initializeFile(Transaction* tr, FileSystemWorkload* self, uint64_t id) {
|
|
|
|
Key key = self->keyForFileID(id);
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2019-05-11 05:01:52 +08:00
|
|
|
int pathLen = self->pathMinChars + deterministicRandom()->randomInt(0, self->pathCharRange);
|
2017-05-26 04:48:44 +08:00
|
|
|
std::string path = "";
|
2021-03-11 02:06:03 +08:00
|
|
|
for (int i = 0; i < pathLen; i += 4)
|
|
|
|
path +=
|
|
|
|
format(format("%%0%dx", std::min(pathLen - i, 4)).c_str(), deterministicRandom()->randomInt(0, 0xFFFF));
|
2019-05-11 05:01:52 +08:00
|
|
|
uint64_t userID = deterministicRandom()->randomInt(0, self->userIDCount);
|
|
|
|
int serverID = deterministicRandom()->randomInt(0, self->serverCount);
|
|
|
|
bool deleted = deterministicRandom()->random01() < self->deletedFilesRatio;
|
2017-05-26 04:48:44 +08:00
|
|
|
double time = now();
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
tr->set(key, path);
|
2017-05-26 04:48:44 +08:00
|
|
|
std::string keyStr(key.toString());
|
2021-04-15 01:30:21 +08:00
|
|
|
tr->set(keyStr + "/size", format("%d", deterministicRandom()->randomInt(0, std::numeric_limits<int>::max())));
|
2021-03-11 02:06:03 +08:00
|
|
|
tr->set(keyStr + "/server", format("%d", deterministicRandom()->randomInt(0, self->serverCount)));
|
|
|
|
tr->set(keyStr + "/deleted", deleted ? LiteralStringRef("1") : LiteralStringRef("0"));
|
|
|
|
tr->set(keyStr + "/server", format("%d", serverID));
|
|
|
|
tr->set(keyStr + "/created", doubleToTestKey(time));
|
|
|
|
tr->set(keyStr + "/lastupdated", doubleToTestKey(time));
|
|
|
|
tr->set(keyStr + "/userid", format("%016llx", userID));
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
if (deleted)
|
|
|
|
tr->set(format("/files/server/%08x/deleted/%016llx", serverID, id), doubleToTestKey(time));
|
|
|
|
tr->set(format("/files/user/%016llx/updated/%016llx/%016llx", userID, *(uint64_t*)&time, id), path);
|
|
|
|
tr->set(format("/files/user/%016llx/path/", userID) + path, format("%016llx", id));
|
2017-05-26 04:48:44 +08:00
|
|
|
// This index was not specified in the original test: it removes duplicated paths
|
2021-03-11 02:06:03 +08:00
|
|
|
tr->set("/files/path/" + path, format("%016llx", id));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
ACTOR Future<Void> setupRange(Database cx, FileSystemWorkload* self, int begin, int end) {
|
2017-05-26 04:48:44 +08:00
|
|
|
state Transaction tr(cx);
|
|
|
|
while (true) {
|
|
|
|
try {
|
2021-03-11 02:06:03 +08:00
|
|
|
Optional<Value> f = wait(tr.get(self->keyForFileID(begin)));
|
|
|
|
if (f.present())
|
|
|
|
break; // The transaction already completed!
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
for (int n = begin; n < end; n++)
|
|
|
|
self->initializeFile(&tr, self, n);
|
|
|
|
wait(tr.commit());
|
2017-05-26 04:48:44 +08:00
|
|
|
break;
|
|
|
|
} catch (Error& e) {
|
2021-03-11 02:06:03 +08:00
|
|
|
wait(tr.onError(e));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Void();
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
ACTOR Future<Void> nodeSetup(Database cx, FileSystemWorkload* self) {
|
2017-05-26 04:48:44 +08:00
|
|
|
state int i;
|
|
|
|
state vector<int> order;
|
|
|
|
state int nodesToSetUp = self->fileCount / self->clientCount + 1;
|
|
|
|
state int startingNode = nodesToSetUp * self->clientId;
|
|
|
|
state int batchCount = 5;
|
2021-03-11 02:06:03 +08:00
|
|
|
for (int o = 0; o <= nodesToSetUp / batchCount; o++)
|
|
|
|
order.push_back(o * batchCount);
|
2019-05-11 05:01:52 +08:00
|
|
|
deterministicRandom()->randomShuffle(order);
|
2021-03-11 02:06:03 +08:00
|
|
|
for (i = 0; i < order.size();) {
|
2017-05-26 04:48:44 +08:00
|
|
|
vector<Future<Void>> fs;
|
2021-03-11 02:06:03 +08:00
|
|
|
for (int j = 0; j < 100 && i < order.size(); j++) {
|
|
|
|
fs.push_back(self->setupRange(
|
|
|
|
cx,
|
|
|
|
self,
|
|
|
|
startingNode + order[i],
|
|
|
|
std::min(startingNode + order[i] + batchCount, nodesToSetUp * (self->clientId + 1))));
|
2017-05-26 04:48:44 +08:00
|
|
|
i++;
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
wait(waitForAll(fs));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
TraceEvent("FileSetupOK")
|
|
|
|
.detail("ClientIdx", self->clientId)
|
|
|
|
.detail("ClientCount", self->clientCount)
|
|
|
|
.detail("StartingFile", startingNode)
|
|
|
|
.detail("FilesToSetUp", nodesToSetUp);
|
2017-05-26 04:48:44 +08:00
|
|
|
return Void();
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
ACTOR Future<Void> _start(Database cx, FileSystemWorkload* self) {
|
|
|
|
state FileSystemOp* operation;
|
|
|
|
if (self->operationName == "deletionQuery")
|
2017-05-26 04:48:44 +08:00
|
|
|
operation = new ServerDeletionCountQuery();
|
|
|
|
else
|
|
|
|
operation = new RecentModificationQuery();
|
2021-03-11 02:06:03 +08:00
|
|
|
wait(timeout(self->operationClient(cx, self, operation, 0.01), 1.0, Void()));
|
2017-05-26 04:48:44 +08:00
|
|
|
self->queries.clear();
|
|
|
|
self->writes.clear();
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
if (self->performingWrites) {
|
|
|
|
for (int c = 0; c < self->writeActorCount; c++) {
|
|
|
|
self->clients.push_back(timeout(self->writeClient(cx, self), self->testDuration, Void()));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
for (int c = 0; c < self->actorCount; c++) {
|
|
|
|
self->clients.push_back(
|
|
|
|
timeout(self->operationClient(cx, self, operation, self->actorCount / self->transactionsPerSecond),
|
|
|
|
self->testDuration,
|
|
|
|
Void()));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
wait(waitForAll(self->clients));
|
2017-05-26 04:48:44 +08:00
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
wait(delay(0.01)); // Make sure the deletion happens after actor cancellation
|
2017-05-26 04:48:44 +08:00
|
|
|
delete operation;
|
|
|
|
return Void();
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
bool shouldRecord(double clientBegin) {
|
2017-05-26 04:48:44 +08:00
|
|
|
double n = now();
|
|
|
|
return !discardEdgeMeasurements ||
|
2021-03-11 02:06:03 +08:00
|
|
|
(n > (clientBegin + testDuration * 0.125) && n < (clientBegin + testDuration * 0.875));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
ACTOR Future<Void> operationClient(Database cx, FileSystemWorkload* self, FileSystemOp* operation, double delay) {
|
2017-05-26 04:48:44 +08:00
|
|
|
state double clientBegin = now();
|
|
|
|
state double lastTime = now();
|
|
|
|
loop {
|
2021-03-11 02:06:03 +08:00
|
|
|
wait(poisson(&lastTime, delay));
|
2017-05-26 04:48:44 +08:00
|
|
|
state double tstart = now();
|
|
|
|
state Transaction tr(cx);
|
|
|
|
loop {
|
|
|
|
try {
|
2021-03-11 02:06:03 +08:00
|
|
|
Optional<Version> ver = wait(operation->run(self, &tr));
|
|
|
|
if (ver.present())
|
2017-05-26 04:48:44 +08:00
|
|
|
break;
|
|
|
|
} catch (Error& e) {
|
2021-03-11 02:06:03 +08:00
|
|
|
wait(tr.onError(e));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
if (self->shouldRecord(clientBegin)) {
|
2017-05-26 04:48:44 +08:00
|
|
|
++self->queries;
|
|
|
|
double latency = now() - tstart;
|
2021-03-11 02:06:03 +08:00
|
|
|
self->latencies.addSample(latency);
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
static int testKeyToInt(const KeyRef& p) {
|
2017-05-26 04:48:44 +08:00
|
|
|
int x = 0;
|
2021-03-11 02:06:03 +08:00
|
|
|
sscanf(p.toString().c_str(), "%d", &x);
|
2017-05-26 04:48:44 +08:00
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
ACTOR Future<Void> writeClient(Database cx, FileSystemWorkload* self) {
|
2017-05-26 04:48:44 +08:00
|
|
|
state double clientBegin = now();
|
|
|
|
loop {
|
2019-05-11 05:01:52 +08:00
|
|
|
state int fileID = deterministicRandom()->randomInt(0, self->fileCount);
|
|
|
|
state bool isDeleting = deterministicRandom()->random01() < 0.25;
|
2021-04-15 01:30:21 +08:00
|
|
|
state int size = isDeleting ? 0 : deterministicRandom()->randomInt(0, std::numeric_limits<int>::max());
|
2021-03-11 02:06:03 +08:00
|
|
|
state std::string keyStr = self->keyForFileID(fileID).toString();
|
2017-05-26 04:48:44 +08:00
|
|
|
state double tstart = now();
|
|
|
|
state Transaction tr(cx);
|
|
|
|
loop {
|
|
|
|
try {
|
|
|
|
state double time = now();
|
2021-03-11 02:06:03 +08:00
|
|
|
if (isDeleting) {
|
|
|
|
state Optional<Value> deleted = wait(tr.get(StringRef(keyStr + "/deleted")));
|
|
|
|
ASSERT(deleted.present());
|
|
|
|
Optional<Value> serverStr = wait(tr.get(StringRef(keyStr + "/server")));
|
|
|
|
ASSERT(serverStr.present());
|
|
|
|
int serverID = testKeyToInt(serverStr.get());
|
|
|
|
if (deleted.get().toString() == "1") {
|
|
|
|
tr.set(keyStr + "/deleted", LiteralStringRef("0"));
|
|
|
|
tr.clear(format("/files/server/%08x/deleted/%016llx", serverID, fileID));
|
2017-05-26 04:48:44 +08:00
|
|
|
} else {
|
2021-03-11 02:06:03 +08:00
|
|
|
tr.set(keyStr + "/deleted", LiteralStringRef("1"));
|
|
|
|
tr.set(format("/files/server/%08x/deleted/%016llx", serverID, fileID),
|
|
|
|
doubleToTestKey(time));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
} else {
|
2021-03-11 02:06:03 +08:00
|
|
|
tr.set(keyStr + "/size", format("%d", size));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
tr.set(keyStr + "/lastupdated", doubleToTestKey(time));
|
|
|
|
wait(tr.commit());
|
2017-05-26 04:48:44 +08:00
|
|
|
break;
|
|
|
|
} catch (Error& e) {
|
2021-03-11 02:06:03 +08:00
|
|
|
wait(tr.onError(e));
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
if (self->shouldRecord(clientBegin)) {
|
2017-05-26 04:48:44 +08:00
|
|
|
++self->writes;
|
2021-03-11 02:06:03 +08:00
|
|
|
self->writeLatencies.addSample(now() - tstart);
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
ACTOR Future<Optional<Version>> modificationQuery(FileSystemWorkload* self, Transaction* tr) {
|
2019-05-11 05:01:52 +08:00
|
|
|
state uint64_t userID = deterministicRandom()->randomInt(0, self->userIDCount);
|
2017-05-26 04:48:44 +08:00
|
|
|
state std::string base = format("/files/user/%016llx", userID);
|
2021-03-11 02:06:03 +08:00
|
|
|
if (self->loggingQueries)
|
2017-05-26 04:48:44 +08:00
|
|
|
TraceEvent("UserQuery").detail("UserID", userID).detail("PathBase", base);
|
|
|
|
Key keyEnd(base + "/updated0");
|
2021-05-04 04:14:16 +08:00
|
|
|
RangeResult val = wait(tr->getRange(firstGreaterOrEqual(keyEnd) - 10, firstGreaterOrEqual(keyEnd), 10));
|
2017-05-26 04:48:44 +08:00
|
|
|
Key keyBegin(base + "/updated/");
|
2021-03-11 02:06:03 +08:00
|
|
|
for (int i = val.size() - 1; i >= 0; i--) {
|
|
|
|
if (val[i].key.startsWith(keyBegin) && self->loggingQueries) {
|
|
|
|
TraceEvent("UserQueryResults")
|
|
|
|
.detail("UserID", userID)
|
|
|
|
.detail("PathBase", base)
|
|
|
|
.detail("LastModified", printable(val[i].key.substr(54)));
|
2017-05-26 04:48:44 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Optional<Version>(Version(0));
|
|
|
|
}
|
|
|
|
|
2021-03-11 02:06:03 +08:00
|
|
|
ACTOR Future<Optional<Version>> deletionQuery(FileSystemWorkload* self, Transaction* tr) {
|
2019-05-11 05:01:52 +08:00
|
|
|
state uint64_t serverID = deterministicRandom()->randomInt(0, self->serverCount);
|
2017-05-26 04:48:44 +08:00
|
|
|
state std::string base = format("/files/server/%08x/deleted", serverID);
|
2021-03-11 02:06:03 +08:00
|
|
|
if (self->loggingQueries)
|
2017-05-26 04:48:44 +08:00
|
|
|
TraceEvent("DeletionQuery").detail("ServerID", serverID).detail("PathBase", base);
|
|
|
|
state Key keyBegin(base + "/");
|
|
|
|
state Key keyEnd(base + "0");
|
2021-03-11 02:06:03 +08:00
|
|
|
state KeySelectorRef begin = firstGreaterThan(keyBegin);
|
|
|
|
state KeySelectorRef end = firstGreaterOrEqual(keyEnd);
|
2017-05-26 04:48:44 +08:00
|
|
|
state int transfered = 1000;
|
|
|
|
state int transferSize = 1000;
|
|
|
|
state uint64_t deletedFiles = 0;
|
2021-03-11 02:06:03 +08:00
|
|
|
while (transfered == transferSize) {
|
2021-05-04 04:14:16 +08:00
|
|
|
RangeResult val = wait(tr->getRange(begin, end, transferSize));
|
2017-05-26 04:48:44 +08:00
|
|
|
transfered = val.size();
|
|
|
|
deletedFiles += transfered;
|
|
|
|
begin = begin + transfered;
|
|
|
|
}
|
2021-03-11 02:06:03 +08:00
|
|
|
if (self->loggingQueries) {
|
|
|
|
TraceEvent("DeletionQueryResults")
|
|
|
|
.detail("ServerID", serverID)
|
|
|
|
.detail("PathBase", base)
|
|
|
|
.detail("DeletedFiles", deletedFiles);
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
|
|
|
return Optional<Version>(Version(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
class RecentModificationQuery : public FileSystemOp {
|
2021-01-26 09:55:43 +08:00
|
|
|
Future<Optional<Version>> run(FileSystemWorkload* self, Transaction* tr) override {
|
2021-03-11 02:06:03 +08:00
|
|
|
return self->modificationQuery(self, tr);
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
2021-01-26 09:55:43 +08:00
|
|
|
const char* name() override { return "RecentUserModifications"; }
|
2017-05-26 04:48:44 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class ServerDeletionCountQuery : public FileSystemOp {
|
2021-01-26 09:55:43 +08:00
|
|
|
Future<Optional<Version>> run(FileSystemWorkload* self, Transaction* tr) override {
|
2021-03-11 02:06:03 +08:00
|
|
|
return self->deletionQuery(self, tr);
|
2017-05-26 04:48:44 +08:00
|
|
|
}
|
2021-01-26 09:55:43 +08:00
|
|
|
const char* name() override { return "ServerDeletions"; }
|
2017-05-26 04:48:44 +08:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
WorkloadFactory<FileSystemWorkload> FileSystemWorkloadFactory("FileSystem");
|