diff --git a/fdbcli/DebugCommands.actor.cpp b/fdbcli/DebugCommands.actor.cpp new file mode 100644 index 0000000000..6170ea24ab --- /dev/null +++ b/fdbcli/DebugCommands.actor.cpp @@ -0,0 +1,93 @@ +/* + * DebugCommands.actor.cpp + * + * This source file is part of the FoundationDB open source project + * + * Copyright 2013-2023 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 "fdbcli/fdbcli.actor.h" + +#include "fdbclient/NativeAPI.actor.h" + +namespace fdb_cli { + +// The command is used to get all storage server addresses for a given key. +ACTOR Future getLocationCommandActor(Database cx, std::vector tokens, Version version) { + if (tokens.size() != 2) { + printf("getlocation \n" + "fetch the storage server address for a given key.\n" + "Displays the addresses of storage servers, or `not found' if location is not found."); + return false; + } + + KeyRangeLocationInfo loc = wait(getKeyLocation_internal( + cx, {}, tokens[1], SpanID(), Optional(), UseProvisionalProxies::False, Reverse::False, version)); + + if (loc.locations) { + printf("version is %ld\n", version); + printf("`%s' is at:\n", printable(tokens[1]).c_str()); + auto locations = loc.locations->locations(); + for (int i = 0; locations && i < locations->size(); i++) { + printf(" %s\n", locations->getInterface(i).address().toString().c_str()); + } + } else { + printf("`%s': location not found\n", printable(tokens[1]).c_str()); + } + return true; +} +// hidden commands, no help text for now +CommandFactory getLocationCommandFactory("getlocation"); + +// The command is used to get values from all storage servers that have the given key. +ACTOR Future getallCommandActor(Database cx, std::vector tokens, Version version) { + if (tokens.size() != 2) { + printf("getall \n" + "fetch values from all storage servers that have the given key.\n" + "Displays the value and the addresses of storage servers, or `not found' if key is not found."); + return false; + } + + KeyRangeLocationInfo loc = wait(getKeyLocation_internal( + cx, {}, tokens[1], SpanID(), Optional(), UseProvisionalProxies::False, Reverse::False, version)); + + if (loc.locations) { + printf("version is %ld\n", version); + printf("`%s' is at:\n", printable(tokens[1]).c_str()); + state Reference locations = loc.locations->locations(); + state std::vector> replies; + for (int i = 0; locations && i < locations->size(); i++) { + GetValueRequest req({}, {}, tokens[1], version, {}, {}, {}); + replies.push_back(locations->get(i, &StorageServerInterface::getValue).getReply(req)); + } + wait(waitForAll(replies)); + for (int i = 0; i < replies.size(); i++) { + std::string ssi = locations->getInterface(i).address().toString(); + if (replies[i].isError()) { + fprintf(stderr, "ERROR: %s %s\n", ssi.c_str(), replies[i].getError().what()); + } else { + Optional v = replies[i].get().value; + printf(" %s %s\n", ssi.c_str(), v.present() ? printable(v.get()).c_str() : "(not found)"); + } + } + } else { + printf("`%s': location not found\n", printable(tokens[1]).c_str()); + } + return true; +} +// hidden commands, no help text for now +CommandFactory getallCommandFactory("getall"); + +} // namespace fdb_cli \ No newline at end of file diff --git a/fdbcli/fdbcli.actor.cpp b/fdbcli/fdbcli.actor.cpp index 7b7fd2bc09..386b34575b 100644 --- a/fdbcli/fdbcli.actor.cpp +++ b/fdbcli/fdbcli.actor.cpp @@ -1194,7 +1194,6 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise, Reference warn; loop { if (warn.isValid()) @@ -1618,6 +1617,24 @@ ACTOR Future cli(CLIOptions opt, LineNoise* plinenoise, ReferencegetReadVersion()))); + bool _result = wait(makeInterruptable(getLocationCommandActor(localDb, tokens, _v))); + if (!_result) + is_error = true; + continue; + } + + if (tokencmp(tokens[0], "getall")) { + Version _v = wait(makeInterruptable( + safeThreadFutureToFuture(getTransaction(db, tenant, tr, options, intrans)->getReadVersion()))); + bool _result = wait(makeInterruptable(getallCommandActor(localDb, tokens, _v))); + if (!_result) + is_error = true; + continue; + } + if (tokencmp(tokens[0], "getversion")) { if (tokens.size() != 1) { printUsage(tokens[0]); diff --git a/fdbcli/include/fdbcli/fdbcli.actor.h b/fdbcli/include/fdbcli/fdbcli.actor.h index 9e6ef07cd8..367ff90fe7 100644 --- a/fdbcli/include/fdbcli/fdbcli.actor.h +++ b/fdbcli/include/fdbcli/fdbcli.actor.h @@ -291,6 +291,10 @@ ACTOR Future idempotencyIdsCommandActor(Database cx, std::vector rangeConfigCommandActor(Database cx, std::vector tokens); +// debug commands: getlocation, getall +ACTOR Future getLocationCommandActor(Database cx, std::vector tokens, Version version); +ACTOR Future getallCommandActor(Database cx, std::vector tokens, Version version); + } // namespace fdb_cli #include "flow/unactorcompiler.h" diff --git a/fdbclient/include/fdbclient/NativeAPI.actor.h b/fdbclient/include/fdbclient/NativeAPI.actor.h index b11de1ab54..ff03d71057 100644 --- a/fdbclient/include/fdbclient/NativeAPI.actor.h +++ b/fdbclient/include/fdbclient/NativeAPI.actor.h @@ -19,8 +19,6 @@ */ #pragma once -#include "flow/IRandom.h" -#include "fdbclient/Tracing.h" #if defined(NO_INTELLISENSE) && !defined(FDBCLIENT_NATIVEAPI_ACTOR_G_H) #define FDBCLIENT_NATIVEAPI_ACTOR_G_H #include "fdbclient/NativeAPI.actor.g.h" @@ -31,6 +29,7 @@ #include "flow/flow.h" #include "flow/WipedString.h" #include "flow/TDMetric.actor.h" +#include "flow/IRandom.h" #include "fdbclient/FDBTypes.h" #include "fdbclient/CommitProxyInterface.h" #include "fdbclient/ClientBooleanParams.h" @@ -39,6 +38,7 @@ #include "fdbclient/ClusterInterface.h" #include "fdbclient/ClientLogEvents.h" #include "fdbclient/KeyRangeMap.h" +#include "fdbclient/Tracing.h" #include "flow/actorcompiler.h" // has to be last include // CLIENT_BUGGIFY should be used to randomly introduce failures at run time (like BUGGIFY but for client side testing) @@ -683,5 +683,15 @@ namespace NativeAPI { ACTOR Future>> getServerListAndProcessClasses( Transaction* tr); } + +ACTOR Future getKeyLocation_internal(Database cx, + Optional tenant, + Key key, + SpanID spanID, + Optional debugID, + UseProvisionalProxies useProvisionalProxies, + Reverse isBackward, + Version version); + #include "flow/unactorcompiler.h" #endif