use of com.azure.storage.blob.models.BlobRequestConditions in project ambry by linkedin.
the class AzureBlobDataAccessor method updateBlobMetadata.
/**
* Update the metadata for the specified blob.
* @param blobId The {@link BlobId} to update.
* @param updateFields Map of field names and new values to modify.
* @param cloudUpdateValidator {@link CloudUpdateValidator} validator for the update passed by the caller.
* @return a {@link AzureCloudDestination.UpdateResponse} with the updated metadata.
* @throws BlobStorageException if the blob does not exist or an error occurred.
* @throws IllegalStateException on request timeout.
*/
public AzureCloudDestination.UpdateResponse updateBlobMetadata(BlobId blobId, Map<String, Object> updateFields, CloudUpdateValidator cloudUpdateValidator) throws Exception {
Objects.requireNonNull(blobId, "BlobId cannot be null");
updateFields.keySet().forEach(field -> Objects.requireNonNull(updateFields.get(field), String.format("%s cannot be null", field)));
try {
Timer.Context storageTimer = azureMetrics.blobUpdateTime.time();
try {
BlobProperties blobProperties = storageClient.getPropertiesWithResponse(blobId, defaultRequestConditions, requestTimeout);
// Note: above throws 404 exception if blob does not exist.
String etag = blobProperties.getETag();
Map<String, String> metadata = blobProperties.getMetadata();
if (!cloudUpdateValidator.validateUpdate(CloudBlobMetadata.fromMap(metadata), blobId, updateFields)) {
return new AzureCloudDestination.UpdateResponse(false, metadata);
}
// Update only if any of the values have changed
Map<String, String> changedFields = updateFields.entrySet().stream().filter(entry -> !String.valueOf(entry.getValue()).equals(metadata.get(entry.getKey()))).collect(Collectors.toMap(Map.Entry::getKey, entry -> String.valueOf(entry.getValue())));
if (changedFields.size() > 0) {
changedFields.forEach(metadata::put);
if (updateCallback != null) {
try {
updateCallback.call();
} catch (Exception ex) {
logger.error("Error in update callback", ex);
}
}
// Set condition to ensure we don't clobber a concurrent update
BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setIfMatch(etag);
storageClient.setMetadataWithResponse(blobId, metadata, blobRequestConditions, requestTimeout, Context.NONE);
return new AzureCloudDestination.UpdateResponse(true, metadata);
} else {
return new AzureCloudDestination.UpdateResponse(false, metadata);
}
} finally {
storageTimer.stop();
}
} catch (BlobStorageException e) {
if (isNotFoundError(e.getErrorCode())) {
logger.warn("Blob {} not found, cannot update {}.", blobId, updateFields.keySet());
}
if (e.getErrorCode() == BlobErrorCode.CONDITION_NOT_MET) {
azureMetrics.blobUpdateConflictCount.inc();
}
throw e;
}
}
use of com.azure.storage.blob.models.BlobRequestConditions in project ambry by linkedin.
the class AzureBlobDataAccessor method uploadIfNotExists.
/**
* Upload the blob to Azure storage if it does not already exist in the designated container.
* @param blobId the blobId to upload
* @param inputLength the input stream length, if known (-1 if not)
* @param cloudBlobMetadata the blob metadata
* @param blobInputStream the input stream
* @return {@code true} if the upload was successful, {@code false} if the blob already exists.
* @throws BlobStorageException for any error on ABS side.
* @throws IOException for any error with supplied data stream.
*/
public boolean uploadIfNotExists(BlobId blobId, long inputLength, CloudBlobMetadata cloudBlobMetadata, InputStream blobInputStream) throws BlobStorageException, IOException {
BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setIfNoneMatch("*");
azureMetrics.blobUploadRequestCount.inc();
Timer.Context storageTimer = azureMetrics.blobUploadTime.time();
try {
Map<String, String> metadata = cloudBlobMetadata.toMap();
storageClient.uploadWithResponse(blobId, blobInputStream, inputLength, null, metadata, null, null, blobRequestConditions, uploadTimeout);
logger.debug("Uploaded blob {} to ABS", blobId);
azureMetrics.blobUploadSuccessCount.inc();
return true;
} catch (UncheckedIOException e) {
// error processing input stream
throw e.getCause();
} catch (BlobStorageException e) {
if (e.getErrorCode() == BlobErrorCode.BLOB_ALREADY_EXISTS) {
logger.debug("Skipped upload of existing blob {}", blobId);
azureMetrics.blobUploadConflictCount.inc();
return false;
} else {
throw e;
}
} finally {
storageTimer.stop();
}
}
Aggregations