Search in sources :

Example 1 with ObsoleteVersionException

use of voldemort.versioning.ObsoleteVersionException in project voldemort by voldemort.

the class KratiStorageEngine method put.

@Override
public void put(ByteArray key, Versioned<byte[]> value, byte[] transforms) throws VoldemortException {
    StoreUtils.assertValidKey(key);
    synchronized (this.locks.lockFor(key.get())) {
        // First get the value
        List<Versioned<byte[]>> existingValuesList = this.get(key, null);
        // If no value, add one
        if (existingValuesList.size() == 0) {
            existingValuesList = new ArrayList<Versioned<byte[]>>();
            existingValuesList.add(new Versioned<byte[]>(value.getValue(), value.getVersion()));
        } else {
            // Update the value
            List<Versioned<byte[]>> removedValueList = new ArrayList<Versioned<byte[]>>();
            for (Versioned<byte[]> versioned : existingValuesList) {
                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)
                    removedValueList.add(versioned);
            }
            existingValuesList.removeAll(removedValueList);
            existingValuesList.add(value);
        }
        try {
            datastore.put(key.get(), assembleValues(existingValuesList));
        } catch (Exception e) {
            String message = "Failed to put key " + key;
            logger.error(message, e);
            throw new VoldemortException(message, e);
        }
    }
}
Also used : ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) Versioned(voldemort.versioning.Versioned) ArrayList(java.util.ArrayList) VoldemortException(voldemort.VoldemortException) Occurred(voldemort.versioning.Occurred) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) VoldemortException(voldemort.VoldemortException) IOException(java.io.IOException)

Example 2 with ObsoleteVersionException

use of voldemort.versioning.ObsoleteVersionException in project voldemort by voldemort.

the class R2Store method put.

@Override
public void put(ByteArray key, Versioned<byte[]> value, byte[] transform) throws VoldemortException {
    RestResponse response = null;
    try {
        byte[] payload = value.getValue();
        // Create the REST request with this byte array
        String base64Key = RestUtils.encodeVoldemortKey(key.get());
        RestRequestBuilder rb = new RestRequestBuilder(new URI(this.restBootstrapURL + "/" + getName() + "/" + base64Key));
        // Create a HTTP POST request
        rb.setMethod(POST);
        rb.setEntity(payload);
        rb.setHeader(CONTENT_TYPE, "binary");
        rb.setHeader(CONTENT_LENGTH, "" + payload.length);
        String timeoutStr = Long.toString(this.config.getTimeoutConfig().getOperationTimeout(VoldemortOpCode.PUT_OP_CODE));
        rb.setHeader(RestMessageHeaders.X_VOLD_REQUEST_TIMEOUT_MS, timeoutStr);
        rb.setHeader(RestMessageHeaders.X_VOLD_REQUEST_ORIGIN_TIME_MS, String.valueOf(System.currentTimeMillis()));
        if (this.routingTypeCode != null) {
            rb.setHeader(RestMessageHeaders.X_VOLD_ROUTING_TYPE_CODE, this.routingTypeCode);
        }
        if (this.zoneId != INVALID_ZONE_ID) {
            rb.setHeader(RestMessageHeaders.X_VOLD_ZONE_ID, String.valueOf(this.zoneId));
        }
        // Serialize the Vector clock
        VectorClock vc = (VectorClock) value.getVersion();
        // doing the put.
        if (vc != null) {
            String serializedVC = null;
            if (!vc.getEntries().isEmpty()) {
                serializedVC = RestUtils.getSerializedVectorClock(vc);
            }
            if (serializedVC != null && serializedVC.length() > 0) {
                rb.setHeader(RestMessageHeaders.X_VOLD_VECTOR_CLOCK, serializedVC);
            }
        }
        RestRequest request = rb.build();
        Future<RestResponse> f = client.restRequest(request);
        // This will block
        response = f.get();
        String serializedUpdatedVC = response.getHeader(RestMessageHeaders.X_VOLD_VECTOR_CLOCK);
        if (serializedUpdatedVC == null || serializedUpdatedVC.length() == 0) {
            if (logger.isDebugEnabled()) {
                logger.debug("Received empty vector clock in the response");
            }
        } else {
            VectorClock updatedVC = RestUtils.deserializeVectorClock(serializedUpdatedVC);
            VectorClock originalVC = (VectorClock) value.getVersion();
            originalVC.copyFromVectorClock(updatedVC);
        }
        final ByteString entity = response.getEntity();
        if (entity == null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Empty response !");
            }
        }
    } catch (ExecutionException e) {
        if (e.getCause() instanceof RestException) {
            RestException exception = (RestException) e.getCause();
            if (logger.isDebugEnabled()) {
                logger.debug("REST EXCEPTION STATUS : " + exception.getResponse().getStatus());
            }
            int httpErrorStatus = exception.getResponse().getStatus();
            if (httpErrorStatus == BAD_REQUEST.getCode()) {
                throw new VoldemortException("Bad request: " + e.getMessage(), e);
            } else if (httpErrorStatus == PRECONDITION_FAILED.getCode()) {
                throw new ObsoleteVersionException(e.getMessage());
            } else if (httpErrorStatus == REQUEST_TIMEOUT.getCode() || httpErrorStatus == INTERNAL_SERVER_ERROR.getCode()) {
                throw new InsufficientOperationalNodesException(e.getMessage());
            }
        }
        throw new VoldemortException("Unknown HTTP request execution exception: " + e.getMessage(), e);
    } catch (InterruptedException e) {
        if (logger.isDebugEnabled()) {
            logger.debug("Operation interrupted : " + e.getMessage());
        }
        throw new VoldemortException("Unknown Voldemort exception: " + e.getMessage());
    } catch (URISyntaxException e) {
        throw new VoldemortException("Illegal HTTP URL" + e.getMessage());
    }
}
Also used : RestResponse(com.linkedin.r2.message.rest.RestResponse) ByteString(com.linkedin.data.ByteString) VectorClock(voldemort.versioning.VectorClock) RestException(com.linkedin.r2.message.rest.RestException) ByteString(com.linkedin.data.ByteString) URISyntaxException(java.net.URISyntaxException) URI(java.net.URI) VoldemortException(voldemort.VoldemortException) RestRequest(com.linkedin.r2.message.rest.RestRequest) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) ExecutionException(java.util.concurrent.ExecutionException)

