/**
* SAMOA - PROTOCOL FRAMEWORK
* Copyright (C) 2005 Olivier Rütti (EPFL) (olivier.rutti@a3.epfl.ch)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package seqSamoa.protocols.fd;
import java.io.OutputStream;
import java.util.LinkedList;
import seqSamoa.Message;
import seqSamoa.ProtocolModule;
import seqSamoa.ProtocolStack;
import seqSamoa.ServiceCallOrResponse;
import seqSamoa.exceptions.AlreadyExistingProtocolModuleException;
import seqSamoa.services.fd.FD;
import seqSamoa.services.fd.FDCallParameters;
import seqSamoa.services.fd.FDResponseParameters;
import seqSamoa.services.fd.Leader;
import seqSamoa.services.fd.LeaderCallParameters;
import seqSamoa.services.fd.LeaderResponseParameters;
import uka.transport.Transportable;
import framework.Constants;
import framework.GroupCommEventArgs;
import framework.GroupCommException;
import framework.PID;
import framework.libraries.Trigger;
import framework.libraries.serialization.TList;
import framework.libraries.serialization.TSet;
import groupcomm.common.fd.LeaderHandler;
/**
* This class implement a Protocol that detect distant process failure. It
* implement the failure detector needed by the consensus protocol described by
* Chandra and Toueg.
*
* This Protocol need a Protocol that implements FD.
*
* The service implemented is Leader (described in util/Services.java)
*/
public class ProtocolOmega extends ProtocolModule implements Trigger {
// Service provided
private Leader leader;
// Service required
private FD fd;
// The object containig the Omega algorithm
private LeaderHandler handlers = null;
// The Executer
// It start to monitor the processes in parameters
protected Leader.Executer leaderExecuter;
// The Listener
// It wait for suspicions of FD
protected FD.Listener fdListener;
/**
* Constructor. <br>
*
* @param name
* Name of the layer
* @param stack
* The stack in which the module will be
*/
public ProtocolOmega(String name, ProtocolStack stack, Leader leader, FD fd) throws AlreadyExistingProtocolModuleException {
super(name, stack);
handlers = new LeaderHandler(this, stack.getPID());
this.leader = leader;
this.fd = fd;
LinkedList<ServiceCallOrResponse> initiatedLeader = new LinkedList<ServiceCallOrResponse>();
initiatedLeader.add(ServiceCallOrResponse.createServiceCallOrResponse(fd, true));
initiatedLeader.add(ServiceCallOrResponse.createServiceCallOrResponse(leader, false));
leaderExecuter = leader.new Executer(this, initiatedLeader) {
public void evaluate(LeaderCallParameters params, Message dmessage) {
synchronized (this.parent) {
GroupCommEventArgs ga = new GroupCommEventArgs();
ga.add(params.startMonitoring);
ga.add(params.stopMonitoring);
try {
handlers.handleStartStopMonitor(ga);
} catch (GroupCommException ex) {
throw new RuntimeException("ProtocolOmega: "
+ "leaderExecuter: " + ex.getMessage());
}
}
}
};
LinkedList<ServiceCallOrResponse> initiatedFd = new LinkedList<ServiceCallOrResponse>();
initiatedFd.add(ServiceCallOrResponse.createServiceCallOrResponse(leader, false));
fdListener = fd.new Listener(this, initiatedFd) {
public void evaluate(FDResponseParameters infos,
Transportable response) {
synchronized (this.parent) {
GroupCommEventArgs ga = new GroupCommEventArgs();
ga.add(infos.suspected);
handlers.handleSuspect(ga);
}
}
};
}
synchronized public void dump(OutputStream stream) {
handlers.dump(stream);
}
/**
* Manage the triggering of the events
*/
public void trigger(int type, GroupCommEventArgs e) {
switch (type) {
case Constants.STARTSTOPMONITOR:
FDCallParameters params = new FDCallParameters((TSet) e.remove(0),
(TSet) e.remove(0));
fd.call(params, null);
break;
case Constants.NEWLEADER:
LeaderResponseParameters infos = new LeaderResponseParameters(
(PID) e.remove(0), (TList) e.remove(0));
leader.response(infos, null);
break;
default:
// This shouldn't ever happen
throw new RuntimeException("ProtocolOmega: trigger: "
+ "Unexpected event type");
}
}
}