package org.prevayler.implementation.replication;
import java.io.IOException;
import org.prevayler.foundation.network.ObjectSocket;
import org.prevayler.implementation.Capsule;
import org.prevayler.implementation.TransactionTimestamp;
import org.prevayler.implementation.publishing.POBox;
import org.prevayler.implementation.publishing.TransactionPublisher;
import org.prevayler.implementation.publishing.TransactionSubscriber;
/**
* Reserved for future implementation.
*/
class ServerConnection extends Thread implements TransactionSubscriber {
static final String SUBSCRIBER_UP_TO_DATE="SubscriberUpToDate";
static final String REMOTE_TRANSACTION="RemoteTransaction";
private final TransactionPublisher _publisher;
private Capsule _remoteCapsule;
private final ObjectSocket _remote;
private final Thread _clockTickSender=createClockTickSender();
ServerConnection( TransactionPublisher publisher, ObjectSocket remoteSocket) throws IOException {
_publisher=publisher;
_remote=remoteSocket;
setDaemon(true);
start();
}
public void run(){
try {
long initialTransaction=((Long)_remote.readObject()).longValue();
POBox poBox=new POBox(this);
_publisher.subscribe(poBox,initialTransaction);
poBox.waitToEmpty();
send(SUBSCRIBER_UP_TO_DATE);
startSendingClockTicks();
while (true) publishRemoteTransaction();
}
catch ( IOException ex) {
close();
}
catch ( ClassNotFoundException ex) {
close();
}
}
private void startSendingClockTicks(){
_clockTickSender.setDaemon(true);
_clockTickSender.start();
}
private Thread createClockTickSender(){
return new Thread(){
public void run(){
try {
while (true) {
synchronized (_remote) {
_remote.writeObject(_publisher.clock().time());
}
Thread.sleep(1000);
}
}
catch ( InterruptedException ix) {
}
catch ( IOException iox) {
close();
}
}
}
;
}
void publishRemoteTransaction() throws IOException, ClassNotFoundException {
_remoteCapsule=(Capsule)_remote.readObject();
try {
_publisher.publish(_remoteCapsule);
}
catch ( RuntimeException rx) {
send(rx);
}
catch ( Error error) {
send(error);
}
}
public void receive( TransactionTimestamp tt){
if (tt.capsule() == _remoteCapsule) tt=new TransactionTimestamp(null,tt.systemVersion(),tt.executionTime());
try {
synchronized (_remote) {
_remote.writeObject(tt);
}
}
catch ( IOException ex) {
close();
}
}
private synchronized void close(){
_clockTickSender.interrupt();
this.interrupt();
_publisher.cancelSubscription(this);
}
private void send( Object object){
synchronized (_remote) {
try {
_remote.writeObject(object);
}
catch ( IOException e) {
e.printStackTrace();
}
}
}
}