Example 3 with ObsoleteVersionException

use of voldemort.versioning.ObsoleteVersionException 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());
            }
        }
    }
}
Also used : RocksDBException(org.rocksdb.RocksDBException) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) Versioned(voldemort.versioning.Versioned) PersistenceFailureException(voldemort.store.PersistenceFailureException) Occurred(voldemort.versioning.Occurred)

Example 4 with ObsoleteVersionException

use of voldemort.versioning.ObsoleteVersionException in project voldemort by voldemort.

the class MysqlStorageEngine method put.

@Override
public void put(ByteArray key, Versioned<byte[]> value, byte[] transforms) throws PersistenceFailureException {
    StoreUtils.assertValidKey(key);
    boolean doCommit = false;
    Connection conn = null;
    PreparedStatement insert = null;
    PreparedStatement select = null;
    ResultSet results = null;
    String insertSql = "insert into " + getName() + " (key_, version_, value_) values (?, ?, ?)";
    String selectSql = "select version_ from " + getName() + " where key_ = ?";
    try {
        conn = datasource.getConnection();
        conn.setAutoCommit(false);
        // check for superior versions
        select = conn.prepareStatement(selectSql);
        select.setBytes(1, key.get());
        results = select.executeQuery();
        while (results.next()) {
            VectorClock version = new VectorClock(results.getBytes("version_"));
            Occurred occurred = value.getVersion().compare(version);
            if (occurred == Occurred.BEFORE)
                throw new ObsoleteVersionException("Attempt to put version " + value.getVersion() + " which is superceeded by " + version + ".");
            else if (occurred == Occurred.AFTER)
                delete(conn, key.get(), version.toBytes());
        }
        // Okay, cool, now put the value
        insert = conn.prepareStatement(insertSql);
        insert.setBytes(1, key.get());
        VectorClock clock = (VectorClock) value.getVersion();
        insert.setBytes(2, clock.toBytes());
        insert.setBytes(3, value.getValue());
        insert.executeUpdate();
        doCommit = true;
    } catch (SQLException e) {
        if (e.getErrorCode() == MYSQL_ERR_DUP_KEY || e.getErrorCode() == MYSQL_ERR_DUP_ENTRY) {
            throw new ObsoleteVersionException("Key or value already used.");
        } else {
            throw new PersistenceFailureException("Fix me!", e);
        }
    } finally {
        if (conn != null) {
            try {
                if (doCommit)
                    conn.commit();
                else
                    conn.rollback();
            } catch (SQLException e) {
            }
        }
        tryClose(results);
        tryClose(insert);
        tryClose(select);
        tryClose(conn);
    }
}
Also used : ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) SQLException(java.sql.SQLException) VectorClock(voldemort.versioning.VectorClock) Connection(java.sql.Connection) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement) PersistenceFailureException(voldemort.store.PersistenceFailureException) Occurred(voldemort.versioning.Occurred)

Example 5 with ObsoleteVersionException

use of voldemort.versioning.ObsoleteVersionException in project voldemort by voldemort.

the class StorageEnginePerformanceTest method main.

