All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.protocols.FORWARD_TO_COORD Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 33.0.2.Final
Show newest version
package org.jgroups.protocols;

import org.jgroups.*;
import org.jgroups.annotations.MBean;
import org.jgroups.annotations.ManagedAttribute;
import org.jgroups.annotations.Property;
import org.jgroups.stack.Protocol;
import org.jgroups.util.Bits;
import org.jgroups.util.ForwardQueue;
import org.jgroups.util.Util;

import java.io.DataInput;
import java.io.DataOutput;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

/**
 * Forwards a message to the current coordinator. When the coordinator changes, forwards all pending messages to
 * the new coordinator. Only looks at unicast messages.

* Note that the ordering of messages sent in parallel to the resending of messages is currently (Sept 2012) undefined: * when resending messages 1-4, and concurrently sending (new) messages 5 and 6, then FORWARD_TO_COORD only guarantees * that messages [1,2,3,4] are delivered in that order and messages [5,6] are delivered in that order, too, but * there are no guarantees regarding the ordering between [1,2,3,4] and [5,6], e.g. a receiver could deliver * 1,5,2,3,6,4.

* This is currently not an issue, as the main consumer of FORWARD_TO_COORD is RELAY2, which is used by Infinispan to * invoke sync or async RPCs across sites. In the former case, a unicast #2 will not be sent until unicast #1 is either * ack'ed or times out.

* In a future version, ordering may be provided. Note though that OOB or UNRELIABLE messages don't need to be ordered. * @author Bela Ban * @since 3.2 */ @MBean(description="Forwards unicast messages to the current coordinator") public class FORWARD_TO_COORD extends Protocol { @Property(description="The delay (in ms) to wait until we resend a message to member P after P told us that " + "it isn't the coordinator. Thsi can happen when we see P as new coordinator, but P hasn't yet installed the view " + "which makes it coordinator (perhaps due to a slight delay)",deprecatedMessage="not used anymore, will be ignored") @Deprecated protected long resend_delay=500; /** the address of the current coordinator, all msgs are forwarded to it */ protected volatile Address coord=null; protected volatile Address local_addr; /** ID to be used to identify forwarded messages. Wrap-around shouldn't be an issue. */ protected final AtomicLong current_id=new AtomicLong(0); protected final ForwardQueue fwd_queue=new ForwardQueue(log); /** Set when NOT_COORD message has been received. This will trigger a fwd_queue flush even if the coord didn't change */ protected volatile boolean received_not_coord; public FORWARD_TO_COORD() { } @ManagedAttribute(description="Number of messages for which no ack has been received yet") public int getForwardTableSize() {return fwd_queue.size();} @ManagedAttribute(description="Total number of all seqnos maintained for all receivers") public int getDeliveryTableSize() {return fwd_queue.deliveryTableSize();} public List providedUpServices() {return Arrays.asList(Event.FORWARD_TO_COORD);} public void start() throws Exception { super.start(); received_not_coord=false; fwd_queue.setUpProt(up_prot); fwd_queue.setDownProt(down_prot); fwd_queue.start(); } public void stop() { super.stop(); fwd_queue.stop(); coord=null; } public Object down(Event evt) { switch(evt.getType()) { case Event.FORWARD_TO_COORD: Address target=coord; if(target == null) throw new IllegalStateException("coord is null; dropping message"); Message msg=(Message)evt.getArg(); long msg_id=getNextId(); ForwardHeader hdr=new ForwardHeader(ForwardHeader.MSG, msg_id); msg.putHeader(id, hdr); msg.setDest(target); if(log.isTraceEnabled()) log.trace(local_addr + ": forwarding message with id=" + msg_id + " to current coordinator " + target); fwd_queue.send(msg_id, msg); return null; // FORWARD_TO_COORD is not passed down any further case Event.VIEW_CHANGE: handleViewChange((View)evt.getArg()); break; case Event.SET_LOCAL_ADDRESS: local_addr=(Address)evt.getArg(); fwd_queue.setLocalAddr(local_addr); break; } return down_prot.down(evt); } public Object up(Event evt) { switch(evt.getType()) { case Event.MSG: Message msg=(Message)evt.getArg(); ForwardHeader hdr=(ForwardHeader)msg.getHeader(id); if(hdr == null) break; long msg_id=hdr.getId(); Address sender=msg.getSrc(); switch(hdr.getType()) { case ForwardHeader.MSG: if(local_addr != null && !local_addr.equals(coord)) { // I'm not the coord if(log.isWarnEnabled()) log.warn(local_addr + ": received a message with id=" + msg_id + " from " + sender + ", but I'm not coordinator (" + coord + " is); dropping the message"); sendNotCoord(sender, msg_id); return null; } try { if(log.isTraceEnabled()) log.trace(local_addr + ": received a message with id=" + msg_id + " from " + sender); fwd_queue.receive(msg_id, msg); return null; } finally { sendAck(sender, msg_id); } case ForwardHeader.ACK: fwd_queue.ack(msg_id); if(log.isTraceEnabled()) log.trace(local_addr + ": received an ack from " + sender + " for " + msg_id); return null; case ForwardHeader.NOT_COORD: if(!received_not_coord) received_not_coord=true; return null; } break; case Event.VIEW_CHANGE: handleViewChange((View)evt.getArg()); break; } return up_prot.up(evt); } protected long getNextId() {return current_id.incrementAndGet();} protected void handleViewChange(View view) { Address new_coord=Util.getCoordinator(view); boolean coord_changed=coord == null || !coord.equals(new_coord); if(coord_changed || received_not_coord) { if(received_not_coord) received_not_coord=false; // resend all messages to the new coordinator (make copies) fwd_queue.flush(new_coord, view.getMembers()); coord=new_coord; } } protected void sendAck(Address target, long ack_id) { send(target,ack_id,ForwardHeader.ACK); } protected void sendNotCoord(Address target, long ack_id) { send(target,ack_id,ForwardHeader.NOT_COORD); } protected void send(Address target, long ack_id, byte type) { down_prot.down(new Event(Event.MSG, new Message(target).putHeader(id, new ForwardHeader(type, ack_id)))); } protected static class ForwardHeader extends Header { protected static final byte MSG = 1; // attached to the messages to the coord protected static final byte ACK = 2; // sent back by the coord protected static final byte NOT_COORD = 3; // sent by the coord when it is *not* the coord protected byte type; protected long id; public ForwardHeader() { } public ForwardHeader(byte type, long id) { this.type=type; this.id=id; } public long getId() {return id;} public byte getType() {return type;} public int size() {return Global.BYTE_SIZE + Bits.size(id);} public void writeTo(DataOutput out) throws Exception { out.writeByte(type); Bits.writeLong(id,out); } public void readFrom(DataInput in) throws Exception { type=in.readByte(); id=Bits.readLong(in); } public String toString() { return typeToString(type) + "(" + id + ")"; } protected static String typeToString(byte type) { switch(type) { case MSG: return "MSG"; case ACK: return "ACK"; case NOT_COORD: return "NOT_COORD"; default: return "n/a"; } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy