All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.azure.storage.blob.specialized.PageBlobAsyncClient Maven / Gradle / Ivy

There is a newer version: 12.29.0
Show newest version
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.azure.storage.blob.specialized;

import com.azure.core.annotation.ReturnType;
import com.azure.core.annotation.ServiceClient;
import com.azure.core.annotation.ServiceMethod;
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.HttpRange;
import com.azure.core.http.HttpResponse;
import com.azure.core.http.RequestConditions;
import com.azure.core.http.rest.PagedFlux;
import com.azure.core.http.rest.PagedResponse;
import com.azure.core.http.rest.PagedResponseBase;
import com.azure.core.http.rest.Response;
import com.azure.core.http.rest.ResponseBase;
import com.azure.core.http.rest.SimpleResponse;
import com.azure.core.util.Context;
import com.azure.core.util.FluxUtil;
import com.azure.core.util.UrlBuilder;
import com.azure.core.util.logging.ClientLogger;
import com.azure.storage.blob.BlobAsyncClient;
import com.azure.storage.blob.BlobServiceVersion;
import com.azure.storage.blob.implementation.models.EncryptionScope;
import com.azure.storage.blob.implementation.models.PageBlobsClearPagesHeaders;
import com.azure.storage.blob.implementation.models.PageBlobsCreateHeaders;
import com.azure.storage.blob.implementation.models.PageBlobsGetPageRangesDiffHeaders;
import com.azure.storage.blob.implementation.models.PageBlobsGetPageRangesHeaders;
import com.azure.storage.blob.implementation.models.PageBlobsResizeHeaders;
import com.azure.storage.blob.implementation.models.PageBlobsUpdateSequenceNumberHeaders;
import com.azure.storage.blob.implementation.models.PageBlobsUploadPagesFromURLHeaders;
import com.azure.storage.blob.implementation.models.PageBlobsUploadPagesHeaders;
import com.azure.storage.blob.implementation.models.PageListHelper;
import com.azure.storage.blob.implementation.util.ModelHelper;
import com.azure.storage.blob.models.BlobHttpHeaders;
import com.azure.storage.blob.models.BlobImmutabilityPolicy;
import com.azure.storage.blob.models.BlobRange;
import com.azure.storage.blob.models.BlobRequestConditions;
import com.azure.storage.blob.models.BlobStorageException;
import com.azure.storage.blob.models.ClearRange;
import com.azure.storage.blob.models.CopyStatusType;
import com.azure.storage.blob.models.CpkInfo;
import com.azure.storage.blob.models.CustomerProvidedKey;
import com.azure.storage.blob.models.PageBlobCopyIncrementalRequestConditions;
import com.azure.storage.blob.models.PageBlobItem;
import com.azure.storage.blob.models.PageBlobRequestConditions;
import com.azure.storage.blob.models.PageList;
import com.azure.storage.blob.models.PageRange;
import com.azure.storage.blob.models.PageRangeItem;
import com.azure.storage.blob.models.SequenceNumberActionType;
import com.azure.storage.blob.options.ListPageRangesDiffOptions;
import com.azure.storage.blob.options.ListPageRangesOptions;
import com.azure.storage.blob.options.PageBlobCopyIncrementalOptions;
import com.azure.storage.blob.options.PageBlobCreateOptions;
import com.azure.storage.blob.options.PageBlobUploadPagesFromUrlOptions;
import com.azure.storage.common.implementation.Constants;
import com.azure.storage.common.implementation.StorageImplUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.azure.core.util.FluxUtil.monoError;
import static com.azure.core.util.FluxUtil.withContext;

/**
 * Client to a page blob. It may only be instantiated through a {@link SpecializedBlobClientBuilder} or via the method
 * {@link BlobAsyncClient#getPageBlobAsyncClient()}. This class does not hold any state about a particular blob, but is
 * instead a convenient way of sending appropriate requests to the resource on the service.
 *
 * 

* Please refer to the Azure Docs for more information. * *

* Note this client is an async client that returns reactive responses from Spring Reactor Core project * (https://projectreactor.io/). Calling the methods in this client will NOT start the actual network * operation, until {@code .subscribe()} is called on the reactive response. You can simply convert one of these * responses to a {@link java.util.concurrent.CompletableFuture} object through {@link Mono#toFuture()}. */ @ServiceClient(builder = SpecializedBlobClientBuilder.class, isAsync = true) public final class PageBlobAsyncClient extends BlobAsyncClientBase { /** * Indicates the number of bytes in a page. */ public static final int PAGE_BYTES = 512; /** * Indicates the maximum number of bytes that may be sent in a call to putPage. */ public static final int MAX_PUT_PAGES_BYTES = 4 * Constants.MB; private static final ClientLogger LOGGER = new ClientLogger(PageBlobAsyncClient.class); /** * Package-private constructor for use by {@link SpecializedBlobClientBuilder}. * * @param pipeline The pipeline used to send and receive service requests. * @param url The endpoint where to send service requests. * @param serviceVersion The version of the service to receive requests. * @param accountName The storage account name. * @param containerName The container name. * @param blobName The blob name. * @param snapshot The snapshot identifier for the blob, pass {@code null} to interact with the blob directly. * @param customerProvidedKey Customer provided key used during encryption of the blob's data on the server, pass * {@code null} to allow the service to use its own encryption. * @param encryptionScope Encryption scope used during encryption of the blob's data on the server, pass * {@code null} to allow the service to use its own encryption. * @param versionId The version identifier for the blob, pass {@code null} to interact with the latest blob version. */ PageBlobAsyncClient(HttpPipeline pipeline, String url, BlobServiceVersion serviceVersion, String accountName, String containerName, String blobName, String snapshot, CpkInfo customerProvidedKey, EncryptionScope encryptionScope, String versionId) { super(pipeline, url, serviceVersion, accountName, containerName, blobName, snapshot, customerProvidedKey, encryptionScope, versionId); } /** * Creates a new {@link PageBlobAsyncClient} with the specified {@code encryptionScope}. * * @param encryptionScope the encryption scope for the blob, pass {@code null} to use no encryption scope. * @return a {@link PageBlobAsyncClient} with the specified {@code encryptionScope}. */ @Override public PageBlobAsyncClient getEncryptionScopeAsyncClient(String encryptionScope) { EncryptionScope finalEncryptionScope = null; if (encryptionScope != null) { finalEncryptionScope = new EncryptionScope().setEncryptionScope(encryptionScope); } return new PageBlobAsyncClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(), getContainerName(), getBlobName(), getSnapshotId(), getCustomerProvidedKey(), finalEncryptionScope, getVersionId()); } /** * Creates a new {@link PageBlobAsyncClient} with the specified {@code customerProvidedKey}. * * @param customerProvidedKey the {@link CustomerProvidedKey} for the blob, * pass {@code null} to use no customer provided key. * @return a {@link PageBlobAsyncClient} with the specified {@code customerProvidedKey}. */ @Override public PageBlobAsyncClient getCustomerProvidedKeyAsyncClient(CustomerProvidedKey customerProvidedKey) { CpkInfo finalCustomerProvidedKey = null; if (customerProvidedKey != null) { finalCustomerProvidedKey = new CpkInfo() .setEncryptionKey(customerProvidedKey.getKey()) .setEncryptionKeySha256(customerProvidedKey.getKeySha256()) .setEncryptionAlgorithm(customerProvidedKey.getEncryptionAlgorithm()); } return new PageBlobAsyncClient(getHttpPipeline(), getAccountUrl(), getServiceVersion(), getAccountName(), getContainerName(), getBlobName(), getSnapshotId(), finalCustomerProvidedKey, encryptionScope, getVersionId()); } private static String pageRangeToString(PageRange pageRange) { if (pageRange.getStart() < 0 || pageRange.getEnd() <= 0) { throw new IllegalArgumentException("PageRange's start and end values must be greater than or equal to " + "0 if specified."); } if (pageRange.getStart() % PAGE_BYTES != 0) { throw new IllegalArgumentException("PageRange's start value must be a multiple of 512."); } if (pageRange.getEnd() % PAGE_BYTES != PAGE_BYTES - 1) { throw new IllegalArgumentException("PageRange's end value must be 1 less than a multiple of 512."); } if (pageRange.getEnd() <= pageRange.getStart()) { throw new IllegalArgumentException("PageRange's End value must be after the start."); } return "bytes=" + pageRange.getStart() + '-' + pageRange.getEnd(); } /** * Creates a page blob of the specified length. By default, this method will not overwrite an existing blob. * Call PutPage to upload data to a page blob. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * client.create(size).subscribe(response -> System.out.printf(
     *     "Created page blob with sequence number %s%n", response.getBlobSequenceNumber()));
     * 
* * * @param size Specifies the maximum size for the page blob, up to 8 TB. The page blob size must be aligned to a * 512-byte boundary. * * @return A reactive response containing the information of the created page blob. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono create(long size) { return create(size, false); } /** * Creates a page blob of the specified length. Call PutPage to upload data to a page blob. For more * information, see the * Azure Docs. * *

Code Samples

* * *
     * boolean overwrite = false; // Default behavior
     * client.create(size, overwrite).subscribe(response -> System.out.printf(
     *     "Created page blob with sequence number %s%n", response.getBlobSequenceNumber()));
     * 
* * * @param size Specifies the maximum size for the page blob, up to 8 TB. The page blob size must be aligned to a * 512-byte boundary. * @param overwrite Whether to overwrite, should data exist on the blob. * @return A reactive response containing the information of the created page blob. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono create(long size, boolean overwrite) { BlobRequestConditions blobRequestConditions = new BlobRequestConditions(); if (!overwrite) { blobRequestConditions.setIfNoneMatch(Constants.HeaderConstants.ETAG_WILDCARD); } return createWithResponse(size, null, null, null, blobRequestConditions).flatMap(FluxUtil::toMono); } /** * Creates a page blob of the specified length. Call PutPage to upload data to a page blob. For more * information, see the * Azure Docs. *

* To avoid overwriting, pass "*" to {@link BlobRequestConditions#setIfNoneMatch(String)}. * *

Code Samples

* * *
     * BlobHttpHeaders headers = new BlobHttpHeaders()
     *     .setContentLanguage("en-US")
     *     .setContentType("binary");
     * BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setLeaseId(leaseId);
     *
     * client.createWithResponse(size, sequenceNumber, headers, metadata, blobRequestConditions)
     *     .subscribe(response -> System.out.printf(
     *         "Created page blob with sequence number %s%n", response.getValue().getBlobSequenceNumber()));
     *
     * 
* * * @param size Specifies the maximum size for the page blob, up to 8 TB. The page blob size must be aligned to a * 512-byte boundary. * @param sequenceNumber A user-controlled value that you can use to track requests. The value of the sequence * number must be between 0 and 2^63 - 1.The default value is 0. * @param headers {@link BlobHttpHeaders} * @param metadata Metadata to associate with the blob. If there is leading or trailing whitespace in any * metadata key or value, it must be removed or encoded. * @param requestConditions {@link BlobRequestConditions} * @return A reactive response containing the information of the created page blob. * * @throws IllegalArgumentException If {@code size} isn't a multiple of {@link PageBlobAsyncClient#PAGE_BYTES} or * {@code sequenceNumber} isn't null and is less than 0. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> createWithResponse(long size, Long sequenceNumber, BlobHttpHeaders headers, Map metadata, BlobRequestConditions requestConditions) { return this.createWithResponse(new PageBlobCreateOptions(size).setSequenceNumber(sequenceNumber) .setHeaders(headers).setMetadata(metadata).setRequestConditions(requestConditions)); } /** * Creates a page blob of the specified length. Call PutPage to upload data to a page blob. For more * information, see the * Azure Docs. *

* To avoid overwriting, pass "*" to {@link BlobRequestConditions#setIfNoneMatch(String)}. * *

Code Samples

* * *
     * BlobHttpHeaders headers = new BlobHttpHeaders()
     *     .setContentLanguage("en-US")
     *     .setContentType("binary");
     * BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setLeaseId(leaseId);
     *
     * client.createWithResponse(new PageBlobCreateOptions(size).setSequenceNumber(sequenceNumber)
     *     .setHeaders(headers).setMetadata(metadata).setTags(tags).setRequestConditions(blobRequestConditions))
     *     .subscribe(response -> System.out.printf(
     *         "Created page blob with sequence number %s%n", response.getValue().getBlobSequenceNumber()));
     *
     * 
* * * @param options {@link PageBlobCreateOptions} * @return A reactive response containing the information of the created page blob. * * @throws IllegalArgumentException If {@code size} isn't a multiple of {@link PageBlobAsyncClient#PAGE_BYTES} or * {@code sequenceNumber} isn't null and is less than 0. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> createWithResponse(PageBlobCreateOptions options) { try { return withContext(context -> createWithResponse(options, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> createWithResponse(PageBlobCreateOptions options, Context context) { StorageImplUtils.assertNotNull("options", options); BlobRequestConditions requestConditions = options.getRequestConditions() == null ? new BlobRequestConditions() : options.getRequestConditions(); if (options.getSize() % PAGE_BYTES != 0) { // Throwing is preferred to Single.error because this will error out immediately instead of waiting until // subscription. throw LOGGER.logExceptionAsError( new IllegalArgumentException("size must be a multiple of PageBlobAsyncClient.PAGE_BYTES.")); } if (options.getSequenceNumber() != null && options.getSequenceNumber() < 0) { // Throwing is preferred to Single.error because this will error out immediately instead of waiting until // subscription. throw LOGGER.logExceptionAsError( new IllegalArgumentException("SequenceNumber must be greater than or equal to 0.")); } context = context == null ? Context.NONE : context; BlobImmutabilityPolicy immutabilityPolicy = options.getImmutabilityPolicy() == null ? new BlobImmutabilityPolicy() : options.getImmutabilityPolicy(); return this.azureBlobStorage.getPageBlobs().createWithResponseAsync(containerName, blobName, 0, options.getSize(), null, null, options.getMetadata(), requestConditions.getLeaseId(), requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(), requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), requestConditions.getTagsConditions(), options.getSequenceNumber(), null, tagsToString(options.getTags()), immutabilityPolicy.getExpiryTime(), immutabilityPolicy.getPolicyMode(), options.isLegalHold(), options.getHeaders(), getCustomerProvidedKey(), encryptionScope, context) .map(rb -> { PageBlobsCreateHeaders hd = rb.getDeserializedHeaders(); PageBlobItem item = new PageBlobItem(hd.getETag(), hd.getLastModified(), hd.getContentMD5(), hd.isXMsRequestServerEncrypted(), hd.getXMsEncryptionKeySha256(), hd.getXMsEncryptionScope(), null, hd.getXMsVersionId()); return new SimpleResponse<>(rb, item); }); } /** * Creates a page blob of the specified length if it does not exist. * Call PutPage to upload data to a page blob. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * client.createIfNotExists(size).subscribe(response ->
     *     System.out.printf("Created page blob with sequence number %s%n", response.getBlobSequenceNumber()));
     * 
* * * @param size Specifies the maximum size for the page blob, up to 8 TB. The page blob size must be aligned to a * 512-byte boundary. * * @return A reactive response {@link Mono} signaling completion. {@link PageBlobItem} contains information of * the newly created page blob. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono createIfNotExists(long size) { return createIfNotExistsWithResponse(new PageBlobCreateOptions(size)).flatMap(FluxUtil::toMono); } /** * Creates a page blob of the specified length if it does not exist. Call PutPage to upload data to a page blob. * For more information, see the * Azure Docs. * *

Code Samples

* * *
     * BlobHttpHeaders headers = new BlobHttpHeaders()
     *     .setContentLanguage("en-US")
     *     .setContentType("binary");
     *
     * client.createIfNotExistsWithResponse(new PageBlobCreateOptions(size).setSequenceNumber(sequenceNumber)
     *     .setHeaders(headers).setMetadata(metadata).setTags(tags)).subscribe(response -> {
     *         if (response.getStatusCode() == 409) {
     *             System.out.println("Already exists.");
     *         } else {
     *             System.out.println("successfully created.");
     *         }
     *     });
     * 
* * * @param options {@link PageBlobCreateOptions} * @return A {@link Mono} containing {@link Response} signaling completion, whose {@link Response#getValue() value} * contains a {@link PageBlobItem} containing information about the page blob. If {@link Response}'s status code is * 201, a new page blob was successfully created. If status code is 409, a page blob already existed at this location. * * @throws IllegalArgumentException If {@code size} isn't a multiple of {@link PageBlobAsyncClient#PAGE_BYTES} or * {@code sequenceNumber} isn't null and is less than 0. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> createIfNotExistsWithResponse(PageBlobCreateOptions options) { try { return createIfNotExistsWithResponse(options, null); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> createIfNotExistsWithResponse(PageBlobCreateOptions options, Context context) { try { options.setRequestConditions(new BlobRequestConditions().setIfNoneMatch(Constants.HeaderConstants.ETAG_WILDCARD) .setIfNoneMatch(Constants.HeaderConstants.ETAG_WILDCARD)); return createWithResponse(options, context).onErrorResume(t -> t instanceof BlobStorageException && ((BlobStorageException) t).getStatusCode() == 409, t -> { HttpResponse response = ((BlobStorageException) t).getResponse(); return Mono.just(new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), null)); }); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } /** * Writes one or more pages to the page blob. Write size must be a multiple of 512. For more information, see * the Azure Docs. *

* Note that the data passed must be replayable if retries are enabled (the default). In other words, the * {@code Flux} must produce the same data each time it is subscribed to. * *

Code Samples

* * *
     * PageRange pageRange = new PageRange()
     *     .setStart(0)
     *     .setEnd(511);
     *
     * client.uploadPages(pageRange, body).subscribe(response -> System.out.printf(
     *     "Uploaded page blob with sequence number %s%n", response.getBlobSequenceNumber()));
     * 
* * * @param pageRange A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start * offset must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges * are 0-511, 512-1023, etc. * @param body The data to upload. Note that this {@code Flux} must be replayable if retries are enabled (the * default). In other words, the Flowable must produce the same data each time it is subscribed to. * * @return A reactive response containing the information of the uploaded pages. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadPages(PageRange pageRange, Flux body) { return uploadPagesWithResponse(pageRange, body, null, null).flatMap(FluxUtil::toMono); } /** * Writes one or more pages to the page blob. Write size must be a multiple of 512. For more information, see * the Azure Docs. *

* Note that the data passed must be replayable if retries are enabled (the default). In other words, the * {@code Flux} must produce the same data each time it is subscribed to. * *

Code Samples

* * *
     * PageRange pageRange = new PageRange()
     *     .setStart(0)
     *     .setEnd(511);
     *
     * byte[] md5 = MessageDigest.getInstance("MD5").digest("data".getBytes(StandardCharsets.UTF_8));
     * PageBlobRequestConditions pageBlobRequestConditions = new PageBlobRequestConditions().setLeaseId(leaseId);
     *
     * client.uploadPagesWithResponse(pageRange, body, md5, pageBlobRequestConditions)
     *     .subscribe(response -> System.out.printf(
     *         "Uploaded page blob with sequence number %s%n", response.getValue().getBlobSequenceNumber()));
     * 
* * * @param pageRange A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start * offset must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges * are 0-511, 512-1023, etc. * @param body The data to upload. Note that this {@code Flux} must be replayable if retries are enabled (the * default). In other words, the Flowable must produce the same data each time it is subscribed to. * @param contentMd5 An MD5 hash of the page content. This hash is used to verify the integrity of the page during * transport. When this header is specified, the storage service compares the hash of the content that has arrived * with this header value. Note that this MD5 hash is not stored with the blob. If the two hashes do not match, the * operation will fail. * @param pageBlobRequestConditions {@link PageBlobRequestConditions} * @return A reactive response containing the information of the uploaded pages. * * @throws IllegalArgumentException If {@code pageRange} is {@code null} */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> uploadPagesWithResponse(PageRange pageRange, Flux body, byte[] contentMd5, PageBlobRequestConditions pageBlobRequestConditions) { try { return withContext(context -> uploadPagesWithResponse(pageRange, body, contentMd5, pageBlobRequestConditions, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> uploadPagesWithResponse(PageRange pageRange, Flux body, byte[] contentMd5, PageBlobRequestConditions pageBlobRequestConditions, Context context) { pageBlobRequestConditions = pageBlobRequestConditions == null ? new PageBlobRequestConditions() : pageBlobRequestConditions; if (pageRange == null) { // Throwing is preferred to Single.error because this will error out immediately instead of waiting until // subscription. throw LOGGER.logExceptionAsError(new IllegalArgumentException("pageRange cannot be null.")); } String pageRangeStr = pageRangeToString(pageRange); context = context == null ? Context.NONE : context; return this.azureBlobStorage.getPageBlobs().uploadPagesWithResponseAsync(containerName, blobName, pageRange.getEnd() - pageRange.getStart() + 1, body, contentMd5, null, null, pageRangeStr, pageBlobRequestConditions.getLeaseId(), pageBlobRequestConditions.getIfSequenceNumberLessThanOrEqualTo(), pageBlobRequestConditions.getIfSequenceNumberLessThan(), pageBlobRequestConditions.getIfSequenceNumberEqualTo(), pageBlobRequestConditions.getIfModifiedSince(), pageBlobRequestConditions.getIfUnmodifiedSince(), pageBlobRequestConditions.getIfMatch(), pageBlobRequestConditions.getIfNoneMatch(), pageBlobRequestConditions.getTagsConditions(), null, getCustomerProvidedKey(), encryptionScope, context) .map(rb -> { PageBlobsUploadPagesHeaders hd = rb.getDeserializedHeaders(); PageBlobItem item = new PageBlobItem(hd.getETag(), hd.getLastModified(), hd.getContentMD5(), hd.isXMsRequestServerEncrypted(), hd.getXMsEncryptionKeySha256(), hd.getXMsEncryptionScope(), hd.getXMsBlobSequenceNumber()); return new SimpleResponse<>(rb, item); }); } /** * Writes one or more pages from the source page blob to this page blob. Write size must be a multiple of 512. * For more information, see the * Azure Docs. * *

Code Samples

* * *
     * PageRange pageRange = new PageRange()
     *     .setStart(0)
     *     .setEnd(511);
     *
     * client.uploadPagesFromUrl(pageRange, url, sourceOffset)
     *     .subscribe(response -> System.out.printf(
     *         "Uploaded page blob from URL with sequence number %s%n", response.getBlobSequenceNumber()));
     * 
* * * @param range A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start * offset must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges * are 0-511, 512-1023, etc. * @param sourceUrl The url to the blob that will be the source of the copy. A source blob in the same storage * account can be authenticated via Shared Key. However, if the source is a blob in another account, the source blob * must either be public or must be authenticated via a shared access signature. If the source blob is public, no * authentication is required to perform the operation. * @param sourceOffset The source offset to copy from. Pass null or 0 to copy from the beginning of source page * blob. * * @return A reactive response containing the information of the uploaded pages. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono uploadPagesFromUrl(PageRange range, String sourceUrl, Long sourceOffset) { return uploadPagesFromUrlWithResponse(range, sourceUrl, sourceOffset, null, null, null) .flatMap(FluxUtil::toMono); } /** * Writes one or more pages from the source page blob to this page blob. Write size must be a multiple of 512. * For more information, see the * Azure Docs. * *

Code Samples

* * *
     * PageRange pageRange = new PageRange()
     *     .setStart(0)
     *     .setEnd(511);
     * InputStream dataStream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
     * byte[] sourceContentMD5 = new byte[512];
     * PageBlobRequestConditions pageBlobRequestConditions = new PageBlobRequestConditions().setLeaseId(leaseId);
     * BlobRequestConditions sourceRequestConditions = new BlobRequestConditions()
     *     .setIfUnmodifiedSince(OffsetDateTime.now().minusDays(3));
     *
     * client.uploadPagesFromUrlWithResponse(pageRange, url, sourceOffset, sourceContentMD5, pageBlobRequestConditions,
     *         sourceRequestConditions)
     *     .subscribe(response -> System.out.printf(
     *         "Uploaded page blob from URL with sequence number %s%n", response.getValue().getBlobSequenceNumber()));
     * 
* * * @param range The destination {@link PageRange} range. Given that pages must be aligned with 512-byte boundaries, * the start offset must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte * ranges are 0-511, 512-1023, etc. * @param sourceUrl The url to the blob that will be the source of the copy. A source blob in the same storage * account can be authenticated via Shared Key. However, if the source is a blob in another account, the source blob * must either be public or must be authenticated via a shared access signature. If the source blob is public, no * authentication is required to perform the operation. * @param sourceOffset The source offset to copy from. Pass null or 0 to copy from the beginning of source blob. * @param sourceContentMd5 An MD5 hash of the page content. This hash is used to verify the integrity of the page * during transport. When this header is specified, the storage service compares the hash of the content that has * arrived with this header value. Note that this MD5 hash is not stored with the blob. If the two hashes do not * match, the operation will fail. * @param destRequestConditions {@link PageBlobRequestConditions} * @param sourceRequestConditions {@link BlobRequestConditions} * @return A reactive response containing the information of the uploaded pages. * * @throws IllegalArgumentException If {@code range} is {@code null} */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> uploadPagesFromUrlWithResponse(PageRange range, String sourceUrl, Long sourceOffset, byte[] sourceContentMd5, PageBlobRequestConditions destRequestConditions, BlobRequestConditions sourceRequestConditions) { return uploadPagesFromUrlWithResponse(new PageBlobUploadPagesFromUrlOptions(range, sourceUrl) .setSourceOffset(sourceOffset).setSourceContentMd5(sourceContentMd5) .setDestinationRequestConditions(destRequestConditions) .setSourceRequestConditions(sourceRequestConditions)); } /** * Writes one or more pages from the source page blob to this page blob. Write size must be a multiple of 512. * For more information, see the * Azure Docs. * *

Code Samples

* * *
     * PageRange pageRange = new PageRange()
     *     .setStart(0)
     *     .setEnd(511);
     * InputStream dataStream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
     * byte[] sourceContentMD5 = new byte[512];
     * PageBlobRequestConditions pageBlobRequestConditions = new PageBlobRequestConditions().setLeaseId(leaseId);
     * BlobRequestConditions sourceRequestConditions = new BlobRequestConditions()
     *     .setIfUnmodifiedSince(OffsetDateTime.now().minusDays(3));
     *
     * client.uploadPagesFromUrlWithResponse(new PageBlobUploadPagesFromUrlOptions(pageRange, url)
     *     .setSourceOffset(sourceOffset).setSourceContentMd5(sourceContentMD5)
     *     .setDestinationRequestConditions(pageBlobRequestConditions)
     *     .setSourceRequestConditions(sourceRequestConditions))
     *     .subscribe(response -> System.out.printf(
     *         "Uploaded page blob from URL with sequence number %s%n", response.getValue().getBlobSequenceNumber()));
     * 
* * * @param options Parameters for the operation. * @return A reactive response containing the information of the uploaded pages. * * @throws IllegalArgumentException If {@code range} is {@code null} */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> uploadPagesFromUrlWithResponse(PageBlobUploadPagesFromUrlOptions options) { try { return withContext(context -> uploadPagesFromUrlWithResponse(options, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> uploadPagesFromUrlWithResponse(PageBlobUploadPagesFromUrlOptions options, Context context) { if (options.getRange() == null) { // Throwing is preferred to Single.error because this will error out immediately instead of waiting until // subscription. throw LOGGER.logExceptionAsError(new IllegalArgumentException("range cannot be null.")); } String rangeString = pageRangeToString(options.getRange()); long sourceOffset = options.getSourceOffset() == null ? 0L : options.getSourceOffset(); String sourceRangeString = pageRangeToString(new PageRange() .setStart(sourceOffset) .setEnd(sourceOffset + (options.getRange().getEnd() - options.getRange().getStart()))); PageBlobRequestConditions destRequestConditions = (options.getDestinationRequestConditions() == null) ? new PageBlobRequestConditions() : options.getDestinationRequestConditions(); BlobRequestConditions sourceRequestConditions = (options.getSourceRequestConditions() == null) ? new BlobRequestConditions() : options.getSourceRequestConditions(); try { new URL(options.getSourceUrl()); } catch (MalformedURLException ex) { throw LOGGER.logExceptionAsError(new IllegalArgumentException("'sourceUrl' is not a valid url.", ex)); } context = context == null ? Context.NONE : context; String sourceAuth = options.getSourceAuthorization() == null ? null : options.getSourceAuthorization().toString(); return this.azureBlobStorage.getPageBlobs().uploadPagesFromURLWithResponseAsync( containerName, blobName, options.getSourceUrl(), sourceRangeString, 0, rangeString, options.getSourceContentMd5(), null, null, destRequestConditions.getLeaseId(), destRequestConditions.getIfSequenceNumberLessThanOrEqualTo(), destRequestConditions.getIfSequenceNumberLessThan(), destRequestConditions.getIfSequenceNumberEqualTo(), destRequestConditions.getIfModifiedSince(), destRequestConditions.getIfUnmodifiedSince(), destRequestConditions.getIfMatch(), destRequestConditions.getIfNoneMatch(), destRequestConditions.getTagsConditions(), sourceRequestConditions.getIfModifiedSince(), sourceRequestConditions.getIfUnmodifiedSince(), sourceRequestConditions.getIfMatch(), sourceRequestConditions.getIfNoneMatch(), null, sourceAuth, getCustomerProvidedKey(), encryptionScope, context) .map(rb -> { PageBlobsUploadPagesFromURLHeaders hd = rb.getDeserializedHeaders(); PageBlobItem item = new PageBlobItem(hd.getETag(), hd.getLastModified(), hd.getContentMD5(), hd.isXMsRequestServerEncrypted(), hd.getXMsEncryptionKeySha256(), hd.getXMsEncryptionScope(), null); return new SimpleResponse<>(rb, item); }); } /** * Frees the specified pages from the page blob. The size of the range must be a multiple of 512. For more * information, see the Azure Docs. * *

Code Samples

* * *
     * PageRange pageRange = new PageRange()
     *     .setStart(0)
     *     .setEnd(511);
     *
     * client.clearPages(pageRange).subscribe(response -> System.out.printf(
     *     "Cleared page blob with sequence number %s%n", response.getBlobSequenceNumber()));
     * 
* * * @param pageRange A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start * offset must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges * are 0-511, 512-1023, etc. * * @return A reactive response containing the information of the cleared pages. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono clearPages(PageRange pageRange) { return clearPagesWithResponse(pageRange, null).flatMap(FluxUtil::toMono); } /** * Frees the specified pages from the page blob. The size of the range must be a multiple of 512. For more * information, see the Azure Docs. * *

Code Samples

* * *
     * PageRange pageRange = new PageRange()
     *     .setStart(0)
     *     .setEnd(511);
     * PageBlobRequestConditions pageBlobRequestConditions = new PageBlobRequestConditions().setLeaseId(leaseId);
     *
     * client.clearPagesWithResponse(pageRange, pageBlobRequestConditions)
     *     .subscribe(response -> System.out.printf(
     *         "Cleared page blob with sequence number %s%n", response.getValue().getBlobSequenceNumber()));
     * 
* * * @param pageRange A {@link PageRange} object. Given that pages must be aligned with 512-byte boundaries, the start * offset must be a modulus of 512 and the end offset must be a modulus of 512 - 1. Examples of valid byte ranges * are 0-511, 512-1023, etc. * @param pageBlobRequestConditions {@link PageBlobRequestConditions} * @return A reactive response containing the information of the cleared pages. * * @throws IllegalArgumentException If {@code pageRange} is {@code null} */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> clearPagesWithResponse(PageRange pageRange, PageBlobRequestConditions pageBlobRequestConditions) { try { return withContext(context -> clearPagesWithResponse(pageRange, pageBlobRequestConditions, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> clearPagesWithResponse(PageRange pageRange, PageBlobRequestConditions pageBlobRequestConditions, Context context) { pageBlobRequestConditions = pageBlobRequestConditions == null ? new PageBlobRequestConditions() : pageBlobRequestConditions; if (pageRange == null) { // Throwing is preferred to Single.error because this will error out immediately instead of waiting until // subscription. throw LOGGER.logExceptionAsError(new IllegalArgumentException("pageRange cannot be null.")); } String pageRangeStr = pageRangeToString(pageRange); context = context == null ? Context.NONE : context; return this.azureBlobStorage.getPageBlobs().clearPagesWithResponseAsync(containerName, blobName, 0, null, pageRangeStr, pageBlobRequestConditions.getLeaseId(), pageBlobRequestConditions.getIfSequenceNumberLessThanOrEqualTo(), pageBlobRequestConditions.getIfSequenceNumberLessThan(), pageBlobRequestConditions.getIfSequenceNumberEqualTo(), pageBlobRequestConditions.getIfModifiedSince(), pageBlobRequestConditions.getIfUnmodifiedSince(), pageBlobRequestConditions.getIfMatch(), pageBlobRequestConditions.getIfNoneMatch(), pageBlobRequestConditions.getTagsConditions(), null, getCustomerProvidedKey(), encryptionScope, context) .map(rb -> { PageBlobsClearPagesHeaders hd = rb.getDeserializedHeaders(); PageBlobItem item = new PageBlobItem(hd.getETag(), hd.getLastModified(), hd.getContentMD5(), hd.isXMsRequestServerEncrypted(), hd.getXMsEncryptionKeySha256(), null, hd.getXMsBlobSequenceNumber()); return new SimpleResponse<>(rb, item); }); } /** * Returns the list of valid page ranges for a page blob or snapshot of a page blob. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * BlobRange blobRange = new BlobRange(offset);
     *
     * client.getPageRanges(blobRange).subscribe(response -> {
     *     System.out.println("Valid Page Ranges are:");
     *     for (PageRange pageRange : response.getPageRange()) {
     *         System.out.printf("Start: %s, End: %s%n", pageRange.getStart(), pageRange.getEnd());
     *     }
     * });
     * 
* * * @param blobRange {@link BlobRange} * * @return A reactive response containing the information of the cleared pages. * @deprecated Use {@link #listPageRanges(BlobRange)} */ @ServiceMethod(returns = ReturnType.SINGLE) @Deprecated public Mono getPageRanges(BlobRange blobRange) { return getPageRangesWithResponse(blobRange, null).flatMap(FluxUtil::toMono); } /** * Returns the list of valid page ranges for a page blob or snapshot of a page blob. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * BlobRange blobRange = new BlobRange(offset);
     * BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setLeaseId(leaseId);
     *
     * client.getPageRangesWithResponse(blobRange, blobRequestConditions)
     *     .subscribe(response -> {
     *         System.out.println("Valid Page Ranges are:");
     *         for (PageRange pageRange : response.getValue().getPageRange()) {
     *             System.out.printf("Start: %s, End: %s%n", pageRange.getStart(), pageRange.getEnd());
     *         }
     *     });
     * 
* * * @param blobRange {@link BlobRange} * @param requestConditions {@link BlobRequestConditions} * @return A reactive response emitting all the page ranges. * @deprecated Use {@link #listPageRanges(ListPageRangesOptions)} */ @ServiceMethod(returns = ReturnType.SINGLE) @Deprecated public Mono> getPageRangesWithResponse(BlobRange blobRange, BlobRequestConditions requestConditions) { try { return withContext(context -> getPageRangesWithResponse(blobRange, requestConditions, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> getPageRangesWithResponse(BlobRange blobRange, BlobRequestConditions requestConditions, Context context) { blobRange = blobRange == null ? new BlobRange(0) : blobRange; requestConditions = requestConditions == null ? new BlobRequestConditions() : requestConditions; context = context == null ? Context.NONE : context; return this.azureBlobStorage.getPageBlobs().getPageRangesWithResponseAsync(containerName, blobName, getSnapshotId(), null, blobRange.toHeaderValue(), requestConditions.getLeaseId(), requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(), requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), requestConditions.getTagsConditions(), null, null, null, context) .map(response -> new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), response.getValue())); } /** * Returns the list of valid page ranges for a page blob or snapshot of a page blob. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * BlobRange blobRange = new BlobRange(offset);
     *
     * System.out.println("Valid Page Ranges are:");
     * client.listPageRanges(blobRange).subscribe(rangeItem -> System.out.printf("Offset: %s, Length: %s%n",
     *     rangeItem.getRange().getOffset(), rangeItem.getRange().getLength()));
     * 
* * * @param blobRange {@link BlobRange} * * @return A reactive response containing the information of the cleared pages. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PagedFlux listPageRanges(BlobRange blobRange) { return listPageRanges(new ListPageRangesOptions(blobRange)); } /** * Returns the list of valid page ranges for a page blob or snapshot of a page blob. For more information, see the * Azure Docs. * *

Code Samples

* * *
     * ListPageRangesOptions options = new ListPageRangesOptions(new BlobRange(offset))
     *     .setMaxResultsPerPage(1000).setRequestConditions(new BlobRequestConditions().setLeaseId(leaseId));
     *
     * client.listPageRanges(options)
     *     .subscribe(rangeItem -> System.out.printf("Offset: %s, Length: %s%n", rangeItem.getRange().getOffset(),
     *         rangeItem.getRange().getLength()));
     * 
* * * @param options {@link ListPageRangesOptions} * @return A reactive response emitting all the page ranges. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PagedFlux listPageRanges(ListPageRangesOptions options) { return new PagedFlux<>( pageSize -> withContext(context -> listPageRangesWithOptionalTimeout(options, null, context).apply(null, pageSize)), (continuationToken, pageSize) -> withContext(context -> listPageRangesWithOptionalTimeout(options, null, context).apply(continuationToken, pageSize))); } /* * Implementation for this paged listing operation, supporting an optional timeout provided by the synchronous * ContainerClient. Applies the given timeout to each Mono backing the * PagedFlux. * * @param delimiter The delimiter for blob hierarchy, "/" for hierarchy based on directories * @param options {@link PageBlobGetPageRangesOptions} * @param timeout An optional timeout to be applied to the network asynchronous operations. * @return A reactive response emitting the listed blobs, flattened. */ BiFunction>> listPageRangesWithOptionalTimeout( ListPageRangesOptions options, Duration timeout, Context context) { return (marker, pageSize) -> { ListPageRangesOptions finalOptions; /* If pageSize was not set in a .byPage(int) method, the page size from options will be preserved. Otherwise, prefer the new value. */ if (pageSize != null) { finalOptions = new ListPageRangesOptions(options.getRange()).setMaxResultsPerPage(pageSize); } else { finalOptions = options; } return getPageRangesSegment(marker, finalOptions, timeout, context) .map(response -> { List value = response.getValue() == null ? Collections.emptyList() : Stream.concat( response.getValue().getPageRange().stream().map(PageBlobAsyncClient::toPageBlobRange), response.getValue().getClearRange().stream().map(PageBlobAsyncClient::toPageBlobRange) ).collect(Collectors.toList()); return new PagedResponseBase<>( response.getRequest(), response.getStatusCode(), response.getHeaders(), value, PageListHelper.getNextMarker(response.getValue()), response.getDeserializedHeaders()); }); }; } private Mono> getPageRangesSegment(String marker, ListPageRangesOptions options, Duration timeout, Context context) { BlobRequestConditions requestConditions = options.getRequestConditions() == null ? new BlobRequestConditions() : options.getRequestConditions(); context = context == null ? Context.NONE : context; return StorageImplUtils.applyOptionalTimeout( this.azureBlobStorage.getPageBlobs().getPageRangesWithResponseAsync(containerName, blobName, getSnapshotId(), null, options.getRange().toHeaderValue(), requestConditions.getLeaseId(), requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(), requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), requestConditions.getTagsConditions(), null, marker, options.getMaxResultsPerPage(), context), timeout); } private static PageRangeItem toPageBlobRange(PageRange range) { return new PageRangeItem(new HttpRange(range.getStart(), range.getEnd() - range.getStart() + 1), false); } private static PageRangeItem toPageBlobRange(ClearRange range) { return new PageRangeItem(new HttpRange(range.getStart(), range.getEnd() - range.getStart() + 1), true); } /** * Gets the collection of page ranges that differ between a specified snapshot and this page blob. For more * information, see the Azure * Docs. * *

Code Samples

* * *
     * BlobRange blobRange = new BlobRange(offset);
     * final String prevSnapshot = "previous snapshot";
     *
     * client.getPageRangesDiff(blobRange, prevSnapshot).subscribe(response -> {
     *     System.out.println("Valid Page Ranges are:");
     *     for (PageRange pageRange : response.getPageRange()) {
     *         System.out.printf("Start: %s, End: %s%n", pageRange.getStart(), pageRange.getEnd());
     *     }
     * });
     * 
* * * @param blobRange {@link BlobRange} * @param prevSnapshot Specifies that the response will contain only pages that were changed between target blob and * previous snapshot. Changed pages include both updated and cleared pages. The target blob may be a snapshot, as * long as the snapshot specified by prevsnapshot is the older of the two. * * @return A reactive response emitting all the different page ranges. * @deprecated See {@link #listPageRangesDiff(BlobRange, String)} */ @ServiceMethod(returns = ReturnType.SINGLE) @Deprecated public Mono getPageRangesDiff(BlobRange blobRange, String prevSnapshot) { return getPageRangesDiffWithResponse(blobRange, prevSnapshot, null).flatMap(FluxUtil::toMono); } /** * Gets the collection of page ranges that differ between a specified snapshot and this page blob. For more * information, see the Azure * Docs. * *

Code Samples

* * *
     * BlobRange blobRange = new BlobRange(offset);
     * final String prevSnapshot = "previous snapshot";
     * BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setLeaseId(leaseId);
     *
     * client.getPageRangesDiffWithResponse(blobRange, prevSnapshot, blobRequestConditions)
     *     .subscribe(response -> {
     *         System.out.println("Valid Page Ranges are:");
     *         for (PageRange pageRange : response.getValue().getPageRange()) {
     *             System.out.printf("Start: %s, End: %s%n", pageRange.getStart(), pageRange.getEnd());
     *         }
     *     });
     * 
* * * @param blobRange {@link BlobRange} * @param prevSnapshot Specifies that the response will contain only pages that were changed between target blob and * previous snapshot. Changed pages include both updated and cleared pages. The target blob may be a snapshot, as * long as the snapshot specified by prevsnapshot is the older of the two. * @param requestConditions {@link BlobRequestConditions} * @return A reactive response emitting all the different page ranges. * * @throws IllegalArgumentException If {@code prevSnapshot} is {@code null} * @deprecated See {@link #listPageRangesDiff(ListPageRangesDiffOptions)} */ @ServiceMethod(returns = ReturnType.SINGLE) @Deprecated public Mono> getPageRangesDiffWithResponse(BlobRange blobRange, String prevSnapshot, BlobRequestConditions requestConditions) { try { return withContext(context -> getPageRangesDiffWithResponse(blobRange, prevSnapshot, null, requestConditions, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } /** * Gets the collection of page ranges that differ between a specified snapshot and this page blob. For more * information, see the Azure * Docs. * *

Code Samples

* * *
     * BlobRange blobRange = new BlobRange(offset);
     * String prevSnapshot = "previous snapshot";
     *
     * System.out.println("Valid Page Ranges are:");
     * client.listPageRangesDiff(blobRange, prevSnapshot).subscribe(rangeItem ->
     *     System.out.printf("Offset: %s, Length: %s, isClear: %s%n",
     *     rangeItem.getRange().getOffset(), rangeItem.getRange().getLength(), rangeItem.isClear()));
     * 
* * * @param blobRange {@link BlobRange} * @param prevSnapshot Specifies that the response will contain only pages that were changed between target blob and * previous snapshot. Changed pages include both updated and cleared pages. The target blob may be a snapshot, as * long as the snapshot specified by prevsnapshot is the older of the two. * * @return A reactive response emitting all the different page ranges. */ @ServiceMethod(returns = ReturnType.COLLECTION) public PagedFlux listPageRangesDiff(BlobRange blobRange, String prevSnapshot) { return listPageRangesDiff(new ListPageRangesDiffOptions(blobRange, prevSnapshot)); } /** * Gets the collection of page ranges that differ between a specified snapshot and this page blob. For more * information, see the Azure * Docs. * *

Code Samples

* * *
     * ListPageRangesDiffOptions options = new ListPageRangesDiffOptions(new BlobRange(offset), "previous snapshot")
     *     .setRequestConditions(new BlobRequestConditions().setLeaseId(leaseId))
     *     .setMaxResultsPerPage(1000);
     *
     * client.listPageRangesDiff(options)
     *     .subscribe(rangeItem -> System.out.printf("Offset: %s, Length: %s, isClear: %s%n",
     *         rangeItem.getRange().getOffset(), rangeItem.getRange().getLength(), rangeItem.isClear()));
     * 
* * * @param options {@link ListPageRangesDiffOptions}. * @return A reactive response emitting all the different page ranges. * * @throws IllegalArgumentException If {@code prevSnapshot} is {@code null} */ @ServiceMethod(returns = ReturnType.COLLECTION) public PagedFlux listPageRangesDiff(ListPageRangesDiffOptions options) { return new PagedFlux<>( pageSize -> withContext(context -> listPageRangesDiffWithOptionalTimeout(options, null, context).apply(null, pageSize)), (continuationToken, pageSize) -> withContext(context -> listPageRangesDiffWithOptionalTimeout(options, null, context).apply(continuationToken, pageSize))); } /** * This API only works for managed disk accounts. *

Gets the collection of page ranges that differ between a specified snapshot and this page blob. For more * information, see the Azure * Docs.

* *

Code Samples

* * *
     * BlobRange blobRange = new BlobRange(offset);
     * final String prevSnapshotUrl = "previous snapshot url";
     *
     * client.getPageRangesDiff(blobRange, prevSnapshotUrl).subscribe(response -> {
     *     System.out.println("Valid Page Ranges are:");
     *     for (PageRange pageRange : response.getPageRange()) {
     *         System.out.printf("Start: %s, End: %s%n", pageRange.getStart(), pageRange.getEnd());
     *     }
     * });
     * 
* * * @param blobRange {@link BlobRange} * @param prevSnapshotUrl Specifies the URL of a previous snapshot of the target blob. Specifies that the * response will contain only pages that were changed between target blob and previous snapshot. Changed pages * include both updated and cleared pages. The target blob may be a snapshot, as long as the snapshot specified by * prevsnapshot is the older of the two. * * @return A reactive response emitting all the different page ranges. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono getManagedDiskPageRangesDiff(BlobRange blobRange, String prevSnapshotUrl) { return getManagedDiskPageRangesDiffWithResponse(blobRange, prevSnapshotUrl, null).flatMap(FluxUtil::toMono); } /** * This API only works for managed disk accounts. *

Gets the collection of page ranges that differ between a specified snapshot and this page blob. For more * information, see the Azure * Docs.

* *

Code Samples

* * *
     * BlobRange blobRange = new BlobRange(offset);
     * final String prevSnapshotUrl = "previous snapshot url";
     * BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setLeaseId(leaseId);
     *
     * client.getPageRangesDiffWithResponse(blobRange, prevSnapshotUrl, blobRequestConditions)
     *     .subscribe(response -> {
     *         System.out.println("Valid Page Ranges are:");
     *         for (PageRange pageRange : response.getValue().getPageRange()) {
     *             System.out.printf("Start: %s, End: %s%n", pageRange.getStart(), pageRange.getEnd());
     *         }
     *     });
     * 
* * * @param blobRange {@link BlobRange} * @param prevSnapshotUrl Specifies the URL of a previous snapshot of the target blob. Specifies that the * response will contain only pages that were changed between target blob and previous snapshot. Changed pages * include both updated and cleared pages. The target blob may be a snapshot, as long as the snapshot specified by * prevsnapshot is the older of the two. * @param requestConditions {@link BlobRequestConditions} * @return A reactive response emitting all the different page ranges. * * @throws IllegalArgumentException If {@code prevSnapshot} is {@code null} */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> getManagedDiskPageRangesDiffWithResponse(BlobRange blobRange, String prevSnapshotUrl, BlobRequestConditions requestConditions) { try { return withContext(context -> getPageRangesDiffWithResponse(blobRange, null, prevSnapshotUrl, requestConditions, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> getPageRangesDiffWithResponse(BlobRange blobRange, String prevSnapshot, String prevSnapshotUrl, BlobRequestConditions requestConditions, Context context) { blobRange = blobRange == null ? new BlobRange(0) : blobRange; requestConditions = requestConditions == null ? new BlobRequestConditions() : requestConditions; if (prevSnapshotUrl == null && prevSnapshot == null) { throw LOGGER.logExceptionAsError(new IllegalArgumentException("prevSnapshot cannot be null")); } if (prevSnapshotUrl != null) { try { new URL(prevSnapshotUrl); } catch (MalformedURLException ex) { throw LOGGER.logExceptionAsError(new IllegalArgumentException("'prevSnapshotUrl' is not a valid url.", ex)); } } context = context == null ? Context.NONE : context; return this.azureBlobStorage.getPageBlobs().getPageRangesDiffWithResponseAsync(containerName, blobName, getSnapshotId(), null, prevSnapshot, prevSnapshotUrl, blobRange.toHeaderValue(), requestConditions.getLeaseId(), requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(), requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), requestConditions.getTagsConditions(), null, null, null, context) .map(response -> new SimpleResponse<>(response.getRequest(), response.getStatusCode(), response.getHeaders(), response.getValue())); } /* * Implementation for this paged listing operation, supporting an optional timeout provided by the synchronous * ContainerClient. Applies the given timeout to each Mono backing the * PagedFlux. * * @param delimiter The delimiter for blob hierarchy, "/" for hierarchy based on directories * @param options {@link PageBlobGetPageRangesDiffOptions} * @param timeout An optional timeout to be applied to the network asynchronous operations. * @return A reactive response emitting the listed blobs, flattened. */ BiFunction>> listPageRangesDiffWithOptionalTimeout(ListPageRangesDiffOptions options, Duration timeout, Context context) { return (marker, pageSize) -> { ListPageRangesDiffOptions finalOptions; /* If pageSize was not set in a .byPage(int) method, the page size from options will be preserved. Otherwise, prefer the new value. */ if (pageSize != null) { finalOptions = new ListPageRangesDiffOptions(options.getRange(), options.getPreviousSnapshot()) .setRequestConditions(options.getRequestConditions()).setMaxResultsPerPage(pageSize); } else { finalOptions = options; } return getPageRangesDiffSegment(marker, finalOptions, timeout, context) .map(response -> { List value = response.getValue() == null ? Collections.emptyList() : Stream.concat( response.getValue().getPageRange().stream().map(PageBlobAsyncClient::toPageBlobRange), response.getValue().getClearRange().stream().map(PageBlobAsyncClient::toPageBlobRange)) .collect(Collectors.toList()); return new PagedResponseBase<>( response.getRequest(), response.getStatusCode(), response.getHeaders(), value, PageListHelper.getNextMarker(response.getValue()), response.getDeserializedHeaders()); }); }; } private Mono> getPageRangesDiffSegment(String marker, ListPageRangesDiffOptions options, Duration timeout, Context context) { BlobRequestConditions requestConditions = options.getRequestConditions() == null ? new BlobRequestConditions() : options.getRequestConditions(); context = context == null ? Context.NONE : context; return StorageImplUtils.applyOptionalTimeout( this.azureBlobStorage.getPageBlobs().getPageRangesDiffWithResponseAsync(containerName, blobName, getSnapshotId(), null, options.getPreviousSnapshot(), null, options.getRange().toHeaderValue(), requestConditions.getLeaseId(), requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(), requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), requestConditions.getTagsConditions(), null, marker, options.getMaxResultsPerPage(), context), timeout); } /** * Resizes the page blob to the specified size (which must be a multiple of 512). For more information, see the Azure Docs. * *

Code Samples

* * *
     * client.resize(size).subscribe(response -> System.out.printf(
     *     "Page blob resized with sequence number %s%n", response.getBlobSequenceNumber()));
     * 
* * * @param size Resizes a page blob to the specified size. If the specified value is less than the current size of * the blob, then all pages above the specified value are cleared. * * @return A reactive response emitting the resized page blob. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono resize(long size) { return resizeWithResponse(size, null).flatMap(FluxUtil::toMono); } /** * Resizes the page blob to the specified size (which must be a multiple of 512). For more information, see the Azure Docs. * *

Code Samples

* * *
     * BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setLeaseId(leaseId);
     *
     * client.resizeWithResponse(size, blobRequestConditions)
     *     .subscribe(response -> System.out.printf(
     *         "Page blob resized with sequence number %s%n", response.getValue().getBlobSequenceNumber()));
     * 
* * * @param size Resizes a page blob to the specified size. If the specified value is less than the current size of * the blob, then all pages above the specified value are cleared. * @param requestConditions {@link BlobRequestConditions} * @return A reactive response emitting the resized page blob. * * @throws IllegalArgumentException If {@code size} isn't a multiple of {@link PageBlobAsyncClient#PAGE_BYTES} */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> resizeWithResponse(long size, BlobRequestConditions requestConditions) { try { return withContext(context -> resizeWithResponse(size, requestConditions, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> resizeWithResponse(long size, BlobRequestConditions requestConditions, Context context) { if (size % PAGE_BYTES != 0) { // Throwing is preferred to Single.error because this will error out immediately instead of waiting until // subscription. throw LOGGER.logExceptionAsError( new IllegalArgumentException("size must be a multiple of PageBlobAsyncClient.PAGE_BYTES.")); } requestConditions = requestConditions == null ? new BlobRequestConditions() : requestConditions; context = context == null ? Context.NONE : context; return this.azureBlobStorage.getPageBlobs().resizeWithResponseAsync(containerName, blobName, size, null, requestConditions.getLeaseId(), requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(), requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), requestConditions.getTagsConditions(), null, getCustomerProvidedKey(), encryptionScope, context) .map(rb -> { PageBlobsResizeHeaders hd = rb.getDeserializedHeaders(); PageBlobItem item = new PageBlobItem(hd.getETag(), hd.getLastModified(), null, null, null, null, hd.getXMsBlobSequenceNumber()); return new SimpleResponse<>(rb, item); }); } /** * Sets the page blob's sequence number. For more information, see the * Azure * Docs. * *

Code Samples

* * *
     * client.updateSequenceNumber(SequenceNumberActionType.INCREMENT, size)
     *     .subscribe(response -> System.out.printf(
     *         "Page blob updated to sequence number %s%n", response.getBlobSequenceNumber()));
     * 
* * * @param action Indicates how the service should modify the blob's sequence number. * @param sequenceNumber The blob's sequence number. The sequence number is a user-controlled property that you can * use to track requests and manage concurrency issues. * * @return A reactive response emitting the updated page blob. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono updateSequenceNumber(SequenceNumberActionType action, Long sequenceNumber) { return updateSequenceNumberWithResponse(action, sequenceNumber, null).flatMap(FluxUtil::toMono); } /** * Sets the page blob's sequence number. For more information, see the Azure * Docs. * *

Code Samples

* * *
     * BlobRequestConditions blobRequestConditions = new BlobRequestConditions().setLeaseId(leaseId);
     *
     * client.updateSequenceNumberWithResponse(SequenceNumberActionType.INCREMENT, size, blobRequestConditions)
     *     .subscribe(response -> System.out.printf(
     *         "Page blob updated to sequence number %s%n", response.getValue().getBlobSequenceNumber()));
     * 
* * * @param action Indicates how the service should modify the blob's sequence number. * @param sequenceNumber The blob's sequence number. The sequence number is a user-controlled property that you can * use to track requests and manage concurrency issues. * @param requestConditions {@link BlobRequestConditions} * @return A reactive response emitting the updated page blob. * * @throws IllegalArgumentException If {@code sequenceNumber} isn't null and is less than 0 */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> updateSequenceNumberWithResponse(SequenceNumberActionType action, Long sequenceNumber, BlobRequestConditions requestConditions) { try { return withContext(context -> updateSequenceNumberWithResponse(action, sequenceNumber, requestConditions, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> updateSequenceNumberWithResponse(SequenceNumberActionType action, Long sequenceNumber, BlobRequestConditions requestConditions, Context context) { if (sequenceNumber != null && sequenceNumber < 0) { // Throwing is preferred to Single.error because this will error out immediately instead of waiting until // subscription. throw LOGGER.logExceptionAsError( new IllegalArgumentException("SequenceNumber must be greater than or equal to 0.")); } requestConditions = requestConditions == null ? new BlobRequestConditions() : requestConditions; sequenceNumber = action == SequenceNumberActionType.INCREMENT ? null : sequenceNumber; context = context == null ? Context.NONE : context; return this.azureBlobStorage.getPageBlobs().updateSequenceNumberWithResponseAsync(containerName, blobName, action, null, requestConditions.getLeaseId(), requestConditions.getIfModifiedSince(), requestConditions.getIfUnmodifiedSince(), requestConditions.getIfMatch(), requestConditions.getIfNoneMatch(), requestConditions.getTagsConditions(), sequenceNumber, null, context) .map(rb -> { PageBlobsUpdateSequenceNumberHeaders hd = rb.getDeserializedHeaders(); PageBlobItem item = new PageBlobItem(hd.getETag(), hd.getLastModified(), null, null, null, null, hd.getXMsBlobSequenceNumber()); return new SimpleResponse<>(rb, item); }); } /** * Begins an operation to start an incremental copy from one page blob's snapshot to this page blob. The snapshot * is * copied such that only the differential changes between the previously copied snapshot are transferred to the * destination. The copied snapshots are complete copies of the original snapshot and can be read or copied from as * usual. For more information, see the Azure Docs * here * and * here. * *

Code Samples

* * *
     * final String snapshot = "copy snapshot";
     * client.copyIncremental(url, snapshot).subscribe(statusType -> {
     *     switch (statusType) {
     *         case SUCCESS:
     *             System.out.println("Page blob copied successfully");
     *             break;
     *         case FAILED:
     *             System.out.println("Page blob copied failed");
     *             break;
     *         case ABORTED:
     *             System.out.println("Page blob copied aborted");
     *             break;
     *         case PENDING:
     *             System.out.println("Page blob copied pending");
     *             break;
     *         default:
     *             break;
     *     }
     * });
     * 
* * * @param source The source page blob. * @param snapshot The snapshot on the copy source. * * @return A reactive response emitting the copy status. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono copyIncremental(String source, String snapshot) { return copyIncrementalWithResponse(source, snapshot, null).flatMap(FluxUtil::toMono); } /** * Begins an operation to start an incremental copy from one page blob's snapshot to this page blob. The snapshot * is * copied such that only the differential changes between the previously copied snapshot are transferred to the * destination. The copied snapshots are complete copies of the original snapshot and can be read or copied from as * usual. For more information, see the Azure Docs * here * and * here. * *

Code Samples

* * *
     * final String snapshot = "copy snapshot";
     * RequestConditions modifiedRequestConditions = new RequestConditions()
     *     .setIfNoneMatch("snapshotMatch");
     *
     * client.copyIncrementalWithResponse(url, snapshot, modifiedRequestConditions)
     *     .subscribe(response -> {
     *         CopyStatusType statusType = response.getValue();
     *
     *         switch (statusType) {
     *             case SUCCESS:
     *                 System.out.println("Page blob copied successfully");
     *                 break;
     *             case FAILED:
     *                 System.out.println("Page blob copied failed");
     *                 break;
     *             case ABORTED:
     *                 System.out.println("Page blob copied aborted");
     *                 break;
     *             case PENDING:
     *                 System.out.println("Page blob copied pending");
     *                 break;
     *             default:
     *                 break;
     *         }
     *     });
     * 
* * * @param source The source page blob. * @param snapshot The snapshot on the copy source. * @param modifiedRequestConditions Standard HTTP Access conditions related to the modification of data. ETag and * LastModifiedTime are used to construct conditions related to when the blob was changed relative to the given * request. The request will fail if the specified condition is not satisfied. * * @return A reactive response emitting the copy status. * * @throws IllegalStateException If {@code source} and {@code snapshot} form a malformed URL. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> copyIncrementalWithResponse(String source, String snapshot, RequestConditions modifiedRequestConditions) { return copyIncrementalWithResponse(new PageBlobCopyIncrementalOptions(source, snapshot) .setRequestConditions(ModelHelper.populateBlobDestinationRequestConditions(modifiedRequestConditions))); } /** * Begins an operation to start an incremental copy from one page blob's snapshot to this page blob. The snapshot * is * copied such that only the differential changes between the previously copied snapshot are transferred to the * destination. The copied snapshots are complete copies of the original snapshot and can be read or copied from as * usual. For more information, see the Azure Docs * here * and * here. * *

Code Samples

* * *
     * final String snapshot = "copy snapshot";
     * PageBlobCopyIncrementalRequestConditions destinationRequestConditions = new PageBlobCopyIncrementalRequestConditions()
     *     .setIfNoneMatch("snapshotMatch");
     *
     * client.copyIncrementalWithResponse(new PageBlobCopyIncrementalOptions(url, snapshot)
     *     .setRequestConditions(destinationRequestConditions))
     *     .subscribe(response -> {
     *         CopyStatusType statusType = response.getValue();
     *
     *         switch (statusType) {
     *             case SUCCESS:
     *                 System.out.println("Page blob copied successfully");
     *                 break;
     *             case FAILED:
     *                 System.out.println("Page blob copied failed");
     *                 break;
     *             case ABORTED:
     *                 System.out.println("Page blob copied aborted");
     *                 break;
     *             case PENDING:
     *                 System.out.println("Page blob copied pending");
     *                 break;
     *             default:
     *                 break;
     *         }
     *     });
     * 
* * * @param options {@link PageBlobCopyIncrementalOptions} * * @return A reactive response emitting the copy status. * * @throws IllegalStateException If {@code source} and {@code snapshot} form a malformed URL. */ @ServiceMethod(returns = ReturnType.SINGLE) public Mono> copyIncrementalWithResponse(PageBlobCopyIncrementalOptions options) { try { return withContext(context -> copyIncrementalWithResponse(options, context)); } catch (RuntimeException ex) { return monoError(LOGGER, ex); } } Mono> copyIncrementalWithResponse(PageBlobCopyIncrementalOptions options, Context context) { StorageImplUtils.assertNotNull("options", options); UrlBuilder builder = UrlBuilder.parse(options.getSource()); builder.setQueryParameter(Constants.UrlConstants.SNAPSHOT_QUERY_PARAMETER, options.getSnapshot()); PageBlobCopyIncrementalRequestConditions modifiedRequestConditions = (options.getRequestConditions() == null) ? new PageBlobCopyIncrementalRequestConditions() : options.getRequestConditions(); try { builder.toUrl(); } catch (MalformedURLException e) { // We are parsing a valid url and adding a query parameter. If this fails, we can't recover. throw LOGGER.logExceptionAsError(new IllegalArgumentException(e)); } context = context == null ? Context.NONE : context; return this.azureBlobStorage.getPageBlobs().copyIncrementalWithResponseAsync(containerName, blobName, builder.toString(), null, modifiedRequestConditions.getIfModifiedSince(), modifiedRequestConditions.getIfUnmodifiedSince(), modifiedRequestConditions.getIfMatch(), modifiedRequestConditions.getIfNoneMatch(), modifiedRequestConditions.getTagsConditions(), null, context) .map(rb -> new SimpleResponse<>(rb, rb.getDeserializedHeaders().getXMsCopyStatus())); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy