package edu.uw.zookeeper.protocol;
import io.netty.buffer.ByteBuf;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import org.apache.jute.InputArchive;
import org.apache.jute.OutputArchive;
import org.apache.jute.Record;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import edu.uw.zookeeper.common.DefaultsFactory;
import edu.uw.zookeeper.common.Pair;
import edu.uw.zookeeper.common.TimeValue;
import edu.uw.zookeeper.protocol.proto.ByteBufInputArchive;
import edu.uw.zookeeper.protocol.proto.ByteBufOutputArchive;
import edu.uw.zookeeper.protocol.proto.IConnectRequest;
import edu.uw.zookeeper.protocol.proto.IConnectResponse;
import edu.uw.zookeeper.protocol.proto.IOperationalRecord;
import edu.uw.zookeeper.protocol.proto.OpCode;
import edu.uw.zookeeper.protocol.proto.Operational;
import edu.uw.zookeeper.protocol.proto.Records;
@Operational(value=OpCode.CREATE_SESSION)
public abstract class ConnectMessage<T extends Record & Records.ConnectGetter> extends IOperationalRecord<T>
implements Message.Session, Records.ConnectGetter {
public static abstract class Request extends
ConnectMessage<IConnectRequest> implements
Records.Request, Message.ClientSession {
public static RequestsFactory factory(
TimeValue timeOut,
ZxidReference lastZxid) {
return new RequestsFactory(timeOut, lastZxid);
}
public static class RequestsFactory extends Pair<TimeValue, ZxidReference> implements DefaultsFactory<edu.uw.zookeeper.protocol.Session, ConnectMessage.Request> {
public RequestsFactory(
TimeValue timeOut,
ZxidReference lastZxid) {
super(timeOut, lastZxid);
}
@Override
public ConnectMessage.Request get() {
return NewRequest.newInstance(first(), second().get());
}
@Override
public ConnectMessage.Request get(edu.uw.zookeeper.protocol.Session session) {
return RenewRequest.newInstance(session, second().get());
}
}
public static ConnectMessage.Request decode(ByteBuf input) throws IOException {
return deserialize(new ByteBufInputArchive(input));
}
public static ConnectMessage.Request deserialize(InputArchive archive) throws IOException {
archive.startRecord(Records.CONNECT_TAG);
IConnectRequest record = new IConnectRequest();
record.deserialize(archive, Records.CONNECT_TAG);
boolean readOnly = false;
boolean legacy = false;
try {
readOnly = archive.readBool("readOnly");
} catch (IOException e) {
legacy = true;
}
archive.endRecord(Records.CONNECT_TAG);
ConnectMessage.Request out = newInstance(record, readOnly, legacy);
return out;
}
public static ConnectMessage.Request newInstance(IConnectRequest record, boolean readOnly,
boolean legacy) {
if (record.getSessionId() == edu.uw.zookeeper.protocol.Session.uninitialized().id()) {
return NewRequest.newInstance(record, readOnly, legacy);
} else {
return RenewRequest.newInstance(record, readOnly, legacy);
}
}
protected Request(IConnectRequest record) {
super(record);
}
protected Request(IConnectRequest record, boolean readOnly, boolean legacy) {
super(record, readOnly, legacy);
}
public long getLastZxidSeen() {
return record.getLastZxidSeen();
}
public static class NewRequest extends ConnectMessage.Request {
public static IConnectRequest newRecord() {
return toRecord(0, 0L);
}
public static IConnectRequest toRecord(TimeValue timeOut, long lastZxid) {
return toRecord((int) timeOut.value(TIMEOUT_UNIT), lastZxid);
}
public static IConnectRequest toRecord(int timeOutMillis, long lastZxid) {
IConnectRequest record = new IConnectRequest(
Records.PROTOCOL_VERSION,
lastZxid,
timeOutMillis,
edu.uw.zookeeper.protocol.Session.uninitialized().id(),
edu.uw.zookeeper.protocol.Session.Parameters.uninitialized().password());
return record;
}
public static NewRequest newInstance() {
return newInstance(newRecord());
}
public static NewRequest newInstance(TimeValue timeOut, long lastZxid) {
return newInstance(toRecord(timeOut, lastZxid));
}
public static NewRequest newInstance(IConnectRequest record) {
return newInstance(record, false, false);
}
public static NewRequest newInstance(IConnectRequest record, boolean readOnly, boolean legacy) {
return new NewRequest(record, readOnly, legacy);
}
private NewRequest(IConnectRequest record, boolean readOnly, boolean legacy) {
super(record, readOnly, legacy);
}
}
public static class RenewRequest extends ConnectMessage.Request {
public static IConnectRequest toRecord(edu.uw.zookeeper.protocol.Session session) {
return toRecord(session, 0L);
}
public static IConnectRequest toRecord(edu.uw.zookeeper.protocol.Session session, long lastZxid) {
IConnectRequest record = new IConnectRequest(
Records.PROTOCOL_VERSION,
lastZxid,
(int) session.parameters().timeOut().value(TIMEOUT_UNIT),
session.id(),
session.parameters().password());
return record;
}
public static RenewRequest newInstance(edu.uw.zookeeper.protocol.Session session) {
return newInstance(toRecord(session));
}
public static RenewRequest newInstance(edu.uw.zookeeper.protocol.Session session, long lastZxid) {
return newInstance(toRecord(session, lastZxid));
}
public static RenewRequest newInstance(IConnectRequest record) {
return newInstance(record, false, false);
}
public static RenewRequest newInstance(IConnectRequest record, boolean readOnly, boolean legacy) {
return new RenewRequest(record, readOnly, legacy);
}
private RenewRequest(IConnectRequest record, boolean readOnly, boolean legacy) {
super(record, readOnly, legacy);
}
}
}
public static abstract class Response extends
ConnectMessage<IConnectResponse> implements
Records.Response, Message.ServerSession {
public static ConnectMessage.Response newInstance(IConnectResponse record, boolean readOnly,
boolean legacy) {
return Valid.newInstance(record, readOnly, legacy);
}
public static ConnectMessage.Response decode(ByteBuf input) throws IOException {
return deserialize(new ByteBufInputArchive(input));
}
public static ConnectMessage.Response deserialize(InputArchive archive) throws IOException {
archive.startRecord(Records.CONNECT_TAG);
IConnectResponse record = new IConnectResponse();
record.deserialize(archive, Records.CONNECT_TAG);
boolean readOnly = false;
boolean legacy = false;
try {
readOnly = archive.readBool("readOnly");
} catch (IOException e) {
legacy = true;
}
archive.endRecord(Records.CONNECT_TAG);
ConnectMessage.Response out = ConnectMessage.Response.newInstance(record, readOnly, legacy);
return out;
}
protected Response(IConnectResponse record) {
super(record);
}
protected Response(IConnectResponse record, boolean readOnly, boolean legacy) {
super(record, readOnly, legacy);
}
public static class Valid extends ConnectMessage.Response implements Operation.Response {
public static IConnectResponse toRecord(edu.uw.zookeeper.protocol.Session session) {
IConnectResponse record = new IConnectResponse(
Records.PROTOCOL_VERSION,
(int) session.parameters().timeOut().value(TIMEOUT_UNIT),
session.id(),
session.parameters().password());
return record;
}
public static ConnectMessage.Response newInstance(edu.uw.zookeeper.protocol.Session session) {
return newInstance(session, false, false);
}
public static ConnectMessage.Response newInstance(edu.uw.zookeeper.protocol.Session session, boolean readOnly, boolean legacy) {
return newInstance(toRecord(session), readOnly, legacy);
}
public static ConnectMessage.Response newInstance(IConnectResponse record) {
return newInstance(record, false, false);
}
public static ConnectMessage.Response newInstance(IConnectResponse record, boolean readOnly,
boolean legacy) {
if (record.getSessionId() == edu.uw.zookeeper.protocol.Session.uninitialized().id()) {
return Invalid.newInstance(readOnly, legacy);
} else {
return new Valid(record, readOnly, legacy);
}
}
private Valid(IConnectResponse record, boolean readOnly, boolean legacy) {
super(record, readOnly, legacy);
}
}
public static class Invalid extends ConnectMessage.Response {
protected final static IConnectResponse RECORD =
new IConnectResponse(Records.PROTOCOL_VERSION, 0, edu.uw.zookeeper.protocol.Session.uninitialized().id(), edu.uw.zookeeper.protocol.Session.Parameters.uninitialized().password());
public static Invalid newInstance() {
return newInstance(false, false);
}
public static Invalid newInstance(boolean readOnly, boolean legacy) {
return new Invalid(readOnly, legacy);
}
private Invalid(boolean readOnly, boolean legacy) {
super(RECORD, readOnly, legacy);
}
@Override
public edu.uw.zookeeper.protocol.Session toSession() {
return edu.uw.zookeeper.protocol.Session.uninitialized();
}
@Override
public edu.uw.zookeeper.protocol.Session.Parameters toParameters() {
return edu.uw.zookeeper.protocol.Session.Parameters.uninitialized();
}
}
}
protected static final TimeUnit TIMEOUT_UNIT = TimeUnit.MILLISECONDS;
protected final boolean readOnly;
protected final boolean legacy;
protected ConnectMessage(T record) {
this(record, false, false);
}
protected ConnectMessage(T record, boolean readOnly, boolean legacy) {
super(record);
this.readOnly = readOnly;
this.legacy = legacy;
}
public boolean legacy() {
return legacy;
}
public boolean getReadOnly() {
return readOnly;
}
@Override
public int getProtocolVersion() {
return record.getProtocolVersion();
}
@Override
public int getTimeOut() {
return record.getTimeOut();
}
@Override
public long getSessionId() {
return record.getSessionId();
}
@Override
public byte[] getPasswd() {
return record.getPasswd();
}
public edu.uw.zookeeper.protocol.Session toSession() {
return edu.uw.zookeeper.protocol.Session.create(getSessionId(), toParameters());
}
public edu.uw.zookeeper.protocol.Session.Parameters toParameters() {
return edu.uw.zookeeper.protocol.Session.Parameters.create(getTimeOut(), getPasswd());
}
@Override
public void serialize(OutputArchive archive, String tag) throws IOException {
archive.startRecord(this, tag);
record.serialize(archive, tag);
if (!legacy) {
archive.writeBool(readOnly, "readOnly");
}
archive.endRecord(this, tag);
}
@Override
public void encode(ByteBuf output) throws IOException {
ByteBufOutputArchive archive = new ByteBufOutputArchive(output);
serialize(archive, Records.CONNECT_TAG);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("record", record)
.add("readOnly", readOnly)
.add("legacy", legacy).toString();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ConnectMessage<?> other = (ConnectMessage<?>) obj;
return Objects.equal(record, other.record)
&& Objects.equal(readOnly, other.readOnly)
&& Objects.equal(legacy, other.legacy);
}
}