Merge pull request #6637 from sfc-gh-tclinkenbeard/fix-tag-throttle-cli

Fix `fdbcli` output for unthrottling tag
This commit is contained in:
Trevor Clinkenbeard 2022-03-19 13:02:49 -07:00 committed by GitHub
commit a818191a42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 72 additions and 25 deletions

View File

@ -33,6 +33,8 @@
namespace fdb_cli {
static constexpr int defaultThrottleListLimit = 100;
ACTOR Future<bool> throttleCommandActor(Reference<IDatabase> db, std::vector<StringRef> tokens) {
if (tokens.size() == 1) {
@ -40,10 +42,9 @@ ACTOR Future<bool> throttleCommandActor(Reference<IDatabase> db, std::vector<Str
return false;
} else if (tokencmp(tokens[1], "list")) {
if (tokens.size() > 4) {
printf("Usage: throttle list [throttled|recommended|all] [LIMIT]\n");
printf("\n");
printf("Lists tags that are currently throttled.\n");
printf("The default LIMIT is 100 tags.\n");
fmt::print("Usage: throttle list [throttled|recommended|all] [LIMIT]\n\n");
fmt::print("Lists tags that are currently throttled.\n");
fmt::print("The default LIMIT is {} tags.\n", defaultThrottleListLimit);
return false;
}
@ -62,7 +63,7 @@ ACTOR Future<bool> throttleCommandActor(Reference<IDatabase> db, std::vector<Str
}
}
state int throttleListLimit = 100;
state int throttleListLimit = defaultThrottleListLimit;
if (tokens.size() >= 4) {
char* end;
throttleListLimit = std::strtol((const char*)tokens[3].begin(), &end, 10);
@ -74,7 +75,7 @@ ACTOR Future<bool> throttleCommandActor(Reference<IDatabase> db, std::vector<Str
state std::vector<TagThrottleInfo> tags;
if (reportThrottled && reportRecommended) {
wait(store(tags, ThrottleApi::getThrottledTags(db, throttleListLimit, true)));
wait(store(tags, ThrottleApi::getThrottledTags(db, throttleListLimit, ContainsRecommended::True)));
} else if (reportThrottled) {
wait(store(tags, ThrottleApi::getThrottledTags(db, throttleListLimit)));
} else if (reportRecommended) {
@ -177,14 +178,14 @@ ACTOR Future<bool> throttleCommandActor(Reference<IDatabase> db, std::vector<Str
}
}
TagSet tags;
tags.addTag(tokens[3]);
TagSet tagSet;
tagSet.addTag(tokens[3]);
wait(ThrottleApi::throttleTags(db, tags, tpsRate, duration, TagThrottleType::MANUAL, priority));
wait(ThrottleApi::throttleTags(db, tagSet, tpsRate, duration, TagThrottleType::MANUAL, priority));
printf("Tag `%s' has been throttled\n", tokens[3].toString().c_str());
} else if (tokencmp(tokens[1], "off")) {
int nextIndex = 2;
TagSet tags;
state TagSet tagSet;
bool throttleTypeSpecified = false;
bool is_error = false;
Optional<TagThrottleType> throttleType = TagThrottleType::MANUAL;
@ -241,12 +242,14 @@ ACTOR Future<bool> throttleCommandActor(Reference<IDatabase> db, std::vector<Str
priority = TransactionPriority::BATCH;
++nextIndex;
} else if (tokencmp(tokens[nextIndex], "tag")) {
if (tags.size() > 0 || nextIndex == tokens.size() - 1) {
if (tagSet.size() > 0 || nextIndex == tokens.size() - 1) {
is_error = true;
continue;
}
tags.addTag(tokens[nextIndex + 1]);
tagSet.addTag(tokens[nextIndex + 1]);
nextIndex += 2;
} else {
is_error = true;
}
}
@ -256,15 +259,15 @@ ACTOR Future<bool> throttleCommandActor(Reference<IDatabase> db, std::vector<Str
state std::string priorityString =
priority.present() ? format(" at %s priority", transactionPriorityToString(priority.get(), false)) : "";
if (tags.size() > 0) {
bool success = wait(ThrottleApi::unthrottleTags(db, tags, throttleType, priority));
if (tagSet.size() > 0) {
bool success = wait(ThrottleApi::unthrottleTags(db, tagSet, throttleType, priority));
if (success) {
printf("Unthrottled tag `%s'%s\n", tokens[3].toString().c_str(), priorityString.c_str());
fmt::print("Unthrottled {0}{1}\n", tagSet.toString(), priorityString);
} else {
printf("Tag `%s' was not %sthrottled%s\n",
tokens[3].toString().c_str(),
throttleTypeString,
priorityString.c_str());
fmt::print("{0} was not {1}throttled{2}\n",
tagSet.toString(Capitalize::True),
throttleTypeString,
priorityString);
}
} else {
bool unthrottled = wait(ThrottleApi::unthrottleAll(db, throttleType, priority));

View File

@ -47,6 +47,19 @@ size_t TagSet::size() const {
return tags.size();
}
std::string TagSet::toString(Capitalize capitalize) const {
ASSERT(!tags.empty());
if (tags.size() == 1) {
std::string start = capitalize ? "Tag" : "tag";
return format("%s `%s'", start.c_str(), tags[0].toString().c_str());
}
std::string result = capitalize ? "Tags (" : "tags (";
for (int index = 0; index < tags.size() - 1; ++index) {
result += format("`%s', ", tags[index].toString().c_str());
}
return result + format("`%s')", tags.back().toString().c_str());
}
// Format for throttle key:
//
// tagThrottleKeysPrefix + [auto-throttled (1-byte 0/1)] + [priority (1-byte)] + [tag list]
@ -110,3 +123,26 @@ TagThrottleValue TagThrottleValue::fromValue(const ValueRef& value) {
reader >> throttleValue;
return throttleValue;
}
FDB_DEFINE_BOOLEAN_PARAM(ContainsRecommended);
FDB_DEFINE_BOOLEAN_PARAM(Capitalize);
TEST_CASE("TagSet/toString") {
{
TagSet tagSet;
tagSet.addTag("a"_sr);
ASSERT(tagSet.toString() == "tag `a'");
ASSERT(tagSet.toString(Capitalize::True) == "Tag `a'");
}
{
// Order is not guaranteed when multiple tags are present
TagSet tagSet;
tagSet.addTag("a"_sr);
tagSet.addTag("b"_sr);
auto tagString = tagSet.toString();
ASSERT(tagString == "tags (`a', `b')" || tagString == "tags (`b', `a')");
auto capitalizedTagString = tagSet.toString(Capitalize::True);
ASSERT(capitalizedTagString == "Tags (`a', `b')" || capitalizedTagString == "Tags (`b', `a')");
}
return Void();
}

View File

@ -27,6 +27,7 @@
#pragma once
#include "contrib/fmt-8.1.1/include/fmt/format.h"
#include "flow/Error.h"
#include "flow/flow.h"
#include "flow/network.h"
@ -39,6 +40,9 @@
typedef StringRef TransactionTagRef;
typedef Standalone<TransactionTagRef> TransactionTag;
FDB_DECLARE_BOOLEAN_PARAM(ContainsRecommended);
FDB_DECLARE_BOOLEAN_PARAM(Capitalize);
class TagSet {
public:
typedef std::vector<TransactionTagRef>::const_iterator const_iterator;
@ -58,7 +62,7 @@ public:
}
template <class Context>
void save(uint8_t* out, Context& c) const {
void save(uint8_t* out, Context&) const {
uint8_t* start = out;
for (const auto& tag : *this) {
*(out++) = (uint8_t)tag.size();
@ -94,6 +98,9 @@ public:
const Arena& getArena() const { return arena; }
// Used by fdbcli commands
std::string toString(Capitalize = Capitalize::False) const;
private:
size_t bytes;
Arena arena;
@ -295,13 +302,14 @@ Future<std::vector<TagThrottleInfo>> getRecommendedTags(Reference<DB> db, int li
}
ACTOR template <class DB>
Future<std::vector<TagThrottleInfo>> getThrottledTags(Reference<DB> db, int limit, bool containsRecommend = false) {
Future<std::vector<TagThrottleInfo>>
getThrottledTags(Reference<DB> db, int limit, ContainsRecommended containsRecommended = ContainsRecommended::False) {
state Reference<typename DB::TransactionT> tr = db->createTransaction();
state bool reportAuto = containsRecommend;
state bool reportAuto = containsRecommended;
loop {
tr->setOption(FDBTransactionOptions::READ_SYSTEM_KEYS);
try {
if (!containsRecommend) {
if (!containsRecommended) {
wait(store(reportAuto, getValidAutoEnabled(tr)));
}
state typename DB::TransactionT::template FutureT<RangeResult> f = tr->getRange(

View File

@ -310,9 +310,9 @@ struct WriteTagThrottlingWorkload : KVWorkload {
state Reference<DatabaseContext> db = cx.getReference();
loop {
wait(delay(1.0));
wait(store(tags, ThrottleApi::getThrottledTags(db, CLIENT_KNOBS->TOO_MANY, true)));
wait(store(tags, ThrottleApi::getThrottledTags(db, CLIENT_KNOBS->TOO_MANY, ContainsRecommended::True)));
self->recordThrottledTags(tags);
};
}
}
static std::string setToString(const std::set<std::string>& myset) {