use of voldemort.versioning.Versioned in project voldemort by voldemort.
the class RocksDbStorageEngine method put.
@Override
public void put(ByteArray key, Versioned<byte[]> value, byte[] transforms) throws PersistenceFailureException {
StoreUtils.assertValidKey(key);
long startTimeNs = -1;
if (logger.isTraceEnabled())
startTimeNs = System.nanoTime();
synchronized (this.locks.lockFor(key.get())) {
/*
* Get the existing values. Make sure to "get" from the underlying
* storage instead of using the get method described in this class.
* Invoking the get method from this class will unnecessarily double
* prefix the key in case of PartitionPrefixedRocksdbStorageEngine
* and can cause unpredictable results.
*/
List<Versioned<byte[]>> currentValues;
try {
byte[] result = getRocksDB().get(storeHandle, key.get());
if (result != null) {
currentValues = StoreBinaryFormat.fromByteArray(result);
} else {
currentValues = Collections.emptyList();
}
} catch (RocksDBException e) {
logger.error(e);
throw new PersistenceFailureException(e);
}
if (currentValues.size() > 0) {
// compare vector clocks and throw out old ones, for updates
Iterator<Versioned<byte[]>> iter = currentValues.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 {
// if value does not exist add the value from put request to
// existing values
currentValues = new ArrayList<Versioned<byte[]>>(1);
}
currentValues.add(value);
try {
getRocksDB().put(storeHandle, key.get(), StoreBinaryFormat.toByteArray(currentValues));
} catch (RocksDBException e) {
logger.error(e);
throw new PersistenceFailureException(e);
} finally {
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.Versioned in project voldemort by voldemort.
the class RocksDbStorageEngine method getValueForKey.
private List<Versioned<byte[]>> getValueForKey(ByteArray key, byte[] transforms) throws PersistenceFailureException {
long startTimeNs = -1;
if (logger.isTraceEnabled())
startTimeNs = System.nanoTime();
List<Versioned<byte[]>> value = null;
try {
byte[] result = getRocksDB().get(storeHandle, key.get());
if (result != null) {
value = StoreBinaryFormat.fromByteArray(result);
} else {
return Collections.emptyList();
}
} catch (RocksDBException e) {
logger.error(e);
throw new PersistenceFailureException(e);
} finally {
if (logger.isTraceEnabled()) {
logger.trace("Completed GET (" + getName() + ") from key " + key + " (keyRef: " + System.identityHashCode(key) + ") in " + (System.nanoTime() - startTimeNs) + " ns at " + System.currentTimeMillis());
}
}
return value;
}
use of voldemort.versioning.Versioned in project voldemort by voldemort.
the class RocksDbStorageEngine method delete.
@Override
public boolean delete(ByteArray key, Version version) throws PersistenceFailureException {
StoreUtils.assertValidKey(key);
long startTimeNs = -1;
if (logger.isTraceEnabled())
startTimeNs = System.nanoTime();
synchronized (this.locks.lockFor(key.get())) {
try {
byte[] value = getRocksDB().get(storeHandle, key.get());
if (value == null) {
return false;
}
if (version == null) {
// unversioned delete. Just blow away the whole thing
getRocksDB().remove(storeHandle, key.get());
return true;
} else {
// versioned deletes; need to determine what to delete
List<Versioned<byte[]>> vals = StoreBinaryFormat.fromByteArray(value);
Iterator<Versioned<byte[]>> iter = vals.iterator();
int numVersions = vals.size();
int numDeletedVersions = 0;
// supplied version
while (iter.hasNext()) {
Versioned<byte[]> curr = iter.next();
Version currentVersion = curr.getVersion();
if (currentVersion.compare(version) == Occurred.BEFORE) {
iter.remove();
numDeletedVersions++;
}
}
if (numDeletedVersions < numVersions) {
// we still have some valid versions
value = StoreBinaryFormat.toByteArray(vals);
getRocksDB().put(storeHandle, key.get(), value);
} else {
// we have deleted all the versions; so get rid of the
// entry
// in the database
getRocksDB().remove(storeHandle, key.get());
}
return numDeletedVersions > 0;
}
} catch (RocksDBException e) {
logger.error(e);
throw new PersistenceFailureException(e);
} finally {
if (logger.isTraceEnabled()) {
logger.trace("Completed DELETE (" + getName() + ") of key " + ByteUtils.toHexString(key.get()) + " (keyRef: " + System.identityHashCode(key) + ") in " + (System.nanoTime() - startTimeNs) + " ns at " + System.currentTimeMillis());
}
}
}
}
use of voldemort.versioning.Versioned in project voldemort by voldemort.
the class RocksDbStorageEngine method multiVersionPut.
@Override
public List<Versioned<byte[]>> multiVersionPut(ByteArray key, List<Versioned<byte[]>> values) {
// TODO Implement getandLock() and putAndUnlock() and then remove this
// method
StoreUtils.assertValidKey(key);
long startTimeNs = -1;
if (logger.isTraceEnabled())
startTimeNs = System.nanoTime();
List<Versioned<byte[]>> currentValues = null;
List<Versioned<byte[]>> obsoleteVals = null;
synchronized (this.locks.lockFor(key.get())) {
/*
* Get the existing values. Make sure to "get" from the underlying
* storage instead of using the get method described in this class.
* Invoking the get method from this class will unnecessarily double
* prefix the key in case of PartitionPrefixedRocksdbStorageEngine
* and can cause unpredictable results.
*/
try {
byte[] result = getRocksDB().get(storeHandle, key.get());
if (result != null) {
currentValues = StoreBinaryFormat.fromByteArray(result);
} else {
currentValues = new ArrayList<Versioned<byte[]>>();
}
} catch (RocksDBException e) {
logger.error(e);
throw new PersistenceFailureException(e);
}
obsoleteVals = resolveAndConstructVersionsToPersist(currentValues, values);
try {
getRocksDB().put(storeHandle, key.get(), StoreBinaryFormat.toByteArray(currentValues));
} catch (RocksDBException e) {
logger.error(e);
throw new PersistenceFailureException(e);
} finally {
if (logger.isTraceEnabled()) {
String valueStr = "";
for (Versioned<byte[]> val : currentValues) {
valueStr += val + ",";
}
logger.trace("Completed PUT (" + getName() + ") to key " + key + " (keyRef: " + System.identityHashCode(key) + " values " + valueStr + " in " + (System.nanoTime() - startTimeNs) + " ns at " + System.currentTimeMillis());
}
}
}
return obsoleteVals;
}
use of voldemort.versioning.Versioned in project voldemort by voldemort.
the class RedirectingStore method redirectingPut.
/**
* This is slightly different from other redirecting*** methods in that,
* this updates the remote proxy node, with this put request, so we can
* switch back to the old cluster topology if needed
*
* @param key
* @param value
* @param transforms
* @throws VoldemortException
*/
private void redirectingPut(ByteArray key, Versioned<byte[]> value, byte[] transforms) throws VoldemortException {
Cluster currentCluster = metadata.getCluster();
// TODO:refactor O(n) linear lookup of storedef here. Ideally should be
// a hash lookup.
StoreDefinition storeDef = metadata.getStoreDef(getName());
/*
* defensively, error out if this is a read-only store and someone is
* doing puts against it. We don't to do extra work and fill the log
* with errors in that case.
*/
if (storeDef.getType().compareTo(ReadOnlyStorageConfiguration.TYPE_NAME) == 0) {
throw new UnsupportedOperationException("put() not supported on read-only store");
}
BaseStoreRoutingPlan currentRoutingPlan = new BaseStoreRoutingPlan(currentCluster, storeDef);
Integer redirectNode = getProxyNode(currentRoutingPlan, storeDef, key.get());
/**
* If I am rebalancing for this key, try to do remote get() if this node
* does not have the key , put it locally first to get the correct
* version ignoring any {@link ObsoleteVersionException}
*/
if (redirectNode != null) {
/*
* first check if the key exists locally. If so, it means, it has
* been moved over (either by a proxy fetch or background fetch) and
* we are good simply issuing the put on top of that.
*/
List<Versioned<byte[]>> vals = getInnerStore().get(key, transforms);
if (vals.isEmpty()) {
// if not, then go proxy fetch it
if (logger.isTraceEnabled()) {
logger.trace("Proxying GET (before PUT) on stealer:" + metadata.getNodeId() + " for key " + ByteUtils.toHexString(key.get()) + " to node:" + redirectNode);
}
proxyGetAndLocalPut(key, redirectNode, transforms);
}
}
// Here we are sure that the current node has caught up with the proxy
// for this key. Moving on to the put logic.
// put the data locally, if this step fails, there will be no proxy puts
getInnerStore().put(key, value, transforms);
// OVE). So do not send proxy puts in those cases.
if (redirectNode != null && !currentRoutingPlan.getReplicationNodeList(key.get()).contains(redirectNode)) {
AsyncProxyPutTask asyncProxyPutTask = new AsyncProxyPutTask(this, key, value, transforms, redirectNode);
proxyPutStats.reportProxyPutSubmission();
proxyPutWorkerPool.submit(asyncProxyPutTask);
}
}
Aggregations