package lsr.paxos.client;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.List;
import lsr.common.Configuration;
import lsr.common.PID;
import lsr.service.SerializableService;
/**
* Class represents TCP connection to replica. It should be used by clients, to
* communicates with service on replicas. Only one request can be sent by client
* at the same time. After receiving reply, next request can be sent.
* <p>
* <b>Note</b>: To write object to underlying TCP socket java serialization is
* used. Because of that this class should be used mainly for connecting to
* services which extends <code>SerializableService</code>.
* <p>
*
* <p>
* Example of usage:
* <p>
* <blockquote>
*
* <pre>
* public static void main(String[] args) throws IOException {
* Client client = new Client();
* client.connect();
* Object request = new String("my request");
* Object reply = client.execute(request);
* }
* </pre>
*
* </blockquote>
*
* @see SerializableService
*/
public class SerializableClient extends Client {
/**
* Loads the configuration from the default configuration file, as defined
* in the class {@link Configuration}
*
* @throws IOException if I/O error occurs while reading configuration
*/
public SerializableClient() throws IOException {
super();
}
public SerializableClient(Configuration conf) throws IOException {
super(conf);
}
/**
* Creates new connection used by client to connect to replicas.
*
* Use {@link #SerializableClient()} or
* {@link #SerializableClient(Configuration)} instead.
*
* @param replicas - information about replicas to connect to
*/
@Deprecated
public SerializableClient(List<PID> replicas) {
super(replicas);
}
public SerializableClient(int contactReplicaId) throws IOException {
super(contactReplicaId);
}
public SerializableClient(Configuration conf, int contactReplicaId) {
super(conf, contactReplicaId);
}
/**
* Sends request to replica, to execute service with specified object as
* argument. This object should be known to replica, which generate reply.
* This method will block until response from replica is received.
* <p>
* Note: Default java serialization will be used to send this object as byte
* array.
*
* @param request - argument for service
* @return reply from service
* @throws ReplicationException
*/
public Object execute(Serializable request) throws IOException, ClassNotFoundException,
ReplicationException {
// serialize object to byte array
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
new ObjectOutputStream(byteOutputStream).writeObject(request);
// execute command
byte[] response = execute(byteOutputStream.toByteArray());
// deserialize response
ObjectInputStream objectInputStream = new ObjectInputStream(new ByteArrayInputStream(
response));
return objectInputStream.readObject();
}
}