blob: 49c35b811e3ae553ce012e977e60dcc0ec92a8dd [file] [log] [blame]
/*
* Copyright (c) 2013, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial design and implementation
package org.eclipse.persistence.sessions.coordination.jgroups;
import java.util.Map;
import org.eclipse.persistence.exceptions.RemoteCommandManagerException;
import org.eclipse.persistence.internal.sessions.coordination.RemoteConnection;
import org.eclipse.persistence.internal.sessions.coordination.broadcast.BroadcastRemoteConnection;
import org.eclipse.persistence.internal.sessions.coordination.jgroups.JGroupsRemoteConnection;
import org.eclipse.persistence.sessions.coordination.broadcast.BroadcastTransportManager;
import org.eclipse.persistence.sessions.coordination.RemoteCommandManager;
import org.jgroups.JChannel;
/**
* <p>
* <b>Purpose</b>: Provide a transport implementation for the Remote Command Module (RCM) that publishes
* to a JGroup channel.
* <p>
* JGroups is a library for distributed communications.
* <p>
* If issues are encountered with the default setting try,<br>
* -Djava.net.preferIPv4Stack=true
*
* @author James Sutherland
* @since EclipseLink 2.6
*/
public class JGroupsTransportManager extends BroadcastTransportManager {
private String configFile = "";
/**
* PUBLIC:
* Creates a JGroupsTransportManager.
*/
public JGroupsTransportManager() {
}
/**
* PUBLIC:
* Creates a JGroupsTransportManager.
*/
public JGroupsTransportManager(RemoteCommandManager rcm) {
super(rcm);
}
/**
* INTERNAL:
* This method creates JGroupsRemoteConnection to be used by this TransportManager.
* It uses a JGroups JChannel using the RCM channel name and specified (or defaulted) config file.
* Channel is set to not receive own messages.
*/
protected BroadcastRemoteConnection createConnection(boolean isLocalConnectionBeingCreated) throws RemoteCommandManagerException {
try {
JChannel channel;
if (configFile != null && !configFile.isEmpty()) {
channel = new JChannel(configFile);
} else {
channel = new JChannel();
}
channel.connect(this.rcm.getChannel());
channel.setDiscardOwnMessages(true);
return new JGroupsRemoteConnection(this.rcm, channel, isLocalConnectionBeingCreated);
} catch (Exception ex) {
throw RemoteCommandManagerException.errorCreatingJGroupsConnection(this.configFile, ex);
}
}
/**
* INTERNAL:
* JGroups does not require a DiscoveryManager, therefore
* this method is called during RCM initialization to create all the necessary connections.
*/
@Override
public void createConnections() {
createLocalConnection();
createExternalConnection();
}
/**
* INTERNAL:
* JGroups only has a single connection.
* Verify there are no external connections, use the local connection as the external connection.
*/
public void createExternalConnection() {
synchronized (this.connectionsToExternalServices) {
if (this.connectionsToExternalServices.isEmpty()) {
try {
this.connectionsToExternalServices.put(this.rcm.getServiceId().getId(), this.localConnection);
} catch (RemoteCommandManagerException rcmException) {
// to recover handle RemoteCommandManagerException.ERROR_CREATING_JMS_CONNECTION:
// after changing something (for instance config)
// call createExternalConnection method again.
rcm.handleException(rcmException);
}
}
}
}
/**
* INTERNAL:
* JGroups only requires a single connection.
* In case the local connection doesn't exist, this method creates it.
*/
@Override
public synchronized void createLocalConnection() {
if (this.localConnection == null) {
try {
this.localConnection = createConnection(true);
} catch (RemoteCommandManagerException rcmException) {
// to recover handle RemoteCommandManagerException.ERROR_CREATING_LOCAL_JMS_CONNECTION:
// after changing something (for instance jmsHostUrl)
// call createLocalConnection method again.
rcm.handleException(rcmException);
}
}
}
/**
* INTERNAL:
* In case there's no external connection attempts to create one.
* Returns external connections (only a single connection for JGroups).
*/
@Override
public Map<String, RemoteConnection> getConnectionsToExternalServicesForCommandPropagation() {
if (getConnectionsToExternalServices().isEmpty() && !this.rcm.isStopped()) {
createExternalConnection();
}
return super.getConnectionsToExternalServicesForCommandPropagation();
}
/**
* INTERNAL:
* No-op, as the local connection does not need to be removed as JGroups manages registration.
*/
@Override
public void removeLocalConnection() {}
/**
* PUBLIC:
* Return the JGroups config xml file name.
*/
public String getConfigFile() {
return configFile;
}
/**
* PUBLIC:
* Set the JGroups config xml file name.
*/
@Deprecated
public void setConfigFile(String configFile) {
this.configFile = configFile;
}
@Override
public void setConfig(String config) {
configFile = config;
}
}