Search in sources :

Example 1 with VoldemortApplicationException

use of voldemort.VoldemortApplicationException in project voldemort by voldemort.

the class AbstractReadRepair method execute.

public void execute(Pipeline pipeline) {
    insertNodeValues();
    long startTimeNs = -1;
    if (logger.isDebugEnabled())
        startTimeNs = System.nanoTime();
    if (nodeValues.size() > 1 && preferred > 1) {
        List<NodeValue<ByteArray, byte[]>> toReadRepair = Lists.newArrayList();
        /*
             * We clone after computing read repairs in the assumption that the
             * output will be smaller than the input. Note that we clone the
             * version, but not the key or value as the latter two are not
             * mutated.
             */
        for (NodeValue<ByteArray, byte[]> v : readRepairer.getRepairs(nodeValues)) {
            Versioned<byte[]> versioned = Versioned.value(v.getVersioned().getValue(), ((VectorClock) v.getVersion()).clone());
            toReadRepair.add(new NodeValue<ByteArray, byte[]>(v.getNodeId(), v.getKey(), versioned));
        }
        for (NodeValue<ByteArray, byte[]> v : toReadRepair) {
            try {
                if (logger.isDebugEnabled())
                    logger.debug("Doing read repair on node " + v.getNodeId() + " for key '" + ByteUtils.toHexString(v.getKey().get()) + "' with version " + v.getVersion() + ".");
                NonblockingStore store = nonblockingStores.get(v.getNodeId());
                store.submitPutRequest(v.getKey(), v.getVersioned(), null, null, timeoutMs);
            } catch (VoldemortApplicationException e) {
                if (logger.isDebugEnabled())
                    logger.debug("Read repair cancelled due to application level exception on node " + v.getNodeId() + " for key '" + ByteUtils.toHexString(v.getKey().get()) + "' with version " + v.getVersion() + ": " + e.getMessage());
            } catch (Exception e) {
                logger.debug("Read repair failed: ", e);
            }
        }
        if (logger.isDebugEnabled()) {
            String logStr = "Repaired (node, key, version): (";
            for (NodeValue<ByteArray, byte[]> v : toReadRepair) {
                logStr += "(" + v.getNodeId() + ", " + v.getKey() + "," + v.getVersion() + ") ";
            }
            logStr += "in " + (System.nanoTime() - startTimeNs) + " ns";
            logger.debug(logStr);
        }
    }
    pipeline.addEvent(completeEvent);
}
Also used : NodeValue(voldemort.store.routed.NodeValue) NonblockingStore(voldemort.store.nonblockingstore.NonblockingStore) VoldemortApplicationException(voldemort.VoldemortApplicationException) ByteArray(voldemort.utils.ByteArray) VoldemortApplicationException(voldemort.VoldemortApplicationException)

Example 2 with VoldemortApplicationException

use of voldemort.VoldemortApplicationException in project voldemort by voldemort.

the class ThreadPoolRoutedStore method getAll.

