Search in sources :

Example 6 with CloudStorageException

use of com.github.ambry.cloud.CloudStorageException in project ambry by linkedin.

the class AzureContainerCompactor method saveLatestContainerDeletionTime.

/**
 * Save the deleted container update checkpoint {@code latestContainerDeletionTimestamp} to Azure Blob Store.
 * @param latestContainerDeletionTimestamp timestamp representing deleteTriggerTime upto which deleted containers have been updated in cloud.
 * @throws CloudStorageException in case of any error.
 */
private void saveLatestContainerDeletionTime(long latestContainerDeletionTimestamp) throws CloudStorageException {
    try {
        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
        buffer.putLong(latestContainerDeletionTimestamp);
        ByteArrayInputStream bais = new ByteArrayInputStream(buffer.array());
        requestAgent.doWithRetries(() -> {
            azureBlobDataAccessor.uploadFile(AzureCloudDestination.CHECKPOINT_CONTAINER, CONTAINER_DELETION_CHECKPOINT_FILE, bais);
            return null;
        }, "update-container-deletion-checkpoint", null);
    } catch (CloudStorageException e) {
        logger.error("Could not save update deprecated container progress", e);
        throw e;
    }
}
Also used : ByteArrayInputStream(java.io.ByteArrayInputStream) CloudStorageException(com.github.ambry.cloud.CloudStorageException) ByteBuffer(java.nio.ByteBuffer)

Example 7 with CloudStorageException

use of com.github.ambry.cloud.CloudStorageException in project ambry by linkedin.

the class AzureCloudDestination method getBlobMetadata.

@Override
public Map<String, CloudBlobMetadata> getBlobMetadata(List<BlobId> blobIds) throws CloudStorageException {
    Objects.requireNonNull(blobIds, "blobIds cannot be null");
    if (blobIds.isEmpty()) {
        return Collections.emptyMap();
    }
    // needs to include that store key to replay the upload.
    if (!isVcr && blobIds.size() == 1) {
        CloudBlobMetadata metadata = azureBlobDataAccessor.getBlobMetadata(blobIds.get(0));
        return metadata == null ? Collections.emptyMap() : Collections.singletonMap(metadata.getId(), metadata);
    }
    // CosmosDB has query size limit of 256k chars.
    // Break list into chunks if necessary to avoid overflow.
    List<CloudBlobMetadata> metadataList = new ArrayList<>();
    List<List<BlobId>> chunkedBlobIdList = Utils.partitionList(blobIds, queryBatchSize);
    for (List<BlobId> batchOfBlobs : chunkedBlobIdList) {
        metadataList.addAll(getBlobMetadataChunked(batchOfBlobs));
    }
    return metadataList.stream().collect(Collectors.toMap(CloudBlobMetadata::getId, Function.identity(), (x, y) -> x));
}
Also used : DocumentClientException(com.microsoft.azure.cosmosdb.DocumentClientException) BlobStorageException(com.azure.storage.blob.models.BlobStorageException) LoggerFactory(org.slf4j.LoggerFactory) VcrMetrics(com.github.ambry.cloud.VcrMetrics) HashMap(java.util.HashMap) Function(java.util.function.Function) CloudDestination(com.github.ambry.cloud.CloudDestination) ArrayList(java.util.ArrayList) CloudConfig(com.github.ambry.config.CloudConfig) StatusCodes(com.microsoft.azure.cosmosdb.internal.HttpConstants.StatusCodes) CloudContainerCompactor(com.github.ambry.cloud.CloudContainerCompactor) CloudUpdateValidator(com.github.ambry.cloud.CloudUpdateValidator) Map(java.util.Map) StoreException(com.github.ambry.store.StoreException) BlobBatchClient(com.azure.storage.blob.batch.BlobBatchClient) BlobLayout(com.github.ambry.cloud.azure.AzureBlobLayoutStrategy.BlobLayout) OutputStream(java.io.OutputStream) Container(com.github.ambry.account.Container) CloudStorageException(com.github.ambry.cloud.CloudStorageException) FindResult(com.github.ambry.cloud.FindResult) MetricRegistry(com.codahale.metrics.MetricRegistry) Properties(java.util.Properties) Logger(org.slf4j.Logger) AsyncDocumentClient(com.microsoft.azure.cosmosdb.rx.AsyncDocumentClient) VerifiableProperties(com.github.ambry.config.VerifiableProperties) Collection(java.util.Collection) ClusterMap(com.github.ambry.clustermap.ClusterMap) Utils(com.github.ambry.utils.Utils) IOException(java.io.IOException) Collectors(java.util.stream.Collectors) Objects(java.util.Objects) TimeUnit(java.util.concurrent.TimeUnit) BlobServiceClient(com.azure.storage.blob.BlobServiceClient) BlobErrorCode(com.azure.storage.blob.models.BlobErrorCode) HttpConstants(com.microsoft.azure.cosmosdb.internal.HttpConstants) List(java.util.List) Document(com.microsoft.azure.cosmosdb.Document) Timer(com.codahale.metrics.Timer) FindToken(com.github.ambry.replication.FindToken) CloudBlobMetadata(com.github.ambry.cloud.CloudBlobMetadata) Collections(java.util.Collections) PartitionId(com.github.ambry.clustermap.PartitionId) BlobId(com.github.ambry.commons.BlobId) ResourceResponse(com.microsoft.azure.cosmosdb.ResourceResponse) InputStream(java.io.InputStream) CloudBlobMetadata(com.github.ambry.cloud.CloudBlobMetadata) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) BlobId(com.github.ambry.commons.BlobId)

