@Override
  public Future<GetBlobResult> getBlob(String blobId, GetBlobOptions options, Callback<GetBlobResult> callback,
      QuotaChargeCallback quotaChargeCallback) {
    FutureResult<GetBlobResult> futureResult = new FutureResult<>();
    if (!handlePrechecks(futureResult, callback)) {
      return futureResult;
    }
    ReadableStreamChannel blobDataChannel = null;
    BlobInfo blobInfo = null;
    List<StoreKey> blobChunkIds = new ArrayList<>();
    Exception exception = null;
    try {
      checkBlobId(blobId);
      if (deletedBlobs.contains(blobId) && !ALLOW_DELETED_BLOB_GET.contains(options.getGetOption())) {
        exception = new RouterException("Blob deleted", RouterErrorCode.BlobDeleted);
      } else if (!blobs.containsKey(blobId)) {
        exception = new RouterException("Blob not found", RouterErrorCode.BlobDoesNotExist);
      } else {
        InMemoryBlob blob = blobs.get(blobId);
        long expiresAtMs = Utils.addSecondsToEpochTime(blob.getBlobProperties().getCreationTimeInMs(),
            blob.getBlobProperties().getTimeToLiveInSeconds());
        if (expiresAtMs == Utils.Infinite_Time || expiresAtMs > SystemTime.getInstance().milliseconds()
            || ALLOW_EXPIRED_BLOB_GET.contains(options.getGetOption())) {
          switch (options.getOperationType()) {
            case Data:
              blobDataChannel = new ByteBufferRSC(blob.getBlob(options));
              break;
            case BlobInfo:
              blobInfo = new BlobInfo(blob.getBlobProperties(), blob.getUserMetadata());
              break;
            case BlobChunkIds:
              blobInfo = new BlobInfo(blob.getBlobProperties(), blob.getUserMetadata());
              blobChunkIds = new ArrayList<>(mockedBlobChunkIds);
              break;
            case All:
              blobDataChannel = new ByteBufferRSC(blob.getBlob(options));
              blobInfo = new BlobInfo(blob.getBlobProperties(), blob.getUserMetadata());
              break;
          }
        } else {
          exception = new RouterException("Blob expired", RouterErrorCode.BlobExpired);
        }
      }
    } catch (RouterException e) {
      exception = e;
    } catch (Exception e) {
      exception = new RouterException(e, RouterErrorCode.UnexpectedInternalError);
    } finally {
      GetBlobResult operationResult =
          exception == null ? new GetBlobResult(blobInfo, blobDataChannel, blobChunkIds) : null;
      completeOperation(futureResult, callback, operationResult, exception);
    }
    return futureResult;
  }
Set the lifeVersion of this blob.
@param lifeVersion The lifeVersion to set.
ambry-test-utils/src/main/java/com/github/ambry/router/InMemoryRouter.java