@Override
public Map<ByteArray, List<Versioned<byte[]>>> getAll(Iterable<ByteArray> keys, Map<ByteArray, byte[]> transforms) throws VoldemortException {
    StoreUtils.assertValidKeys(keys);
    Map<ByteArray, List<Versioned<byte[]>>> result = StoreUtils.newEmptyHashMap(keys);
    // Keys for each node needed to satisfy storeDef.getPreferredReads() if
    // no failures.
    Map<Node, List<ByteArray>> nodeToKeysMap = Maps.newHashMap();
    // Keep track of nodes per key that might be needed if there are
    // failures during getAll
    Map<ByteArray, List<Node>> keyToExtraNodesMap = Maps.newHashMap();
    for (ByteArray key : keys) {
        List<Node> availableNodes = availableNodes(routingStrategy.routeRequest(key.get()));
        // quickly fail if there aren't enough nodes to meet the requirement
        checkRequiredReads(availableNodes);
        int preferredReads = storeDef.getPreferredReads();
        List<Node> preferredNodes = Lists.newArrayListWithCapacity(preferredReads);
        List<Node> extraNodes = Lists.newArrayListWithCapacity(3);
        for (Node node : availableNodes) {
            if (preferredNodes.size() < preferredReads)
                preferredNodes.add(node);
            else
                extraNodes.add(node);
        }
        for (Node node : preferredNodes) {
            List<ByteArray> nodeKeys = nodeToKeysMap.get(node);
            if (nodeKeys == null) {
                nodeKeys = Lists.newArrayList();
                nodeToKeysMap.put(node, nodeKeys);
            }
            nodeKeys.add(key);
        }
        if (!extraNodes.isEmpty()) {
            List<Node> nodes = keyToExtraNodesMap.get(key);
            if (nodes == null)
                keyToExtraNodesMap.put(key, extraNodes);
            else
                nodes.addAll(extraNodes);
        }
    }
    List<Callable<GetAllResult>> callables = Lists.newArrayList();
    for (Map.Entry<Node, List<ByteArray>> entry : nodeToKeysMap.entrySet()) {
        final Node node = entry.getKey();
        final Collection<ByteArray> nodeKeys = entry.getValue();
        if (failureDetector.isAvailable(node))
            callables.add(new GetAllCallable(node, nodeKeys, transforms));
    }
    // A list of thrown exceptions, indicating the number of failures
    List<Throwable> failures = new CopyOnWriteArrayList<Throwable>();
    List<NodeValue<ByteArray, byte[]>> nodeValues = Lists.newArrayList();
    Map<ByteArray, MutableInt> keyToSuccessCount = Maps.newHashMap();
    for (ByteArray key : keys) keyToSuccessCount.put(key, new MutableInt(0));
    List<Future<GetAllResult>> futures;
    long timeoutMs = timeoutConfig.getOperationTimeout(VoldemortOpCode.GET_ALL_OP_CODE);
    try {
        // TODO What to do about timeouts? They should be longer as getAll
        // is likely to
        // take longer. At the moment, it's just timeoutMs * 3, but should
        // this be based on the number of the keys?
        futures = executor.invokeAll(callables, timeoutMs * 3, TimeUnit.MILLISECONDS);
    } catch (InterruptedException e) {
        throw new InsufficientOperationalNodesException("getAll operation interrupted.", e);
    }
    for (Future<GetAllResult> f : futures) {
        if (f.isCancelled()) {
            logger.warn("Get operation timed out after " + timeoutMs + " ms.");
            continue;
        }
        try {
            GetAllResult getResult = f.get();
            if (getResult.exception != null) {
                if (getResult.exception instanceof VoldemortApplicationException) {
                    throw (VoldemortException) getResult.exception;
                }
                failures.add(getResult.exception);
                continue;
            }
            for (ByteArray key : getResult.callable.nodeKeys) {
                List<Versioned<byte[]>> retrieved = getResult.retrieved.get(key);
                MutableInt successCount = keyToSuccessCount.get(key);
                successCount.increment();
                /*
                     * retrieved can be null if there are no values for the key
                     * provided
                     */
                if (retrieved != null) {
                    List<Versioned<byte[]>> existing = result.get(key);
                    if (existing == null)
                        result.put(key, Lists.newArrayList(retrieved));
                    else
                        existing.addAll(retrieved);
                }
            }
            nodeValues.addAll(getResult.nodeValues);
        } catch (InterruptedException e) {
            throw new InsufficientOperationalNodesException("getAll operation interrupted.", e);
        } catch (ExecutionException e) {
            // should never happen
            if (e.getCause() instanceof Error)
                throw (Error) e.getCause();
            else
                logger.error(e.getMessage(), e);
        }
    }
    for (ByteArray key : keys) {
        MutableInt successCountWrapper = keyToSuccessCount.get(key);
        int successCount = successCountWrapper.intValue();
        if (successCount < storeDef.getPreferredReads()) {
            List<Node> extraNodes = keyToExtraNodesMap.get(key);
            if (extraNodes != null) {
                for (Node node : extraNodes) {
                    long startNs = System.nanoTime();
                    try {
                        List<Versioned<byte[]>> values = innerStores.get(node.getId()).get(key, transforms == null ? null : transforms.get(key));
                        fillRepairReadsValues(nodeValues, key, node, values);
                        List<Versioned<byte[]>> versioneds = result.get(key);
                        if (versioneds == null)
                            result.put(key, Lists.newArrayList(values));
                        else
                            versioneds.addAll(values);
                        recordSuccess(node, startNs);
                        if (++successCount >= storeDef.getPreferredReads())
                            break;
                    } catch (UnreachableStoreException e) {
                        failures.add(e);
                        recordException(node, startNs, e);
                    } catch (VoldemortApplicationException e) {
                        throw e;
                    } catch (Exception e) {
                        logger.warn("Error in GET_ALL on node " + node.getId() + "(" + node.getHost() + ")", e);
                        failures.add(e);
                    }
                }
            }
        }
        successCountWrapper.setValue(successCount);
    }
    repairReads(nodeValues, repairReads && (transforms == null || transforms.size() == 0));
    for (Map.Entry<ByteArray, MutableInt> mapEntry : keyToSuccessCount.entrySet()) {
        int successCount = mapEntry.getValue().intValue();
        if (successCount < storeDef.getRequiredReads())
            throw new InsufficientOperationalNodesException(this.storeDef.getRequiredReads() + " reads required, but " + successCount + " succeeded.", failures);
    }
    return result;
}
Also used : Versioned(voldemort.versioning.Versioned) Node(voldemort.cluster.Node) VoldemortException(voldemort.VoldemortException) Callable(java.util.concurrent.Callable) ByteArray(voldemort.utils.ByteArray) ArrayList(java.util.ArrayList) List(java.util.List) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) UnreachableStoreException(voldemort.store.UnreachableStoreException) ExecutionException(java.util.concurrent.ExecutionException) VoldemortApplicationException(voldemort.VoldemortApplicationException) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) VoldemortException(voldemort.VoldemortException) VoldemortApplicationException(voldemort.VoldemortApplicationException) UnreachableStoreException(voldemort.store.UnreachableStoreException) ExecutionException(java.util.concurrent.ExecutionException) MutableInt(org.apache.commons.lang.mutable.MutableInt) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) Future(java.util.concurrent.Future) Map(java.util.Map) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList)

