code: private CompletableFuture<Void> validateConditionalUpdate(DirectSegmentAccess segment, TableKeyBatch batch, TimeoutTimer timer) {
          Exceptions.checkNotClosed(this.closed.get(), this);
          List<UUID> hashes = batch.getVersionedItems().stream()
                  .map(TableKeyBatch.Item::getHash)
                  .collect(Collectors.toList());
          CompletableFuture<Void> result = getBucketOffsets(segment, hashes, timer)
                  .thenAccept(offsets -> validateConditionalUpdate(batch.getVersionedItems(), offsets, segment.getInfo().getName()));
          return Futures.exceptionallyCompose(
                  result,
                  ex -> {
                      ex = Exceptions.unwrap(ex);
                      if (ex instanceof BadKeyVersionException) {
                          return validateConditionalUpdateFailures(segment, ((BadKeyVersionException) ex).getExpectedVersions(), timer);
                      }
  
                      // Some other exception. Re-throw.
                      return Futures.failedFuture(ex);
                  });
      }
docs: Validates all the conditional updates specified in the given TableKeyBatch.
  
  @param segment The Segment to operate on.
  @param batch   The TableKeyBatch to validate.
  @param timer   Timer for the operation.
  @return A CompletableFuture that, when completed, will indicate that validation succeeded. If the validation did
  not pass, it will be failed with the appropriate exception. Notable exceptions:
  <ul>
  <li>{@link KeyNotExistsException} If a Key does not exist and was conditioned as having to exist.
  <li>{@link BadKeyVersionException} If a Key does exist but had a version mismatch.
  </ul>