@Override public void close() { VoldemortException exception = null; for (NonblockingStore store : nonblockingStores.values()) { try { store.close(); } catch (VoldemortException e) { exception = e; } } if (this.jmxEnabled) { JmxUtils.unregisterMbean( JmxUtils.createObjectName( JmxUtils.getPackageName(stats.getClass()), getName() + identifierString)); } if (exception != null) throw exception; super.close(); }
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 (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); responses.put(node.getId(), response); latch.countDown(); // Note errors that come in after the pipeline has finished. // These will *not* get a chance to be called in the loop of // responses below. if (pipeline.isFinished() && response.getValue() instanceof Exception) { if (response.getValue() instanceof InvalidMetadataException) { 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()); 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()); } } 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.getFailures())); pipeline.abort(); } } else { if (pipelineData.getZonesRequired() != null) { int zonesSatisfied = pipelineData.getZoneResponses().size(); if (zonesSatisfied >= (pipelineData.getZonesRequired() + 1)) { pipeline.addEvent(completeEvent); } else { 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); } } }