Example 3 with VoldemortApplicationException

use of voldemort.VoldemortApplicationException in project voldemort by voldemort.

the class ThreadPoolRoutedStore method get.

/*
     * 1. Attempt preferredReads, and then wait for these to complete 2. If we
     * got all the reads we wanted, then we are done. 3. If not then continue
     * serially attempting to read from each node until we get preferredReads or
     * run out of nodes. 4. If we have multiple results do a read repair 5. If
     * we have at least requiredReads return. Otherwise throw an exception.
     */
private <R> List<R> get(final ByteArray key, final byte[] transforms, StoreOp<R> fetcher, Function<List<GetResult<R>>, Void> preReturnProcedure) throws VoldemortException {
    StoreUtils.assertValidKey(key);
    final List<Node> nodes = availableNodes(routingStrategy.routeRequest(key.get()));
    // quickly fail if there aren't enough nodes to meet the requirement
    checkRequiredReads(nodes);
    final List<GetResult<R>> retrieved = Lists.newArrayList();
    // A count of the number of successful operations
    int successes = 0;
    // A list of thrown exceptions, indicating the number of failures
    final List<Throwable> failures = new CopyOnWriteArrayList<Throwable>();
    // Do the preferred number of reads in parallel
    int attempts = Math.min(this.storeDef.getPreferredReads(), nodes.size());
    int nodeIndex = 0;
    List<Callable<GetResult<R>>> callables = Lists.newArrayListWithCapacity(attempts);
    for (; nodeIndex < attempts; nodeIndex++) {
        final Node node = nodes.get(nodeIndex);
        callables.add(new GetCallable<R>(node, key, transforms, fetcher));
    }
    List<Future<GetResult<R>>> futures;
    long timeoutMs = (fetcher == VERSION_OP) ? timeoutConfig.getOperationTimeout(VoldemortOpCode.GET_VERSION_OP_CODE) : timeoutConfig.getOperationTimeout(VoldemortOpCode.GET_OP_CODE);
    try {
        futures = executor.invokeAll(callables, timeoutMs, TimeUnit.MILLISECONDS);
    } catch (InterruptedException e) {
        throw new InsufficientOperationalNodesException("Get operation interrupted!", e);
    }
    for (Future<GetResult<R>> f : futures) {
        if (f.isCancelled()) {
            logger.warn("Get operation timed out after " + timeoutMs + " ms.");
            continue;
        }
        try {
            GetResult<R> getResult = f.get();
            if (getResult.exception != null) {
                if (getResult.exception instanceof VoldemortApplicationException) {
                    throw (VoldemortException) getResult.exception;
                }
                failures.add(getResult.exception);
                continue;
            }
            ++successes;
            retrieved.add(getResult);
        } catch (InterruptedException e) {
            throw new InsufficientOperationalNodesException("Get operation interrupted!", e);
        } catch (ExecutionException e) {
            // part should never happen.
            if (e.getCause() instanceof Error)
                throw (Error) e.getCause();
            else
                logger.error(e.getMessage(), e);
        }
    }
    // reads to make up for these.
    while (successes < this.storeDef.getPreferredReads() && nodeIndex < nodes.size()) {
        Node node = nodes.get(nodeIndex);
        long startNs = System.nanoTime();
        try {
            retrieved.add(new GetResult<R>(node, key, fetcher.execute(innerStores.get(node.getId()), key, transforms), null));
            ++successes;
            recordSuccess(node, startNs);
        } catch (UnreachableStoreException e) {
            failures.add(e);
            recordException(node, startNs, e);
        } catch (VoldemortApplicationException e) {
            throw e;
        } catch (Exception e) {
            logger.warn("Error in GET on node " + node.getId() + "(" + node.getHost() + ")", e);
            failures.add(e);
        }
        nodeIndex++;
    }
    if (logger.isTraceEnabled())
        logger.trace("GET retrieved the following node values: " + formatNodeValues(retrieved));
    if (preReturnProcedure != null)
        preReturnProcedure.apply(retrieved);
    if (successes >= this.storeDef.getRequiredReads()) {
        List<R> result = Lists.newArrayListWithExpectedSize(retrieved.size());
        for (GetResult<R> getResult : retrieved) result.addAll(getResult.retrieved);
        return result;
    } else
        throw new InsufficientOperationalNodesException(this.storeDef.getRequiredReads() + " reads required, but " + successes + " succeeded.", failures);
}
Also used : Node(voldemort.cluster.Node) VoldemortException(voldemort.VoldemortException) Callable(java.util.concurrent.Callable) UnreachableStoreException(voldemort.store.UnreachableStoreException) ExecutionException(java.util.concurrent.ExecutionException) VoldemortApplicationException(voldemort.VoldemortApplicationException) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) VoldemortException(voldemort.VoldemortException) VoldemortApplicationException(voldemort.VoldemortApplicationException) UnreachableStoreException(voldemort.store.UnreachableStoreException) ExecutionException(java.util.concurrent.ExecutionException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) Future(java.util.concurrent.Future) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList)