Example 8 with CloudStorageException

use of com.github.ambry.cloud.CloudStorageException in project ambry by linkedin.

the class AzureCloudDestinationTest method testFindEntriesSinceUsingChangeFeedWithInvalidToken.

/**
 * Query changefeed with invalid token and check for cache miss.
 * @param findToken {@link CosmosChangeFeedFindToken} to continue from.
 * @throws CloudStorageException
 */
private void testFindEntriesSinceUsingChangeFeedWithInvalidToken(CosmosChangeFeedFindToken findToken) throws CloudStorageException {
    // Invalid session id.
    CosmosChangeFeedFindToken invalidFindToken = new CosmosChangeFeedFindToken(findToken.getBytesRead(), findToken.getStartContinuationToken(), findToken.getEndContinuationToken(), findToken.getIndex(), findToken.getTotalItems(), UUID.randomUUID().toString(), findToken.getVersion());
    FindResult findResult = azureDest.findEntriesSince(blobId.getPartition().toPathString(), invalidFindToken, 10);
    findToken = (CosmosChangeFeedFindToken) findResult.getUpdatedFindToken();
    assertEquals("Unexpected change feed cache miss count", 2, azureMetrics.changeFeedCacheMissRate.getCount());
    assertEquals("Unexpected change feed cache refresh count", 1, azureMetrics.changeFeedCacheRefreshRate.getCount());
    assertEquals("Unexpected change feed cache hit count", 3, azureMetrics.changeFeedCacheHitRate.getCount());
    // invalid end token.
    invalidFindToken = new CosmosChangeFeedFindToken(findToken.getBytesRead(), findToken.getStartContinuationToken(), "5000", findToken.getIndex(), findToken.getTotalItems(), findToken.getCacheSessionId(), findToken.getVersion());
    findResult = azureDest.findEntriesSince(blobId.getPartition().toPathString(), invalidFindToken, 10);
    findToken = (CosmosChangeFeedFindToken) findResult.getUpdatedFindToken();
    assertEquals("Unexpected change feed cache miss count", 3, azureMetrics.changeFeedCacheMissRate.getCount());
    assertEquals("Unexpected change feed cache refresh count", 1, azureMetrics.changeFeedCacheRefreshRate.getCount());
    assertEquals("Unexpected change feed cache hit count", 3, azureMetrics.changeFeedCacheHitRate.getCount());
    // invalid start token.
    invalidFindToken = new CosmosChangeFeedFindToken(findToken.getBytesRead(), "5000", findToken.getEndContinuationToken(), findToken.getIndex(), findToken.getTotalItems(), findToken.getCacheSessionId(), findToken.getVersion());
    try {
        azureDest.findEntriesSince(blobId.getPartition().toPathString(), invalidFindToken, 10);
    } catch (Exception ex) {
    }
    assertEquals("Unexpected change feed cache miss count", 4, azureMetrics.changeFeedCacheMissRate.getCount());
    assertEquals("Unexpected change feed cache refresh count", 1, azureMetrics.changeFeedCacheRefreshRate.getCount());
    assertEquals("Unexpected change feed cache hit count", 3, azureMetrics.changeFeedCacheHitRate.getCount());
    // invalid total items.
    invalidFindToken = new CosmosChangeFeedFindToken(findToken.getBytesRead(), findToken.getStartContinuationToken(), findToken.getEndContinuationToken(), findToken.getIndex(), 9000, findToken.getCacheSessionId(), findToken.getVersion());
    azureDest.findEntriesSince(blobId.getPartition().toPathString(), invalidFindToken, 10);
    assertEquals("Unexpected change feed cache miss count", 5, azureMetrics.changeFeedCacheMissRate.getCount());
    assertEquals("Unexpected change feed cache refresh count", 1, azureMetrics.changeFeedCacheRefreshRate.getCount());
    assertEquals("Unexpected change feed cache hit count", 3, azureMetrics.changeFeedCacheHitRate.getCount());
}
Also used : DocumentClientException(com.microsoft.azure.cosmosdb.DocumentClientException) BlobStorageException(com.azure.storage.blob.models.BlobStorageException) CloudStorageException(com.github.ambry.cloud.CloudStorageException) IOException(java.io.IOException) FindResult(com.github.ambry.cloud.FindResult)

