From a29e3805162a2bb74ffbe26efbc9fcf1c8c5caac Mon Sep 17 00:00:00 2001 From: Chaoguang Lin Date: Thu, 8 Jul 2021 22:29:04 +0000 Subject: [PATCH 1/3] Print out setclass special keys' related error if present --- fdbcli/SetClassCommand.actor.cpp | 29 +++++++++++++++++++++-------- fdbcli/fdbcli.actor.h | 2 ++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/fdbcli/SetClassCommand.actor.cpp b/fdbcli/SetClassCommand.actor.cpp index b46f837385..11b8c1da96 100644 --- a/fdbcli/SetClassCommand.actor.cpp +++ b/fdbcli/SetClassCommand.actor.cpp @@ -23,6 +23,8 @@ #include "fdbclient/FDBOptions.g.h" #include "fdbclient/IClientApi.h" #include "fdbclient/Knobs.h" +#include "fdbclient/Schemas.h" +#include "fdbclient/Status.h" #include "flow/Arena.h" #include "flow/FastRef.h" @@ -71,15 +73,26 @@ ACTOR Future printProcessClass(Reference db) { }; ACTOR Future setProcessClass(Reference db, KeyRef network_address, KeyRef class_type) { - state Reference tr = db->createTransaction(); + state Reference tr = db->createTransaction(); loop { tr->setOption(FDBTransactionOptions::SPECIAL_KEY_SPACE_ENABLE_WRITES); try { - tr->set(network_address.withPrefix(fdb_cli::processClassTypeSpecialKeyRange.begin), class_type); - wait(safeThreadFutureToFuture(tr->commit())); - return true; - } catch (Error& e) { - wait(safeThreadFutureToFuture(tr->onError(e))); + tr->set(network_address.withPrefix(fdb_cli::processClassTypeSpecialKeyRange.begin), class_type); + wait(safeThreadFutureToFuture(tr->commit())); + return true; + } catch (Error& e) { + state Error err(e); + if (e.code() == error_code_special_keys_api_failure) { + Optional errorMsg = wait(safeThreadFutureToFuture(tr->get(fdb_cli::errorMsgSpecialKey))); + ASSERT(errorMsg.present()); + std::string errorMsgStr; + auto valueObj = readJSONStrictly(errorMsg.get().toString()).get_obj(); + auto schema = readJSONStrictly(JSONSchemas::managementApiErrorSchema.toString()).get_obj(); + // error message already has \n at the end + fprintf(stderr, "%s", valueObj["message"].get_str().c_str()); + return false; + } + wait(safeThreadFutureToFuture(tr->onError(err))); } } } @@ -103,8 +116,8 @@ ACTOR Future setClassCommandActor(Reference db, std::vector Date: Fri, 9 Jul 2021 10:00:53 +0000 Subject: [PATCH 2/3] Refactor transaction related commands like begin, commit, etc. --- fdbcli/fdbcli.actor.cpp | 49 +++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/fdbcli/fdbcli.actor.cpp b/fdbcli/fdbcli.actor.cpp index 1726999d5f..e3718938ed 100644 --- a/fdbcli/fdbcli.actor.cpp +++ b/fdbcli/fdbcli.actor.cpp @@ -44,6 +44,7 @@ #include "flow/Platform.h" #include "flow/TLSConfig.actor.h" +#include "flow/ThreadHelper.actor.h" #include "flow/SimpleOpt.h" #include "fdbcli/FlowLineNoise.h" @@ -1968,6 +1969,16 @@ ACTOR Future commitTransaction(Reference tr) { return Void(); } +ACTOR Future commitTransaction(Reference tr) { + wait(makeInterruptable(safeThreadFutureToFuture(tr->commit()))); + auto ver = tr->getCommittedVersion(); + if (ver != invalidVersion) + printf("Committed (%" PRId64 ")\n", ver); + else + printf("Nothing to commit\n"); + return Void(); +} + ACTOR Future configure(Database db, std::vector tokens, Reference ccf, @@ -3447,7 +3458,8 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { } if (tokencmp(tokens[0], "waitopen")) { - wait(success(getTransaction(db, tr, options, intrans)->getReadVersion())); + wait(success( + safeThreadFutureToFuture(getTransaction(db, tr, tr2, options, intrans)->getReadVersion()))); continue; } @@ -3657,7 +3669,7 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { } else { activeOptions = FdbOptions(globalOptions); options = &activeOptions; - getTransaction(db, tr, options, false); + getTransaction(db, tr, tr2, options, false); intrans = true; printf("Transaction started\n"); } @@ -3672,7 +3684,7 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { fprintf(stderr, "ERROR: No active transaction\n"); is_error = true; } else { - wait(commitTransaction(tr)); + wait(commitTransaction(tr2)); intrans = false; options = &globalOptions; } @@ -3689,9 +3701,11 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { is_error = true; } else { tr->reset(); + tr2->reset(); activeOptions = FdbOptions(globalOptions); options = &activeOptions; options->apply(tr); + options->apply(tr2); printf("Transaction reset\n"); } continue; @@ -3717,8 +3731,8 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { printUsage(tokens[0]); is_error = true; } else { - Optional> v = - wait(makeInterruptable(getTransaction(db, tr, options, intrans)->get(tokens[1]))); + Optional> v = wait(makeInterruptable( + safeThreadFutureToFuture(getTransaction(db, tr, tr2, options, intrans)->get(tokens[1])))); if (v.present()) printf("`%s' is `%s'\n", printable(tokens[1]).c_str(), printable(v.get()).c_str()); @@ -3733,7 +3747,8 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { printUsage(tokens[0]); is_error = true; } else { - Version v = wait(makeInterruptable(getTransaction(db, tr, options, intrans)->getReadVersion())); + Version v = wait(makeInterruptable( + safeThreadFutureToFuture(getTransaction(db, tr, tr2, options, intrans)->getReadVersion()))); printf("%ld\n", v); } continue; @@ -4238,7 +4253,8 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { } RangeResult kvs = wait(makeInterruptable( - getTransaction(db, tr, options, intrans)->getRange(KeyRangeRef(tokens[1], endKey), limit))); + safeThreadFutureToFuture(getTransaction(db, tr, tr2, options, intrans) + ->getRange(KeyRangeRef(tokens[1], endKey), limit)))); printf("\nRange limited to %d keys\n", limit); for (auto iter = kvs.begin(); iter < kvs.end(); iter++) { @@ -4281,11 +4297,11 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { printUsage(tokens[0]); is_error = true; } else { - getTransaction(db, tr, options, intrans); - tr->set(tokens[1], tokens[2]); + getTransaction(db, tr, tr2, options, intrans); + tr2->set(tokens[1], tokens[2]); if (!intrans) { - wait(commitTransaction(tr)); + wait(commitTransaction(tr2)); } } continue; @@ -4302,11 +4318,11 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { printUsage(tokens[0]); is_error = true; } else { - getTransaction(db, tr, options, intrans); - tr->clear(tokens[1]); + getTransaction(db, tr, tr2, options, intrans); + tr2->clear(tokens[1]); if (!intrans) { - wait(commitTransaction(tr)); + wait(commitTransaction(tr2)); } } continue; @@ -4323,11 +4339,11 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { printUsage(tokens[0]); is_error = true; } else { - getTransaction(db, tr, options, intrans); - tr->clear(KeyRangeRef(tokens[1], tokens[2])); + getTransaction(db, tr, tr2, options, intrans); + tr2->clear(KeyRangeRef(tokens[1], tokens[2])); if (!intrans) { - wait(commitTransaction(tr)); + wait(commitTransaction(tr2)); } } continue; @@ -4476,6 +4492,7 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise) { intrans = false; options = &globalOptions; options->apply(tr); + options->apply(tr2); } } From 8de3417f24ce27a7aa5a5ea2e31b8df73274b31c Mon Sep 17 00:00:00 2001 From: Chaoguang Lin Date: Tue, 24 Aug 2021 14:18:43 -0700 Subject: [PATCH 3/3] Fix comment, add a new function for reading special keys' error message --- fdbcli/CMakeLists.txt | 2 +- fdbcli/SetClassCommand.actor.cpp | 10 ++-------- fdbcli/{Util.cpp => Util.actor.cpp} | 21 ++++++++++++++++++++- fdbcli/fdbcli.actor.h | 3 +++ 4 files changed, 26 insertions(+), 10 deletions(-) rename fdbcli/{Util.cpp => Util.actor.cpp} (61%) diff --git a/fdbcli/CMakeLists.txt b/fdbcli/CMakeLists.txt index c4fe3d8371..2d9ceefb84 100644 --- a/fdbcli/CMakeLists.txt +++ b/fdbcli/CMakeLists.txt @@ -10,7 +10,7 @@ set(FDBCLI_SRCS SetClassCommand.actor.cpp SnapshotCommand.actor.cpp ThrottleCommand.actor.cpp - Util.cpp + Util.actor.cpp linenoise/linenoise.h) if(NOT WIN32) diff --git a/fdbcli/SetClassCommand.actor.cpp b/fdbcli/SetClassCommand.actor.cpp index 11b8c1da96..ee3ebfe454 100644 --- a/fdbcli/SetClassCommand.actor.cpp +++ b/fdbcli/SetClassCommand.actor.cpp @@ -23,8 +23,6 @@ #include "fdbclient/FDBOptions.g.h" #include "fdbclient/IClientApi.h" #include "fdbclient/Knobs.h" -#include "fdbclient/Schemas.h" -#include "fdbclient/Status.h" #include "flow/Arena.h" #include "flow/FastRef.h" @@ -83,13 +81,9 @@ ACTOR Future setProcessClass(Reference db, KeyRef network_addre } catch (Error& e) { state Error err(e); if (e.code() == error_code_special_keys_api_failure) { - Optional errorMsg = wait(safeThreadFutureToFuture(tr->get(fdb_cli::errorMsgSpecialKey))); - ASSERT(errorMsg.present()); - std::string errorMsgStr; - auto valueObj = readJSONStrictly(errorMsg.get().toString()).get_obj(); - auto schema = readJSONStrictly(JSONSchemas::managementApiErrorSchema.toString()).get_obj(); + std::string errorMsgStr = wait(fdb_cli::getSpecialKeysFailureErrorMessage(tr)); // error message already has \n at the end - fprintf(stderr, "%s", valueObj["message"].get_str().c_str()); + fprintf(stderr, "%s", errorMsgStr.c_str()); return false; } wait(safeThreadFutureToFuture(tr->onError(err))); diff --git a/fdbcli/Util.cpp b/fdbcli/Util.actor.cpp similarity index 61% rename from fdbcli/Util.cpp rename to fdbcli/Util.actor.cpp index f67f27c774..c68602e7fe 100644 --- a/fdbcli/Util.cpp +++ b/fdbcli/Util.actor.cpp @@ -1,5 +1,5 @@ /* - * Util.cpp + * Util.actor.cpp * * This source file is part of the FoundationDB open source project * @@ -19,9 +19,14 @@ */ #include "fdbcli/fdbcli.actor.h" +#include "fdbclient/ManagementAPI.actor.h" +#include "fdbclient/Schemas.h" +#include "fdbclient/Status.h" #include "flow/Arena.h" +#include "flow/actorcompiler.h" // This must be the last #include. + namespace fdb_cli { bool tokencmp(StringRef token, const char* command) { @@ -40,4 +45,18 @@ void printUsage(StringRef command) { fprintf(stderr, "ERROR: Unknown command `%s'\n", command.toString().c_str()); } +ACTOR Future getSpecialKeysFailureErrorMessage(Reference tr) { + Optional errorMsg = wait(safeThreadFutureToFuture(tr->get(fdb_cli::errorMsgSpecialKey))); + // Error message should be present + ASSERT(errorMsg.present()); + // Read the json string + auto valueObj = readJSONStrictly(errorMsg.get().toString()).get_obj(); + // verify schema + auto schema = readJSONStrictly(JSONSchemas::managementApiErrorSchema.toString()).get_obj(); + std::string errorStr; + ASSERT(schemaMatch(schema, valueObj, errorStr, SevError, true)); + // return the error message + return valueObj["message"].get_str(); +} + } // namespace fdb_cli diff --git a/fdbcli/fdbcli.actor.h b/fdbcli/fdbcli.actor.h index 735eec6478..bf73e35ca1 100644 --- a/fdbcli/fdbcli.actor.h +++ b/fdbcli/fdbcli.actor.h @@ -75,6 +75,9 @@ inline const KeyRef errorMsgSpecialKey = LiteralStringRef("\xff\xff/error_messag bool tokencmp(StringRef token, const char* command); // print the usage of the specified command void printUsage(StringRef command); +// Pre: tr failed with special_keys_api_failure error +// Read the error message special key and return the message +ACTOR Future getSpecialKeysFailureErrorMessage(Reference tr); // All fdbcli commands (alphabetically) // advanceversion command