foundationdb/fdbclient/ClusterInterface.h

237 lines
7.3 KiB
C++
Executable File

/*
* ClusterInterface.h
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2013-2018 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.
*/
#ifndef FDBCLIENT_ClusterInterface_H
#define FDBCLIENT_ClusterInterface_H
#pragma once
#include "FDBTypes.h"
#include "fdbrpc/FailureMonitor.h"
#include "Status.h"
#include "ClientDBInfo.h"
#include "ClientWorkerInterface.h"
struct ClusterInterface {
RequestStream< struct OpenDatabaseRequest > openDatabase;
RequestStream< struct FailureMonitoringRequest > failureMonitoring;
RequestStream< struct StatusRequest > databaseStatus;
RequestStream< ReplyPromise<Void> > ping;
RequestStream< struct GetClientWorkersRequest > getClientWorkers;
RequestStream< struct ForceRecoveryRequest > forceRecovery;
bool operator == (ClusterInterface const& r) const { return id() == r.id(); }
bool operator != (ClusterInterface const& r) const { return id() != r.id(); }
UID id() const { return openDatabase.getEndpoint().token; }
NetworkAddress address() const { return openDatabase.getEndpoint().address; }
void initEndpoints() {
openDatabase.getEndpoint( TaskClusterController );
failureMonitoring.getEndpoint( TaskFailureMonitor );
databaseStatus.getEndpoint( TaskClusterController );
ping.getEndpoint( TaskClusterController );
getClientWorkers.getEndpoint( TaskClusterController );
forceRecovery.getEndpoint( TaskClusterController );
}
template <class Ar>
void serialize( Ar& ar ) {
ar & openDatabase & failureMonitoring & databaseStatus & ping & getClientWorkers & forceRecovery;
}
};
struct ClientVersionRef {
StringRef clientVersion;
StringRef sourceVersion;
StringRef protocolVersion;
ClientVersionRef() {
initUnknown();
}
ClientVersionRef(Arena &arena, ClientVersionRef const& cv) : clientVersion(arena, cv.clientVersion), sourceVersion(arena, cv.sourceVersion), protocolVersion(arena, cv.protocolVersion) {}
ClientVersionRef(std::string versionString) {
size_t index = versionString.find(",");
if(index == versionString.npos) {
initUnknown();
return;
}
clientVersion = StringRef((uint8_t*)&versionString[0], index);
size_t nextIndex = versionString.find(",", index+1);
if(index == versionString.npos) {
initUnknown();
return;
}
sourceVersion = StringRef((uint8_t*)&versionString[index+1], nextIndex-(index+1));
protocolVersion = StringRef((uint8_t*)&versionString[nextIndex+1], versionString.length()-(nextIndex+1));
}
void initUnknown() {
clientVersion = LiteralStringRef("Unknown");
sourceVersion = LiteralStringRef("Unknown");
protocolVersion = LiteralStringRef("Unknown");
}
template <class Ar>
void serialize(Ar& ar) {
ar & clientVersion & sourceVersion & protocolVersion;
}
size_t expectedSize() const { return clientVersion.size() + sourceVersion.size() + protocolVersion.size(); }
bool operator<(const ClientVersionRef& rhs) const {
if(protocolVersion != rhs.protocolVersion) {
return protocolVersion < rhs.protocolVersion;
}
// These comparisons are arbitrary because they aren't ordered
if(clientVersion != rhs.clientVersion) {
return clientVersion < rhs.clientVersion;
}
return sourceVersion < rhs.sourceVersion;
}
};
struct OpenDatabaseRequest {
// Sent by the native API to the cluster controller to open a database and track client
// info changes. Returns immediately if the current client info id is different from
// knownClientInfoID; otherwise returns when it next changes (or perhaps after a long interval)
Arena arena;
StringRef dbName, issues, traceLogGroup;
VectorRef<ClientVersionRef> supportedVersions;
UID knownClientInfoID;
ReplyPromise< struct ClientDBInfo > reply;
template <class Ar>
void serialize(Ar& ar) {
ASSERT( ar.protocolVersion() >= 0x0FDB00A400040001LL );
ar & dbName & issues & supportedVersions & traceLogGroup & knownClientInfoID & reply & arena;
}
};
struct SystemFailureStatus {
NetworkAddress address;
FailureStatus status;
SystemFailureStatus() : address(0,0) {}
SystemFailureStatus( NetworkAddress const& a, FailureStatus const& s ) : address(a), status(s) {}
template <class Ar>
void serialize(Ar& ar) {
ar & address & status;
}
};
struct FailureMonitoringRequest {
// Sent by all participants to the cluster controller reply.clientRequestIntervalMS
// ms after receiving the previous reply.
// Provides the controller the self-diagnosed status of the sender, and also
// requests the status of other systems. Failure to timely send one of these implies
// a failed status.
// If !senderStatus.present(), the sender wants to receive the latest failure information
// but doesn't want to be monitored.
// The failureInformationVersion returned in reply should be passed back to the
// next request to facilitate delta compression of the failure information.
Optional<FailureStatus> senderStatus;
Version failureInformationVersion;
ReplyPromise< struct FailureMonitoringReply > reply;
template <class Ar>
void serialize(Ar& ar) {
ar & senderStatus & failureInformationVersion & reply;
}
};
struct FailureMonitoringReply {
VectorRef< SystemFailureStatus > changes;
Version failureInformationVersion;
bool allOthersFailed; // If true, changes are relative to all servers being failed, otherwise to the version given in the request
int clientRequestIntervalMS, // after this many milliseconds, send another request
considerServerFailedTimeoutMS; // after this many additional milliseconds, consider the ClusterController itself to be failed
Arena arena;
template <class Ar>
void serialize(Ar& ar) {
ar & changes & failureInformationVersion & allOthersFailed & clientRequestIntervalMS & considerServerFailedTimeoutMS & arena;
}
};
struct StatusRequest {
ReplyPromise< struct StatusReply > reply;
template <class Ar>
void serialize(Ar& ar) {
ar & reply;
}
};
struct StatusReply {
StatusObject statusObj;
std::string statusStr;
StatusReply() {}
explicit StatusReply(StatusObject obj) : statusObj(obj), statusStr(json_spirit::write_string(json_spirit::mValue(obj))) {}
explicit StatusReply(std::string &&text) : statusStr(text) {}
template <class Ar>
void serialize(Ar& ar) {
ar & statusStr;
if( ar.isDeserializing ) {
json_spirit::mValue mv;
if(g_network->isSimulated()) {
mv = readJSONStrictly(statusStr);
}
else {
// In non-simulation allow errors because some status data is better than no status data
json_spirit::read_string( statusStr, mv );
}
statusObj = std::move(mv.get_obj());
}
}
};
struct GetClientWorkersRequest {
ReplyPromise<vector<ClientWorkerInterface>> reply;
GetClientWorkersRequest() {}
template <class Ar>
void serialize(Ar& ar) {
ar & reply;
}
};
struct ForceRecoveryRequest {
ReplyPromise<Void> reply;
ForceRecoveryRequest() {}
template <class Ar>
void serialize(Ar& ar) {
ar & reply;
}
};
#endif