Example 9 with CloudStorageException

use of com.github.ambry.cloud.CloudStorageException in project ambry by linkedin.

the class AzureCloudDestinationTest method testDeleteAfterPartialCompaction.

/**
 * Test delete when record is in Cosmos but not ABS.
 */
@Test
public void testDeleteAfterPartialCompaction() throws Exception {
    BlobStorageException ex = mockStorageException(BlobErrorCode.BLOB_NOT_FOUND);
    when(mockBlockBlobClient.getPropertiesWithResponse(any(), any(), any())).thenThrow(ex);
    // Rig Cosmos to return us a deleted blob on read request
    long deletionTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(10);
    CloudBlobMetadata deletedMetadata = new CloudBlobMetadata().setId(blobId.getID()).setDeletionTime(deletionTime);
    Observable<ResourceResponse<Document>> mockResponse = getMockedObservableForSingleResource(deletedMetadata);
    when(mockumentClient.readDocument(anyString(), any(RequestOptions.class))).thenReturn(mockResponse);
    // Now delete the puppy, Cosmos record should get purged.
    try {
        assertFalse("Expected update to recover and return false", azureDest.deleteBlob(blobId, deletionTime, (short) 0, dummyCloudUpdateValidator));
    } catch (CloudStorageException cex) {
        assertTrue(cex.getCause() instanceof BlobStorageException);
        assertEquals(((BlobStorageException) cex.getCause()).getErrorCode(), BlobErrorCode.BLOB_NOT_FOUND);
    }
    assertEquals("Expected recovery", 1, azureMetrics.blobUpdateRecoverCount.getCount());
    verify(mockumentClient).deleteDocument(anyString(), any());
}
Also used : ResourceResponse(com.microsoft.azure.cosmosdb.ResourceResponse) RequestOptions(com.microsoft.azure.cosmosdb.RequestOptions) CloudBlobMetadata(com.github.ambry.cloud.CloudBlobMetadata) CloudStorageException(com.github.ambry.cloud.CloudStorageException) BlobStorageException(com.azure.storage.blob.models.BlobStorageException) Test(org.junit.Test)

Example 10 with CloudStorageException

use of com.github.ambry.cloud.CloudStorageException in project ambry by linkedin.

the class AzureIntegrationTest method testNormalFlow.

/**
 * Test normal operations.
 * @throws Exception on error
 */
