package com.zqh.twopc.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import com.zqh.twopc.shared.Message;
public class Participant{
private boolean stop;
private boolean active;
InputStream in;
OutputStream out;
private Socket socket;
private Map<Socket, Participant> connections;
private ResponseEvent awaitingResponse;
private Timer awaitingTimeout;
public Participant(Socket socket, Map<Socket, Participant> connections) {
stop = false;
this.socket = socket;
this.connections = connections;
try {
socket.setSoTimeout(500);
in = socket.getInputStream();
out = socket.getOutputStream();
active = true;
} catch (IOException e) {
e.printStackTrace();
active = false;
return;
}
ListenThread lt = new ListenThread();
new Thread(lt).start();
}
public void finish(){
System.out.println("closing " + toString() + ".");
stop = true;
active = false;
try {
connections.remove(socket);
socket.close();
} catch (IOException e) {}
}
public void sendMessage(Message message){
try {
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(message);
System.out.println("Sent " + message.type);
} catch (IOException e) {
finish();
e.printStackTrace();
}
}
public void sendMessage(Message message, ResponseEvent e){
awaitingResponse = e;
sendMessage(message);
}
public void sendMessage(Message message, ResponseEvent e, ResponseEvent timeout){
final ResponseEvent requestTimeout = timeout;
Timer timer = new Timer();
TimerTask tt = new TimerTask() {
@Override
public void run() {
awaitingTimeout = null;
requestTimeout.notify(null);
}
};
this.awaitingTimeout = timer;
timer.schedule(tt, Main.TIMEOUT);
sendMessage(message, e);
}
private void handleMessage(Message o){
if(awaitingTimeout != null){
awaitingTimeout.cancel();
awaitingTimeout = null;
}
ResponseEvent e = awaitingResponse;
System.out.println("Received " + o.type);
awaitingResponse = null;
e.notify(o);
}
private class ListenThread implements Runnable{
@Override
public void run() {
while(!stop){
try {
ObjectInputStream ois = new ObjectInputStream(in);
Message o = (Message) ois.readObject();
//ois.close();
handleMessage(o);
} catch(SocketTimeoutException e){
continue;
}catch (ClassNotFoundException | IOException e) {
finish();
}
}
}
}
public String toString(){
return socket.getInetAddress().toString() + ":" + socket.getPort();
}
}