Search in sources :

Example 21 with ObsoleteVersionException

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

the class PerformParallelPutRequests method execute.

@Override
public void execute(final Pipeline pipeline) {
    final Node masterNode = pipelineData.getMaster();
    final List<Node> nodes = pipelineData.getNodes();
    final Versioned<byte[]> versionedCopy = pipelineData.getVersionedCopy();
    final Integer numNodesTouchedInSerialPut = nodes.indexOf(masterNode) + 1;
    numNodesPendingResponse = nodes.size() - numNodesTouchedInSerialPut;
    if (logger.isDebugEnabled())
        logger.debug("PUT {key:" + key + "} MasterNode={id:" + masterNode.getId() + "} totalNodesToAsyncPut=" + numNodesPendingResponse);
    // initiate parallel puts
    for (int i = numNodesTouchedInSerialPut; i < nodes.size(); i++) {
        final Node node = nodes.get(i);
        pipelineData.incrementNodeIndex();
        NonblockingStoreCallback callback = new NonblockingStoreCallback() {

            @Override
            public void requestComplete(Object result, long requestTime) {
                boolean responseHandledByMaster = false;
                if (logger.isDebugEnabled())
                    logger.debug("PUT {key:" + key + "} response received from node={id:" + node.getId() + "} in " + requestTime + " ms)");
                Response<ByteArray, Object> response;
                response = new Response<ByteArray, Object>(node, key, result, requestTime);
                if (logger.isDebugEnabled()) {
                    logger.debug("PUT {key:" + key + "} Parallel put thread trying to return result to main thread");
                }
                responseHandledByMaster = pipelineData.getSynchronizer().tryDelegateResponseHandling(response);
                if (logger.isDebugEnabled()) {
                    logger.debug("PUT {key:" + key + "} Master thread accepted the response: " + responseHandledByMaster);
                }
                if (!responseHandledByMaster) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("PUT {key:" + key + "} Master thread did not accept the response: will handle in worker thread");
                    }
                    if (PipelineRoutedStore.isSlopableFailure(response.getValue()) || response.getValue() instanceof QuotaExceededException) {
                        if (logger.isDebugEnabled())
                            logger.debug("PUT {key:" + key + "} failed on node={id:" + node.getId() + ",host:" + node.getHost() + "}");
                        if (isHintedHandoffEnabled()) {
                            boolean triedDelegateSlop = pipelineData.getSynchronizer().tryDelegateSlop(node);
                            if (logger.isDebugEnabled()) {
                                logger.debug("PUT {key:" + key + "} triedDelegateSlop: " + triedDelegateSlop);
                            }
                            if (!triedDelegateSlop) {
                                Slop slop = new Slop(pipelineData.getStoreName(), Slop.Operation.PUT, key, versionedCopy.getValue(), transforms, node.getId(), new Date());
                                pipelineData.addFailedNode(node);
                                if (logger.isDebugEnabled())
                                    logger.debug("PUT {key:" + key + "} Start registering Slop(node:" + node.getId() + ",host:" + node.getHost() + ")");
                                hintedHandoff.sendHintParallel(node, versionedCopy.getVersion(), slop);
                                if (logger.isDebugEnabled())
                                    logger.debug("PUT {key:" + key + "} Sent out request to register Slop(node: " + node.getId() + ",host:" + node.getHost() + ")");
                            }
                        }
                    } else {
                        // the exception is ignorable
                        if (logger.isDebugEnabled()) {
                            if (result instanceof Exception) {
                                logger.debug("PUT {key:" + key + "} will not send hint. Response is ignorable exception: " + result.getClass().toString());
                            } else {
                                logger.debug("PUT {key:" + key + "} will not send hint. Response is success");
                            }
                        }
                    }
                    if (result instanceof Exception && !(result instanceof ObsoleteVersionException)) {
                        if (response.getValue() instanceof InvalidMetadataException) {
                            pipelineData.reportException((InvalidMetadataException) response.getValue());
                            logger.warn("Received invalid metadata problem after a successful " + pipeline.getOperation().getSimpleName() + " call on node " + node.getId() + ", store '" + pipelineData.getStoreName() + "'");
                        } else if (response.getValue() instanceof QuotaExceededException) {
                            /**
                                 * TODO Not sure if we need to count this
                                 * Exception for stats or silently ignore and
                                 * just log a warning. While
                                 * QuotaExceededException thrown from other
                                 * places mean the operation failed, this one
                                 * does not fail the operation but instead
                                 * stores slops. Introduce a new Exception in
                                 * client side to just monitor how mamy Async
                                 * writes fail on exceeding Quota?
                                 * 
                                 */
                            logger.warn("Received QuotaExceededException after a successful " + pipeline.getOperation().getSimpleName() + " call on node " + node.getId() + ", store '" + pipelineData.getStoreName() + "', master-node '" + masterNode.getId() + "'");
                        } else {
                            handleResponseError(response, pipeline, failureDetector);
                        }
                    }
                }
            }
        };
        if (logger.isTraceEnabled())
            logger.trace("Submitting " + pipeline.getOperation().getSimpleName() + " request on node " + node.getId() + " for key " + key);
        NonblockingStore store = nonblockingStores.get(node.getId());
        store.submitPutRequest(key, versionedCopy, transforms, callback, timeoutMs);
    }
    try {
        boolean preferredSatisfied = false;
        while (true) {
            long elapsedNs = System.nanoTime() - pipelineData.getStartTimeNs();
            long remainingNs = (timeoutMs * Time.NS_PER_MS) - elapsedNs;
            remainingNs = Math.max(0, remainingNs);
            // preferred check
            if (numResponsesGot >= preferred - 1) {
                preferredSatisfied = true;
            }
            quorumSatisfied = isQuorumSatisfied();
            zonesSatisfied = isZonesSatisfied();
            if (quorumSatisfied && zonesSatisfied && preferredSatisfied || remainingNs <= 0 || numNodesPendingResponse <= 0) {
                pipelineData.getSynchronizer().cutoffHandling();
                break;
            } else {
                if (logger.isTraceEnabled()) {
                    logger.trace("PUT {key:" + key + "} trying to poll from queue");
                }
                Response<ByteArray, Object> response = pipelineData.getSynchronizer().responseQueuePoll(remainingNs, TimeUnit.NANOSECONDS);
                processResponse(response, pipeline);
                if (logger.isTraceEnabled()) {
                    logger.trace("PUT {key:" + key + "} tried to poll from queue. Null?: " + (response == null) + " numResponsesGot:" + numResponsesGot + " parallelResponseToWait: " + numNodesPendingResponse + "; preferred-1: " + (preferred - 1) + "; preferredOK: " + preferredSatisfied + " quorumOK: " + quorumSatisfied + "; zoneOK: " + zonesSatisfied);
                }
            }
        }
        // leftover)
        while (!pipelineData.getSynchronizer().responseQueueIsEmpty()) {
            Response<ByteArray, Object> response = pipelineData.getSynchronizer().responseQueuePoll(0, TimeUnit.NANOSECONDS);
            processResponse(response, pipeline);
        }
        quorumSatisfied = isQuorumSatisfied();
        zonesSatisfied = isZonesSatisfied();
        if (quorumSatisfied && zonesSatisfied) {
            if (logger.isDebugEnabled()) {
                logger.debug("PUT {key:" + key + "} succeeded at parallel put stage");
            }
            pipelineData.getSynchronizer().disallowDelegateSlop();
            pipeline.addEvent(completeEvent);
        } else {
            VoldemortException fatalError;
            if (!quorumSatisfied) {
                if (logger.isDebugEnabled()) {
                    logger.debug("PUT {key:" + key + "} failed due to insufficient nodes. required=" + required + " success=" + pipelineData.getSuccesses());
                }
                fatalError = new InsufficientOperationalNodesException(required + " " + pipeline.getOperation().getSimpleName() + "s required, but only " + pipelineData.getSuccesses() + " succeeded", pipelineData.getReplicationSet(), pipelineData.getNodes(), pipelineData.getFailedNodes(), pipelineData.getFailures());
                pipelineData.setFatalError(fatalError);
            } else if (!zonesSatisfied) {
                if (logger.isDebugEnabled()) {
                    logger.debug("PUT {key:" + key + "} failed due to insufficient zones. required=" + pipelineData.getZonesRequired() + 1 + " success=" + pipelineData.getZoneResponses().size());
                }
                fatalError = new InsufficientZoneResponsesException((pipelineData.getZonesRequired() + 1) + " " + pipeline.getOperation().getSimpleName() + "s required zone, but only " + (pipelineData.getZoneResponses().size()) + " succeeded. Failing nodes : " + pipelineData.getFailedNodes());
                pipelineData.setFatalError(fatalError);
            }
            pipeline.abort();
        }
    } catch (InterruptedException e) {
        if (logger.isEnabledFor(Level.WARN))
            logger.warn(e, e);
    } catch (NoSuchElementException e) {
        if (logger.isEnabledFor(Level.ERROR))
            logger.error("Response Queue is empty. There may be a bug in PerformParallelPutRequest", e);
    } finally {
        if (logger.isDebugEnabled()) {
            logger.debug("PUT {key:" + key + "} marking parallel put stage finished");
        }
    }
}
Also used : QuotaExceededException(voldemort.store.quota.QuotaExceededException) NonblockingStore(voldemort.store.nonblockingstore.NonblockingStore) Node(voldemort.cluster.Node) InvalidMetadataException(voldemort.store.InvalidMetadataException) VoldemortException(voldemort.VoldemortException) Date(java.util.Date) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) InsufficientZoneResponsesException(voldemort.store.InsufficientZoneResponsesException) NoSuchElementException(java.util.NoSuchElementException) VoldemortException(voldemort.VoldemortException) InvalidMetadataException(voldemort.store.InvalidMetadataException) QuotaExceededException(voldemort.store.quota.QuotaExceededException) NonblockingStoreCallback(voldemort.store.nonblockingstore.NonblockingStoreCallback) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) InsufficientZoneResponsesException(voldemort.store.InsufficientZoneResponsesException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) ByteArray(voldemort.utils.ByteArray) Slop(voldemort.store.slop.Slop) NoSuchElementException(java.util.NoSuchElementException)

