public void put(
      ByteArray key, Versioned<byte[]> versioned, byte[] transforms, long putOpTimeoutInMs)
      throws VoldemortException {

    long startTimeMs = -1;
    long startTimeNs = -1;

    if (logger.isDebugEnabled()) {
      startTimeMs = System.currentTimeMillis();
      startTimeNs = System.nanoTime();
    }

    StoreUtils.assertValidKey(key);
    PutPipelineData pipelineData = new PutPipelineData();
    if (zoneRoutingEnabled) pipelineData.setZonesRequired(storeDef.getZoneCountWrites());
    else pipelineData.setZonesRequired(null);
    pipelineData.setStartTimeNs(System.nanoTime());
    pipelineData.setStoreName(getName());
    pipelineData.setStats(stats);

    Pipeline pipeline = new Pipeline(Operation.PUT, putOpTimeoutInMs, TimeUnit.MILLISECONDS);
    pipeline.setEnableHintedHandoff(isHintedHandoffEnabled());

    HintedHandoff hintedHandoff = null;

    // Get the correct type of configure nodes action depending on the store
    // requirements
    AbstractConfigureNodes<ByteArray, Void, PutPipelineData> configureNodes =
        makeNodeConfigurationForPut(pipelineData, key);

    if (isHintedHandoffEnabled())
      hintedHandoff =
          new HintedHandoff(
              failureDetector,
              slopStores,
              nonblockingSlopStores,
              handoffStrategy,
              pipelineData.getFailedNodes(),
              putOpTimeoutInMs);

    pipeline.addEventAction(Event.STARTED, configureNodes);

    pipeline.addEventAction(
        Event.CONFIGURED,
        new PerformSerialPutRequests(
            pipelineData,
            isHintedHandoffEnabled() ? Event.RESPONSES_RECEIVED : Event.COMPLETED,
            key,
            transforms,
            failureDetector,
            innerStores,
            storeDef.getRequiredWrites(),
            versioned,
            time,
            Event.MASTER_DETERMINED));
    pipeline.addEventAction(
        Event.MASTER_DETERMINED,
        new PerformParallelPutRequests(
            pipelineData,
            Event.RESPONSES_RECEIVED,
            key,
            transforms,
            failureDetector,
            storeDef.getPreferredWrites(),
            storeDef.getRequiredWrites(),
            putOpTimeoutInMs,
            nonblockingStores,
            hintedHandoff));
    if (isHintedHandoffEnabled()) {
      pipeline.addEventAction(
          Event.ABORTED,
          new PerformPutHintedHandoff(
              pipelineData, Event.ERROR, key, versioned, transforms, hintedHandoff, time));
      pipeline.addEventAction(
          Event.RESPONSES_RECEIVED,
          new PerformPutHintedHandoff(
              pipelineData,
              Event.HANDOFF_FINISHED,
              key,
              versioned,
              transforms,
              hintedHandoff,
              time));
      pipeline.addEventAction(
          Event.HANDOFF_FINISHED,
          new IncrementClock(pipelineData, Event.COMPLETED, versioned, time));
    } else
      pipeline.addEventAction(
          Event.RESPONSES_RECEIVED,
          new IncrementClock(pipelineData, Event.COMPLETED, versioned, time));

    pipeline.addEvent(Event.STARTED);
    if (logger.isDebugEnabled()) {
      logger.debug(
          "Operation "
              + pipeline.getOperation().getSimpleName()
              + " Key "
              + ByteUtils.toHexString(key.get()));
    }
    try {
      pipeline.execute();
    } catch (VoldemortException e) {
      stats.reportException(e);
      throw e;
    }

    if (logger.isDebugEnabled()) {
      logger.debug(
          "Finished "
              + pipeline.getOperation().getSimpleName()
              + " for key "
              + ByteUtils.toHexString(key.get())
              + " keyRef: "
              + System.identityHashCode(key)
              + "; started at "
              + startTimeMs
              + " took "
              + (System.nanoTime() - startTimeNs)
              + " value: "
              + versioned.getValue()
              + " (size: "
              + versioned.getValue().length
              + ")");
    }

    if (pipelineData.getFatalError() != null) throw pipelineData.getFatalError();
  }
  protected boolean delete(final ByteArray key, final Version version, long deleteOpTimeout)
      throws VoldemortException {
    StoreUtils.assertValidKey(key);

    long startTimeMs = -1;
    long startTimeNs = -1;

    if (logger.isDebugEnabled()) {
      startTimeMs = System.currentTimeMillis();
      startTimeNs = System.nanoTime();
    }

    BasicPipelineData<Boolean> pipelineData = new BasicPipelineData<Boolean>();
    if (zoneRoutingEnabled) pipelineData.setZonesRequired(storeDef.getZoneCountWrites());
    else pipelineData.setZonesRequired(null);
    pipelineData.setStoreName(getName());
    pipelineData.setStats(stats);

    Pipeline pipeline = new Pipeline(Operation.DELETE, deleteOpTimeout, TimeUnit.MILLISECONDS);
    pipeline.setEnableHintedHandoff(isHintedHandoffEnabled());

    HintedHandoff hintedHandoff = null;

    if (isHintedHandoffEnabled())
      hintedHandoff =
          new HintedHandoff(
              failureDetector,
              slopStores,
              nonblockingSlopStores,
              handoffStrategy,
              pipelineData.getFailedNodes(),
              deleteOpTimeout);

    pipeline.addEventAction(
        Event.STARTED,
        new ConfigureNodes<Boolean, BasicPipelineData<Boolean>>(
            pipelineData,
            Event.CONFIGURED,
            failureDetector,
            storeDef.getRequiredWrites(),
            routingStrategy,
            key,
            clientZone));
    pipeline.addEventAction(
        Event.CONFIGURED,
        new PerformParallelDeleteRequests<Boolean, BasicPipelineData<Boolean>>(
            pipelineData,
            isHintedHandoffEnabled() ? Event.RESPONSES_RECEIVED : Event.COMPLETED,
            key,
            failureDetector,
            storeDef.getPreferredWrites(),
            storeDef.getRequiredWrites(),
            deleteOpTimeout,
            nonblockingStores,
            hintedHandoff,
            version));

    if (isHintedHandoffEnabled()) {
      pipeline.addEventAction(
          Event.RESPONSES_RECEIVED,
          new PerformDeleteHintedHandoff(
              pipelineData, Event.COMPLETED, key, version, hintedHandoff));
      pipeline.addEventAction(
          Event.ABORTED,
          new PerformDeleteHintedHandoff(pipelineData, Event.ERROR, key, version, hintedHandoff));
    }

    pipeline.addEvent(Event.STARTED);
    if (logger.isDebugEnabled()) {
      logger.debug(
          "Operation "
              + pipeline.getOperation().getSimpleName()
              + " Key "
              + ByteUtils.toHexString(key.get()));
    }
    try {
      pipeline.execute();
    } catch (VoldemortException e) {
      stats.reportException(e);
      throw e;
    }

    if (logger.isDebugEnabled()) {
      logger.debug(
          "Finished "
              + pipeline.getOperation().getSimpleName()
              + " for key "
              + ByteUtils.toHexString(key.get())
              + " keyRef: "
              + System.identityHashCode(key)
              + "; started at "
              + startTimeMs
              + " took "
              + (System.nanoTime() - startTimeNs));
    }

    if (pipelineData.getFatalError() != null) throw pipelineData.getFatalError();

    for (Response<ByteArray, Boolean> response : pipelineData.getResponses()) {
      if (response.getValue().booleanValue()) return true;
    }

    return false;
  }