package voldemort.store.readonly;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.log4j.Logger;
import org.junit.After;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import voldemort.Attempt;
import voldemort.ServerTestUtils;
import voldemort.TestUtils;
import voldemort.VoldemortException;
import voldemort.cluster.Cluster;
import voldemort.cluster.Node;
import voldemort.routing.RoutingStrategy;
import voldemort.routing.RoutingStrategyFactory;
import voldemort.routing.RoutingStrategyType;
import voldemort.serialization.Compression;
import voldemort.serialization.DefaultSerializerFactory;
import voldemort.serialization.Serializer;
import voldemort.serialization.SerializerDefinition;
import voldemort.serialization.SerializerFactory;
import voldemort.store.Store;
import voldemort.store.StoreDefinition;
import voldemort.utils.ByteArray;
import voldemort.utils.ClosableIterator;
import voldemort.utils.Pair;
import voldemort.utils.Utils;
import voldemort.versioning.Versioned;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
@RunWith(Parameterized.class)
public class ReadOnlyStorageEngineTest {
private static final Logger logger = Logger.getLogger(ReadOnlyStorageEngineTest.class);
private static int TOTAL_NUMBER_OF_RECORDS = 100;
private static int PARTITIONS_PER_NODE = 5;
private static int[][] complexPartitionMap = {
{7, 24, 41, 45, 46}, // Node 0
{2, 10, 15, 23, 38}, // Node 1
{4, 13, 32, 33, 44}, // Node 2
{11, 19, 27, 31, 40}, // Node 3
{9, 17, 22, 25, 39}, // Node 4
{12, 34, 35, 37, 48}, // Node 5
{0, 16, 29, 36, 49}, // Node 6
{1, 18, 20, 43, 47}, // Node 7
{5, 6, 14, 21, 30}, // Node 8
{3, 8, 26, 28, 42} // Node 9
};
@Parameters
public static Collection<Object[]> configs() {
return Arrays.asList(new Object[][] {
// Replication factor 1, 1 node, simple partition assignment
{ new BinarySearchStrategy(), ReadOnlyStorageFormat.READONLY_V0, 1, 1, null },
{ new InterpolationSearchStrategy(), ReadOnlyStorageFormat.READONLY_V0, 1, 1, null },
{ new BinarySearchStrategy(), ReadOnlyStorageFormat.READONLY_V1, 1, 1, null },
{ new InterpolationSearchStrategy(), ReadOnlyStorageFormat.READONLY_V1, 1, 1, null },
{ new BinarySearchStrategy(), ReadOnlyStorageFormat.READONLY_V2, 1, 1, null },
{ new InterpolationSearchStrategy(), ReadOnlyStorageFormat.READONLY_V2, 1, 1, null },
// Replication factor 2, 10 nodes, simple partition assignment
{ new BinarySearchStrategy(), ReadOnlyStorageFormat.READONLY_V0, 2, 10, null },
{ new InterpolationSearchStrategy(), ReadOnlyStorageFormat.READONLY_V0, 2, 10, null },
{ new BinarySearchStrategy(), ReadOnlyStorageFormat.READONLY_V1, 2, 10, null },
{ new InterpolationSearchStrategy(), ReadOnlyStorageFormat.READONLY_V1, 2, 10, null },
{ new BinarySearchStrategy(), ReadOnlyStorageFormat.READONLY_V2, 2, 10, null },
{ new InterpolationSearchStrategy(), ReadOnlyStorageFormat.READONLY_V2, 2, 10, null },
// Replication factor 2, 10 nodes, complex partition assignment
{ new BinarySearchStrategy(), ReadOnlyStorageFormat.READONLY_V0, 2, 10, complexPartitionMap },
{ new InterpolationSearchStrategy(), ReadOnlyStorageFormat.READONLY_V0, 2, 10, complexPartitionMap },
{ new BinarySearchStrategy(), ReadOnlyStorageFormat.READONLY_V1, 2, 10, complexPartitionMap },
{ new InterpolationSearchStrategy(), ReadOnlyStorageFormat.READONLY_V1, 2, 10, complexPartitionMap },
{ new BinarySearchStrategy(), ReadOnlyStorageFormat.READONLY_V2, 2, 10, complexPartitionMap },
{ new InterpolationSearchStrategy(), ReadOnlyStorageFormat.READONLY_V2, 2, 10, complexPartitionMap }
});
}
private File dir;
private SearchStrategy strategy;
private SerializerDefinition serDef;
private SerializerDefinition lzfSerDef;
private StoreDefinition storeDef;
private Node node;
private RoutingStrategy routingStrategy;
private ReadOnlyStorageFormat storageType;
private int indexEntrySize, replicationFactor, numberOfNodes;
private int[][] partitionMap;
public ReadOnlyStorageEngineTest(SearchStrategy strategy,
ReadOnlyStorageFormat storageType,
int replicationFactor,
int numberOfNodes,
int[][] partitionMap) {
this.strategy = strategy;
this.replicationFactor = replicationFactor;
this.numberOfNodes = numberOfNodes;
this.dir = TestUtils.createTempDir();
logger.info("temp dir: " + dir);
this.serDef = new SerializerDefinition("json", "'string'");
this.lzfSerDef = new SerializerDefinition("json",
ImmutableMap.of(0, "'string'"),
true,
new Compression("lzf", null));
this.storeDef = ServerTestUtils.getStoreDef("test",
replicationFactor,
1,
1,
1,
1,
RoutingStrategyType.CONSISTENT_STRATEGY);
if (partitionMap == null) {
this.partitionMap = new int[numberOfNodes][PARTITIONS_PER_NODE];
for (int nodeId = 0; nodeId < numberOfNodes; nodeId++) {
for (int partition = 0; partition < PARTITIONS_PER_NODE; partition++) {
this.partitionMap[nodeId][partition] = nodeId + numberOfNodes * partition;
}
}
} else {
this.partitionMap = partitionMap;
}
Cluster cluster = ServerTestUtils.getLocalCluster(numberOfNodes, this.partitionMap);
this.node = cluster.getNodeById(0);
this.storageType = storageType;
switch(this.storageType) {
case READONLY_V0:
case READONLY_V1:
// 16 (md5) + 4 (position)
this.indexEntrySize = 20;
break;
case READONLY_V2:
// 8 (upper 8 bytes of md5) + 4 (position)
this.indexEntrySize = 12;
break;
default:
throw new VoldemortException("Unsupported storage format type");
}
this.routingStrategy = new RoutingStrategyFactory().updateRoutingStrategy(storeDef, cluster);
}
@After
public void tearDown() {
if(dir != null) {
Utils.rm(dir);
}
}
/**
* For each key/value pair we built into the store, look it up and test that
* the correct value is returned
*/
private void canGetGoodRecords(ReadOnlyStorageEngineTestInstance testData) throws Exception {
// run test multiple times to check caching
// ^ What's the point of doing this? - FGV
for(int i = 0; i < 3; i++) {
for(Map.Entry<String, String> entry: testData.getData().entrySet()) {
for(Node node: testData.routeRequest(entry.getKey())) {
Store<String, String, String> store = testData.getNodeStores()
.get(node.getId());
List<Versioned<String>> found = store.get(entry.getKey(), null);
assertEquals("Lookup failure for '" + entry.getKey() + "' on iteration " + i
+ " for node " + node.getId() + ".", 1, found.size());
Versioned<String> obj = found.get(0);
assertEquals(entry.getValue(), obj.getValue());
}
}
}
testData.delete();
}
@Test
public void canGetGoodValues() throws Exception {
ReadOnlyStorageEngineTestInstance testData = ReadOnlyStorageEngineTestInstance.create(strategy,
dir,
TOTAL_NUMBER_OF_RECORDS,
numberOfNodes,
replicationFactor,
serDef,
serDef,
storageType,
partitionMap);
canGetGoodRecords(testData);
}
@Test
public void canGetGoodCompressedValues() throws Exception {
ReadOnlyStorageEngineTestInstance testData = ReadOnlyStorageEngineTestInstance.create(strategy,
dir,
TOTAL_NUMBER_OF_RECORDS,
numberOfNodes,
replicationFactor,
serDef,
lzfSerDef,
storageType,
partitionMap);
canGetGoodRecords(testData);
}
/**
* Disabled because Voldemort Build and Push does not support building stores with compressed keys.
*
* This test can be re-enabled if support is added later.
*/
@Test
@Ignore
public void canGetGoodCompressedKeys() throws Exception {
ReadOnlyStorageEngineTestInstance testData = ReadOnlyStorageEngineTestInstance.create(strategy,
dir,
TOTAL_NUMBER_OF_RECORDS,
numberOfNodes,
replicationFactor,
lzfSerDef,
serDef,
storageType,
partitionMap);
canGetGoodRecords(testData);
}
/**
* Do lookups on keys not in the store and test that the keys are not found.
*/
@Test
public void cantGetBadValues() throws Exception {
ReadOnlyStorageEngineTestInstance testData = ReadOnlyStorageEngineTestInstance.create(strategy,
dir,
TOTAL_NUMBER_OF_RECORDS,
numberOfNodes,
replicationFactor,
serDef,
serDef,
storageType,
partitionMap);
// run test multiple times to check caching
for(int i = 0; i < 3; i++) {
for(int j = 0; j < TOTAL_NUMBER_OF_RECORDS; j++) {
String key = TestUtils.randomLetters(10);
if(!testData.getData().containsKey(key)) {
for(int k = 0; k < testData.getNodeStores().size(); k++)
assertEquals("Found key in store where it should not be.",
0,
testData.getNodeStores().get(k).get(key, null).size());
}
}
}
testData.delete();
}
@Test
public void canMultigetGoodValues() throws Exception {
ReadOnlyStorageEngineTestInstance testData = ReadOnlyStorageEngineTestInstance.create(strategy,
dir,
TOTAL_NUMBER_OF_RECORDS,
numberOfNodes,
replicationFactor,
serDef,
serDef,
storageType,
partitionMap);
Set<String> keys = testData.getData().keySet();
Set<String> gotten = new HashSet<String>();
for(Map.Entry<Integer, Store<String, String, String>> entry: testData.getNodeStores()
.entrySet()) {
Set<String> queryKeys = new HashSet<String>();
for(String key: keys)
for(Node node: testData.routeRequest(key))
if(Integer.valueOf(node.getId()).equals(entry.getKey()))
queryKeys.add(key);
Map<String, List<Versioned<String>>> values = entry.getValue().getAll(queryKeys, null);
assertEquals("Returned fewer keys than expected.", queryKeys.size(), values.size());
for(Map.Entry<String, List<Versioned<String>>> returned: values.entrySet()) {
assertTrue(queryKeys.contains(returned.getKey()));
assertEquals(1, returned.getValue().size());
Versioned<String> val = returned.getValue().get(0);
assertEquals(testData.getData().get(returned.getKey()), val.getValue());
gotten.add(returned.getKey());
}
}
assertEquals(keys, gotten);
testData.delete();
}
@Test
public void openInvalidStoreFails() throws Exception {
// empty is okay
testOpenInvalidStoreFails(0, 0, true);
// two entries with 1 byte each of data
testOpenInvalidStoreFails(this.indexEntrySize * 2, this.indexEntrySize * +2, true);
// okay these are corrupt:
// invalid index size
testOpenInvalidStoreFails(73, 1024, false);
// too little data for index (1 byte short for all empty values)
testOpenInvalidStoreFails(this.indexEntrySize * 10, 10 * 4 - 1, false);
// empty index implies no data
testOpenInvalidStoreFails(this.indexEntrySize, 0, false);
}
public void testOpenInvalidStoreFails(int indexBytes, int dataBytes, boolean shouldWork)
throws Exception {
File versionDir = new File(dir, "version-0");
createStoreFiles(versionDir, indexBytes, dataBytes, node, 2);
try {
new ReadOnlyStorageEngine("test", strategy, routingStrategy, 0, dir, 1);
if(!shouldWork)
fail("Able to open corrupt read-only store (index size = " + indexBytes
+ ", data bytes = " + dataBytes + ").");
} catch(VoldemortException e) {
if(shouldWork)
fail("Unexpected failure:" + e.getMessage());
}
}
@Test
public void testSwap() throws Exception {
File versionDir = new File(dir, "version-0");
createStoreFiles(versionDir, this.indexEntrySize * 5, 4 * 5 * 10, this.node, 2);
ReadOnlyStorageEngine engine = new ReadOnlyStorageEngine("test",
strategy,
routingStrategy,
0,
dir,
2);
assertVersionsExist(dir, 0);
// swap to a new version with latest present
File newDirv1 = new File(dir, "version-1");
createStoreFiles(newDirv1, 0, 0, this.node, 2);
engine.swapFiles(newDirv1.getAbsolutePath());
assertVersionsExist(dir, 0, 1);
// swap to a new version with no latest present
File latestSymLink = new File(dir, "latest");
latestSymLink.delete();
File newDirv2 = new File(dir, "version-2");
createStoreFiles(newDirv2, 0, 0, this.node, 2);
engine.swapFiles(newDirv2.getAbsolutePath());
assertVersionsExist(dir, 0, 1, 2);
// rollback
engine.rollback(versionDir);
TestUtils.assertWithBackoff(100, 5000, new Attempt() {
public void checkCondition() throws Exception, AssertionError {
assertVersionsExist(dir, 0);
}
});
// test initial open without latest
engine.close();
latestSymLink.delete();
File newDirv100 = new File(dir, "version-100");
createStoreFiles(newDirv100, 0, 0, this.node, 2);
File newDirv534 = new File(dir, "version-534");
createStoreFiles(newDirv534, 0, 0, this.node, 2);
engine.open(null);
assertTrue(latestSymLink.getCanonicalPath().contains("version-534"));
engine.close();
// test initial open with latest pointing at intermediate version folder
Utils.symlink(newDirv100.getAbsolutePath(), latestSymLink.getAbsolutePath());
engine.open(null);
}
@Test
public void testNodeNotInRoutingStrategy() throws IOException {
File versionDir = new File(dir, "version-0");
createStoreFiles(versionDir, this.indexEntrySize * 5, 4 * 5 * 10, this.node, 2);
ReadOnlyStorageEngine engine = new ReadOnlyStorageEngine("test",
strategy,
routingStrategy,
1,
dir,
2);
// should not have exceptions
engine.get(new ByteArray("ab".getBytes()), null);
}
@Test
public void testSwapRollbackFail() throws IOException {
ReadOnlyStorageEngine engine = new ReadOnlyStorageEngine("test",
strategy,
routingStrategy,
0,
dir,
1);
assertVersionsExist(dir, 0);
// try to rollback nothing
try {
engine.rollback((File) null);
fail("Should have thrown an exception since null is passed");
} catch(VoldemortException e) {}
// try to rollback nothing
engine.rollback(new File(dir, "version-0"));
// swap to a new version
File newDir = new File(dir, "version-100");
createStoreFiles(newDir, 0, 0, node, 2);
engine.swapFiles(newDir.getAbsolutePath());
assertVersionsExist(dir, 0, 100);
// try to swap to a version with version-id less than current max
File newDir2 = new File(dir, "version-99");
createStoreFiles(newDir2, 0, 0, node, 2);
engine.swapFiles(newDir2.getAbsolutePath());
// try to swap a version with wrong name format
File newDir3 = new File(dir, "version-1a3");
createStoreFiles(newDir3, 0, 0, node, 2);
try {
engine.swapFiles(newDir3.getAbsolutePath());
fail("Should have thrown an exception since version directory name format is incorrect");
} catch(VoldemortException e) {}
}
@Test
public void testBadSwapNameThrows() throws IOException {
File versionDir = new File(dir, "version-0");
createStoreFiles(versionDir, this.indexEntrySize * 5, 4 * 5 * 10, node, 2);
ReadOnlyStorageEngine engine = new ReadOnlyStorageEngine("test",
strategy,
routingStrategy,
0,
dir,
2);
assertVersionsExist(dir, 0);
// swap to a directory with an incorrect parent directory
File newDir = TestUtils.createTempDir();
createStoreFiles(newDir, 73, 1024, node, 2);
try {
engine.swapFiles(newDir.getAbsolutePath());
fail("Swap files should have failed since parent directory is incorrect");
} catch(VoldemortException e) {}
// swap to a directory with incorrect name
newDir = new File(dir, "blah");
createStoreFiles(newDir, 73, 1024, node, 2);
try {
engine.swapFiles(newDir.getAbsolutePath());
fail("Swap files should have failed since name is incorrect");
} catch(VoldemortException e) {}
}
@Test
public void testBackupLogic() throws Exception {
File dirv0 = new File(dir, "version-0");
createStoreFiles(dirv0, this.indexEntrySize * 5, 4 * 5 * 10, node, 2);
ReadOnlyStorageEngine engine = new ReadOnlyStorageEngine("test",
strategy,
routingStrategy,
0,
dir,
0);
assertVersionsExist(dir, 0);
// create directory to imitate a fetch state happening concurrently
// with swap
File dirv2 = new File(dir, "version-2");
createStoreFiles(dirv2, this.indexEntrySize * 5, 4 * 5 * 10, node, 2);
// swap in directory 1
File dirv1 = new File(dir, "version-1");
createStoreFiles(dirv1, this.indexEntrySize * 5, 4 * 5 * 10, node, 2);
engine.swapFiles(dirv1.getAbsolutePath());
// check latest symbolic link exists
File latest = new File(dir, "latest");
assertTrue(latest.exists());
// ...and points to 1
assertTrue(latest.getCanonicalPath().contains("version-1"));
// ...and version-2 is still in fetch state. Assert with backoff since
// delete may take time
TestUtils.assertWithBackoff(100, 5000, new Attempt() {
public void checkCondition() throws Exception, AssertionError {
assertEquals(ReadOnlyUtils.getVersionDirs(dir).length, 2);
}
});
}
@Test(expected = VoldemortException.class)
public void testBadSwapDataThrows() throws IOException {
File versionDir = new File(dir, "version-0");
createStoreFiles(versionDir, this.indexEntrySize * 5, 4 * 5 * 10, node, 2);
ReadOnlyStorageEngine engine = new ReadOnlyStorageEngine("test",
strategy,
routingStrategy,
0,
dir,
2);
assertVersionsExist(dir, 0);
// swap to a directory with bad data, rollback should kick-in
File newDir = new File(dir, "version-1");
createStoreFiles(newDir, 73, 1024, node, 2);
engine.swapFiles(newDir.getAbsolutePath());
}
@Test
public void testReadAfterTruncate() throws Exception {
ReadOnlyStorageEngineTestInstance testData = ReadOnlyStorageEngineTestInstance.create(strategy,
dir,
TOTAL_NUMBER_OF_RECORDS,
numberOfNodes,
replicationFactor,
serDef,
serDef,
storageType,
partitionMap);
for(Map.Entry<Integer, ReadOnlyStorageEngine> engine: testData.getReadOnlyStores()
.entrySet()) {
engine.getValue().truncate();
}
for(Map.Entry<String, String> entry: testData.getData().entrySet()) {
for(Node node: testData.routeRequest(entry.getKey())) {
Store<String, String, String> store = testData.getNodeStores().get(node.getId());
List<Versioned<String>> found = store.get(entry.getKey(), null);
assertEquals(found.size(), 0);
}
}
Set<String> keys = testData.getData().keySet();
for(Map.Entry<Integer, Store<String, String, String>> entry: testData.getNodeStores()
.entrySet()) {
Map<String, List<Versioned<String>>> getAllValues = entry.getValue().getAll(keys, null);
assertEquals(getAllValues.size(), 0);
}
testData.delete();
}
@Test
public void testTruncate() throws IOException {
createStoreFiles(dir, this.indexEntrySize * 5, 4 * 5 * 10, node, 2);
ReadOnlyStorageEngine engine = new ReadOnlyStorageEngine("test",
strategy,
routingStrategy,
0,
dir,
2);
assertVersionsExist(dir, 0);
engine.truncate();
assertEquals(dir.exists(), false);
}
@SuppressWarnings("unchecked")
@Test
public void testIteration() throws Exception {
ReadOnlyStorageEngineTestInstance testData = ReadOnlyStorageEngineTestInstance.create(strategy,
dir,
TOTAL_NUMBER_OF_RECORDS,
numberOfNodes,
replicationFactor,
serDef,
serDef,
storageType,
partitionMap);
ListMultimap<Integer, Pair<String, String>> nodeToEntries = ArrayListMultimap.create();
for(Map.Entry<String, String> entry: testData.getData().entrySet()) {
for(Node node: testData.routeRequest(entry.getKey())) {
nodeToEntries.put(node.getId(), Pair.create(entry.getKey(), entry.getValue()));
}
}
SerializerFactory factory = new DefaultSerializerFactory();
Serializer<String> serializer = (Serializer<String>) factory.getSerializer(serDef);
for(Map.Entry<Integer, ReadOnlyStorageEngine> storeEntry: testData.getReadOnlyStores()
.entrySet()) {
List<Pair<String, String>> entries = Lists.newArrayList(nodeToEntries.get(storeEntry.getKey()));
ClosableIterator<ByteArray> keyIterator = null;
ClosableIterator<Pair<ByteArray, Versioned<byte[]>>> entryIterator = null;
try {
keyIterator = storeEntry.getValue().keys();
entryIterator = storeEntry.getValue().entries();
} catch(Exception e) {
if(storageType.compareTo(ReadOnlyStorageFormat.READONLY_V2) == 0) {
fail("Should not have thrown exception since this version supports iteration");
} else {
return;
}
}
// Generate keys from entries
List<String> keys = Lists.newArrayList();
Iterator<Pair<String, String>> pairIterator = entries.iterator();
while(pairIterator.hasNext()) {
keys.add(pairIterator.next().getFirst());
}
// Test keys
int keyCount = 0;
while(keyIterator.hasNext()) {
String key = serializer.toObject(keyIterator.next().get());
Assert.assertEquals(keys.contains(key), true);
keyCount++;
}
Assert.assertEquals(keyCount, entries.size());
// Test entries
int entriesCount = 0;
while(entryIterator.hasNext()) {
Pair<ByteArray, Versioned<byte[]>> entry = entryIterator.next();
Pair<String, String> stringEntry = Pair.create(serializer.toObject(entry.getFirst()
.get()),
serializer.toObject(entry.getSecond()
.getValue()));
Assert.assertEquals(entries.contains(stringEntry), true);
entriesCount++;
}
Assert.assertEquals(entriesCount, entries.size());
}
}
private void assertVersionsExist(File dir, int... versions) throws IOException {
int max = 0;
for(int i = 0; i < versions.length; i++) {
File versionDir = new File(dir, "version-" + versions[i]);
if(versions[i] > max)
max = versions[i];
assertTrue("Could not find " + dir + "/version-" + versions[i], versionDir.exists());
}
// check latest symbolic link exists
File latest = new File(dir, "latest");
assertTrue(latest.exists());
// ...and points to max
assertTrue(latest.getCanonicalPath().contains("version-" + max));
// now check that the next higher version does not exist
File versionDir = new File(dir, "version-" + versions.length);
assertFalse("Found version directory that should not exist.", versionDir.exists());
}
private void createStoreFiles(File dir, int indexBytes, int dataBytes, Node node, int numChunks)
throws IOException, FileNotFoundException {
ReadOnlyStorageMetadata metadata = new ReadOnlyStorageMetadata();
metadata.add(ReadOnlyStorageMetadata.FORMAT, storageType.getCode());
File metadataFile = createFile(dir, ".metadata");
BufferedWriter writer = new BufferedWriter(new FileWriter(metadataFile));
writer.write(metadata.toJsonString());
writer.close();
switch(storageType) {
case READONLY_V0: {
for(int chunk = 0; chunk < numChunks; chunk++) {
File index = createFile(dir, chunk + ".index");
File data = createFile(dir, chunk + ".data");
// write some random crap for index and data
FileOutputStream dataOs = new FileOutputStream(data);
for(int i = 0; i < dataBytes; i++)
dataOs.write(i);
dataOs.close();
FileOutputStream indexOs = new FileOutputStream(index);
for(int i = 0; i < indexBytes; i++)
indexOs.write(i);
indexOs.close();
}
}
break;
case READONLY_V1: {
for(Integer partitionId: node.getPartitionIds()) {
for(int chunkId = 0; chunkId < numChunks; chunkId++) {
File index = createFile(dir,
Integer.toString(partitionId) + "_"
+ Integer.toString(chunkId) + ".index");
File data = createFile(dir,
Integer.toString(partitionId) + "_"
+ Integer.toString(chunkId) + ".data");
// write some random crap for index and data
FileOutputStream dataOs = new FileOutputStream(data);
for(int i = 0; i < dataBytes; i++)
dataOs.write(i);
dataOs.close();
FileOutputStream indexOs = new FileOutputStream(index);
for(int i = 0; i < indexBytes; i++)
indexOs.write(i);
indexOs.close();
}
}
}
break;
case READONLY_V2: {
// Assuming number of replicas = 1, since all these tests use a
// store with replication factor of 1
for(Integer partitionId: node.getPartitionIds()) {
for(int chunkId = 0; chunkId < numChunks; chunkId++) {
File index = createFile(dir, Integer.toString(partitionId) + "_0_"
+ Integer.toString(chunkId) + ".index");
File data = createFile(dir,
Integer.toString(partitionId) + "_0_"
+ Integer.toString(chunkId) + ".data");
// write some random crap for index and data
FileOutputStream dataOs = new FileOutputStream(data);
for(int i = 0; i < dataBytes; i++)
dataOs.write(i);
dataOs.close();
FileOutputStream indexOs = new FileOutputStream(index);
for(int i = 0; i < indexBytes; i++)
indexOs.write(i);
indexOs.close();
}
}
}
break;
default:
throw new VoldemortException("Do not support storage type " + storageType);
}
}
private File createFile(File dir, String name) throws IOException {
dir.mkdirs();
File data = new File(dir, name);
data.createNewFile();
return data;
}
}