com.sleepycat.je.rep.stream.Protocol Maven / Gradle / Ivy
The newest version!
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.je.rep.stream;
import java.nio.ByteBuffer;
import java.util.UUID;
import com.sleepycat.je.JEVersion;
import com.sleepycat.je.dbi.DatabaseId;
import com.sleepycat.je.log.LogEntryType;
import com.sleepycat.je.log.LogUtils;
import com.sleepycat.je.rep.NodeType;
import com.sleepycat.je.rep.impl.RepGroupImpl;
import com.sleepycat.je.rep.impl.RepImpl;
import com.sleepycat.je.rep.impl.node.NameIdPair;
import com.sleepycat.je.rep.impl.node.RepNode;
import com.sleepycat.je.rep.utilint.RepUtils.Clock;
/**
* {@literal
* Defines the messages used to set up a feeder-replica replication stream.
*
* Note: this protocol is an extension of je.rep.stream.BaseProtocol, which
* defines a set of basic message operation codes that are to be used by
* its subclasses.
*
* From Feeder to Replica
*
* Heartbeat -> HeartbeatResponse
* Commit -> Ack
* Commit+ -> GroupAck
* Entry
* ShutdownRequest -> ShutdownResponse
*
* Note: in the future, we may want to support bulk entry messages
*
* From Replica to Feeder
*
* The following subset of messages represents the handshake protocol that
* precedes the transmission of replication log entries.
*
* ReplicaProtocolVersion -> FeederProtocolVersion | DuplicateNodeReject
* ReplicaJEVersions -> FeederJEVersions | JEVersionsReject
* NodeGroupInfo -> NodeGroupInfoOK | NodeGroupInfoReject
* SNTPRequest -> SNTPResponse
* -> HeartbeatResponse
*
* A HeartbeatResponse is not strictly a response message and may also be sent
* spontaneously if there is no output activity in a heartbeat interval. This
* spontaneous generation of a HeartbeatReponse ensures that a socket is not
* timed out if the feeder or the replica replay are otherwise busy.
*
* Note that there may be multiple SNTPRequest/SNTPResponse message pairs that
* are exchanged as part of a single handshake. So a successful handshake
* requested sequence generated by the Replica looks like:
*
* ReplicaProtocolVersion ReplicaJEVersions MembershipInfo [SNTPRequest]+
*
* For a Subscriber, there is an optional additional message exchange used to
* discover the database ID for the partition generation database if the name
* of the database was supplied and the message is supported by the protocol
* version:
*
* DBIDRequest -> DBIDResponse
*
* The following messages constitute the syncup and the transmission of log
* entries.
*
* EntryRequest -> Entry | EntryNotFound | AlternateMatchpoint
* RestoreRequest -> RestoreResponse
* StartStream
*
* The Protocol instance has local state in terms of buffers that are reused
* across multiple messages. A Protocol instance is expected to be used in
* strictly serial fashion. Consequently, there is an instance for each Replica
* to Feeder connection, and two instances per Feeder to Replica connection:
* one for the InputThread and one for the OutputThread.
* }
*/
public class Protocol extends BaseProtocol {
/**
* Normally the op code should fall in the range defined in BaseProtocol,
* however following op code inherit from original implementation of
* stream protocol thus we just copy them here for backward compatibility.
*/
public final static MessageOp REPLICA_PROTOCOL_VERSION =
new MessageOp((short) 1, ReplicaProtocolVersion.class);
public final static MessageOp FEEDER_PROTOCOL_VERSION =
new MessageOp((short) 2, FeederProtocolVersion.class);
public final static MessageOp DUP_NODE_REJECT =
new MessageOp((short) 3, DuplicateNodeReject.class);
public final static MessageOp REPLICA_JE_VERSIONS =
new MessageOp((short) 4, ReplicaJEVersions.class);
public final static MessageOp FEEDER_JE_VERSIONS =
new MessageOp((short) 5, FeederJEVersions.class);
public final static MessageOp JE_VERSIONS_REJECT =
new MessageOp((short) 6, JEVersionsReject.class);
public final static MessageOp MEMBERSHIP_INFO =
new MessageOp((short) 7, NodeGroupInfo.class);
public final static MessageOp MEMBERSHIP_INFO_OK =
new MessageOp((short) 8, NodeGroupInfoOK.class);
public final static MessageOp MEMBERSHIP_INFO_REJECT =
new MessageOp((short) 9, NodeGroupInfoReject.class);
public final static MessageOp SNTP_REQUEST =
new MessageOp((short)10, SNTPRequest.class);
public final static MessageOp SNTP_RESPONSE =
new MessageOp((short)11, SNTPResponse.class);
public final static MessageOp REAUTHENTICATE =
new MessageOp((short)12, ReAuthenticate.class);
public final static MessageOp DBID_REQUEST =
new MessageOp((short)13, DBIdRequest.class);
public final static MessageOp DBID_RESPONSE =
new MessageOp((short)14, DBIdResponse.class);
public final static MessageOp SECURITY_FAILURE_RESPONSE =
new MessageOp((short)15, SecurityFailureResponse.class);
/** All message ops needed by protocol */
private static final MessageOp[] ALL_MESSAGE_OPS = {
REPLICA_PROTOCOL_VERSION,
FEEDER_PROTOCOL_VERSION,
DUP_NODE_REJECT,
REPLICA_JE_VERSIONS,
FEEDER_JE_VERSIONS,
JE_VERSIONS_REJECT,
MEMBERSHIP_INFO,
MEMBERSHIP_INFO_OK,
MEMBERSHIP_INFO_REJECT,
SNTP_REQUEST,
SNTP_RESPONSE,
ENTRY,
START_STREAM,
HEARTBEAT,
HEARTBEAT_RESPONSE,
COMMIT,
ACK,
ENTRY_REQUEST,
ENTRY_NOTFOUND,
RESTORE_REQUEST,
RESTORE_RESPONSE,
ALT_MATCHPOINT,
SHUTDOWN_REQUEST,
SHUTDOWN_RESPONSE,
GROUP_ACK,
REAUTHENTICATE,
DBID_REQUEST,
DBID_RESPONSE,
SECURITY_FAILURE_RESPONSE
};
private final Clock clock;
/**
* Returns a Protocol object configured that implements the specified
* (supported) protocol version.
*
* @param repImpl the node using the protocol
*
* @param nameIdPair name-id pair of the node using the protocol
*
* @param clock clock used by the node
*
* @param protocolVersion the version of the protocol that must be
* implemented by this object
*
* @param maxProtocolVersion the highest supported protocol version, which
* may be lower than the code version, for testing purposes
*
* @param streamLogVersion the log version of the format used to write log
* entries
*/
private Protocol(final RepImpl repImpl,
final NameIdPair nameIdPair,
final Clock clock,
final int protocolVersion,
final int maxProtocolVersion,
final int streamLogVersion,
@SuppressWarnings("unused")
final int groupFormatVersion) {
super(repImpl, nameIdPair, protocolVersion, maxProtocolVersion,
streamLogVersion, ALL_MESSAGE_OPS,
/* no validity check, from legacy protocol */
false);
this.configuredVersion = protocolVersion;
this.clock = clock;
}
/**
* Returns a protocol object that supports the specific requested protocol
* version, which must not be higher than the specified maximum version, or
* null if no such version is supported.
*/
public static Protocol get(final RepNode repNode,
final int protocolVersion,
final int maxProtocolVersion) {
return get(repNode.getRepImpl(),
repNode.getNameIdPair(),
repNode.getClock(),
protocolVersion,
maxProtocolVersion,
repNode.getGroup().getFormatVersion());
}
public static Protocol get(final RepImpl repImpl,
final NameIdPair nameIdPair,
final Clock clock,
final int protocolVersion,
final int maxProtocolVersion,
final int groupFormatVersion) {
return get(repImpl, nameIdPair, clock,
protocolVersion, maxProtocolVersion,
LogEntryType.LOG_VERSION, groupFormatVersion);
}
/**
* Returns a protocol object that supports the specified protocol, which
* must be less than the specified maximum version, and writes log entries
* in the specified log version format. Returns null if no such version is
* supported.
*/
public static Protocol get(final RepNode repNode,
final int protocolVersion,
final int maxProtocolVersion,
final int streamLogVersion) {
return get(repNode.getRepImpl(),
repNode.getNameIdPair(),
repNode.getClock(),
protocolVersion,
maxProtocolVersion,
streamLogVersion,
repNode.getGroup().getFormatVersion());
}
public static Protocol get(final RepImpl repImpl,
final NameIdPair nameIdPair,
final Clock clock,
final int protocolVersion,
final int maxProtocolVersion,
final int streamLogVersion,
final int groupFormatVersion) {
/*
* If the RepGroupImpl has been upgraded to version 3, then require
* protocol version 5, which is required to support that RepGroupImpl
* version. This check prevents new facilities that depend on
* RepGroupImpl version 3 from being seen by non-upgraded replicas.
*/
int minProtocolVersion = MIN_VERSION;
if (groupFormatVersion >= RepGroupImpl.FORMAT_VERSION_3) {
minProtocolVersion = VERSION_5;
}
return get(repImpl, nameIdPair, clock,
protocolVersion, minProtocolVersion,
maxProtocolVersion, streamLogVersion, groupFormatVersion);
}
/**
* Returns a protocol object using the specified minimum and maximum
* values, returning null if no supported version is found. Use this
* method for testing when the RepGroupImpl object is not available.
*/
static Protocol get(final RepNode repNode,
final int protocolVersion,
final int minProtocolVersion,
final int maxProtocolVersion,
final int streamLogVersion) {
int formatVersion = RepGroupImpl.MAX_FORMAT_VERSION;
if (repNode.getGroup() != null) {
formatVersion = repNode.getGroup().getFormatVersion();
}
return get(repNode.getRepImpl(),
repNode.getNameIdPair(),
repNode.getClock(),
protocolVersion,
minProtocolVersion,
maxProtocolVersion,
streamLogVersion,
formatVersion);
}
private static Protocol get(final RepImpl repImpl,
final NameIdPair nameIdPair,
final Clock clock,
final int protocolVersion,
final int minProtocolVersion,
final int maxProtocolVersion,
final int streamLogVersion,
final int groupFormatVersion) {
if (!isSupportedVersion(protocolVersion, minProtocolVersion,
maxProtocolVersion)) {
return null;
}
/*
* Future code will do what is appropriate in support of the version
* depending on the nature of the incompatibility.
*/
return new Protocol(repImpl, nameIdPair, clock,
protocolVersion, maxProtocolVersion,
streamLogVersion, groupFormatVersion);
}
/**
* Returns a protocol object using the specified protocol version.
*/
static Protocol getProtocol(final RepNode repNode,
final int protocolVersion) {
int formatVersion = RepGroupImpl.MAX_FORMAT_VERSION;
if (repNode.getGroup() != null) {
formatVersion = repNode.getGroup().getFormatVersion();
}
return
getProtocol(repNode.getRepImpl(),
repNode.getNameIdPair(),
repNode.getClock(),
protocolVersion,
formatVersion);
}
static Protocol getProtocol(final RepImpl repImpl,
final NameIdPair nameIdPair,
final Clock clock,
final int protocolVersion,
final int groupFormatVersion) {
return new Protocol(repImpl, nameIdPair, clock,
protocolVersion, protocolVersion,
LogEntryType.LOG_VERSION, groupFormatVersion);
}
/**
* Returns true if the code can support the version.
*
* @param protocolVersion protocol version being queried
* @param minProtocolVersion minimum protocol version supported
* @param maxProtocolVersion maximum protocol version supported
*
* @return true if the protocol version is supported by this implementation
* of the protocol
*/
private static boolean isSupportedVersion(final int protocolVersion,
final int minProtocolVersion,
final int maxProtocolVersion) {
if (protocolVersion == Integer.MIN_VALUE) {
/* For testing purposes. */
return false;
}
/*
* Version compatibility check: for now, a simple range check. We can
* make this fancier in the future if necessary.
*/
return minProtocolVersion <= protocolVersion &&
protocolVersion <= maxProtocolVersion;
}
/**
* Gets the JE version that corresponds to the specified protocol version,
* for use in creating error messages that explain protocol version errors
* in terms of JE versions. Returns null if the associated version is not
* known.
*/
static JEVersion getProtocolJEVersion(final int protocolVersion) {
switch (protocolVersion) {
case VERSION_9:
return VERSION_9_JE_VERSION;
case VERSION_8:
return VERSION_8_JE_VERSION;
case VERSION_7:
return VERSION_7_JE_VERSION;
case VERSION_6:
return VERSION_6_JE_VERSION;
case VERSION_5:
return VERSION_5_JE_VERSION;
case VERSION_4:
return VERSION_4_JE_VERSION;
case VERSION_3:
return VERSION_3_JE_VERSION;
default:
return null;
}
}
/**
* Gets the protocol version that corresponds to the specified JE version,
* throwing an IllegalArgumentException if the version is not supported.
*/
static int getJEVersionProtocolVersion(final JEVersion jeVersion) {
if (jeVersion == null) {
return VERSION_9;
} else if (jeVersion.compareTo(VERSION_9_JE_VERSION) >= 0) {
return VERSION_9;
} else if (jeVersion.compareTo(VERSION_8_JE_VERSION) >= 0) {
return VERSION_8;
} else if (jeVersion.compareTo(VERSION_7_JE_VERSION) >= 0) {
return VERSION_7;
} else if (jeVersion.compareTo(VERSION_6_JE_VERSION) >= 0) {
return VERSION_6;
} else if (jeVersion.compareTo(VERSION_5_JE_VERSION) >= 0) {
return VERSION_5;
} else if (jeVersion.compareTo(VERSION_4_JE_VERSION) >= 0) {
return VERSION_4;
} else if (jeVersion.compareTo(VERSION_3_JE_VERSION) >= 0) {
return VERSION_3;
} else {
throw new IllegalArgumentException(
"JE version not supported: " + jeVersion);
}
}
/**
* The replica sends the feeder its protocol version.
*
* IMPORTANT: This message must not change.
*/
public class ReplicaProtocolVersion extends ProtocolVersion {
public ReplicaProtocolVersion() {
super(configuredVersion);
}
public ReplicaProtocolVersion(ByteBuffer buffer) {
super(buffer);
}
@Override
public MessageOp getOp() {
return REPLICA_PROTOCOL_VERSION;
}
}
/**
* The feeder sends the replica its proposed version.
*
* IMPORTANT: This message must not change.
*/
public class FeederProtocolVersion extends ProtocolVersion {
public FeederProtocolVersion(int proposedVersion) {
super(proposedVersion);
}
public FeederProtocolVersion(ByteBuffer buffer) {
super(buffer);
}
@Override
public MessageOp getOp() {
return FEEDER_PROTOCOL_VERSION;
}
}
/* Reject response to a ReplicaProtocolVersion request */
public class DuplicateNodeReject extends RejectMessage {
DuplicateNodeReject(String errorMessage) {
super(errorMessage);
}
public DuplicateNodeReject(ByteBuffer buffer) {
super(buffer);
}
@Override
public MessageOp getOp() {
return DUP_NODE_REJECT;
}
}
public class SNTPRequest extends HandshakeMessage {
private final long originateTimestamp;
/* Set by the receiver at the time the message is recreated. */
private long receiveTimestamp = -1;
/*
* Determines whether this is the last in a consecutive stream of
* requests to determine the skew.
*/
private boolean isLast = true;
public SNTPRequest(boolean isLast) {
super();
this.isLast = isLast;
originateTimestamp = clock.currentTimeMillis();
}
@Override
public ByteBuffer wireFormat() {
return wireFormat(originateTimestamp, isLast);
}
public SNTPRequest(ByteBuffer buffer) {
this.originateTimestamp = LogUtils.readLong(buffer);
this.isLast = getBoolean(buffer);
this.receiveTimestamp = clock.currentTimeMillis();
}
@Override
public MessageOp getOp() {
return SNTP_REQUEST;
}
public long getOriginateTimestamp() {
return originateTimestamp;
}
public long getReceiveTimestamp() {
return receiveTimestamp;
}
public boolean isLast() {
return isLast;
}
}
public class SNTPResponse extends HandshakeMessage {
/* These fields have the standard SNTP interpretation */
private final long originateTimestamp; // time request sent by client
private final long receiveTimestamp; // time request received by server
/*
* Initialized when the message is serialized to ensure it's as
* accurate as possible.
*/
private long transmitTimestamp = -1; // time reply sent by server
/* Initialized at de-serialization for similar reasons. */
private long destinationTimestamp = -1; //time reply received by client
public SNTPResponse(SNTPRequest request) {
this.originateTimestamp = request.originateTimestamp;
this.receiveTimestamp = request.receiveTimestamp;
}
@Override
public ByteBuffer wireFormat() {
transmitTimestamp = clock.currentTimeMillis();
return wireFormat(originateTimestamp,
receiveTimestamp,
transmitTimestamp);
}
public SNTPResponse(ByteBuffer buffer) {
originateTimestamp = LogUtils.readLong(buffer);
receiveTimestamp = LogUtils.readLong(buffer);
transmitTimestamp = LogUtils.readLong(buffer);
destinationTimestamp = clock.currentTimeMillis();
}
@Override
public MessageOp getOp() {
return SNTP_RESPONSE;
}
public long getOriginateTimestamp() {
return originateTimestamp;
}
public long getReceiveTimestamp() {
return receiveTimestamp;
}
public long getTransmitTimestamp() {
return transmitTimestamp;
}
public long getDestinationTimestamp() {
return destinationTimestamp;
}
public long getDelay() {
assert(destinationTimestamp != -1);
return (destinationTimestamp - originateTimestamp) -
(transmitTimestamp - receiveTimestamp);
}
public long getDelta() {
assert(destinationTimestamp != -1);
return ((receiveTimestamp - originateTimestamp) +
(transmitTimestamp - destinationTimestamp))/2;
}
}
public class ReAuthenticate extends SimpleMessage {
private final byte[] tokenBytes;
public ReAuthenticate(byte[] tokenBytes) {
this.tokenBytes = tokenBytes;
}
@Override
public ByteBuffer wireFormat() {
return wireFormat(tokenBytes);
}
public ReAuthenticate(ByteBuffer buffer) {
tokenBytes = getByteArray(buffer);
}
public byte[] getTokenBytes() {
if (tokenBytes.length == 0) {
return null;
}
return tokenBytes;
}
@Override
public MessageOp getOp() {
return REAUTHENTICATE;
}
}
/**
* Security check failure response message
*/
public class SecurityFailureResponse extends SimpleMessage {
/* non-empty error message */
private final String message;
public SecurityFailureResponse(String message) {
if (message == null || message.isEmpty()) {
throw new IllegalArgumentException(
"Message cannot be null or empty");
}
this.message = message;
}
@Override
public ByteBuffer wireFormat() {
return wireFormat(message);
}
public SecurityFailureResponse(ByteBuffer buffer) {
message = getString(buffer);
}
public String getMessage() {
return message;
}
@Override
public MessageOp getOp() {
return SECURITY_FAILURE_RESPONSE;
}
}
/**
* Request for the partition gen db id
*/
public class DBIdRequest extends SimpleMessage {
final String dbName;
public DBIdRequest(String dbName) {
super();
this.dbName = dbName;
}
public DBIdRequest(ByteBuffer buffer) {
super();
dbName = getString(buffer);
}
public String getDbName() {
return dbName;
}
@Override
public ByteBuffer wireFormat() {
return wireFormat(dbName);
}
@Override
public MessageOp getOp() {
return DBID_REQUEST;
}
}
/**
* Response when the PartMDRequest asks for partition md db id
*/
public class DBIdResponse extends SimpleMessage {
private final DatabaseId dbId;
public DBIdResponse(DatabaseId dbId) {
this.dbId = dbId;
}
public DBIdResponse(ByteBuffer buffer) {
super();
dbId = new DatabaseId(LogUtils.readLong(buffer));
}
public DatabaseId getDbId() {
return dbId;
}
@Override
public ByteBuffer wireFormat() {
return wireFormat(dbId.getId());
}
@Override
public MessageOp getOp() {
return DBID_RESPONSE;
}
}
/**
* Abstract message used as the basis for the exchange of software versions
* between replicated nodes
*/
abstract class JEVersions extends HandshakeMessage {
private final JEVersion version;
private final int logVersion;
public JEVersions(JEVersion version, int logVersion) {
this.version = version;
this.logVersion = logVersion;
}
@Override
public ByteBuffer wireFormat() {
return wireFormat(version.getVersionString(), logVersion);
}
public JEVersions(ByteBuffer buffer) {
this.version = new JEVersion(getString(buffer));
this.logVersion = LogUtils.readInt(buffer);
}
public JEVersion getVersion() {
return version;
}
public byte getLogVersion() {
return (byte)logVersion;
}
}
public class ReplicaJEVersions extends JEVersions {
ReplicaJEVersions(JEVersion version, int logVersion) {
super(version, logVersion);
}
public ReplicaJEVersions(ByteBuffer buffer) {
super(buffer);
}
@Override
public MessageOp getOp() {
return REPLICA_JE_VERSIONS;
}
}
public class FeederJEVersions extends JEVersions {
/* Is null if protocol version < VERSION_7. */
private JEVersion minJEVersion;
FeederJEVersions(JEVersion version,
int logVersion,
JEVersion minJEVersion) {
super(version, logVersion);
this.minJEVersion = minJEVersion;
}
@Override
public ByteBuffer wireFormat() {
if (configuredVersion < VERSION_7){
return super.wireFormat();
}
return wireFormat(
getVersion().getVersionString(),
(int) getLogVersion(),
minJEVersion.getVersionString());
}
public FeederJEVersions(ByteBuffer buffer) {
super(buffer);
if (configuredVersion < VERSION_7){
return;
}
this.minJEVersion = new JEVersion(getString(buffer));
}
@Override
public MessageOp getOp() {
return FEEDER_JE_VERSIONS;
}
/**
* Returns the minJEVersion of the group, or null if unknown (in
* protocol versions < VERSION_7).
*/
public JEVersion getMinJEVersion() {
return minJEVersion;
}
}
/* Reject response to a ReplicaJEVersions request */
public class JEVersionsReject extends RejectMessage {
public JEVersionsReject(String errorMessage) {
super(errorMessage);
}
public JEVersionsReject(ByteBuffer buffer) {
super(buffer);
}
@Override
public MessageOp getOp() {
return JE_VERSIONS_REJECT;
}
}
public class NodeGroupInfo extends HandshakeMessage {
private final String groupName;
private final UUID uuid;
@SuppressWarnings("hiding")
private final NameIdPair nameIdPair;
private final String hostName;
private final int port;
private final NodeType nodeType;
private final boolean designatedPrimary;
/**
* A string version of the JE version running on this node, or the
* empty string if not known.
*/
private final String jeVersion;
NodeGroupInfo(final String groupName,
final UUID uuid,
final NameIdPair nameIdPair,
final String hostName,
final int port,
final NodeType nodeType,
final boolean designatedPrimary,
final JEVersion jeVersion) {
this.groupName = groupName;
this.uuid = uuid;
this.nameIdPair = nameIdPair;
this.hostName = hostName;
this.port = port;
this.nodeType = nodeType;
this.designatedPrimary = designatedPrimary;
this.jeVersion = (jeVersion != null) ?
jeVersion.getNumericVersionString() :
"";
}
@Override
public MessageOp getOp() {
return MEMBERSHIP_INFO;
}
@Override
public ByteBuffer wireFormat() {
final boolean repGroupV3 = (getVersion() >= VERSION_5);
if (!repGroupV3 && nodeType.compareTo(NodeType.ELECTABLE) > 0) {
throw new IllegalStateException(
"Node type not supported before group version 3: " +
nodeType);
}
final Object[] args = new Object[repGroupV3 ? 9 : 8];
args[0] = groupName;
args[1] = uuid.getMostSignificantBits();
args[2] = uuid.getLeastSignificantBits();
args[3] = nameIdPair;
args[4] = hostName;
args[5] = port;
args[6] = nodeType;
args[7] = designatedPrimary;
if (repGroupV3) {
args[8] = jeVersion;
}
return wireFormat(args);
}
public NodeGroupInfo(ByteBuffer buffer) {
this.groupName = getString(buffer);
this.uuid = new UUID(LogUtils.readLong(buffer),
LogUtils.readLong(buffer));
this.nameIdPair = getNameIdPair(buffer);
this.hostName = getString(buffer);
this.port = LogUtils.readInt(buffer);
this.nodeType = getEnum(NodeType.class, buffer);
this.designatedPrimary = getBoolean(buffer);
jeVersion = (getVersion() >= VERSION_5) ? getString(buffer) : "";
}
public String getGroupName() {
return groupName;
}
public UUID getUUID() {
return uuid;
}
public String getNodeName() {
return nameIdPair.getName();
}
public int getNodeId() {
return nameIdPair.getId();
}
public String getHostName() {
return hostName;
}
public NameIdPair getNameIdPair() {
return nameIdPair;
}
public int port() {
return port;
}
public NodeType getNodeType() {
return nodeType;
}
public boolean isDesignatedPrimary() {
return designatedPrimary;
}
/**
* Returns the JE version most recently noted running on the associated
* node, or null if not known.
*/
public JEVersion getJEVersion() {
return !jeVersion.isEmpty() ? new JEVersion(jeVersion) : null;
}
}
/**
* Response to a NodeGroupInfo request that was successful. The object
* contains the group's UUID and the replica's NameIdPair. The group UUID
* is used to update the replica's notion of the group UUID on first
* joining. The NameIdPair is used to update the replica's node ID for a
* secondary node, which is not available in the RepGroupDB.
*/
public class NodeGroupInfoOK extends HandshakeMessage {
private final UUID uuid;
@SuppressWarnings("hiding")
private final NameIdPair nameIdPair;
public NodeGroupInfoOK(UUID uuid, NameIdPair nameIdPair) {
super();
this.uuid = uuid;
this.nameIdPair = nameIdPair;
}
public NodeGroupInfoOK(ByteBuffer buffer) {
uuid = new UUID(LogUtils.readLong(buffer),
LogUtils.readLong(buffer));
nameIdPair = getNameIdPair(buffer);
}
@Override
public ByteBuffer wireFormat() {
return wireFormat(uuid.getMostSignificantBits(),
uuid.getLeastSignificantBits(),
nameIdPair);
}
@Override
public MessageOp getOp() {
return MEMBERSHIP_INFO_OK;
}
public NameIdPair getNameIdPair() {
return nameIdPair;
}
public UUID getUUID() {
return uuid;
}
}
public class NodeGroupInfoReject extends RejectMessage {
NodeGroupInfoReject(String errorMessage) {
super(errorMessage);
}
@Override
public MessageOp getOp() {
return MEMBERSHIP_INFO_REJECT;
}
@Override
public ByteBuffer wireFormat() {
return wireFormat(errorMessage);
}
public NodeGroupInfoReject(ByteBuffer buffer) {
super(buffer);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy