use of voldemort.versioning.ObsoleteVersionException in project voldemort by voldemort.
the class BdbStorageEngine method put.
@Override
public void put(ByteArray key, Versioned<byte[]> value, byte[] transforms) throws PersistenceFailureException {
long startTimeNs = -1;
if (logger.isTraceEnabled())
startTimeNs = System.nanoTime();
StoreUtils.assertValidKey(key);
DatabaseEntry keyEntry = new DatabaseEntry(key.get());
DatabaseEntry valueEntry = new DatabaseEntry();
boolean succeeded = false;
Transaction transaction = null;
List<Versioned<byte[]>> vals = null;
try {
transaction = environment.beginTransaction(null, null);
// do a get for the existing values
OperationStatus status = getBdbDatabase().get(transaction, keyEntry, valueEntry, LockMode.RMW);
if (OperationStatus.SUCCESS == status) {
// update
vals = StoreBinaryFormat.fromByteArray(valueEntry.getData());
// compare vector clocks and throw out old ones, for updates
Iterator<Versioned<byte[]>> iter = vals.iterator();
while (iter.hasNext()) {
Versioned<byte[]> curr = iter.next();
Occurred occurred = value.getVersion().compare(curr.getVersion());
if (occurred == Occurred.BEFORE)
throw new ObsoleteVersionException("Key " + new String(hexCodec.encode(key.get())) + " " + value.getVersion().toString() + " is obsolete, it is no greater than the current version of " + curr.getVersion().toString() + ".");
else if (occurred == Occurred.AFTER)
iter.remove();
}
} else {
// insert
vals = new ArrayList<Versioned<byte[]>>(1);
}
// update the new value
vals.add(value);
valueEntry.setData(StoreBinaryFormat.toByteArray(vals));
status = getBdbDatabase().put(transaction, keyEntry, valueEntry);
if (status != OperationStatus.SUCCESS)
throw new PersistenceFailureException("Put operation failed with status: " + status);
succeeded = true;
} catch (DatabaseException e) {
this.bdbEnvironmentStats.reportException(e);
logger.error("Error in put for store " + this.getName(), e);
throw new PersistenceFailureException(e);
} finally {
if (succeeded)
attemptCommit(transaction);
else
attemptAbort(transaction);
if (logger.isTraceEnabled()) {
logger.trace("Completed PUT (" + getName() + ") to key " + key + " (keyRef: " + System.identityHashCode(key) + " value " + value + " in " + (System.nanoTime() - startTimeNs) + " ns at " + System.currentTimeMillis());
}
}
}
use of voldemort.versioning.ObsoleteVersionException in project voldemort by voldemort.
the class InMemoryStorageEngine method put.
@Override
public synchronized void put(K key, Versioned<V> value, T transforms) throws VoldemortException {
StoreUtils.assertValidKey(key);
List<Versioned<V>> items = map.get(key);
// If we have no value, add the current value
if (items == null) {
items = new ArrayList<Versioned<V>>();
}
// Check for existing versions - remember which items to
// remove in case of success
List<Versioned<V>> itemsToRemove = new ArrayList<Versioned<V>>(items.size());
for (Versioned<V> versioned : items) {
Occurred occurred = value.getVersion().compare(versioned.getVersion());
if (occurred == Occurred.BEFORE) {
throw new ObsoleteVersionException("Obsolete version for key '" + key + "': " + value.getVersion());
} else if (occurred == Occurred.AFTER) {
itemsToRemove.add(versioned);
}
}
items.removeAll(itemsToRemove);
items.add(value);
map.put(key, items);
}
use of voldemort.versioning.ObsoleteVersionException in project voldemort by voldemort.
the class ConfigurationStorageEngine method put.
@Override
public synchronized void put(String key, Versioned<String> value, String transforms) throws VoldemortException {
StoreUtils.assertValidKey(key);
if (null == value.getValue()) {
throw new VoldemortException("metadata cannot be null !!");
}
// Check for obsolete version
File[] files = getDirectory(key).listFiles();
if (files != null) {
for (File file : files) {
if (file.getName().equals(key)) {
VectorClock clock = readVersion(key);
if (value.getVersion().compare(clock) == Occurred.AFTER) {
// continue
} else if (value.getVersion().compare(clock) == Occurred.BEFORE) {
throw new ObsoleteVersionException("A successor version " + clock + " to this " + value.getVersion() + " exists for key " + key);
} else if (value.getVersion().compare(clock) == Occurred.CONCURRENTLY) {
throw new ObsoleteVersionException("Concurrent Operation not allowed on Metadata.");
}
}
}
}
File keyFile = new File(getDirectory(key), key);
VectorClock newClock = (VectorClock) value.getVersion();
if (!keyFile.exists() || keyFile.delete()) {
try {
FileUtils.writeStringToFile(keyFile, value.getValue(), "UTF-8");
writeVersion(key, newClock);
} catch (IOException e) {
throw new VoldemortException(e);
}
}
}
use of voldemort.versioning.ObsoleteVersionException in project voldemort by voldemort.
the class FileBackedCachingStorageEngine method put.
@Override
public /**
* FIXME There is a problem here.. Since the versioning is on the file level, SystemStoreClient.put()
* will throw OVE, on the insert of the second key, value pair.Ideally, the version should be persisted
* along with the entries in the file too..
*/
void put(ByteArray key, Versioned<byte[]> value, byte[] transforms) throws VoldemortException {
StoreUtils.assertValidKey(key);
// Validate the Vector clock
VectorClock clock = readVersion();
if (clock != null) {
if (value.getVersion().compare(clock) == Occurred.BEFORE) {
throw new ObsoleteVersionException("A successor version " + clock + " to this " + value.getVersion() + " exists for the current file : " + getName());
} else if (value.getVersion().compare(clock) == Occurred.CONCURRENTLY) {
throw new ObsoleteVersionException("Concurrent Operation not allowed on Metadata.");
}
}
// Update the cache copy
this.metadataMap.put(new String(key.get()), new String(value.getValue()));
// Flush the data to the file
this.flushData();
// Persist the new Vector clock
writeVersion((VectorClock) value.getVersion());
}
use of voldemort.versioning.ObsoleteVersionException in project voldemort by voldemort.
the class RedirectingStoreTest method testProxyFetchOptimizations.
@Test
public void testProxyFetchOptimizations() {
List<ByteArray> testPrimaryKeys = new ArrayList<ByteArray>(this.proxyPutTestPrimaryEntries.keySet());
List<ByteArray> testSecondaryKeys = new ArrayList<ByteArray>(this.proxyPutTestSecondaryEntries.keySet());
final RedirectingStore redirectingStoreNode2 = getRedirectingStore(2, servers[2].getMetadataStore(), "test");
final RedirectingStore redirectingStoreNode0 = getRedirectingStore(0, servers[0].getMetadataStore(), "test");
final Store<ByteArray, byte[], byte[]> socketStoreNode2 = redirectingStoreNode2.getRedirectingSocketStore("test", 2);
final Store<ByteArray, byte[], byte[]> socketStoreNode0 = redirectingStoreNode0.getRedirectingSocketStore("test", 0);
long time = System.currentTimeMillis();
// 1. Test that once a key is fetched over, get() can serve it locally..
ByteArray primaryKey1 = testPrimaryKeys.get(1);
assertTrue("Originally key should not exist on Node 2", socketStoreNode2.get(primaryKey1, null).size() == 0);
assertTrue("get on Node 2 should return a valid value by proxy fetching from Node 0", redirectingStoreNode2.get(primaryKey1, null).size() > 0);
socketStoreNode0.delete(primaryKey1, makeSuperClock(time++));
assertTrue("Still should be able to serve it locally from Node 2", redirectingStoreNode2.get(primaryKey1, null).size() > 0);
// 2. Test that put is still issued on top of version on remote version.
// But once moved over, can be issued just on local version.
ByteArray secondaryKey1 = testSecondaryKeys.get(1);
VectorClock writeClock = makeSuperClock(time++);
socketStoreNode0.put(secondaryKey1, new Versioned<byte[]>("value-win".getBytes(), writeClock), null);
try {
redirectingStoreNode2.put(secondaryKey1, new Versioned<byte[]>("value-ove".getBytes(), writeClock), null);
fail("Missing OVE.. put should be based on remote version");
} catch (ObsoleteVersionException ove) {
// should have OVE if based on remote version due to equal clock
}
// But would have still move over value from Node 0
assertEquals("Value not moved over from Node 0", "value-win", new String(socketStoreNode2.get(secondaryKey1, null).get(0).getValue()));
socketStoreNode0.delete(secondaryKey1, makeSuperClock(time++));
redirectingStoreNode2.put(secondaryKey1, new Versioned<byte[]>("value-final".getBytes(), makeSuperClock(time++)), null);
assertEquals("Final value not found on node 2", "value-final", new String(socketStoreNode2.get(secondaryKey1, null).get(0).getValue()));
assertEquals("Final value not found on node 0", "value-final", new String(socketStoreNode0.get(secondaryKey1, null).get(0).getValue()));
// begin getAll() tests
for (ByteArray key : testPrimaryKeys) {
socketStoreNode0.delete(key, makeSuperClock(time++));
socketStoreNode2.delete(key, makeSuperClock(time++));
socketStoreNode0.put(key, new Versioned<byte[]>("normal".getBytes(), makeSuperClock(time++)), null);
}
for (ByteArray key : testSecondaryKeys) {
socketStoreNode0.delete(key, makeSuperClock(time++));
socketStoreNode2.delete(key, makeSuperClock(time++));
socketStoreNode0.put(key, new Versioned<byte[]>("normal".getBytes(), makeSuperClock(time++)), null);
}
// 3. Test case where some keys are moved over and some are n't for
// getAlls.
List<ByteArray> keyList = new ArrayList<ByteArray>();
keyList.addAll(testPrimaryKeys);
keyList.addAll(testSecondaryKeys);
keyList.add(new ByteArray("non-existent-key".getBytes()));
// add the first primary & secondary key with bigger vector clock on
// Node 2 and lower clock on Node 0..
VectorClock smallerClock = makeSuperClock(time++);
VectorClock biggerClock = makeSuperClock(time++);
socketStoreNode0.put(testPrimaryKeys.get(0), new Versioned<byte[]>("loser".getBytes(), smallerClock), null);
socketStoreNode2.put(testPrimaryKeys.get(0), new Versioned<byte[]>("winner".getBytes(), biggerClock), null);
socketStoreNode0.put(testSecondaryKeys.get(0), new Versioned<byte[]>("loser".getBytes(), smallerClock), null);
socketStoreNode2.put(testSecondaryKeys.get(0), new Versioned<byte[]>("winner".getBytes(), biggerClock), null);
Map<ByteArray, List<Versioned<byte[]>>> vals = redirectingStoreNode2.getAll(keyList, null);
assertEquals("Should contain exactly as many keys as the primary + secondary keys", testPrimaryKeys.size() + testSecondaryKeys.size(), vals.size());
assertFalse("Should not contain non existent key", vals.containsKey(new ByteArray("non-existent-key".getBytes())));
for (Entry<ByteArray, List<Versioned<byte[]>>> entry : vals.entrySet()) {
String valueStr = new String(entry.getValue().get(0).getValue());
if (entry.getKey().equals(testPrimaryKeys.get(0)) || entry.getKey().equals(testSecondaryKeys.get(0))) {
assertEquals("Value should be 'winner'", "winner", valueStr);
} else {
assertEquals("Value should be 'normal'", "normal", valueStr);
}
}
// Node 2
for (ByteArray key : testPrimaryKeys) {
socketStoreNode0.delete(key, makeSuperClock(time++));
}
for (ByteArray key : testSecondaryKeys) {
socketStoreNode0.delete(key, makeSuperClock(time++));
}
vals = redirectingStoreNode2.getAll(keyList, null);
assertEquals("Should contain exactly as many keys as the primary + secondary keys", testPrimaryKeys.size() + testSecondaryKeys.size(), vals.size());
assertFalse("Should not contain non existent key", vals.containsKey(new ByteArray("non-existent-key".getBytes())));
for (Entry<ByteArray, List<Versioned<byte[]>>> entry : vals.entrySet()) {
String valueStr = new String(entry.getValue().get(0).getValue());
if (entry.getKey().equals(testPrimaryKeys.get(0)) || entry.getKey().equals(testSecondaryKeys.get(0))) {
assertEquals("Value should be 'winner'", "winner", valueStr);
} else {
assertEquals("Value should be 'normal'", "normal", valueStr);
}
}
}
Aggregations