use of voldemort.store.nonblockingstore.NonblockingStore 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);
}
}
}
use of voldemort.store.nonblockingstore.NonblockingStore in project voldemort by voldemort.
the class StorageService method registerNodeStores.
/**
* For server side routing create NodeStore (socketstore) and pass it on to
* a {@link RebootstrappingStore}.
* <p>
*
* The {@link RebootstrappingStore} handles invalid-metadata exceptions
* introduced due to changes in cluster.xml at different nodes.
*
* @param def
* @param cluster
* @param localNode
*/
public void registerNodeStores(StoreDefinition def, Cluster cluster, int localNode) {
Map<Integer, Store<ByteArray, byte[], byte[]>> nodeStores = new HashMap<Integer, Store<ByteArray, byte[], byte[]>>(cluster.getNumberOfNodes());
Map<Integer, NonblockingStore> nonblockingStores = new HashMap<Integer, NonblockingStore>(cluster.getNumberOfNodes());
try {
for (Node node : cluster.getNodes()) {
Store<ByteArray, byte[], byte[]> store = getNodeStore(def.getName(), node, localNode);
this.storeRepository.addNodeStore(node.getId(), store);
nodeStores.put(node.getId(), store);
NonblockingStore nonblockingStore = routedStoreFactory.toNonblockingStore(store);
nonblockingStores.put(node.getId(), nonblockingStore);
}
Store<ByteArray, byte[], byte[]> store = routedStoreFactory.create(cluster, def, nodeStores, nonblockingStores, null, null, failureDetector, routedStoreConfig);
store = new RebootstrappingStore(metadata, storeRepository, voldemortConfig, (RoutedStore) store, storeFactory);
store = new InconsistencyResolvingStore<ByteArray, byte[], byte[]>(store, new VectorClockInconsistencyResolver<byte[]>());
this.storeRepository.addRoutedStore(store);
} catch (Exception e) {
// Roll back
for (Node node : cluster.getNodes()) this.storeRepository.removeNodeStore(def.getName(), node.getId());
throw new VoldemortException(e);
}
}
use of voldemort.store.nonblockingstore.NonblockingStore in project voldemort by voldemort.
the class HintedHandoffFailureTest method customSetup.
/**
* Setup a cluster with 3 nodes, with the following characteristics:
*
* If FAILURE_MODE is FAIL_FIRST_REPLICA_NODE set the first replica store to
* a sleepy force failing store
*
* If FAILURE_MODE is FAIL_ALL_REPLICAS: set all replicas to sleepy force
* failing store
*
* Pseudo master : Standard In-memory store (wrapped by Logging store)
*
* In memory slop stores
*
* @param key The ByteArray representation of the key
* @param failureMode The Failure mode for the replicas
*
* @throws Exception
*/
public List<Integer> customSetup(ByteArray key, FAILURE_MODE failureMode, ReplicaFactor replicaFactor, long sleepTime, long hintDelayTimeMs) throws Exception {
cluster = getThreeNodeCluster();
storeDef = getStoreDef(STORE_NAME, replicaFactor, RoutingStrategyType.CONSISTENT_STRATEGY);
strategy = new RoutingStrategyFactory().updateRoutingStrategy(storeDef, cluster);
InMemoryStorageEngine<ByteArray, byte[], byte[]> inMemoryStorageEngine = new InMemoryStorageEngine<ByteArray, byte[], byte[]>(STORE_NAME);
LoggingStore<ByteArray, byte[], byte[]> loggingStore = new LoggingStore<ByteArray, byte[], byte[]>(inMemoryStorageEngine);
VoldemortException e = new UnreachableStoreException("Node down");
ForceFailStore<ByteArray, byte[], byte[]> failureStore = new ForceFailStore<ByteArray, byte[], byte[]>(loggingStore, e);
SleepyStore<ByteArray, byte[], byte[]> sleepyFailureStore = new SleepyStore<ByteArray, byte[], byte[]>(sleepTime, failureStore);
failureStore.setFail(true);
List<Integer> failingNodeIdList = Lists.newArrayList();
List<Node> replicaList = strategy.routeRequest(key.get());
switch(failureMode) {
case FAIL_FIRST_REPLICA_NODE:
failingNodeIdList.add(replicaList.get(1).getId());
break;
case FAIL_ALL_REPLICAS:
for (int nodeId = 1; nodeId < replicaList.size(); nodeId++) {
failingNodeIdList.add(nodeId);
}
break;
}
subStores.clear();
for (int i = 0; i < NUM_NODES_TOTAL; i++) {
if (failingNodeIdList.contains(i)) {
subStores.put(i, sleepyFailureStore);
} else {
subStores.put(i, loggingStore);
}
}
setFailureDetector(subStores);
routedStoreThreadPool = Executors.newFixedThreadPool(NUM_THREADS);
routedStoreFactory = new RoutedStoreFactory(routedStoreThreadPool);
Map<Integer, NonblockingStore> nonblockingSlopStores = Maps.newHashMap();
for (Node node : cluster.getNodes()) {
int nodeId = node.getId();
SlopStorageEngine slopStorageEngine = new SlopStorageEngine(new InMemoryStorageEngine<ByteArray, byte[], byte[]>(SLOP_STORE_NAME), cluster);
StorageEngine<ByteArray, Slop, byte[]> storageEngine = slopStorageEngine.asSlopStore();
nonblockingSlopStores.put(nodeId, routedStoreFactory.toNonblockingStore(slopStorageEngine));
slopStores.put(nodeId, storageEngine);
}
Map<Integer, NonblockingStore> nonblockingStores = Maps.newHashMap();
for (Map.Entry<Integer, Store<ByteArray, byte[], byte[]>> entry : subStores.entrySet()) nonblockingStores.put(entry.getKey(), routedStoreFactory.toNonblockingStore(entry.getValue()));
store = new DelayedPutPipelineRoutedStore(subStores, nonblockingStores, slopStores, nonblockingSlopStores, cluster, storeDef, failureDetector, hintDelayTimeMs);
return failingNodeIdList;
}
use of voldemort.store.nonblockingstore.NonblockingStore in project voldemort by voldemort.
the class HintedHandoff method sendOneAsyncHint.
/**
* A callback that handles requestComplete event from NIO selector manager
* Will try any possible nodes and pass itself as callback util all nodes
* are exhausted
*
* @param slopKey
* @param slopVersioned
* @param nodesToTry List of nodes to try to contact. Will become shorter
* after each callback
*/
private void sendOneAsyncHint(final ByteArray slopKey, final Versioned<byte[]> slopVersioned, final List<Node> nodesToTry) {
Node nodeToHostHint = null;
boolean foundNode = false;
while (nodesToTry.size() > 0) {
nodeToHostHint = nodesToTry.remove(0);
if (!failedNodes.contains(nodeToHostHint) && failureDetector.isAvailable(nodeToHostHint)) {
foundNode = true;
break;
}
}
if (!foundNode) {
Slop slop = slopSerializer.toObject(slopVersioned.getValue());
logger.error("Trying to send an async hint but used up all nodes. key: " + slop.getKey() + " version: " + slopVersioned.getVersion().toString());
return;
}
final Node node = nodeToHostHint;
int nodeId = node.getId();
NonblockingStore nonblockingStore = nonblockingSlopStores.get(nodeId);
Utils.notNull(nonblockingStore);
final Long startNs = System.nanoTime();
NonblockingStoreCallback callback = new NonblockingStoreCallback() {
@Override
public void requestComplete(Object result, long requestTime) {
Slop slop = null;
boolean loggerDebugEnabled = logger.isDebugEnabled();
if (loggerDebugEnabled) {
slop = slopSerializer.toObject(slopVersioned.getValue());
}
Response<ByteArray, Object> response = new Response<ByteArray, Object>(node, slopKey, result, requestTime);
if (response.getValue() instanceof Exception && !(response.getValue() instanceof ObsoleteVersionException)) {
if (!failedNodes.contains(node))
failedNodes.add(node);
if (response.getValue() instanceof UnreachableStoreException) {
UnreachableStoreException use = (UnreachableStoreException) response.getValue();
if (loggerDebugEnabled) {
logger.debug("Write of key " + slop.getKey() + " for " + slop.getNodeId() + " to node " + node + " failed due to unreachable: " + use.getMessage());
}
failureDetector.recordException(node, (System.nanoTime() - startNs) / Time.NS_PER_MS, use);
}
sendOneAsyncHint(slopKey, slopVersioned, nodesToTry);
}
if (loggerDebugEnabled)
logger.debug("Slop write of key " + slop.getKey() + " for node " + slop.getNodeId() + " to node " + node + " succeeded in " + (System.nanoTime() - startNs) + " ns");
failureDetector.recordSuccess(node, (System.nanoTime() - startNs) / Time.NS_PER_MS);
}
};
nonblockingStore.submitPutRequest(slopKey, slopVersioned, null, callback, timeoutMs);
}
use of voldemort.store.nonblockingstore.NonblockingStore in project voldemort by voldemort.
the class PipelineRoutedStore method close.
@Override
public void close() {
VoldemortException exception = null;
for (NonblockingStore store : nonblockingStores.values()) {
try {
store.close();
} catch (VoldemortException e) {
exception = e;
}
}
if (this.jmxEnabled) {
this.stats.unregisterJmxIfRequired();
}
if (exception != null)
throw exception;
super.close();
}
Aggregations