Search in sources :

Example 96 with Node

use of voldemort.cluster.Node in project voldemort by voldemort.

the class PerformParallelDeleteRequests method executeInternal.

private void executeInternal(final Pipeline pipeline) {
    List<Node> nodes = pipelineData.getNodes();
    final Map<Integer, Response<ByteArray, Object>> responses = new ConcurrentHashMap<Integer, Response<ByteArray, Object>>();
    int attempts = nodes.size();
    int blocks = Math.min(preferred, attempts);
    final CountDownLatch attemptsLatch = new CountDownLatch(attempts);
    final CountDownLatch blocksLatch = new CountDownLatch(blocks);
    if (logger.isTraceEnabled())
        logger.trace("Attempting " + attempts + " " + pipeline.getOperation().getSimpleName() + " operations in parallel");
    long beginTime = System.nanoTime();
    for (int i = 0; i < attempts; i++) {
        final Node node = nodes.get(i);
        pipelineData.incrementNodeIndex();
        NonblockingStoreCallback callback = new NonblockingStoreCallback() {

            public void requestComplete(Object result, long requestTime) {
                if (logger.isTraceEnabled())
                    logger.trace(pipeline.getOperation().getSimpleName() + " response received (" + requestTime + " ms.) from node " + node.getId());
                Response<ByteArray, Object> response = new Response<ByteArray, Object>(node, key, result, requestTime);
                if (logger.isTraceEnabled()) {
                    logger.trace(attemptsLatch.getCount() + " attempts remaining. Will block " + " for " + blocksLatch.getCount() + " more ");
                }
                responses.put(node.getId(), response);
                if (response.getValue() instanceof Exception && isOperationCompleted.get()) {
                    handleException(response, pipeline);
                }
                attemptsLatch.countDown();
                blocksLatch.countDown();
            }
        };
        if (logger.isTraceEnabled())
            logger.info("Submitting " + pipeline.getOperation().getSimpleName() + " request on node " + node.getId());
        NonblockingStore store = nonblockingStores.get(node.getId());
        store.submitDeleteRequest(key, version, callback, timeoutMs);
    }
    try {
        long ellapsedNs = System.nanoTime() - beginTime;
        long remainingNs = (timeoutMs * Time.NS_PER_MS) - ellapsedNs;
        if (remainingNs > 0) {
            blocksLatch.await(remainingNs, TimeUnit.NANOSECONDS);
        }
    } catch (InterruptedException e) {
        if (logger.isEnabledFor(Level.WARN))
            logger.warn(e, e);
    }
    if (processResponses(responses, pipeline))
        return;
    // wait for more responses in case we did not have enough successful
    // response to achieve the required count
    boolean quorumSatisfied = true;
    if (pipelineData.getSuccesses() < required) {
        long ellapsedNs = System.nanoTime() - beginTime;
        long remainingNs = (timeoutMs * Time.NS_PER_MS) - ellapsedNs;
        if (remainingNs > 0) {
            try {
                attemptsLatch.await(remainingNs, TimeUnit.NANOSECONDS);
            } catch (InterruptedException e) {
                if (logger.isEnabledFor(Level.WARN))
                    logger.warn(e, e);
            }
            if (processResponses(responses, pipeline))
                return;
        }
        if (pipelineData.getSuccesses() < required) {
            pipelineData.setFatalError(new InsufficientOperationalNodesException(required + " " + pipeline.getOperation().getSimpleName() + "s required, but only " + pipelineData.getSuccesses() + " succeeded", pipelineData.getReplicationSet(), pipelineData.getNodes(), pipelineData.getFailedNodes(), pipelineData.getFailures()));
            abortPipeline(pipeline);
            quorumSatisfied = false;
        }
    }
    if (quorumSatisfied) {
        if (pipelineData.getZonesRequired() != null) {
            int zonesSatisfied = pipelineData.getZoneResponses().size();
            if (zonesSatisfied >= (pipelineData.getZonesRequired() + 1)) {
                completePipeline(pipeline);
            } else {
                long timeMs = (System.nanoTime() - beginTime) / Time.NS_PER_MS;
                if ((timeoutMs - timeMs) > 0) {
                    try {
                        attemptsLatch.await(timeoutMs - timeMs, TimeUnit.MILLISECONDS);
                    } catch (InterruptedException e) {
                        if (logger.isEnabledFor(Level.WARN))
                            logger.warn(e, e);
                    }
                    if (processResponses(responses, pipeline))
                        return;
                }
                if (pipelineData.getZoneResponses().size() >= (pipelineData.getZonesRequired() + 1)) {
                    completePipeline(pipeline);
                } else {
                    pipelineData.setFatalError(new InsufficientZoneResponsesException((pipelineData.getZonesRequired() + 1) + " " + pipeline.getOperation().getSimpleName() + "s required zone, but only " + zonesSatisfied + " succeeded"));
                    abortPipeline(pipeline);
                }
            }
        } else {
            completePipeline(pipeline);
        }
    }
}
Also used : NonblockingStore(voldemort.store.nonblockingstore.NonblockingStore) Node(voldemort.cluster.Node) CountDownLatch(java.util.concurrent.CountDownLatch) ObsoleteVersionException(voldemort.versioning.ObsoleteVersionException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) InsufficientZoneResponsesException(voldemort.store.InsufficientZoneResponsesException) UnreachableStoreException(voldemort.store.UnreachableStoreException) InvalidMetadataException(voldemort.store.InvalidMetadataException) QuotaExceededException(voldemort.store.quota.QuotaExceededException) Response(voldemort.store.routed.Response) NonblockingStoreCallback(voldemort.store.nonblockingstore.NonblockingStoreCallback) InsufficientZoneResponsesException(voldemort.store.InsufficientZoneResponsesException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) ByteArray(voldemort.utils.ByteArray) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 97 with Node

use of voldemort.cluster.Node in project voldemort by voldemort.

the class PerformParallelGetAllRequests method execute.

@SuppressWarnings("unchecked")
public void execute(final Pipeline pipeline) {
    int attempts = pipelineData.getNodeToKeysMap().size();
    final Map<Integer, Response<Iterable<ByteArray>, Object>> responses = new ConcurrentHashMap<Integer, Response<Iterable<ByteArray>, Object>>();
    final CountDownLatch latch = new CountDownLatch(attempts);
    if (logger.isTraceEnabled())
        logger.trace("Attempting " + attempts + " " + pipeline.getOperation().getSimpleName() + " operations in parallel");
    Map<ByteArray, byte[]> transforms = pipelineData.getTransforms();
    final AtomicBoolean isResponseProcessed = new AtomicBoolean(false);
    for (Map.Entry<Node, List<ByteArray>> entry : pipelineData.getNodeToKeysMap().entrySet()) {
        final Node node = entry.getKey();
        final Collection<ByteArray> keys = entry.getValue();
        NonblockingStoreCallback callback = new NonblockingStoreCallback() {

            public void requestComplete(Object result, long requestTime) {
                if (logger.isTraceEnabled())
                    logger.trace(pipeline.getOperation().getSimpleName() + " response received (" + requestTime + " ms.) from node " + node.getId());
                Response<Iterable<ByteArray>, Object> response = new Response<Iterable<ByteArray>, Object>(node, keys, result, requestTime);
                responses.put(node.getId(), response);
                latch.countDown();
                // This reduces the window where an exception is lost
                if (isResponseProcessed.get() && response.getValue() instanceof Exception)
                    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 {
                        handleResponseError(response, pipeline, failureDetector);
                    }
            }
        };
        if (logger.isTraceEnabled())
            logger.trace("Submitting " + pipeline.getOperation().getSimpleName() + " request on node " + node.getId());
        NonblockingStore store = nonblockingStores.get(node.getId());
        store.submitGetAllRequest(keys, transforms, callback, timeoutMs);
    }
    try {
        latch.await(timeoutMs, TimeUnit.MILLISECONDS);
    } catch (InterruptedException e) {
        if (logger.isEnabledFor(Level.WARN))
            logger.warn(e, e);
    }
    for (Response<Iterable<ByteArray>, Object> response : responses.values()) {
        if (response.getValue() instanceof Exception) {
            if (handleResponseError(response, pipeline, failureDetector))
                return;
        } else {
            Map<ByteArray, List<Versioned<byte[]>>> values = (Map<ByteArray, List<Versioned<byte[]>>>) response.getValue();
            for (ByteArray key : response.getKey()) {
                MutableInt successCount = pipelineData.getSuccessCount(key);
                successCount.increment();
                List<Versioned<byte[]>> retrieved = values.get(key);
                /*
                     * retrieved can be null if there are no values for the key
                     * provided
                     */
                if (retrieved != null) {
                    List<Versioned<byte[]>> existing = pipelineData.getResult().get(key);
                    if (existing == null)
                        pipelineData.getResult().put(key, Lists.newArrayList(retrieved));
                    else
                        existing.addAll(retrieved);
                }
                HashSet<Integer> zoneResponses = null;
                if (pipelineData.getKeyToZoneResponse().containsKey(key)) {
                    zoneResponses = pipelineData.getKeyToZoneResponse().get(key);
                } else {
                    zoneResponses = new HashSet<Integer>();
                    pipelineData.getKeyToZoneResponse().put(key, zoneResponses);
                }
                zoneResponses.add(response.getNode().getZoneId());
            }
            pipelineData.getResponses().add(new Response<Iterable<ByteArray>, Map<ByteArray, List<Versioned<byte[]>>>>(response.getNode(), response.getKey(), values, response.getRequestTime()));
            failureDetector.recordSuccess(response.getNode(), response.getRequestTime());
        }
    }
    isResponseProcessed.set(true);
    pipeline.addEvent(completeEvent);
}
Also used : Versioned(voldemort.versioning.Versioned) Node(voldemort.cluster.Node) InvalidMetadataException(voldemort.store.InvalidMetadataException) NonblockingStoreCallback(voldemort.store.nonblockingstore.NonblockingStoreCallback) ByteArray(voldemort.utils.ByteArray) List(java.util.List) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) NonblockingStore(voldemort.store.nonblockingstore.NonblockingStore) CountDownLatch(java.util.concurrent.CountDownLatch) InvalidMetadataException(voldemort.store.InvalidMetadataException) Response(voldemort.store.routed.Response) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MutableInt(org.apache.commons.lang.mutable.MutableInt) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Map(java.util.Map)

Example 98 with Node

use of voldemort.cluster.Node 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 99 with Node

use of voldemort.cluster.Node in project voldemort by voldemort.

the class PerformParallelRequests method execute.

public void execute(final Pipeline pipeline) {
    List<Node> nodes = pipelineData.getNodes();
    int attempts = Math.min(preferred, nodes.size());
    final Map<Integer, Response<ByteArray, Object>> responses = new ConcurrentHashMap<Integer, Response<ByteArray, Object>>();
    final CountDownLatch latch = new CountDownLatch(attempts);
    if (logger.isTraceEnabled())
        logger.trace("Attempting " + attempts + " " + pipeline.getOperation().getSimpleName() + " operations in parallel for key " + key);
    final AtomicBoolean isResponseProcessed = new AtomicBoolean(false);
    for (int i = 0; i < attempts; i++) {
        final Node node = nodes.get(i);
        pipelineData.incrementNodeIndex();
        final long startMs = logger.isDebugEnabled() ? System.currentTimeMillis() : -1;
        NonblockingStoreCallback callback = new NonblockingStoreCallback() {

            public void requestComplete(Object result, long requestTime) {
                if (logger.isTraceEnabled())
                    logger.trace(pipeline.getOperation().getSimpleName() + " response received (" + requestTime + " ms.) from node " + node.getId() + "for key " + key);
                Response<ByteArray, Object> response = new Response<ByteArray, Object>(node, key, result, requestTime);
                if (logger.isDebugEnabled())
                    logger.debug("Finished " + pipeline.getOperation().getSimpleName() + " for key " + ByteUtils.toHexString(key.get()) + " (keyRef: " + System.identityHashCode(key) + "); started at " + startMs + " took " + requestTime + " ms on node " + node.getId() + "(" + node.getHost() + ")");
                responses.put(node.getId(), response);
                latch.countDown();
                // This reduces the window where an exception is lost
                if (isResponseProcessed.get() && response.getValue() instanceof Exception) {
                    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() + "' for key " + key);
                    } 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());
        if (pipeline.getOperation() == Operation.GET)
            store.submitGetRequest(key, transforms, callback, timeoutMs);
        else if (pipeline.getOperation() == Operation.GET_VERSIONS)
            store.submitGetVersionsRequest(key, callback, timeoutMs);
        else
            throw new IllegalStateException(getClass().getName() + " does not support pipeline operation " + pipeline.getOperation());
    }
    try {
        latch.await(timeoutMs, TimeUnit.MILLISECONDS);
    } catch (InterruptedException e) {
        if (logger.isEnabledFor(Level.WARN))
            logger.warn(e, e);
    }
    for (Response<ByteArray, Object> response : responses.values()) {
        if (response.getValue() instanceof Exception) {
            if (handleResponseError(response, pipeline, failureDetector))
                return;
        } else {
            pipelineData.incrementSuccesses();
            Response<ByteArray, V> rCast = Utils.uncheckedCast(response);
            pipelineData.getResponses().add(rCast);
            failureDetector.recordSuccess(response.getNode(), response.getRequestTime());
            pipelineData.getZoneResponses().add(response.getNode().getZoneId());
        }
    }
    isResponseProcessed.set(true);
    if (logger.isDebugEnabled())
        logger.debug("GET for key " + ByteUtils.toHexString(key.get()) + " (keyRef: " + System.identityHashCode(key) + "); successes: " + pipelineData.getSuccesses() + " preferred: " + preferred + " required: " + required);
    if (pipelineData.getSuccesses() < required) {
        if (insufficientSuccessesEvent != null) {
            pipeline.addEvent(insufficientSuccessesEvent);
        } else {
            pipelineData.setFatalError(new InsufficientOperationalNodesException(required + " " + pipeline.getOperation().getSimpleName() + "s required, but only " + pipelineData.getSuccesses() + " succeeded", pipelineData.getReplicationSet(), pipelineData.getNodes(), pipelineData.getFailedNodes(), pipelineData.getFailures()));
            pipeline.abort();
        }
    } else {
        if (pipelineData.getZonesRequired() != null) {
            int zonesSatisfied = pipelineData.getZoneResponses().size();
            if (zonesSatisfied >= (pipelineData.getZonesRequired() + 1)) {
                pipeline.addEvent(completeEvent);
            } else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Operation " + pipeline.getOperation().getSimpleName() + "failed due to insufficient zone responses, required " + pipelineData.getZonesRequired() + " obtained " + zonesSatisfied + " " + pipelineData.getZoneResponses() + " for key " + key);
                }
                if (this.insufficientZonesEvent != null) {
                    pipeline.addEvent(this.insufficientZonesEvent);
                } else {
                    pipelineData.setFatalError(new InsufficientZoneResponsesException((pipelineData.getZonesRequired() + 1) + " " + pipeline.getOperation().getSimpleName() + "s required zone, but only " + zonesSatisfied + " succeeded"));
                }
            }
        } else {
            pipeline.addEvent(completeEvent);
        }
    }
}
Also used : NonblockingStore(voldemort.store.nonblockingstore.NonblockingStore) Node(voldemort.cluster.Node) InvalidMetadataException(voldemort.store.InvalidMetadataException) CountDownLatch(java.util.concurrent.CountDownLatch) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) InsufficientZoneResponsesException(voldemort.store.InsufficientZoneResponsesException) InvalidMetadataException(voldemort.store.InvalidMetadataException) Response(voldemort.store.routed.Response) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) NonblockingStoreCallback(voldemort.store.nonblockingstore.NonblockingStoreCallback) InsufficientZoneResponsesException(voldemort.store.InsufficientZoneResponsesException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) ByteArray(voldemort.utils.ByteArray) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 100 with Node

use of voldemort.cluster.Node in project voldemort by voldemort.

the class PerformSerialPutRequests method execute.

public void execute(Pipeline pipeline) {
    int currentNode = 0;
    List<Node> nodes = pipelineData.getNodes();
    long startMasterMs = -1;
    long startMasterNs = -1;
    if (logger.isDebugEnabled()) {
        startMasterMs = System.currentTimeMillis();
        startMasterNs = System.nanoTime();
    }
    if (logger.isDebugEnabled())
        logger.debug("Performing serial put requests to determine master");
    Node node = null;
    for (; currentNode < nodes.size(); currentNode++) {
        node = nodes.get(currentNode);
        pipelineData.incrementNodeIndex();
        VectorClock versionedClock = (VectorClock) versioned.getVersion();
        final Versioned<byte[]> versionedCopy = new Versioned<byte[]>(versioned.getValue(), versionedClock.incremented(node.getId(), time.getMilliseconds()));
        if (logger.isDebugEnabled())
            logger.debug("Attempt #" + (currentNode + 1) + " to perform put (node " + node.getId() + ")");
        long start = System.nanoTime();
        try {
            stores.get(node.getId()).put(key, versionedCopy, transforms);
            long requestTime = (System.nanoTime() - start) / Time.NS_PER_MS;
            pipelineData.incrementSuccesses();
            failureDetector.recordSuccess(node, requestTime);
            if (logger.isDebugEnabled())
                logger.debug("Put on node " + node.getId() + " succeeded, using as master");
            pipelineData.setMaster(node);
            pipelineData.setVersionedCopy(versionedCopy);
            pipelineData.getZoneResponses().add(node.getZoneId());
            currentNode++;
            break;
        } catch (Exception e) {
            long requestTime = (System.nanoTime() - start) / Time.NS_PER_MS;
            if (logger.isDebugEnabled())
                logger.debug("Master PUT at node " + currentNode + "(" + node.getHost() + ")" + " failed (" + e.getMessage() + ") in " + (System.nanoTime() - start) + " ns" + " (keyRef: " + System.identityHashCode(key) + ")");
            if (PipelineRoutedStore.isSlopableFailure(e)) {
                pipelineData.getSynchronizer().tryDelegateSlop(node);
            }
            if (handleResponseError(e, node, requestTime, pipeline, failureDetector))
                return;
        }
    }
    if (logger.isTraceEnabled()) {
        logger.trace("PUT {key:" + key + "} currentNode=" + currentNode + " nodes.size()=" + nodes.size());
    }
    if (pipelineData.getSuccesses() < 1) {
        List<Exception> failures = pipelineData.getFailures();
        pipelineData.setFatalError(new InsufficientOperationalNodesException("No master node succeeded!", failures.size() > 0 ? failures.get(0) : null));
        pipeline.abort();
        return;
    }
    // There aren't any more requests to make...
    if (currentNode == nodes.size()) {
        if (pipelineData.getSuccesses() < required) {
            pipelineData.setFatalError(new InsufficientOperationalNodesException(required + " " + pipeline.getOperation().getSimpleName() + "s required, but only " + pipelineData.getSuccesses() + " succeeded", pipelineData.getReplicationSet(), pipelineData.getNodes(), pipelineData.getFailedNodes(), pipelineData.getFailures()));
            pipeline.abort();
        } else {
            if (pipelineData.getZonesRequired() != null) {
                int zonesSatisfied = pipelineData.getZoneResponses().size();
                if (zonesSatisfied >= (pipelineData.getZonesRequired() + 1)) {
                    pipeline.addEvent(completeEvent);
                } else {
                    pipelineData.setFatalError(new InsufficientZoneResponsesException((pipelineData.getZonesRequired() + 1) + " " + pipeline.getOperation().getSimpleName() + "s required zone, but only " + zonesSatisfied + " succeeded"));
                    pipeline.abort();
                }
            } else {
                if (logger.isDebugEnabled())
                    logger.debug("Finished master PUT for key " + ByteUtils.toHexString(key.get()) + " (keyRef: " + System.identityHashCode(key) + "); started at " + startMasterMs + " took " + (System.nanoTime() - startMasterNs) + " ns on node " + (node == null ? "NULL" : node.getId()) + "(" + (node == null ? "NULL" : node.getHost()) + "); now complete");
                pipeline.addEvent(completeEvent);
            }
        }
    } else {
        if (logger.isDebugEnabled())
            logger.debug("Finished master PUT for key " + ByteUtils.toHexString(key.get()) + " (keyRef: " + System.identityHashCode(key) + "); started at " + startMasterMs + " took " + (System.nanoTime() - startMasterNs) + " ns on node " + (node == null ? "NULL" : node.getId()) + "(" + (node == null ? "NULL" : node.getHost()) + ")");
        pipeline.addEvent(masterDeterminedEvent);
    }
}
Also used : Versioned(voldemort.versioning.Versioned) InsufficientZoneResponsesException(voldemort.store.InsufficientZoneResponsesException) Node(voldemort.cluster.Node) VectorClock(voldemort.versioning.VectorClock) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) InsufficientOperationalNodesException(voldemort.store.InsufficientOperationalNodesException) InsufficientZoneResponsesException(voldemort.store.InsufficientZoneResponsesException)

Aggregations

Node (voldemort.cluster.Node)253 Cluster (voldemort.cluster.Cluster)72 ByteArray (voldemort.utils.ByteArray)61 ArrayList (java.util.ArrayList)60 Test (org.junit.Test)58 VoldemortException (voldemort.VoldemortException)50 HashMap (java.util.HashMap)43 StoreDefinition (voldemort.store.StoreDefinition)43 Properties (java.util.Properties)28 UnreachableStoreException (voldemort.store.UnreachableStoreException)27 Versioned (voldemort.versioning.Versioned)27 List (java.util.List)26 AdminClient (voldemort.client.protocol.admin.AdminClient)25 File (java.io.File)24 IOException (java.io.IOException)24 VoldemortServer (voldemort.server.VoldemortServer)23 InsufficientOperationalNodesException (voldemort.store.InsufficientOperationalNodesException)23 Store (voldemort.store.Store)23 Before (org.junit.Before)21 RoutingStrategy (voldemort.routing.RoutingStrategy)21