@Test
public void testNormalFlow() throws Exception {
    PartitionId partitionId = new MockPartitionId(testPartition, MockClusterMap.DEFAULT_PARTITION_CLASS);
    BlobId blobId = new BlobId(BLOB_ID_V6, BlobIdType.NATIVE, dataCenterId, accountId, containerId, partitionId, false, BlobDataType.DATACHUNK);
    byte[] uploadData = TestUtils.getRandomBytes(blobSize);
    InputStream inputStream = new ByteArrayInputStream(uploadData);
    long now = System.currentTimeMillis();
    CloudBlobMetadata cloudBlobMetadata = new CloudBlobMetadata(blobId, now, now + 60000, blobSize, CloudBlobMetadata.EncryptionOrigin.VCR, vcrKmsContext, cryptoAgentFactory, blobSize, (short) 0);
    // attempt undelete before uploading blob
    try {
        undeleteBlobWithRetry(blobId, (short) 1);
        fail("Undelete of a non existent blob should fail.");
    } catch (CloudStorageException cex) {
        assertEquals(cex.getStatusCode(), HttpConstants.StatusCodes.NOTFOUND);
    }
    assertTrue("Expected upload to return true", AzureTestUtils.uploadBlobWithRetry(blobId, blobSize, cloudBlobMetadata, inputStream, cloudRequestAgent, azureDest));
    // Get blob should return the same data
    verifyDownloadMatches(blobId, uploadData);
    // Try to upload same blob again
    assertFalse("Expected duplicate upload to return false", AzureTestUtils.uploadBlobWithRetry(blobId, blobSize, cloudBlobMetadata, new ByteArrayInputStream(uploadData), cloudRequestAgent, azureDest));
    // ttl update
    long expirationTime = Utils.Infinite_Time;
    try {
        updateBlobExpirationWithRetry(blobId, expirationTime);
    } catch (Exception ex) {
        fail("Expected update to be successful");
    }
    CloudBlobMetadata metadata = getBlobMetadataWithRetry(Collections.singletonList(blobId), partitionId.toPathString(), cloudRequestAgent, azureDest).get(blobId.getID());
    assertEquals(expirationTime, metadata.getExpirationTime());
    // delete blob
    long deletionTime = now + 10000;
    // TODO add a test case here to verify life version after delete.
    assertTrue("Expected deletion to return true", cloudRequestAgent.doWithRetries(() -> azureDest.deleteBlob(blobId, deletionTime, (short) 0, dummyCloudUpdateValidator), "DeleteBlob", partitionId.toPathString()));
    metadata = getBlobMetadataWithRetry(Collections.singletonList(blobId), partitionId.toPathString(), cloudRequestAgent, azureDest).get(blobId.getID());
    assertEquals(deletionTime, metadata.getDeletionTime());
    // undelete blob
    assertEquals(undeleteBlobWithRetry(blobId, (short) 1), 1);
    metadata = getBlobMetadataWithRetry(Collections.singletonList(blobId), partitionId.toPathString(), cloudRequestAgent, azureDest).get(blobId.getID());
    assertEquals(metadata.getDeletionTime(), Utils.Infinite_Time);
    assertEquals(metadata.getLifeVersion(), 1);
    // undelete with a higher life version updates life version.
    assertEquals(undeleteBlobWithRetry(blobId, (short) 2), 2);
    metadata = getBlobMetadataWithRetry(Collections.singletonList(blobId), partitionId.toPathString(), cloudRequestAgent, azureDest).get(blobId.getID());
    assertEquals(metadata.getDeletionTime(), Utils.Infinite_Time);
    assertEquals(metadata.getLifeVersion(), 2);
    // delete after undelete.
    long newDeletionTime = now + 20000;
    // TODO add a test case here to verify life version after delete.
    assertTrue("Expected deletion to return true", cloudRequestAgent.doWithRetries(() -> azureDest.deleteBlob(blobId, newDeletionTime, (short) 3, dummyCloudUpdateValidator), "DeleteBlob", partitionId.toPathString()));
    metadata = getBlobMetadataWithRetry(Collections.singletonList(blobId), partitionId.toPathString(), cloudRequestAgent, azureDest).get(blobId.getID());
    assertEquals(newDeletionTime, metadata.getDeletionTime());
    // delete changes life version.
    assertEquals(metadata.getLifeVersion(), 3);
    // compact partition
    azureDest.compactPartition(partitionId.toPathString());
    assertTrue("Expected empty set after purge", getBlobMetadataWithRetry(Collections.singletonList(blobId), partitionId.toPathString(), cloudRequestAgent, azureDest).isEmpty());
    // Get blob should fail after purge
    try {
        verifyDownloadMatches(blobId, uploadData);
        fail("download blob should fail after data is purged");
    } catch (CloudStorageException csex) {
    }
}
Also used : MockPartitionId(com.github.ambry.clustermap.MockPartitionId) ByteArrayInputStream(java.io.ByteArrayInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) CloudBlobMetadata(com.github.ambry.cloud.CloudBlobMetadata) CloudStorageException(com.github.ambry.cloud.CloudStorageException) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PartitionId(com.github.ambry.clustermap.PartitionId) BlobId(com.github.ambry.commons.BlobId) CloudStorageException(com.github.ambry.cloud.CloudStorageException) IOException(java.io.IOException) Test(org.junit.Test)

Aggregations

CloudStorageException (com.github.ambry.cloud.CloudStorageException)13 IOException (java.io.IOException)7 Test (org.junit.Test)7 BlobStorageException (com.azure.storage.blob.models.BlobStorageException)6 CloudBlobMetadata (com.github.ambry.cloud.CloudBlobMetadata)6 ByteArrayInputStream (java.io.ByteArrayInputStream)6 PartitionId (com.github.ambry.clustermap.PartitionId)4 BlobId (com.github.ambry.commons.BlobId)4 DocumentClientException (com.microsoft.azure.cosmosdb.DocumentClientException)4 InputStream (java.io.InputStream)4 MockPartitionId (com.github.ambry.clustermap.MockPartitionId)3 FindResult (com.github.ambry.cloud.FindResult)2 VcrMetrics (com.github.ambry.cloud.VcrMetrics)2 CloudConfig (com.github.ambry.config.CloudConfig)2 RequestOptions (com.microsoft.azure.cosmosdb.RequestOptions)2 AsyncDocumentClient (com.microsoft.azure.cosmosdb.rx.AsyncDocumentClient)2 ArrayList (java.util.ArrayList)2 Collections (java.util.Collections)2 Date (java.util.Date)2 HashMap (java.util.HashMap)2