Example 22 with ObsoleteVersionException

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

the class ImportTextDumpToBDB method main.

public static void main(String[] argv) throws Exception {
    OptionParser parser = getParser();
    OptionSet options = parser.parse(argv);
    validateOptions(options);
    String inputPath = (String) options.valueOf("input");
    String storeBdbFolderPath = (String) options.valueOf("bdb");
    String clusterXmlPath = (String) options.valueOf("cluster-xml");
    String storesXmlPath = (String) options.valueOf("stores-xml");
    Integer nodeId = (Integer) options.valueOf("node-id");
    File input = new File(inputPath);
    List<File> dataFiles = new ArrayList<File>();
    if (input.isDirectory()) {
        File[] files = input.listFiles();
        if (files != null)
            Collections.addAll(dataFiles, files);
    } else if (input.isFile()) {
        dataFiles.add(input);
    } else {
        System.err.println(inputPath + "is not file or directory");
    }
    File storeBdbFolder = new File(storeBdbFolderPath);
    final String storeName = storeBdbFolder.getName();
    Cluster cluster = new ClusterMapper().readCluster(new File(clusterXmlPath));
    List<StoreDefinition> storeDefs = new StoreDefinitionsMapper().readStoreList(new File(storesXmlPath));
    StoreDefinition storeDef = null;
    for (StoreDefinition sd : storeDefs) {
        if (sd.getName() != null && sd.getName().equals(storeName)) {
            storeDef = sd;
        }
    }
    if (storeDef == null) {
        throw new VoldemortException("StoreNotfound: " + storeName);
    }
    RoutingStrategy routingStrategy = new RoutingStrategyFactory().updateRoutingStrategy(storeDef, cluster);
    Properties properties = new Properties();
    properties.put("node.id", "0");
    properties.put("voldemort.home", storeBdbFolder.getParent());
    VoldemortConfig voldemortConfig = new VoldemortConfig(properties);
    voldemortConfig.setBdbDataDirectory(storeBdbFolder.getParent());
    voldemortConfig.setEnableJmx(false);
    voldemortConfig.setBdbOneEnvPerStore(true);
    BdbStorageConfiguration bdbConfiguration = new BdbStorageConfiguration(voldemortConfig);
    class MockStoreDefinition extends StoreDefinition {

        public MockStoreDefinition() {
            super(storeName, null, null, null, null, null, null, null, 0, null, 0, null, 0, null, null, null, null, null, null, null, null, null, null, null, null, 0);
        }

        @Override
        public boolean hasMemoryFootprint() {
            return false;
        }
    }
    StoreDefinition mockStoreDef = new MockStoreDefinition();
    StorageEngine<ByteArray, byte[], byte[]> engine = bdbConfiguration.getStore(mockStoreDef, routingStrategy);
    long reportIntervalMs = 10000L;
    long lastCount = 0;
    long lastInserted = 0;
    Reporter<Boolean> rp = new Reporter<Boolean>(reportIntervalMs);
    long count = 0;
    long inserted = 0;
    for (File f : dataFiles) {
        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader(f), READER_BUFFER_SIZE);
            engine.beginBatchModifications();
            while (true) {
                String line = bufferedReader.readLine();
                if (line == null) {
                    break;
                }
                Pair<ByteArray, Versioned<byte[]>> entry;
                try {
                    entry = lineToEntry(line);
                } catch (Exception e) {
                    System.err.println("Skipping line: " + line);
                    e.printStackTrace();
                    continue;
                }
                ByteArray key = entry.getFirst();
                List<Node> nodeList = routingStrategy.routeRequest(key.get());
                for (Node node : nodeList) {
                    if (nodeId == node.getId()) {
                        try {
                            engine.put(key, entry.getSecond(), null);
                            inserted++;
                        } catch (ObsoleteVersionException e) {
                            e.printStackTrace();
                        }
                        break;
                    }
                }
                count++;
                final Long countObject = count;
                final Long insertedObject = inserted;
                Boolean reported = rp.tryReport(new Callable<Boolean>() {

                    @Override
                    public Boolean call() throws Exception {
                        System.out.print(String.format("Imported %15d entries; Inserted %15d entries", countObject, insertedObject));
                        return true;
                    }
                });
                if (reported != null) {
                    long importSpeed = (count - lastCount) / (reportIntervalMs / 1000);
                    long insertSpeed = (inserted - lastInserted) / (reportIntervalMs / 1000);
                    System.out.println(String.format("; ImportSpeed: %8d/s; InsertSpeed: %8d/s ", importSpeed, insertSpeed));
                    lastCount = count;
                    lastInserted = inserted;
                }
            }
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            engine.endBatchModifications();
        }
    }
    engine.close();
    System.out.println(String.format("Finished importing %d entries (%d inserted, rest discarded)", count, inserted));
}
Also used : Versioned(voldemort.versioning.Versioned) RoutingStrategyFactory(voldemort.routing.RoutingStrategyFactory) Node(voldemort.cluster.Node) OptionParser(joptsimple.OptionParser) VoldemortException(voldemort.VoldemortException) VoldemortConfig(voldemort.server.VoldemortConfig) StoreDefinition(voldemort.store.StoreDefinition) RoutingStrategy(voldemort.routing.RoutingStrategy) ByteArray(voldemort.utils.ByteArray) BdbStorageConfiguration(voldemort.store.bdb.BdbStorageConfiguration) StoreDefinitionsMapper(voldemort.xml.StoreDefinitionsMapper) Cluster(voldemort.cluster.Cluster) ClusterMapper(voldemort.xml.ClusterMapper) VoldemortException(voldemort.VoldemortException) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) DecoderException(org.apache.commons.codec.DecoderException) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) OptionSet(joptsimple.OptionSet)

