/*
* Copyright 2013 LinkedIn, 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 voldemort.utils;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import voldemort.TestUtils;
import voldemort.client.protocol.admin.AdminClient;
import voldemort.client.protocol.admin.QueryKeyResult;
import voldemort.store.routed.NodeValue;
import voldemort.utils.ConsistencyFix.BadKey;
import voldemort.versioning.Versioned;
public class ConsistencyFixWorkerTest {
public void testRepair(int putNodes[], boolean orphan) {
byte[] bKey = TestUtils.randomBytes(10);
String hexKey = ByteUtils.toHexString(bKey);
ByteArray baKey = new ByteArray(bKey);
BadKey badKey;
QueryKeyResult queryKeyResult;
if(!orphan) {
badKey = new BadKey(hexKey, hexKey + "\n");
queryKeyResult = null;
} else {
StringBuilder orphanInput = new StringBuilder();
orphanInput.append(hexKey + "," + "1\n");
List<Versioned<byte[]>> values = new ArrayList<Versioned<byte[]>>(0);
int arbitraryNodeId = 2;
Versioned<byte[]> versioned = TestUtils.getVersioned(TestUtils.randomBytes(25),
arbitraryNodeId);
orphanInput.append(ByteUtils.toHexString(versioned.getValue()));
orphanInput.append("," + versioned.toString() + "\n");
values.add(versioned);
badKey = new BadKey(hexKey, orphanInput.toString());
queryKeyResult = new QueryKeyResult(baKey, values);
}
Versioned<byte[]> value = TestUtils.getVersioned(TestUtils.randomBytes(25), 0);
String url = ConsistencyFixTest.setUpCluster();
ConsistencyFix consistencyFix = new ConsistencyFix(url,
ConsistencyFixTest.STORE_NAME,
100,
100,
false,
false);
AdminClient adminClient = consistencyFix.getAdminClient();
System.out.println("Initial get");
for(int i = 0; i < 4; ++i) {
List<Versioned<byte[]>> results;
results = adminClient.storeOps.getNodeKey(ConsistencyFixTest.STORE_NAME, i, baKey);
assertTrue(results.size() == 0);
}
System.out.println("Puts");
for(int putNode: putNodes) {
NodeValue<ByteArray, byte[]> nodeKeyValue;
nodeKeyValue = new NodeValue<ByteArray, byte[]>(putNode, baKey, value);
adminClient.storeOps.putNodeKeyValue(ConsistencyFixTest.STORE_NAME, nodeKeyValue);
}
// Construct normal consistency fix worker
ConsistencyFixWorker consistencyFixWorker = null;
if(!orphan) {
consistencyFixWorker = new ConsistencyFixWorker(badKey, consistencyFix, null);
} else {
consistencyFixWorker = new ConsistencyFixWorker(badKey,
consistencyFix,
null,
queryKeyResult);
}
consistencyFixWorker.run();
System.out.println("Second get");
int expectedNumVersions = 0;
if(putNodes.length > 0) {
expectedNumVersions++;
}
if(orphan) {
expectedNumVersions++;
}
for(int i = 0; i < 4; ++i) {
System.out.println("Node : " + i);
List<Versioned<byte[]>> results;
results = adminClient.storeOps.getNodeKey(ConsistencyFixTest.STORE_NAME, i, baKey);
for(Versioned<byte[]> v: results) {
System.out.println("\t" + v.getVersion());
}
assertTrue(results.size() == expectedNumVersions);
}
}
@Test
public void repairPutOne() {
int putNodes[] = { 1 };
testRepair(putNodes, false);
}
@Test
public void repairPutTwo() {
int putNodes[] = { 0, 3 };
testRepair(putNodes, false);
}
@Test
public void repairPutThree() {
int putNodes[] = { 1, 2, 3 };
testRepair(putNodes, false);
}
@Test
public void repairPutFour() {
int putNodes[] = { 0, 1, 2, 3 };
testRepair(putNodes, false);
}
@Test
public void repairPutZero() {
int putNodes[] = {};
testRepair(putNodes, false);
}
@Test
public void orphanPutOne() {
int putNodes[] = { 1 };
testRepair(putNodes, true);
}
@Test
public void orphanPutTwo() {
int putNodes[] = { 0, 3 };
testRepair(putNodes, true);
}
@Test
public void orphanPutThree() {
int putNodes[] = { 1, 2, 3 };
testRepair(putNodes, true);
}
@Test
public void orphanPutFour() {
int putNodes[] = { 0, 1, 2, 3 };
testRepair(putNodes, true);
}
@Test
public void orphanPutZero() {
int putNodes[] = {};
testRepair(putNodes, true);
}
}