/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.activemq.artemis.tests.integration.cluster.failover;
import java.util.ArrayList;
import java.util.List;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.core.client.impl.ServerLocatorInternal;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.HAPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.ReplicaPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.ReplicatedPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreMasterPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreSlavePolicyConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.NodeManager;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.tests.integration.cluster.util.SameProcessActiveMQServer;
import org.apache.activemq.artemis.tests.integration.cluster.util.TestableServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.TransportConfigurationUtils;
import org.junit.Before;
public abstract class MultipleServerFailoverTestBase extends ActiveMQTestBase {
// Constants -----------------------------------------------------
// TODO: find a better solution for this
// this is necessary because the cluster connection is using "jms" as its match; see org.apache.activemq.artemis.tests.util.ActiveMQTestBase.basicClusterConnectionConfig()
protected static final SimpleString ADDRESS = new SimpleString("jms.FailoverTestAddress");
// Attributes ----------------------------------------------------
protected List<TestableServer> liveServers = new ArrayList<>();
protected List<TestableServer> backupServers = new ArrayList<>();
protected List<Configuration> backupConfigs = new ArrayList<>();
protected List<Configuration> liveConfigs = new ArrayList<>();
protected List<NodeManager> nodeManagers;
public abstract int getLiveServerCount();
public abstract int getBackupServerCount();
public abstract boolean isNetty();
public abstract boolean isSharedStore();
public abstract String getNodeGroupName();
@Override
@Before
public void setUp() throws Exception {
super.setUp();
liveServers = new ArrayList<>();
backupServers = new ArrayList<>();
backupConfigs = new ArrayList<>();
liveConfigs = new ArrayList<>();
for (int i = 0; i < getLiveServerCount(); i++) {
HAPolicyConfiguration haPolicyConfiguration = null;
if (isSharedStore()) {
haPolicyConfiguration = new SharedStoreMasterPolicyConfiguration();
} else {
haPolicyConfiguration = new ReplicatedPolicyConfiguration();
if (getNodeGroupName() != null) {
((ReplicatedPolicyConfiguration) haPolicyConfiguration).setGroupName(getNodeGroupName() + "-" + i);
}
}
Configuration configuration = createDefaultConfig(isNetty()).clearAcceptorConfigurations().addAcceptorConfiguration(getAcceptorTransportConfiguration(true, i)).setHAPolicyConfiguration(haPolicyConfiguration);
if (!isSharedStore()) {
configuration.setBindingsDirectory(getBindingsDir(i, false));
configuration.setJournalDirectory(getJournalDir(i, false));
configuration.setPagingDirectory(getPageDir(i, false));
configuration.setLargeMessagesDirectory(getLargeMessagesDir(i, false));
} else {
//todo
}
TransportConfiguration livetc = getConnectorTransportConfiguration(true, i);
configuration.addConnectorConfiguration(livetc.getName(), livetc);
List<String> connectors = new ArrayList<>();
for (int j = 0; j < getLiveServerCount(); j++) {
if (j != i) {
TransportConfiguration staticTc = getConnectorTransportConfiguration(true, j);
configuration.getConnectorConfigurations().put(staticTc.getName(), staticTc);
connectors.add(staticTc.getName());
}
}
String[] input = new String[connectors.size()];
connectors.toArray(input);
configuration.addClusterConfiguration(basicClusterConnectionConfig(livetc.getName(), input));
liveConfigs.add(configuration);
ActiveMQServer server = createServer(true, configuration);
TestableServer activeMQServer = new SameProcessActiveMQServer(server);
activeMQServer.setIdentity("Live-" + i);
liveServers.add(activeMQServer);
}
for (int i = 0; i < getBackupServerCount(); i++) {
HAPolicyConfiguration haPolicyConfiguration = null;
if (isSharedStore()) {
haPolicyConfiguration = new SharedStoreSlavePolicyConfiguration();
} else {
haPolicyConfiguration = new ReplicaPolicyConfiguration();
if (getNodeGroupName() != null) {
((ReplicaPolicyConfiguration) haPolicyConfiguration).setGroupName(getNodeGroupName() + "-" + i);
}
}
Configuration configuration = createDefaultConfig(isNetty()).clearAcceptorConfigurations().addAcceptorConfiguration(getAcceptorTransportConfiguration(false, i)).setHAPolicyConfiguration(haPolicyConfiguration);
if (!isSharedStore()) {
configuration.setBindingsDirectory(getBindingsDir(i, true));
configuration.setJournalDirectory(getJournalDir(i, true));
configuration.setPagingDirectory(getPageDir(i, true));
configuration.setLargeMessagesDirectory(getLargeMessagesDir(i, true));
} else {
//todo
}
TransportConfiguration backuptc = getConnectorTransportConfiguration(false, i);
configuration.addConnectorConfiguration(backuptc.getName(), backuptc);
List<String> connectors = new ArrayList<>();
for (int j = 0; j < getBackupServerCount(); j++) {
TransportConfiguration staticTc = getConnectorTransportConfiguration(true, j);
configuration.addConnectorConfiguration(staticTc.getName(), staticTc);
connectors.add(staticTc.getName());
}
for (int j = 0; j < getBackupServerCount(); j++) {
if (j != i) {
TransportConfiguration staticTc = getConnectorTransportConfiguration(false, j);
configuration.getConnectorConfigurations().put(staticTc.getName(), staticTc);
connectors.add(staticTc.getName());
}
}
String[] input = new String[connectors.size()];
connectors.toArray(input);
configuration.addClusterConfiguration(basicClusterConnectionConfig(backuptc.getName(), input));
backupConfigs.add(configuration);
ActiveMQServer server = createServer(true, configuration);
TestableServer testableServer = new SameProcessActiveMQServer(server);
testableServer.setIdentity("Backup-" + i);
backupServers.add(testableServer);
}
}
protected TransportConfiguration getAcceptorTransportConfiguration(final boolean live, int node) {
TransportConfiguration transportConfiguration;
if (isNetty()) {
transportConfiguration = TransportConfigurationUtils.getNettyAcceptor(live, node, (live ? "live-" : "backup-") + node);
} else {
transportConfiguration = TransportConfigurationUtils.getInVMAcceptor(live, node, (live ? "live-" : "backup-") + node);
}
return transportConfiguration;
}
protected TransportConfiguration getConnectorTransportConfiguration(final boolean live, int node) {
TransportConfiguration transportConfiguration;
if (isNetty()) {
transportConfiguration = TransportConfigurationUtils.getNettyConnector(live, node, (live ? "live-" : "backup-") + node);
} else {
transportConfiguration = TransportConfigurationUtils.getInVMConnector(live, node, (live ? "live-" : "backup-") + node);
}
return transportConfiguration;
}
protected ServerLocatorInternal getServerLocator(int node) throws Exception {
return (ServerLocatorInternal) addServerLocator(ActiveMQClient.createServerLocatorWithHA(getConnectorTransportConfiguration(true, node))).setRetryInterval(50).setReconnectAttempts(-1).setInitialConnectAttempts(-1);
}
protected ServerLocatorInternal getBackupServerLocator(int node) throws Exception {
return (ServerLocatorInternal) addServerLocator(ActiveMQClient.createServerLocatorWithHA(getConnectorTransportConfiguration(false, node))).setRetryInterval(50).setReconnectAttempts(-1).setInitialConnectAttempts(-1);
}
protected ClientSession createSession(ClientSessionFactory sf,
boolean autoCommitSends,
boolean autoCommitAcks,
int ackBatchSize) throws Exception {
return addClientSession(sf.createSession(autoCommitSends, autoCommitAcks, ackBatchSize));
}
protected ClientSession createSession(ClientSessionFactory sf,
boolean autoCommitSends,
boolean autoCommitAcks) throws Exception {
return addClientSession(sf.createSession(autoCommitSends, autoCommitAcks));
}
protected ClientSession createSession(ClientSessionFactory sf) throws Exception {
return addClientSession(sf.createSession());
}
protected ClientSession createSession(ClientSessionFactory sf,
boolean xa,
boolean autoCommitSends,
boolean autoCommitAcks) throws Exception {
return addClientSession(sf.createSession(xa, autoCommitSends, autoCommitAcks));
}
protected void waitForDistribution(SimpleString address, ActiveMQServer server, int messageCount) throws Exception {
ActiveMQServerLogger.LOGGER.debug("waiting for distribution of messages on server " + server);
long start = System.currentTimeMillis();
long timeout = 5000;
Queue q = (Queue) server.getPostOffice().getBinding(address).getBindable();
do {
if (getMessageCount(q) >= messageCount) {
return;
}
Thread.sleep(10);
} while (System.currentTimeMillis() - start < timeout);
throw new Exception();
}
}