Example 4 with VoldemortApplicationException

use of voldemort.VoldemortApplicationException in project voldemort by voldemort.

the class ThreadPoolRoutedStore method delete.

@Override
public boolean delete(final ByteArray key, final Version version) throws VoldemortException {
    StoreUtils.assertValidKey(key);
    final List<Node> nodes = availableNodes(routingStrategy.routeRequest(key.get()));
    // quickly fail if there aren't enough live nodes to meet the
    // requirements
    final int numNodes = nodes.size();
    if (numNodes < this.storeDef.getRequiredWrites())
        throw new InsufficientOperationalNodesException("Only " + numNodes + " nodes in preference list, but " + this.storeDef.getRequiredWrites() + " writes required.");
    // A count of the number of successful operations
    final AtomicInteger successes = new AtomicInteger(0);
    final AtomicBoolean deletedSomething = new AtomicBoolean(false);
    // A list of thrown exceptions, indicating the number of failures
    final List<Exception> failures = new CopyOnWriteArrayList<Exception>();
    // A semaphore indicating the number of completed operations
    // Once inititialized all permits are acquired, after that
    // permits are released when an operation is completed.
    // semaphore.acquire(n) waits for n operations to complete
    final Semaphore semaphore = new Semaphore(0, false);
    // Add the operations to the pool
    for (final Node node : nodes) {
        this.executor.execute(new Runnable() {

            @Override
            public void run() {
                long startNs = System.nanoTime();
                try {
                    boolean deleted = innerStores.get(node.getId()).delete(key, version);
                    successes.incrementAndGet();
                    deletedSomething.compareAndSet(false, deleted);
                    recordSuccess(node, startNs);
                } catch (UnreachableStoreException e) {
                    failures.add(e);
                    recordException(node, startNs, e);
                } catch (VoldemortApplicationException e) {
                    throw e;
                } catch (Exception e) {
                    failures.add(e);
                    logger.warn("Error in DELETE on node " + node.getId() + "(" + node.getHost() + ")", e);
                } finally {
                    // signal that the operation is complete
                    semaphore.release();
                }
            }
        });
    }
    int attempts = Math.min(storeDef.getPreferredWrites(), numNodes);
    if (this.storeDef.getPreferredWrites() <= 0) {
        return true;
    } else {
        for (int i = 0; i < numNodes; i++) {
            try {
                long timeoutMs = timeoutConfig.getOperationTimeout(VoldemortOpCode.DELETE_OP_CODE);
                boolean acquired = semaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
                if (!acquired)
                    logger.warn("Delete operation timed out waiting for operation " + i + " to complete after waiting " + timeoutMs + " ms.");
                // completed, were they successful?
                if (successes.get() >= attempts)
                    return deletedSomething.get();
            } catch (InterruptedException e) {
                throw new InsufficientOperationalNodesException("Delete operation interrupted!", e);
            }
        }
    }
    // number
    if (successes.get() < storeDef.getRequiredWrites())
        throw new InsufficientOperationalNodesException(this.storeDef.getRequiredWrites() + " deletes required, but " + successes.get() + " succeeded.", failures);
    else
        return deletedSomething.get();
}
Also used : VoldemortApplicationException(voldemort.VoldemortApplicationException) Node(voldemort.cluster.Node) Semaphore(java.util.concurrent.Semaphore) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) VoldemortException(voldemort.VoldemortException) VoldemortApplicationException(voldemort.VoldemortApplicationException) UnreachableStoreException(voldemort.store.UnreachableStoreException) ExecutionException(java.util.concurrent.ExecutionException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) UnreachableStoreException(voldemort.store.UnreachableStoreException) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList)

