Wrap ClusterClientInterface into its own type
When a process joins a cluster it fetches the cluster interface. However, not the whole interface is exposed to the client. This mechanism relies on the fact that the serializer keeps the field ordering and doesn't verify the message before parsing it. To make this work, we provide a client type with one member (the ClusterInterface which is exposed to the client and the server). This client interface has the same FileIdentifier as the ClusterControllerFullInterface which has the same first member. This works because FlatBuffers allows for members to be missing.
This commit is contained in:
parent
9eeb48c43d
commit
92bad76479
|
@ -29,6 +29,7 @@
|
|||
#include "fdbclient/ClientWorkerInterface.h"
|
||||
|
||||
struct ClusterInterface {
|
||||
constexpr static FileIdentifier file_identifier = 15888863;
|
||||
RequestStream< struct OpenDatabaseRequest > openDatabase;
|
||||
RequestStream< struct FailureMonitoringRequest > failureMonitoring;
|
||||
RequestStream< struct StatusRequest > databaseStatus;
|
||||
|
@ -56,6 +57,23 @@ struct ClusterInterface {
|
|||
}
|
||||
};
|
||||
|
||||
struct ClusterControllerClientInterface {
|
||||
constexpr static FileIdentifier file_identifier = 14997695;
|
||||
ClusterInterface clientInterface;
|
||||
|
||||
bool operator==(ClusterControllerClientInterface const& r) const {
|
||||
return clientInterface.id() == r.clientInterface.id();
|
||||
}
|
||||
bool operator!=(ClusterControllerClientInterface const& r) const {
|
||||
return clientInterface.id() != r.clientInterface.id();
|
||||
}
|
||||
|
||||
template <class Ar>
|
||||
void serialize(Ar& ar) {
|
||||
serializer(ar, clientInterface);
|
||||
}
|
||||
};
|
||||
|
||||
struct ClientVersionRef {
|
||||
StringRef clientVersion;
|
||||
StringRef sourceVersion;
|
||||
|
|
|
@ -463,3 +463,22 @@ ACTOR Future<Void> monitorLeaderInternal( Reference<ClusterConnectionFile> connF
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
ACTOR Future<Void> asyncDeserializeClusterInterface(Reference<AsyncVar<Value>> serializedInfo,
|
||||
Reference<AsyncVar<Optional<ClusterInterface>>> outKnownLeader) {
|
||||
state Reference<AsyncVar<Optional<ClusterControllerClientInterface>>> knownLeader(
|
||||
new AsyncVar<Optional<ClusterControllerClientInterface>>{});
|
||||
state Future<Void> deserializer = asyncDeserialize(serializedInfo, knownLeader);
|
||||
loop {
|
||||
choose {
|
||||
when(wait(deserializer)) { UNSTOPPABLE_ASSERT(false); }
|
||||
when(wait(knownLeader->onChange())) {
|
||||
if (knownLeader->get().present()) {
|
||||
outKnownLeader->set(knownLeader->get().get().clientInterface);
|
||||
} else {
|
||||
outKnownLeader->set(Optional<ClusterInterface>{});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "fdbclient/FDBTypes.h"
|
||||
#include "fdbclient/CoordinationInterface.h"
|
||||
#include "fdbclient/ClusterInterface.h"
|
||||
|
||||
#define CLUSTER_FILE_ENV_VAR_NAME "FDB_CLUSTER_FILE"
|
||||
|
||||
|
@ -39,13 +40,33 @@ Future<Void> monitorLeader( Reference<ClusterConnectionFile> const& connFile, Re
|
|||
|
||||
Future<Void> monitorLeaderInternal( Reference<ClusterConnectionFile> const& connFile, Reference<AsyncVar<Value>> const& outSerializedLeaderInfo, Reference<AsyncVar<int>> const& connectedCoordinatorsNum );
|
||||
|
||||
template <class LeaderInterface>
|
||||
struct LeaderDeserializer {
|
||||
Future<Void> operator()(const Reference<AsyncVar<Value>>& serializedInfo,
|
||||
const Reference<AsyncVar<Optional<LeaderInterface>>>& outKnownLeader) {
|
||||
return asyncDeserialize(serializedInfo, outKnownLeader);
|
||||
}
|
||||
};
|
||||
|
||||
Future<Void> asyncDeserializeClusterInterface(const Reference<AsyncVar<Value>>& serializedInfo,
|
||||
const Reference<AsyncVar<Optional<ClusterInterface>>>& outKnownLeader);
|
||||
|
||||
template <>
|
||||
struct LeaderDeserializer<ClusterInterface> {
|
||||
Future<Void> operator()(const Reference<AsyncVar<Value>>& serializedInfo,
|
||||
const Reference<AsyncVar<Optional<ClusterInterface>>>& outKnownLeader) {
|
||||
return asyncDeserializeClusterInterface(serializedInfo, outKnownLeader);
|
||||
}
|
||||
};
|
||||
|
||||
template <class LeaderInterface>
|
||||
Future<Void> monitorLeader( Reference<ClusterConnectionFile> const& connFile, Reference<AsyncVar<Optional<LeaderInterface>>> const& outKnownLeader, Reference<AsyncVar<int>> connectedCoordinatorsNum ) {
|
||||
LeaderDeserializer<LeaderInterface> deserializer;
|
||||
Reference<AsyncVar<Value>> serializedInfo( new AsyncVar<Value> );
|
||||
Future<Void> m = monitorLeaderInternal( connFile, serializedInfo, connectedCoordinatorsNum );
|
||||
return m || asyncDeserialize( serializedInfo, outKnownLeader );
|
||||
return m || deserializer( serializedInfo, outKnownLeader );
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
// This interface and its serialization depend on slicing, since the client will deserialize only the first part of this structure
|
||||
struct ClusterControllerFullInterface {
|
||||
constexpr static FileIdentifier file_identifier =
|
||||
ClusterControllerClientInterface::file_identifier;
|
||||
ClusterInterface clientInterface;
|
||||
RequestStream< struct RecruitFromConfigurationRequest > recruitFromConfiguration;
|
||||
RequestStream< struct RecruitRemoteFromConfigurationRequest > recruitRemoteFromConfiguration;
|
||||
|
|
Loading…
Reference in New Issue