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.
configurationString - a JGroups configuration String
*
configurationXml - JGroups configuration XML as a String
*
configurationFile - String pointing to a JGroups XML configuration file
*
channelLookup - Fully qualified class name of a
* {@link org.infinispan.remoting.transport.jgroups.JGroupsChannelLookup} instance
*
* These are normally passed in as Properties in
* {@link org.infinispan.configuration.global.TransportConfigurationBuilder#withProperties(java.util.Properties)} or
* in the Infinispan XML configuration file.
*
* @author Manik Surtani
* @author Galder Zamarreño
* @since 4.0
*/
public class JGroupsTransport extends AbstractTransport implements MembershipListener {
public static final String CONFIGURATION_STRING = "configurationString";
public static final String CONFIGURATION_XML = "configurationXml";
public static final String CONFIGURATION_FILE = "configurationFile";
public static final String CHANNEL_LOOKUP = "channelLookup";
protected static final String DEFAULT_JGROUPS_CONFIGURATION_FILE = "default-configs/default-jgroups-udp.xml";
static final Log log = LogFactory.getLog(JGroupsTransport.class);
static final boolean trace = log.isTraceEnabled();
protected boolean connectChannel = true, disconnectChannel = true, closeChannel = true;
protected CommandAwareRpcDispatcher dispatcher;
protected TypedProperties props;
protected StreamingMarshaller marshaller;
protected CacheManagerNotifier notifier;
protected GlobalComponentRegistry gcr;
protected TimeService timeService;
protected InboundInvocationHandler globalHandler;
private ScheduledExecutorService timeoutExecutor;
private boolean globalStatsEnabled;
private MBeanServer mbeanServer;
private String domain;
protected Channel channel;
protected Address address;
protected Address physicalAddress;
// these members are not valid until we have received the first view on a second thread
// and channelConnectedLatch is signaled
protected volatile int viewId = -1;
protected volatile List members = null;
protected volatile Address coordinator = null;
protected volatile boolean isCoordinator = false;
protected Lock viewUpdateLock = new ReentrantLock();
protected Condition viewUpdateCondition = viewUpdateLock.newCondition();
/**
* This form is used when the transport is created by an external source and passed in to the
* GlobalConfiguration.
*
* @param channel
* created and running channel to use
*/
public JGroupsTransport(Channel channel) {
this.channel = channel;
if (channel == null)
throw new IllegalArgumentException("Cannot deal with a null channel!");
if (channel.isConnected())
throw new IllegalArgumentException("Channel passed in cannot already be connected!");
}
public JGroupsTransport() {
}
@Override
public Log getLog() {
return log;
}
protected ScheduledExecutorService getTimeoutExecutor() {
return timeoutExecutor;
}
// ------------------------------------------------------------------------------------------------------------------
// Lifecycle and setup stuff
// ------------------------------------------------------------------------------------------------------------------
/**
* Initializes the transport with global cache configuration and transport-specific properties.
*
* @param marshaller marshaller to use for marshalling and unmarshalling
* @param notifier notifier to use
* @param gcr the global component registry
*/
@Inject
public void initialize(@ComponentName(GLOBAL_MARSHALLER) StreamingMarshaller marshaller,
CacheManagerNotifier notifier, GlobalComponentRegistry gcr,
TimeService timeService, InboundInvocationHandler globalHandler,
@ComponentName(KnownComponentNames.TIMEOUT_SCHEDULE_EXECUTOR) ScheduledExecutorService timeoutExecutor) {
this.marshaller = marshaller;
this.notifier = notifier;
this.gcr = gcr;
this.timeService = timeService;
this.globalHandler = globalHandler;
this.timeoutExecutor = timeoutExecutor;
}
@Override
public void start() {
props = TypedProperties.toTypedProperties(configuration.transport().properties());
if (log.isInfoEnabled())
log.startingJGroupsChannel(configuration.transport().clusterName());
initChannelAndRPCDispatcher();
startJGroupsChannelIfNeeded();
waitForInitialNodes();
}
protected void startJGroupsChannelIfNeeded() {
String clusterName = configuration.transport().clusterName();
if (connectChannel) {
try {
channel.connect(clusterName);
} catch (Exception e) {
throw new CacheException("Unable to start JGroups Channel", e);
}
try {
// Normally this would be done by CacheManagerJmxRegistration but
// the channel is not started when the cache manager starts but
// when first cache starts, so it's safer to do it here.
globalStatsEnabled = configuration.globalJmxStatistics().enabled();
if (globalStatsEnabled) {
String groupName = String.format("type=channel,cluster=%s", ObjectName.quote(clusterName));
mbeanServer = JmxUtil.lookupMBeanServer(configuration);
domain = JmxUtil.buildJmxDomain(configuration, mbeanServer, groupName);
JmxConfigurator.registerChannel((JChannel) channel, mbeanServer, domain, clusterName, true);
}
} catch (Exception e) {
throw new CacheException("Channel connected, but unable to register MBeans", e);
}
}
address = fromJGroupsAddress(channel.getAddress());
if (!connectChannel) {
// the channel was already started externally, we need to initialize our member list
viewAccepted(channel.getView());
}
if (log.isInfoEnabled())
log.localAndPhysicalAddress(clusterName, getAddress(), getPhysicalAddresses());
}
@Override
public int getViewId() {
if (channel == null)
throw new CacheException("The cache has been stopped and invocations are not allowed!");
return viewId;
}
@Override
public void waitForView(int viewId) throws InterruptedException {
waitForView(viewId, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
public boolean waitForView(int viewId, long timeout, TimeUnit timeUnit) throws InterruptedException {
if (channel == null)
return false;
log.tracef("Waiting on view %d being accepted", viewId);
long remainingNanos = timeUnit.toNanos(timeout);
viewUpdateLock.lock();
try {
while (channel != null && getViewId() < viewId && remainingNanos > 0) {
remainingNanos = viewUpdateCondition.awaitNanos(remainingNanos);
}
} finally {
viewUpdateLock.unlock();
}
return remainingNanos > 0;
}
@Override
public void stop() {
String clusterName = configuration.transport().clusterName();
try {
if (disconnectChannel && channel != null && channel.isConnected()) {
log.disconnectJGroups(clusterName);
// Unregistering before disconnecting/closing because
// after that the cluster name is null
if (globalStatsEnabled) {
JmxConfigurator.unregisterChannel((JChannel) channel, mbeanServer, domain, channel.getClusterName());
}
channel.disconnect();
}
if (closeChannel && channel != null && channel.isOpen()) {
channel.close();
}
} catch (Exception toLog) {
log.problemClosingChannel(toLog, clusterName);
}
if (dispatcher != null) {
log.stoppingRpcDispatcher(clusterName);
dispatcher.close();
if (channel != null) {
// Remove reference to up_handler
UpHandler handler = channel.getUpHandler();
if (handler instanceof Muxer) {
@SuppressWarnings("unchecked")
Muxer mux = (Muxer) handler;
mux.setDefaultHandler(null);
} else {
channel.setUpHandler(null);
}
}
}
channel = null;
viewId = -1;
members = Collections.emptyList();
coordinator = null;
isCoordinator = false;
dispatcher = null;
// Wake up any view waiters
viewUpdateLock.lock();
try {
viewUpdateCondition.signalAll();
} finally {
viewUpdateLock.unlock();
}
}
protected void initChannel() {
final TransportConfiguration transportCfg = configuration.transport();
if (channel == null) {
buildChannel();
if (connectChannel) {
// Cannot change the name if the channelLookup already connected the channel
String transportNodeName = transportCfg.nodeName();
if (transportNodeName != null && transportNodeName.length() > 0) {
long range = Short.MAX_VALUE * 2;
long randomInRange = (long) ((Math.random() * range) % range) + 1;
transportNodeName = transportNodeName + "-" + randomInRange;
channel.setName(transportNodeName);
}
}
}
// Channel.LOCAL *must* be set to false so we don't see our own messages - otherwise
// invalidations targeted at remote instances will be received by self.
// NOTE: total order needs to deliver own messages. the invokeRemotely method has a total order boolean
// that when it is false, it discard our own messages, maintaining the property needed
channel.setDiscardOwnMessages(false);
// if we have a TopologyAwareConsistentHash, we need to set our own address generator in JGroups
if (transportCfg.hasTopologyInfo()) {
// We can do this only if the channel hasn't been started already
if (connectChannel) {
((JChannel) channel).setAddressGenerator(new AddressGenerator() {
@Override
public org.jgroups.Address generateAddress() {
return TopologyUUID.randomUUID(channel.getName(), transportCfg.siteId(),
transportCfg.rackId(), transportCfg.machineId());
}
});
} else {
if (channel.getAddress() instanceof TopologyUUID) {
TopologyUUID topologyAddress = (TopologyUUID) channel.getAddress();
if (!transportCfg.siteId().equals(topologyAddress.getSiteId())
|| !transportCfg.rackId().equals(topologyAddress.getRackId())
|| !transportCfg.machineId().equals(topologyAddress.getMachineId())) {
throw new CacheException("Topology information does not match the one set by the provided JGroups channel");
}
} else {
throw new CacheException("JGroups address does not contain topology coordinates");
}
}
}
}
private void initChannelAndRPCDispatcher() throws CacheException {
initChannel();
initRPCDispatcher();
}
protected void initRPCDispatcher() {
dispatcher = new CommandAwareRpcDispatcher(channel, this, globalHandler, timeoutExecutor, timeService);
MarshallerAdapter adapter = new MarshallerAdapter(marshaller);
dispatcher.setRequestMarshaller(adapter);
dispatcher.setResponseMarshaller(adapter);
dispatcher.start();
}
// This is per CM, so the CL in use should be the CM CL
private void buildChannel() {
FileLookup fileLookup = FileLookupFactory.newInstance();
// in order of preference - we first look for an external JGroups file, then a set of XML
// properties, and
// finally the legacy JGroups String properties.
String cfg;
if (props != null) {
if (props.containsKey(CHANNEL_LOOKUP)) {
String channelLookupClassName = props.getProperty(CHANNEL_LOOKUP);
try {
JGroupsChannelLookup lookup = Util.getInstance(channelLookupClassName, configuration.classLoader());
channel = lookup.getJGroupsChannel(props);
connectChannel = lookup.shouldConnect();
disconnectChannel = lookup.shouldDisconnect();
closeChannel = lookup.shouldClose();
} catch (ClassCastException e) {
log.wrongTypeForJGroupsChannelLookup(channelLookupClassName, e);
throw new CacheException(e);
} catch (Exception e) {
log.errorInstantiatingJGroupsChannelLookup(channelLookupClassName, e);
throw new CacheException(e);
}
}
if (channel == null && props.containsKey(CONFIGURATION_FILE)) {
cfg = props.getProperty(CONFIGURATION_FILE);
Collection confs = Collections.emptyList();
try {
confs = fileLookup.lookupFileLocations(cfg, configuration.classLoader());
} catch (IOException io) {
//ignore, we check confs later for various states
}
if (confs.isEmpty()) {
throw log.jgroupsConfigurationNotFound(cfg);
} else if (confs.size() > 1) {
log.ambiguousConfigurationFiles(Util.toStr(confs));
}
try {
channel = new JChannel(confs.iterator().next());
} catch (Exception e) {
throw log.errorCreatingChannelFromConfigFile(cfg, e);
}
}
if (channel == null && props.containsKey(CONFIGURATION_XML)) {
cfg = props.getProperty(CONFIGURATION_XML);
try {
channel = new JChannel(XmlConfigHelper.stringToElement(cfg));
} catch (Exception e) {
throw log.errorCreatingChannelFromXML(cfg, e);
}
}
if (channel == null && props.containsKey(CONFIGURATION_STRING)) {
cfg = props.getProperty(CONFIGURATION_STRING);
try {
channel = new JChannel(cfg);
} catch (Exception e) {
throw log.errorCreatingChannelFromConfigString(cfg, e);
}
}
}
if (channel == null) {
log.unableToUseJGroupsPropertiesProvided(props);
try {
channel = new JChannel(fileLookup.lookupFileLocation(DEFAULT_JGROUPS_CONFIGURATION_FILE, configuration.classLoader()));
} catch (Exception e) {
throw log.errorCreatingChannelFromConfigFile(DEFAULT_JGROUPS_CONFIGURATION_FILE, e);
}
}
}
// ------------------------------------------------------------------------------------------------------------------
// querying cluster status
// ------------------------------------------------------------------------------------------------------------------
@Override
public boolean isCoordinator() {
return isCoordinator;
}
@Override
public Address getCoordinator() {
return coordinator;
}
private void waitForInitialNodes() {
int initialClusterSize = configuration.transport().initialClusterSize();
if (initialClusterSize <= 1)
return;
long timeout = configuration.transport().initialClusterTimeout();
long remainingNanos = TimeUnit.MILLISECONDS.toNanos(timeout);
viewUpdateLock.lock();
try {
while (channel != null && channel.getView().getMembers().size() < initialClusterSize &&
remainingNanos > 0) {
log.debugf("Waiting for %d nodes, current view has %d", initialClusterSize,
channel.getView().getMembers().size());
remainingNanos = viewUpdateCondition.awaitNanos(remainingNanos);
}
} catch (InterruptedException e) {
log.interruptedWaitingForCoordinator(e);
Thread.currentThread().interrupt();
} finally {
viewUpdateLock.unlock();
}
if (remainingNanos <= 0) {
throw log.timeoutWaitingForInitialNodes(initialClusterSize, channel.getView().getMembers());
}
log.debugf("Initial cluster size of %d nodes reached", initialClusterSize);
}
@Override
public List getMembers() {
return members != null ? members : Collections.emptyList();
}
@Override
public boolean isMulticastCapable() {
return channel.getProtocolStack().getTransport().supportsMulticasting();
}
@Override
public Address getAddress() {
if (address == null && channel != null) {
address = fromJGroupsAddress(channel.getAddress());
}
return address;
}
@Override
public List getPhysicalAddresses() {
if (physicalAddress == null && channel != null) {
org.jgroups.Address addr = (org.jgroups.Address) channel.down(new Event(Event.GET_PHYSICAL_ADDRESS, channel.getAddress()));
if (addr == null) {
return Collections.emptyList();
}
physicalAddress = new JGroupsAddress(addr);
}
return Collections.singletonList(physicalAddress);
}
// ------------------------------------------------------------------------------------------------------------------
// outbound RPC
// ------------------------------------------------------------------------------------------------------------------
@Override
public Map invokeRemotely(Collection recipients, ReplicableCommand rpcCommand,
ResponseMode mode, long timeout, ResponseFilter responseFilter,
DeliverOrder deliverOrder, boolean anycast) throws Exception {
CompletableFuture