Example 5 with VoldemortApplicationException

use of voldemort.VoldemortApplicationException in project voldemort by voldemort.

the class ReplaceNodeCLI method getMetadataXML.

private Map<Integer, String> getMetadataXML(String key) {
    Map<Integer, String> metadataXMLsInNodes = new HashMap<Integer, String>();
    for (Integer i : cluster.getNodeIds()) {
        try {
            Versioned<String> xmlVersionedValue = adminClient.metadataMgmtOps.getRemoteMetadata(i.intValue(), key);
            String xml = xmlVersionedValue.getValue();
            metadataXMLsInNodes.put(i.intValue(), xml);
        } catch (Exception e) {
            if (i.intValue() == nodeId) {
                logger.info("Ignoring exception on the node being replaced " + nodeId, e);
            } else {
                throw new VoldemortApplicationException("Error retrieving metadata XML from the Node " + i, e);
            }
        }
    }
    if (metadataXMLsInNodes.size() < 1) {
        throw new VoldemortApplicationException("No XML found or only one node in cluster for Key " + key);
    }
    return metadataXMLsInNodes;
}
Also used : HashMap(java.util.HashMap) VoldemortApplicationException(voldemort.VoldemortApplicationException) OptionException(joptsimple.OptionException) VoldemortApplicationException(voldemort.VoldemortApplicationException) UnreachableStoreException(voldemort.store.UnreachableStoreException)

Aggregations

VoldemortApplicationException (voldemort.VoldemortApplicationException)19 Node (voldemort.cluster.Node)10 UnreachableStoreException (voldemort.store.UnreachableStoreException)6 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)4 ExecutionException (java.util.concurrent.ExecutionException)4 OptionException (joptsimple.OptionException)4 VoldemortException (voldemort.VoldemortException)4 InsufficientOperationalNodesException (voldemort.store.InsufficientOperationalNodesException)4 ObsoleteVersionException (voldemort.versioning.ObsoleteVersionException)4 HashMap (java.util.HashMap)3 Map (java.util.Map)3 Cluster (voldemort.cluster.Cluster)3 StoreDefinition (voldemort.store.StoreDefinition)3 StringReader (java.io.StringReader)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 Callable (java.util.concurrent.Callable)2 Future (java.util.concurrent.Future)2 Semaphore (java.util.concurrent.Semaphore)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)2