Example 23 with ObsoleteVersionException

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

the class CacheStorageEnginePerformanceTest method main.

public static void main(String[] args) {
    if (args.length != 3)
        Utils.croak("USAGE: java " + CacheStorageEnginePerformanceTest.class.getName() + " num-threads num-requests read-fraction");
    int numThreads = Integer.parseInt(args[0]);
    int numRequests = Integer.parseInt(args[1]);
    double readPercent = Double.parseDouble(args[2]);
    final int valueRange = numRequests / 10;
    final int mod = 100;
    final int readMax = (int) readPercent * mod;
    final Store<ByteArray, byte[], byte[]> store = new CacheStorageConfiguration(null).getStore(TestUtils.makeStoreDefinition("test"), TestUtils.makeSingleNodeRoutingStrategy());
    final AtomicInteger obsoletes = new AtomicInteger(0);
    PerformanceTest readWriteTest = new PerformanceTest() {

        @Override
        public void doOperation(int index) throws Exception {
            try {
                byte[] bytes = Integer.toString(index % valueRange).getBytes();
                ByteArray key = new ByteArray(bytes);
                if (index % mod < readMax)
                    store.get(key, null);
                else
                    store.put(key, new Versioned<byte[]>(bytes), null);
            } catch (ObsoleteVersionException e) {
                obsoletes.incrementAndGet();
            }
        }
    };
    readWriteTest.run(numRequests, numThreads);
    System.out.println("Cache storage engine performance test results:");
    readWriteTest.printStats();
    System.out.println("Number of obsolete puts: " + obsoletes.get());
}
Also used : ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) Versioned(voldemort.versioning.Versioned) CacheStorageConfiguration(voldemort.store.memory.CacheStorageConfiguration) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ByteArray(voldemort.utils.ByteArray)

Example 24 with ObsoleteVersionException

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

the class DefaultStoreClientTest method testPutVersioned.

@Test
public void testPutVersioned() {
    client.put("k", Versioned.value("v"));
    Versioned<String> v = client.get("k");
    assertEquals("GET should return the version set by PUT.", "v", v.getValue());
    VectorClock expected = new VectorClock();
    expected.incrementVersion(nodeId, time.getMilliseconds());
    assertEquals("The version should be incremented after a put.", expected, v.getVersion());
    try {
        client.put("k", Versioned.value("v"));
        fail("Put of obsolete version should throw exception.");
    } catch (ObsoleteVersionException e) {
    // this is good
    }
    // PUT of a concurrent version should succeed
    client.put("k", new Versioned<String>("v2", new VectorClock().incremented(nodeId + 1, time.getMilliseconds())));
    assertEquals("GET should return the new value set by PUT.", "v2", client.getValue("k"));
    assertEquals("GET should return the new version set by PUT.", expected.incremented(nodeId + 1, time.getMilliseconds()), client.get("k").getVersion());
}
Also used : ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) VectorClock(voldemort.versioning.VectorClock) Test(org.junit.Test)

Example 25 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)

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