Add getlocation and getall fdbcli debug commands
getlocation: returns the SS list for a key getall: returns both the SS list and values on the SS for a key
This commit is contained in:
parent
c510510391
commit
614686f737
|
@ -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<bool> getLocationCommandActor(Database cx, std::vector<StringRef> tokens, Version version) {
|
||||
if (tokens.size() != 2) {
|
||||
printf("getlocation <KEY>\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<UID>(), 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<bool> getallCommandActor(Database cx, std::vector<StringRef> tokens, Version version) {
|
||||
if (tokens.size() != 2) {
|
||||
printf("getall <KEY>\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<UID>(), 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<LocationInfo::Locations> locations = loc.locations->locations();
|
||||
state std::vector<Future<GetValueReply>> 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<Value> 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
|
|
@ -1194,7 +1194,6 @@ ACTOR Future<int> cli(CLIOptions opt, LineNoise* plinenoise, Reference<ClusterCo
|
|||
}
|
||||
|
||||
state bool is_error = false;
|
||||
|
||||
state Future<Void> warn;
|
||||
loop {
|
||||
if (warn.isValid())
|
||||
|
@ -1618,6 +1617,24 @@ ACTOR Future<int> cli(CLIOptions opt, LineNoise* plinenoise, Reference<ClusterCo
|
|||
continue;
|
||||
}
|
||||
|
||||
if (tokencmp(tokens[0], "getlocation")) {
|
||||
Version _v = wait(makeInterruptable(
|
||||
safeThreadFutureToFuture(getTransaction(db, tenant, tr, options, intrans)->getReadVersion())));
|
||||
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]);
|
||||
|
|
|
@ -291,6 +291,10 @@ ACTOR Future<bool> idempotencyIdsCommandActor(Database cx, std::vector<StringRef
|
|||
// rangeconfig command
|
||||
ACTOR Future<bool> rangeConfigCommandActor(Database cx, std::vector<StringRef> tokens);
|
||||
|
||||
// debug commands: getlocation, getall
|
||||
ACTOR Future<bool> getLocationCommandActor(Database cx, std::vector<StringRef> tokens, Version version);
|
||||
ACTOR Future<bool> getallCommandActor(Database cx, std::vector<StringRef> tokens, Version version);
|
||||
|
||||
} // namespace fdb_cli
|
||||
|
||||
#include "flow/unactorcompiler.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<std::vector<std::pair<StorageServerInterface, ProcessClass>>> getServerListAndProcessClasses(
|
||||
Transaction* tr);
|
||||
}
|
||||
|
||||
ACTOR Future<KeyRangeLocationInfo> getKeyLocation_internal(Database cx,
|
||||
Optional<TenantName> tenant,
|
||||
Key key,
|
||||
SpanID spanID,
|
||||
Optional<UID> debugID,
|
||||
UseProvisionalProxies useProvisionalProxies,
|
||||
Reverse isBackward,
|
||||
Version version);
|
||||
|
||||
#include "flow/unactorcompiler.h"
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue