Search in sources :

Example 36 with ObsoleteVersionException

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());
        }
    }
}
Also used : Versioned(voldemort.versioning.Versioned) DatabaseEntry(com.sleepycat.je.DatabaseEntry) PersistenceFailureException(voldemort.store.PersistenceFailureException) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) Transaction(com.sleepycat.je.Transaction) OperationStatus(com.sleepycat.je.OperationStatus) AsyncOperationStatus(voldemort.server.protocol.admin.AsyncOperationStatus) DatabaseException(com.sleepycat.je.DatabaseException) Occurred(voldemort.versioning.Occurred)

Example 37 with ObsoleteVersionException

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);
}
Also used : ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) Versioned(voldemort.versioning.Versioned) ArrayList(java.util.ArrayList) Occurred(voldemort.versioning.Occurred)

Example 38 with ObsoleteVersionException

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);
        }
    }
}
Also used : ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) VectorClock(voldemort.versioning.VectorClock) IOException(java.io.IOException) VoldemortException(voldemort.VoldemortException) File(java.io.File)

Example 39 with ObsoleteVersionException

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());
}
Also used : ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) VectorClock(voldemort.versioning.VectorClock)

Example 40 with ObsoleteVersionException

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);
        }
    }
}
Also used : VectorClock(voldemort.versioning.VectorClock) ArrayList(java.util.ArrayList) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) ByteArray(voldemort.utils.ByteArray) List(java.util.List) ArrayList(java.util.ArrayList) Test(org.junit.Test)

Aggregations

ObsoleteVersionException (voldemort.versioning.ObsoleteVersionException)43 ByteArray (voldemort.utils.ByteArray)23 VectorClock (voldemort.versioning.VectorClock)16 Versioned (voldemort.versioning.Versioned)14 Node (voldemort.cluster.Node)11 VoldemortException (voldemort.VoldemortException)10 Test (org.junit.Test)8 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)7 File (java.io.File)6 UnreachableStoreException (voldemort.store.UnreachableStoreException)6 Occurred (voldemort.versioning.Occurred)5 IOException (java.io.IOException)4 ArrayList (java.util.ArrayList)4 HashMap (java.util.HashMap)4 List (java.util.List)4 VoldemortConfig (voldemort.server.VoldemortConfig)4 Date (java.util.Date)3 Random (java.util.Random)3 OptionParser (joptsimple.OptionParser)3 OptionSet (joptsimple.OptionSet)3