public static void main(String[] args) throws Exception {
    try {
        OptionParser parser = new OptionParser();
        parser.accepts("help", "print usage information");
        parser.accepts("requests", "[REQUIRED] number of requests to execute").withRequiredArg().ofType(Integer.class);
        parser.accepts("num-values", "[REQUIRED] number of values in the store").withRequiredArg().ofType(Integer.class);
        parser.accepts("data-dir", "Data directory for storage data").withRequiredArg().describedAs("directory");
        parser.accepts("threads", "number of threads").withRequiredArg().ofType(Integer.class);
        parser.accepts("storage-configuration-class", "[REQUIRED] class of the storage engine configuration to use [e.g. voldemort.store.bdb.BdbStorageConfiguration]").withRequiredArg().describedAs("class_name");
        parser.accepts("props", "Properties file with configuration for the engine").withRequiredArg().describedAs("config.properties");
        parser.accepts("value-size", "The size of the values in the store").withRequiredArg().describedAs("size").ofType(Integer.class);
        parser.accepts("cache-width", "Percentage of requests to save as possible re-requests").withRequiredArg().describedAs("width").ofType(Integer.class);
        parser.accepts("cache-hit-ratio", "Percentage of requests coming from the last cache-width requests").withRequiredArg().describedAs("ratio").ofType(Double.class);
        parser.accepts("clean-up", "Delete data directory when done.");
        OptionSet options = parser.parse(args);
        if (options.has("help")) {
            parser.printHelpOn(System.out);
            System.exit(0);
        }
        CmdUtils.croakIfMissing(parser, options, "requests");
        final int numThreads = CmdUtils.valueOf(options, "threads", 10);
        final int numRequests = (Integer) options.valueOf("requests");
        final int numValues = (Integer) options.valueOf("num-values");
        final int valueSize = CmdUtils.valueOf(options, "value-size", 1024);
        final int cacheWidth = CmdUtils.valueOf(options, "cache-width", 100000);
        final double cacheHitRatio = CmdUtils.valueOf(options, "cache-hit-ratio", 0.5);
        final String propsFile = (String) options.valueOf("props");
        final boolean cleanUp = options.has("clean-up");
        final String storageEngineClass = CmdUtils.valueOf(options, "storage-configuration-class", BdbStorageConfiguration.class.getName()).trim();
        File dataDir = null;
        if (options.has("data-dir"))
            dataDir = new File((String) options.valueOf("data-dir"));
        else
            dataDir = TestUtils.createTempDir();
        System.out.println("Data dir: " + dataDir);
        // create the storage engine
        Props props = new Props();
        if (propsFile != null)
            props = new Props(new File(propsFile));
        props.put("node.id", 0);
        props.put("data.directory", dataDir.getAbsolutePath());
        props.put("voldemort.home", System.getProperty("user.dir"));
        VoldemortConfig config = new VoldemortConfig(props);
        StorageConfiguration storageConfig = (StorageConfiguration) ReflectUtils.callConstructor(ReflectUtils.loadClass(storageEngineClass), new Object[] { config });
        StorageEngine<ByteArray, byte[], byte[]> engine = storageConfig.getStore(TestUtils.makeStoreDefinition("test"), TestUtils.makeSingleNodeRoutingStrategy());
        @SuppressWarnings("unchecked") final Store<String, byte[], byte[]> store = new SerializingStore(engine, new StringSerializer(), new IdentitySerializer(), null);
        final byte[] value = new byte[valueSize];
        new Random().nextBytes(value);
        // initialize test data
        for (int i = 0; i < numValues; i++) store.put(Integer.toString(i), Versioned.value(value), null);
        // initialize cache lookback data
        int[] recents = new int[cacheWidth];
        System.out.println("Write test:");
        CachedPerformanceTest writeTest = new CachedPerformanceTest(new PerformanceTest() {

            @Override
            public void doOperation(int index) {
                try {
                    String key = Integer.toString(index);
                    List<Versioned<byte[]>> vs = store.get(key, null);
                    VectorClock version;
                    if (vs.size() == 0)
                        version = new VectorClock();
                    else
                        version = (VectorClock) vs.get(0).getVersion();
                    version.incrementVersion(0, 847584375);
                    store.put(key, Versioned.value(value, version), null);
                } catch (ObsoleteVersionException e) {
                // do nothing
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    throw e;
                }
            }
        }, recents, numValues, cacheHitRatio);
        writeTest.run(numRequests, numThreads);
        writeTest.printStats();
        System.out.println();
        System.out.println("Read test:");
        CachedPerformanceTest readTest = new CachedPerformanceTest(new PerformanceTest() {

            @Override
            public void doOperation(int index) {
                store.get(Integer.toString(index), null);
            }
        }, recents, numValues, cacheHitRatio);
        readTest.run(numRequests, numThreads);
        readTest.printStats();
        if (cleanUp)
            Utils.rm(dataDir);
    } catch (Exception e) {
        e.printStackTrace();
        System.exit(1);
    }
}
Also used : Props(voldemort.utils.Props) OptionParser(joptsimple.OptionParser) VoldemortConfig(voldemort.server.VoldemortConfig) Random(java.util.Random) ByteArray(voldemort.utils.ByteArray) IdentitySerializer(voldemort.serialization.IdentitySerializer) List(java.util.List) SerializingStore(voldemort.store.serialized.SerializingStore) StringSerializer(voldemort.serialization.StringSerializer) VectorClock(voldemort.versioning.VectorClock) BdbStorageConfiguration(voldemort.store.bdb.BdbStorageConfiguration) StorageConfiguration(voldemort.store.StorageConfiguration) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) OptionSet(joptsimple.OptionSet) File(java.io.File)

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