private boolean preDeleteValidation(CloudBlobMetadata metadata, StoreKey key, Map<String, Object> updateFields)
      throws StoreException {
    validateAccountAndContainer(Collections.singletonMap(key.getID(), metadata), Collections.singletonList(key));
    short requestedLifeVersion = (short) updateFields.get(FIELD_LIFE_VERSION);
    if (isVcr) {
      // This is a delete request from vcr. Apply delete only if incoming life version is more recent. Don't throw
      // any exception because replication relies on findMissingKeys which in turn is dependent on {@link CloudDestination}
      // implementation and can have some inconsistencies.
      return (!metadata.isDeleted() || metadata.getLifeVersion() < requestedLifeVersion) && (metadata.getLifeVersion()
          <= requestedLifeVersion);
    }
    if (requestedLifeVersion == MessageInfo.LIFE_VERSION_FROM_FRONTEND) {
      // This is a delete request from frontend
      if (metadata.isDeleted()) {
        throw new StoreException("Cannot delete id " + key.getID() + " since it is already marked as deleted in cloud.",
            StoreErrorCodes.IDDeleted);
      }
      // this is delete request from frontend, we use life version only for validation.
      updateFields.remove(FIELD_LIFE_VERSION);
    }
    return true;
  }
Validates existing metadata in cloud destination against requested update for delete.
@param metadata existing {@link CloudBlobMetadata} in cloud.
@param key {@link StoreKey} being deleted.
@param updateFields {@link Map} of fields and values being updated.
@return false only for vcr if local cloud destination life version is more recent. true if validation successful.
@throws StoreException if validation fails.
ambry-cloud/src/main/java/com/github/ambry/cloud/CloudBlobStore.java