/*
* 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.server;
import java.util.Arrays;
import java.util.Collection;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding;
import org.apache.activemq.artemis.core.server.impl.ScaleDownHandler;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.integration.cluster.distribution.ClusterTestBase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
/**
* On this test we will run ScaleDown directly as an unit-test in several cases,
* simulating what would happen during a real scale down.
*/
@RunWith(value = Parameterized.class)
public class ScaleDownDirectTest extends ClusterTestBase {
@Parameterized.Parameters(name = "isNetty={0}")
public static Collection getParameters() {
return Arrays.asList(new Object[][]{{false}, {true}});
}
private final boolean isNetty;
public ScaleDownDirectTest(boolean isNetty) {
this.isNetty = isNetty;
}
@Override
@Before
public void setUp() throws Exception {
super.setUp();
setupLiveServer(0, isFileStorage(), isNetty, true);
setupLiveServer(1, isFileStorage(), isNetty, true);
startServers(0, 1);
setupSessionFactory(0, isNetty);
setupSessionFactory(1, isNetty);
}
@Test
public void testSendMixedSmallMessages() throws Exception {
internalTest(100, 100);
}
@Test
public void testSendMixedLargelMessages() throws Exception {
internalTest(2 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE, 100);
}
protected void internalTest(int bufferSize, int numberOfMessages) throws Exception {
ClientSessionFactory sf = sfs[0];
ClientSession session = sf.createSession(true, true);
session.createQueue("ad1", "queue1", true);
ClientProducer producer = session.createProducer("ad1");
byte[] buffer = new byte[bufferSize];
for (int i = 0; i < bufferSize; i++) {
buffer[i] = getSamplebyte(i);
}
for (int i = 0; i < numberOfMessages; i++) {
ClientMessage message = session.createMessage(true);
message.putIntProperty("i", i);
message.getBodyBuffer().writeBytes(buffer);
producer.send(message);
}
session.createQueue("ad1", "queue2", true);
for (int i = numberOfMessages; i < (numberOfMessages * 2); i++) {
ClientMessage message = session.createMessage(true);
message.putIntProperty("i", i);
message.getBodyBuffer().writeBytes(buffer);
producer.send(message);
}
assertEquals(numberOfMessages * 2, performScaledown());
sfs[0].close();
session.close();
stopServers(0);
session = sfs[1].createSession(true, true);
ClientConsumer consumer1 = session.createConsumer("queue1");
session.start();
for (int i = 0; i < numberOfMessages * 2; i++) {
ClientMessage message = consumer1.receive(5000);
assertNotNull(message);
assertEquals(i, message.getIntProperty("i").intValue());
// message.acknowledge();
checkBody(message, bufferSize);
}
ClientMessage messageCheckNull = consumer1.receiveImmediate();
assertNull(messageCheckNull);
ClientConsumer consumer2 = session.createConsumer("queue2");
for (int i = numberOfMessages; i < numberOfMessages * 2; i++) {
ClientMessage message = consumer2.receive(5000);
assertNotNull(message);
assertEquals(i, message.getIntProperty("i").intValue());
// message.acknowledge();
checkBody(message, bufferSize);
}
messageCheckNull = consumer2.receiveImmediate();
System.out.println("Received " + messageCheckNull);
assertNull(messageCheckNull);
}
@Test
public void testPaging() throws Exception {
final int CHUNK_SIZE = 50;
int messageCount = 0;
final String addressName = "testAddress";
final String queueName = "testQueue";
createQueue(0, addressName, queueName, null, true);
createQueue(1, addressName, queueName, null, true);
ClientSessionFactory sf = sfs[0];
ClientSession session = addClientSession(sf.createSession(false, false));
ClientProducer producer = addClientProducer(session.createProducer(addressName));
AddressSettings defaultSetting = new AddressSettings().setPageSizeBytes(10 * 1024).setMaxSizeBytes(20 * 1024);
servers[0].getAddressSettingsRepository().addMatch("#", defaultSetting);
while (!servers[0].getPagingManager().getPageStore(new SimpleString(addressName)).isPaging()) {
for (int i = 0; i < CHUNK_SIZE; i++) {
Message message = session.createMessage(true);
message.getBodyBuffer().writeBytes(new byte[1024]);
// The only purpose of this count here is for eventually debug messages on print-data / print-pages
// message.putIntProperty("count", messageCount);
producer.send(message);
messageCount++;
}
session.commit();
}
assertEquals(messageCount, performScaledown());
servers[0].stop();
addConsumer(0, 1, queueName, null);
for (int i = 0; i < messageCount; i++) {
ClientMessage message = consumers[0].getConsumer().receive(500);
Assert.assertNotNull(message);
// Assert.assertEquals(i, message.getIntProperty("count").intValue());
}
Assert.assertNull(consumers[0].getConsumer().receiveImmediate());
removeConsumer(0);
}
@Test
public void testBasicScaleDown() throws Exception {
final int TEST_SIZE = 2;
final String addressName = "testAddress";
final String queueName1 = "testQueue1";
final String queueName2 = "testQueue2";
// create 2 queues on each node mapped to the same address
createQueue(0, addressName, queueName1, null, true);
createQueue(0, addressName, queueName2, null, true);
createQueue(1, addressName, queueName1, null, true);
createQueue(1, addressName, queueName2, null, true);
// send messages to node 0
send(0, addressName, TEST_SIZE, true, null);
// consume a message from queue 2
addConsumer(1, 0, queueName2, null, false);
ClientMessage clientMessage = consumers[1].getConsumer().receive(250);
Assert.assertNotNull(clientMessage);
clientMessage.acknowledge();
consumers[1].getSession().commit();
removeConsumer(1);
// at this point on node 0 there should be 2 messages in testQueue1 and 1 message in testQueue2
Assert.assertEquals(TEST_SIZE, getMessageCount(((LocalQueueBinding) servers[0].getPostOffice().getBinding(new SimpleString(queueName1))).getQueue()));
Assert.assertEquals(TEST_SIZE - 1, getMessageCount(((LocalQueueBinding) servers[0].getPostOffice().getBinding(new SimpleString(queueName2))).getQueue()));
assertEquals(TEST_SIZE, performScaledown());
// trigger scaleDown from node 0 to node 1
servers[0].stop();
// get the 2 messages from queue 1
addConsumer(0, 1, queueName1, null);
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNotNull(clientMessage);
clientMessage.acknowledge();
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNotNull(clientMessage);
clientMessage.acknowledge();
// ensure there are no more messages on queue 1
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNull(clientMessage);
removeConsumer(0);
// get the 1 message from queue 2
addConsumer(0, 1, queueName2, null);
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNotNull(clientMessage);
clientMessage.acknowledge();
// ensure there are no more messages on queue 1
clientMessage = consumers[0].getConsumer().receive(250);
Assert.assertNull(clientMessage);
removeConsumer(0);
}
private void checkBody(ClientMessage message, int bufferSize) {
assertEquals(bufferSize, message.getBodySize());
byte[] body = new byte[message.getBodySize()];
message.getBodyBuffer().readBytes(body);
for (int bpos = 0; bpos < bufferSize; bpos++) {
if (getSamplebyte(bpos) != body[bpos]) {
fail("body comparison failure at " + message);
}
}
}
private long performScaledown() throws Exception {
ScaleDownHandler handler = new ScaleDownHandler(servers[0].getPagingManager(), servers[0].getPostOffice(), servers[0].getNodeManager(), servers[0].getClusterManager().getClusterController(), servers[0].getStorageManager());
return handler.scaleDownMessages(sfs[1], servers[1].getNodeID(), servers[0].getConfiguration().getClusterUser(), servers[0].getConfiguration().getClusterPassword());
}
}