protected boolean maybeLaunchCryptoJob(ByteBuf dataBuf, byte[] userMetadata, ByteBuffer encryptionKey,
        BlobId targetBlobId) {
      //
      // Three cases to handle:
      // 1) rawMode false and encryptionKey not null => decrypt buffer
      // 2) rawMode true and encryptionKey is null => encrypt buffer (later)
      // 3) other cases => leave buffer as is
      //
      boolean rawMode = options.getBlobOptions.isRawMode();
      if ((encryptionKey == null && !rawMode) || (encryptionKey != null && rawMode)) {
        return false;
      }

      if (encryptionKey != null && !rawMode) {
        logger.trace("Submitting decrypt job for blob {}", targetBlobId);
        long startTimeMs = System.currentTimeMillis();
        decryptCallbackResultInfo = new DecryptCallBackResultInfo();
        progressTracker.initializeCryptoJobTracker(CryptoJobType.DECRYPTION);
        decryptJobMetricsTracker.onJobSubmission();
        cryptoJobHandler.submitJob(new DecryptJob(targetBlobId, encryptionKey, dataBuf.duplicate(),
            userMetadata != null ? ByteBuffer.wrap(userMetadata) : null, cryptoService, kms, options.getBlobOptions,
            decryptJobMetricsTracker, (DecryptJob.DecryptJobResult result, Exception exception) -> {
          routerMetrics.decryptTimeMs.update(System.currentTimeMillis() - startTimeMs);
          decryptJobMetricsTracker.onJobCallbackProcessingStart();
          logger.trace("Handling decrypt job call back for blob {} to set decrypt callback results", targetBlobId);
          if (isOperationComplete() || operationException.get() != null) {
            if (exception == null && result.getDecryptedBlobContent() != null) {
              ReferenceCountUtil.safeRelease(result.getDecryptedBlobContent());
            }
            return;
          }
          decryptCallbackResultInfo.setResultAndException(result, exception);
          routerCallback.onPollReady();
          decryptJobMetricsTracker.onJobCallbackProcessingComplete();
        }));
        return true;
      } else {
        // encryptionKey == null && rawMode
        // TODO: encrypt buffer if caller wants it
        return false;
      }
    }
Launch a crypto job as needed.
@param dataBuf to buffer to encrypt or decrypt.
@param userMetadata userMetadata of the blob.
@param encryptionKey encryption key for the blob. Could be null for non encrypted blob.
@param targetBlobId the {@link BlobId} of the blob.
@return {@code true} if a crypto job was launched, otherwise {@code false}.
ambry-router/src/main/java/com/github/ambry/router/GetBlobOperation.java