/*
* Copyright 2013 Jive Software, Inc
*
* Licensed 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 com.jivesoftware.os.amza.service;
import com.google.common.io.Files;
import com.jivesoftware.os.amza.api.partition.Consistency;
import com.jivesoftware.os.amza.api.partition.PartitionName;
import com.jivesoftware.os.amza.api.ring.RingHost;
import com.jivesoftware.os.amza.api.ring.RingMember;
import com.jivesoftware.os.amza.api.stream.RowType;
import com.jivesoftware.os.amza.service.AmzaTestCluster.AmzaNode;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import org.testng.Assert;
import org.testng.annotations.Test;
public class AmzaClientTest {
@Test(enabled = true)
public void testAddToReplicatedWAL() throws Exception {
final int maxNumberOfServices = 5;
File createTempDir = Files.createTempDir();
final AmzaTestCluster cluster = new AmzaTestCluster(createTempDir, 0, 0);
for (int i = 0; i < maxNumberOfServices; i++) {
cluster.newNode(new RingMember("localhost-" + i), new RingHost("datacenter", "rack", "localhost", i));
}
Collection<AmzaNode> clusterNodes = cluster.getAllNodes();
testRowType(cluster, maxNumberOfServices, new PartitionName(false, "test".getBytes(), "partition1".getBytes()), RowType.primary);
testRowType(cluster, maxNumberOfServices, new PartitionName(false, "test".getBytes(), "partition2".getBytes()), RowType.snappy_primary);
int falseCount = -1;
while (falseCount != 0) {
falseCount = 0;
System.out.println("---- checking for inconsistencies ----");
List<AmzaNode> nodes = new ArrayList<>(clusterNodes);
DONE:
for (int i = 0; i < nodes.size(); i++) {
AmzaNode a = nodes.get(i);
for (int j = 0; j < nodes.size(); j++) {
if (i == j) {
continue;
}
AmzaNode b = nodes.get(j);
if (!a.compare(Consistency.quorum, b)) {
System.out.println(a + " is NOT consistent with " + b);
falseCount++;
break DONE;
}
System.out.println(a + " is consistent with " + b);
}
}
if (falseCount > 0) {
Thread.sleep(1000);
System.out.println("---------------------------------------------------------------------\n\n\n\n");
}
}
for (AmzaNode a : clusterNodes) {
Assert.assertFalse(a.isEmpty());
}
System.out.println("\n------stopping---------");
for (AmzaNode a : clusterNodes) {
a.stop();
}
System.out.println("\n------PASSED :) ---------");
}
private void testRowType(AmzaTestCluster cluster, int maxNumberOfServices, PartitionName partitionName, RowType rowType) throws Exception {
final int maxUpdates = 100;
final int delayBetweenUpdates = 0;
final int maxFields = 10;
final int maxOffServices = 0;
final int maxRemovedServices = 0;
final int maxAddService = 0;
final Random random = new Random();
final CountDownLatch latch = new CountDownLatch(1);
Executors.newCachedThreadPool().submit(new Runnable() {
int removeService = maxRemovedServices;
int addService = maxAddService;
int offService = maxOffServices;
@Override
public void run() {
for (int i = 0; i < maxUpdates; i++) {
AmzaNode node = cluster.get(new RingMember("localhost-" + random.nextInt(maxNumberOfServices)));
try {
if (node != null) {
node.create(Consistency.quorum, partitionName, "memory_persistent", -1, RowType.primary);
boolean tombstone = random.nextBoolean();
String prefix = "a";
String key = String.valueOf(random.nextInt(maxFields));
byte[] indexPrefix = prefix.getBytes();
byte[] indexKey = key.getBytes();
node.update(Consistency.quorum, partitionName, indexPrefix, indexKey, ("" + random.nextInt()).getBytes(), tombstone);
Thread.sleep(delayBetweenUpdates);
node.get(Consistency.quorum, partitionName, indexPrefix, indexKey);
}
} catch (Exception x) {
System.out.println("Failed to update node: " + node);
x.printStackTrace();
}
if (removeService > 0) {
RingMember key = new RingMember("localhost-" + random.nextInt(maxNumberOfServices));
node = cluster.get(key);
try {
if (node != null) {
System.out.println("Removing node:" + key);
cluster.remove(key);
node.stop();
removeService--;
}
} catch (Exception x) {
System.out.println("Failed to remove node: " + node);
x.printStackTrace();
}
}
if (addService > 0) {
int port = maxNumberOfServices + random.nextInt(maxAddService);
RingMember key = new RingMember("localhost-" + port);
node = cluster.get(key);
try {
if (node == null) {
cluster.newNode(new RingMember("localhost-" + port), new RingHost("datacenter", "rack", "localhost", port));
addService--;
}
} catch (Exception x) {
System.out.println("Failed to add node: " + key);
x.printStackTrace();
}
}
if (offService > 0) {
RingMember key = new RingMember("localhost-" + random.nextInt(maxNumberOfServices));
node = cluster.get(key);
try {
if (node != null) {
node.setOff(!node.isOff());
offService--;
}
} catch (Exception x) {
System.out.println(x.getMessage());
}
}
}
latch.countDown();
}
});
latch.await();
}
}