Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
package org.jgroups.fork;
import org.jgroups.*;
import org.jgroups.protocols.FORK;
import org.jgroups.stack.AddressGenerator;
import org.jgroups.stack.Protocol;
import org.jgroups.stack.ProtocolStack;
import org.jgroups.util.Util;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
/**
* Implementation of a ForkChannel, which is a light-weight channel. Not all methods are supported,
* UnsupportedOperationExceptions will be thrown if an unsupported operation is called.
* See doc/design/FORK.txt for details
* @author Bela Ban
* @since 3.4
*/
public class ForkChannel extends JChannel implements ChannelListener {
protected final JChannel main_channel;
protected final String fork_channel_id;
protected static final Field[] copied_fields;
static {
String[] fields={"state", "local_addr", "name", "cluster_name", "view"};
copied_fields=new Field[fields.length];
for(int i=0; i < fields.length; i++) {
Field field=Util.getField(JChannel.class, fields[i]);
if(field == null)
throw new IllegalStateException("field \"" + fields[i] + "\" not found in JChannel");
copied_fields[i]=field;
}
}
/**
* Creates a new fork-channel from a main-channel. The channel is unconnected and {@link ForkChannel#connect(String)}
* needs to be called to send and receive messages.
* @param main_channel The main-channel. The lifetime of the newly created channel will be less than or equal to
* the main-channel
* @param fork_stack_id The ID to associate the fork-stack with in FORK
* @param fork_channel_id The ID used to map fork-channel IDs to ForkChannels in the fork-channels protocol stack
* @param create_fork_if_absent If true, and FORK doesn't exist, a new FORK protocol will be created and inserted
* into the main-stack at the given position. If false, and FORK doesn't exist, an
* exception will be thrown
* @param position The position at which the newly created FORK will be inserted. {@link ProtocolStack.Position#ABOVE} or
* {@link ProtocolStack.Position#BELOW} are accepted. Ignored if create_fork_if_absent is false.
* @param neighbor The class of the neighbor protocol below or above which the newly created FORK protocol will
* be inserted. Ignored if create_fork_if_absent is false.
* @param protocols A list of protocols (from bottom to top !) to insert as the fork_stack in FORK under the
* given fork_stack_id. If the fork-stack with fork_stack_id already exists, an exception will be
* thrown.
* Can be null if no protocols should be added. This may be the case when an app only wants to use
* a ForkChannel to mux/demux messages, but doesn't need a different protocol stack.
*
* @throws Exception
*/
public ForkChannel(final JChannel main_channel, String fork_stack_id, String fork_channel_id,
boolean create_fork_if_absent, ProtocolStack.Position position, Class extends Protocol> neighbor,
Protocol ... protocols) throws Exception {
super(false);
if(main_channel == null) throw new IllegalArgumentException("main channel cannot be null");
if(fork_stack_id == null) throw new IllegalArgumentException("fork_stack_id cannot be null");
if(fork_channel_id == null) throw new IllegalArgumentException("fork_channel_id cannot be null");
this.main_channel=main_channel;
this.fork_channel_id=fork_channel_id;
FORK fork;
// To prevent multiple concurrent FORK creations https://issues.redhat.com/browse/JGRP-1842
synchronized(this.main_channel) {
fork=getFORK(main_channel, position, neighbor, create_fork_if_absent);
}
// Returns the existing fork stack for fork_stack_id, or creates a new one
prot_stack=fork.createForkStack(fork_stack_id, protocols == null? null : Arrays.asList(protocols), true);
flush_supported=main_channel.flushSupported();
state=State.OPEN;
}
/**
* Creates a new fork-channel from a main-channel. The channel is unconnected and {@link ForkChannel#connect(String)}
* needs to be called to send and receive messages. If FORK is not found in the stack, an exception will be thrown.
* @param main_channel The main-channel. The lifetime of the newly created channel will be less than or equal to
* the main-channel
* @param fork_stack_id The ID to associate the fork-stack with in FORK
* @param fork_channel_id The ID used to map fork-channel IDs to ForkChannels in the fork-channels protocol stack
* @param protocols A list of protocols (from bottom to top !) to insert as the fork_stack in FORK under the
* given fork_stack_id. If the fork-stack with fork_stack_id already exists, an exception will be
* thrown.
* Can be null if no protocols should be added. This may be the case when an app only wants to use
* a ForkChannel to mux/demux messages, but doesn't need a different protocol stack.
* @throws Exception
*/
public ForkChannel(final JChannel main_channel, String fork_stack_id, String fork_channel_id,
Protocol ... protocols) throws Exception {
this(main_channel, fork_stack_id, fork_channel_id, false, ProtocolStack.Position.ABOVE, null, protocols);
}
@Override
public ForkChannel setName(String name) {
log.error("name (%s) cannot be set in a fork-channel", name);
return this;
}
@Override
public JChannel name(String name) {
log.error("name (%s) cannot be set in a fork-channel", name);
return this;
}
@Override public void channelConnected(JChannel channel) {
copyFields();
if(local_addr == null) return;
if(up_handler != null)
up_handler.setLocalAddress(local_addr);
}
@Override public void channelDisconnected(JChannel channel) {
copyFields();
}
@Override public void channelClosed(JChannel channel) {
copyFields();
}
/**
* Connects the fork-channel, which will be operational after this. Note that the fork-channel will
* have the same state as the main-channel, ie. if the main-channel is disconnected, so will the fork-channel be,
* even if connect() was called. This connect() method essentially adds the fork-channel to the fork-stack's hashmap,
* ready to send/receive messages as soon as the main-channel has been connected.
* This method does not affect the main-channel.
* @param cluster_name Ignored, will be the same as the main-channel's cluster name
* @throws Exception
*/
@Override
public ForkChannel connect(String cluster_name) throws Exception {
if(!this.main_channel.isConnected())
throw new IllegalStateException("main channel is not connected");
if(state == State.CONNECTED)
return this;
if(state == State.CLOSED)
throw new IllegalStateException("a closed fork channel cannot reconnect");
state=State.CONNECTING;
this.main_channel.addChannelListener(this);
copyFields();
JChannel existing_ch=((ForkProtocolStack)prot_stack).putIfAbsent(fork_channel_id,this);
if(existing_ch != null && existing_ch != this)
throw new IllegalArgumentException("fork-channel with id=" + fork_channel_id + " is already present");
setLocalAddress(local_addr);
prot_stack.startStack();
prot_stack.down(new Event(Event.CONNECT, cluster_name));
View current_view=main_channel.getView();
if(current_view != null) {
up(new Event(Event.VIEW_CHANGE, current_view));
prot_stack.down(new Event(Event.VIEW_CHANGE, current_view));
}
state=State.CONNECTED;
notifyChannelConnected(this);
return this;
}
@Override
public ForkChannel connect(String cluster_name, Address target, long timeout) throws Exception {
connect(cluster_name);
main_channel.getState(target, timeout);
return this;
}
/** Removes the fork-channel from the fork-stack's hashmap and resets its state. Does not affect the
* main-channel */
@Override
public ForkChannel disconnect() {
if(state != State.CONNECTED)
return this;
prot_stack.down(new Event(Event.DISCONNECT, local_addr)); // will be discarded by ForkProtocol
prot_stack.stopStack(cluster_name);
((ForkProtocolStack)prot_stack).remove(fork_channel_id);
nullFields();
state=State.OPEN;
notifyChannelDisconnected(this);
return this;
}
/** Closes the fork-channel, essentially setting its state to CLOSED. Note that - contrary to a regular channel -
* a closed fork-channel can be connected again: this means re-attaching the fork-channel to the main-channel*/
@Override
public void close() {
((ForkProtocolStack)prot_stack).remove(fork_channel_id);
if(state == State.CLOSED)
return;
disconnect(); // leave cluster if connected
prot_stack.destroy();
state=State.CLOSED;
notifyChannelClosed(this);
}
@Override
public Object down(Message msg) {
setHeader(msg);
return super.down(msg);
}
@Override
public ForkChannel send(Message msg) throws Exception {
checkClosedOrNotConnected();
FORK.ForkHeader hdr=msg.getHeader(FORK.ID);
if(hdr != null)
hdr.setForkChannelId(fork_channel_id);
else {
hdr=new FORK.ForkHeader(null, fork_channel_id);
msg.putHeader(FORK.ID, hdr);
}
prot_stack.down(msg);
return this;
}
@Override
public ForkChannel startFlush(List flushParticipants, boolean automatic_resume) throws Exception {
throw new UnsupportedOperationException();
}
@Override
public ForkChannel startFlush(boolean automatic_resume) throws Exception {
throw new UnsupportedOperationException();
}
@Override
public ForkChannel stopFlush() {
throw new UnsupportedOperationException();
}
@Override
public ForkChannel stopFlush(List flushParticipants) {
throw new UnsupportedOperationException();
}
@Override
public ForkChannel getState(Address target, long timeout) throws Exception {
main_channel.getState(target, timeout);
return this;
}
@Override
public ForkChannel addAddressGenerator(AddressGenerator address_generator) {
main_channel.addAddressGenerator(address_generator);
return this;
}
protected ForkChannel setLocalAddress(Address local_addr) {
if(local_addr != null) {
((ForkProtocolStack)prot_stack).setLocalAddress(local_addr); // sets the address only in the protocols managed by the fork-prot-stack
if(up_handler != null)
up_handler.setLocalAddress(local_addr);
}
return this;
}
/**
* Creates a new FORK protocol, or returns the existing one, or throws an exception. Never returns null.
*/
protected static FORK getFORK(JChannel ch, ProtocolStack.Position position, Class extends Protocol> neighbor,
boolean create_fork_if_absent) throws Exception {
ProtocolStack stack=ch.getProtocolStack();
FORK fork=stack.findProtocol(FORK.class);
if(fork == null) {
if(!create_fork_if_absent)
throw new IllegalArgumentException("FORK not found in main stack");
fork = new FORK();
fork.setProtocolStack(stack);
stack.insertProtocol(fork, position, neighbor);
}
return fork;
}
protected void setHeader(Message msg) {
FORK.ForkHeader hdr=msg.getHeader(FORK.ID);
if(hdr != null)
hdr.setForkChannelId(fork_channel_id);
else
msg.putHeader(FORK.ID, new FORK.ForkHeader(null, fork_channel_id));
}
/** Copies state from main-channel to this fork-channel */
protected void copyFields() {
for(Field field: copied_fields) {
Object value=Util.getField(field,main_channel);
Util.setField(field, this, value);
}
}
protected void nullFields() {
for(Field field: copied_fields)
Util.setField(field, this, null);
}
}