/*
* Copyright 2008-2009 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.store.configuration;
import static voldemort.TestUtils.getClock;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileDeleteStrategy;
import org.junit.Test;
import voldemort.TestUtils;
import voldemort.VoldemortException;
import voldemort.store.AbstractStoreTest;
import voldemort.store.Store;
import voldemort.utils.ByteArray;
import voldemort.versioning.VectorClock;
import voldemort.versioning.Versioned;
/**
* A testclass for verifying the FileBackedCachingStorageEngine
*
* @author csoman
*
*/
public class FileBackedCachingStorageEngineTest extends
AbstractStoreTest<ByteArray, byte[], byte[]> {
private File tempDir;
@Override
public void setUp() throws Exception {
super.setUp();
if(null != tempDir && tempDir.exists())
FileDeleteStrategy.FORCE.delete(tempDir);
}
@Override
public void tearDown() throws Exception {
super.tearDown();
if(null != tempDir && tempDir.exists())
FileDeleteStrategy.FORCE.delete(tempDir);
}
/*
* Calling getStrings to make it readable (easier debugging)
*/
@Override
public List<ByteArray> getKeys(int numKeys) {
List<String> keyList = getStrings(numKeys, 10);
List<ByteArray> byteArrayKeyList = new ArrayList<ByteArray>();
for(String s: keyList) {
byteArrayKeyList.add(new ByteArray(s.getBytes()));
}
return byteArrayKeyList;
}
@Override
public Store<ByteArray, byte[], byte[]> getStore() {
if(null == tempDir || !tempDir.exists()) {
tempDir = TestUtils.createTempDir();
}
return new FileBackedCachingStorageEngine("file-backed-test", tempDir.getAbsolutePath());
}
@Override
protected boolean allowConcurrentOperations() {
return false;
}
@Override
protected boolean valuesEqual(byte[] t1, byte[] t2) {
return Arrays.equals(t1, t2);
}
@Override
public List<byte[]> getValues(int numValues) {
List<String> keyList = getStrings(numValues, 10);
List<byte[]> byteArrayKeyList = new ArrayList<byte[]>();
for(String s: keyList) {
byteArrayKeyList.add(s.getBytes());
}
return byteArrayKeyList;
}
@Override
public void testDelete() {
ByteArray key = getKey();
Store<ByteArray, byte[], byte[]> store = getStore();
VectorClock c1 = getClock(1, 1);
byte[] value = getValue();
// can't delete something that isn't there
assertTrue(!store.delete(key, c1));
store.put(key, new Versioned<byte[]>(value, c1), null);
assertEquals(1, store.get(key, null).size());
// now delete that version too
assertTrue("Delete failed!", store.delete(key, c1));
assertEquals(0, store.get(key, null).size());
}
@Override
@Test
public void testGetAll() throws Exception {
Store<ByteArray, byte[], byte[]> store = getStore();
int putCount = 10;
List<ByteArray> keys = getKeys(putCount);
List<byte[]> values = getValues(putCount);
assertEquals(putCount, values.size());
VectorClock clock = new VectorClock();
for(int i = 0; i < putCount; i++) {
store.put(keys.get(i), new Versioned<byte[]>(values.get(i), clock), null);
clock = clock.incremented(0, System.currentTimeMillis());
}
int countForGet = putCount / 2;
List<ByteArray> keysForGet = keys.subList(0, countForGet);
List<byte[]> valuesForGet = values.subList(0, countForGet);
Map<ByteArray, List<Versioned<byte[]>>> result = store.getAll(keysForGet, null);
assertGetAllValues(keysForGet, valuesForGet, result);
}
@Test
public void testConcurrentWriteFailure() {
ByteArray key = getKey();
Store<ByteArray, byte[], byte[]> store = getStore();
VectorClock c1 = getClock(1, 1);
VectorClock c2 = getClock(1, 2);
byte[] value = getValue();
// put two conflicting versions, then delete one
Versioned<byte[]> v1 = new Versioned<byte[]>(value, c1);
Versioned<byte[]> v2 = new Versioned<byte[]>(value, c2);
store.put(key, v1, null);
try {
store.put(key, v2, null);
fail("Concurrent write succeeded in FileBackedCachingStorageEngine. Should not be allowed.");
} catch(VoldemortException ve) {
// This is OK
}
}
}