Search in sources :

Example 6 with CloudBlobMetadata

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

the class AzureCloudDestinationTest method setup.

@Before
public void setup() throws Exception {
    long partition = 666;
    PartitionId partitionId = new MockPartitionId(partition, MockClusterMap.DEFAULT_PARTITION_CLASS);
    blobId = new BlobId(BLOB_ID_V6, BlobIdType.NATIVE, dataCenterId, accountId, containerId, partitionId, false, BlobDataType.DATACHUNK);
    CloudBlobMetadata blobMetadata = new CloudBlobMetadata(blobId, 0, Utils.Infinite_Time, blobSize, CloudBlobMetadata.EncryptionOrigin.NONE);
    mockServiceClient = mock(BlobServiceClient.class);
    mockBlobBatchClient = mock(BlobBatchClient.class);
    mockBlockBlobClient = AzureBlobDataAccessorTest.setupMockBlobClient(mockServiceClient);
    mockBlobExistence(false);
    mockumentClient = mock(AsyncDocumentClient.class);
    Observable<ResourceResponse<Document>> mockResponse = getMockedObservableForSingleResource(blobMetadata);
    when(mockumentClient.readDocument(anyString(), any(RequestOptions.class))).thenReturn(mockResponse);
    when(mockumentClient.upsertDocument(anyString(), any(Object.class), any(RequestOptions.class), anyBoolean())).thenReturn(mockResponse);
    when(mockumentClient.replaceDocument(any(Document.class), any(RequestOptions.class))).thenReturn(mockResponse);
    when(mockumentClient.deleteDocument(anyString(), any(RequestOptions.class))).thenReturn(mockResponse);
    configProps.setProperty(AzureCloudConfig.AZURE_STORAGE_CONNECTION_STRING, storageConnection);
    configProps.setProperty(AzureCloudConfig.COSMOS_ENDPOINT, "http://ambry.beyond-the-cosmos.com:443");
    configProps.setProperty(AzureCloudConfig.COSMOS_COLLECTION_LINK, "ambry/metadata");
    configProps.setProperty(AzureCloudConfig.COSMOS_DELETED_CONTAINER_COLLECTION_LINK, "ambry/deletedContainer");
    configProps.setProperty(AzureCloudConfig.COSMOS_KEY, "cosmos-key");
    configProps.setProperty("clustermap.cluster.name", "main");
    configProps.setProperty("clustermap.datacenter.name", "uswest");
    configProps.setProperty("clustermap.host.name", "localhost");
    configProps.setProperty(AzureCloudConfig.AZURE_STORAGE_AUTHORITY, "https://login.microsoftonline.com/test-account/");
    configProps.setProperty(AzureCloudConfig.AZURE_STORAGE_CLIENTID, "client-id");
    configProps.setProperty(AzureCloudConfig.AZURE_STORAGE_SECRET, "client-secret");
    configProps.setProperty(AzureCloudConfig.AZURE_STORAGE_ENDPOINT, "https://azure_storage.blob.core.windows.net");
    configProps.setProperty(AzureCloudConfig.AZURE_STORAGE_CLIENT_CLASS, "com.github.ambry.cloud.azure.ConnectionStringBasedStorageClient");
    vcrMetrics = new VcrMetrics(new MetricRegistry());
    azureMetrics = new AzureMetrics(new MetricRegistry());
    clusterMap = mock(ClusterMap.class);
    azureDest = new AzureCloudDestination(mockServiceClient, mockBlobBatchClient, mockumentClient, "foo", "bar", clusterName, azureMetrics, defaultAzureReplicationFeedType, clusterMap, false, configProps);
}
Also used : ClusterMap(com.github.ambry.clustermap.ClusterMap) MockClusterMap(com.github.ambry.clustermap.MockClusterMap) VcrMetrics(com.github.ambry.cloud.VcrMetrics) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) RequestOptions(com.microsoft.azure.cosmosdb.RequestOptions) CloudBlobMetadata(com.github.ambry.cloud.CloudBlobMetadata) MetricRegistry(com.codahale.metrics.MetricRegistry) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PartitionId(com.github.ambry.clustermap.PartitionId) Document(com.microsoft.azure.cosmosdb.Document) ResourceResponse(com.microsoft.azure.cosmosdb.ResourceResponse) BlobServiceClient(com.azure.storage.blob.BlobServiceClient) BlobBatchClient(com.azure.storage.blob.batch.BlobBatchClient) BlobId(com.github.ambry.commons.BlobId) AsyncDocumentClient(com.microsoft.azure.cosmosdb.rx.AsyncDocumentClient) Before(org.junit.Before)

Example 7 with CloudBlobMetadata

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

the class AzureIntegrationTest method cleanup.

/**
 * Cleanup the test setup
 */
private void cleanup() throws Exception {
    String partitionPath = String.valueOf(testPartition);
    Timer dummyTimer = new Timer();
    List<CloudBlobMetadata> allBlobsInPartition = cloudRequestAgent.doWithRetries(() -> azureDest.getCosmosDataAccessor().queryMetadata(partitionPath, "SELECT * FROM c", dummyTimer), "QueryMetadata", partitionPath);
    int numPurged = purgeBlobsWithRetry(allBlobsInPartition, partitionPath);
    logger.info("Cleaned up {} blobs", numPurged);
    // Delete compaction checkpoint blob
    if (azureDest.getAzureBlobDataAccessor().deleteFile(AzureCloudDestination.CHECKPOINT_CONTAINER, partitionPath)) {
        logger.info("Deleted compaction checkpoint");
    }
}
Also used : Timer(com.codahale.metrics.Timer) CloudBlobMetadata(com.github.ambry.cloud.CloudBlobMetadata)

Example 8 with CloudBlobMetadata

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

the class AzureIntegrationTest method testConcurrentUpdates.

/**
 * Test that concurrent updates fail when the precondition does not match.
 * We don't test retries here since CloudBlobStoreTest covers that.
 */
@Test
public void testConcurrentUpdates() 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);
    InputStream inputStream = getBlobInputStream(blobSize);
    long now = System.currentTimeMillis();
    CloudBlobMetadata cloudBlobMetadata = new CloudBlobMetadata(blobId, now, now + 60000, blobSize, CloudBlobMetadata.EncryptionOrigin.NONE);
    uploadBlobWithRetry(blobId, blobSize, cloudBlobMetadata, inputStream, cloudRequestAgent, azureDest);
    // Different instance to simulate concurrent update in separate session.
    AzureCloudDestination concurrentUpdater = getAzureDestination(verifiableProperties);
    String fieldName = CloudBlobMetadata.FIELD_UPLOAD_TIME;
    long newUploadTime = now++;
    // Case 1: concurrent modification to blob metadata.
    azureDest.getAzureBlobDataAccessor().setUpdateCallback(() -> concurrentUpdater.getAzureBlobDataAccessor().updateBlobMetadata(blobId, Collections.singletonMap(fieldName, newUploadTime), dummyCloudUpdateValidator));
    try {
        azureDest.updateBlobExpiration(blobId, ++now, dummyCloudUpdateValidator);
        fail("Expected 412 error");
    } catch (CloudStorageException csex) {
        // TODO: check nested exception is BlobStorageException with status code 412
        assertEquals("Expected update conflict", 1, azureDest.getAzureMetrics().blobUpdateConflictCount.getCount());
    }
    // Case 2: concurrent modification to Cosmos record.
    azureDest.getCosmosDataAccessor().setUpdateCallback(() -> concurrentUpdater.getCosmosDataAccessor().updateMetadata(blobId, Collections.singletonMap(fieldName, Long.toString(newUploadTime))));
    try {
        azureDest.updateBlobExpiration(blobId, ++now, dummyCloudUpdateValidator);
        fail("Expected 412 error");
    } catch (CloudStorageException csex) {
        assertEquals("Expected update conflict", 2, azureDest.getAzureMetrics().blobUpdateConflictCount.getCount());
    }
    azureDest.getCosmosDataAccessor().setUpdateCallback(null);
    try {
        azureDest.updateBlobExpiration(blobId, ++now, dummyCloudUpdateValidator);
    } catch (Exception ex) {
        fail("Expected update to succeed.");
    }
    assertEquals("Expected no new update conflict", 2, azureDest.getAzureMetrics().blobUpdateConflictCount.getCount());
}
Also used : MockPartitionId(com.github.ambry.clustermap.MockPartitionId) 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)

Example 9 with CloudBlobMetadata

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

the class AzureIntegrationTest method testRepairInconsistency.

/**
 * Test that ABS/Cosmos inconsistencies get fixed on update.
 */
@Test
public void testRepairInconsistency() throws Exception {
    // Upload a blob
    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);
    InputStream inputStream = getBlobInputStream(blobSize);
    long now = System.currentTimeMillis();
    CloudBlobMetadata cloudBlobMetadata = new CloudBlobMetadata(blobId, now, now + 60000, blobSize, CloudBlobMetadata.EncryptionOrigin.NONE);
    uploadBlobWithRetry(blobId, blobSize, cloudBlobMetadata, inputStream, cloudRequestAgent, azureDest);
    // Remove blob record from Cosmos to create inconsistency
    azureDest.getCosmosDataAccessor().deleteMetadata(cloudBlobMetadata);
    // Now update the blob and see if it gets fixed
    azureDest.updateBlobExpiration(blobId, Utils.Infinite_Time, dummyCloudUpdateValidator);
    List<CloudBlobMetadata> resultList = azureDest.getCosmosDataAccessor().queryMetadata(partitionId.toPathString(), "SELECT * FROM c WHERE c.id = '" + blobId.getID() + "'", azureDest.getAzureMetrics().missingKeysQueryTime);
    assertEquals("Expected record to exist", 1, resultList.size());
}
Also used : MockPartitionId(com.github.ambry.clustermap.MockPartitionId) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) CloudBlobMetadata(com.github.ambry.cloud.CloudBlobMetadata) MockPartitionId(com.github.ambry.clustermap.MockPartitionId) PartitionId(com.github.ambry.clustermap.PartitionId) BlobId(com.github.ambry.commons.BlobId) Test(org.junit.Test)

Example 10 with CloudBlobMetadata

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

the class AzureIntegrationTest method testRepairAfterIncompleteCompaction.

/**
 * Test that incomplete compaction get fixed on update.
 */
@Test
public void testRepairAfterIncompleteCompaction() throws Exception {
    // Upload a blob
    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);
    InputStream inputStream = getBlobInputStream(blobSize);
    long now = System.currentTimeMillis();
    CloudBlobMetadata cloudBlobMetadata = new CloudBlobMetadata(blobId, now, -1, blobSize, CloudBlobMetadata.EncryptionOrigin.NONE);
    uploadBlobWithRetry(blobId, blobSize, cloudBlobMetadata, inputStream, cloudRequestAgent, azureDest);
    // Mark it deleted in the past
    long deletionTime = now - TimeUnit.DAYS.toMillis(7);
    assertTrue("Expected delete to return true", azureDest.deleteBlob(blobId, deletionTime, (short) 0, dummyCloudUpdateValidator));
    // Simulate incomplete compaction by purging it from ABS only
    azureDest.getAzureBlobDataAccessor().purgeBlobs(Collections.singletonList(cloudBlobMetadata));
    // Try to delete again (to trigger recovery), verify removed from Cosmos
    try {
        azureDest.deleteBlob(blobId, deletionTime, (short) 0, dummyCloudUpdateValidator);
    } catch (CloudStorageException cex) {
        assertEquals("Unexpected error code", HttpConstants.StatusCodes.NOTFOUND, cex.getStatusCode());
    }
    assertNull("Expected record to be purged from Cosmos", azureDest.getCosmosDataAccessor().getMetadataOrNull(blobId));
}
Also used : MockPartitionId(com.github.ambry.clustermap.MockPartitionId) 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) Test(org.junit.Test)

Aggregations

CloudBlobMetadata (com.github.ambry.cloud.CloudBlobMetadata)55 BlobId (com.github.ambry.commons.BlobId)27 Test (org.junit.Test)25 ArrayList (java.util.ArrayList)19 Document (com.microsoft.azure.cosmosdb.Document)14 PartitionId (com.github.ambry.clustermap.PartitionId)12 FeedResponse (com.microsoft.azure.cosmosdb.FeedResponse)12 FeedOptions (com.microsoft.azure.cosmosdb.FeedOptions)11 SqlQuerySpec (com.microsoft.azure.cosmosdb.SqlQuerySpec)11 MockPartitionId (com.github.ambry.clustermap.MockPartitionId)10 InputStream (java.io.InputStream)10 VerifiableProperties (com.github.ambry.config.VerifiableProperties)9 ByteArrayInputStream (java.io.ByteArrayInputStream)8 Timer (com.codahale.metrics.Timer)7 FindResult (com.github.ambry.cloud.FindResult)7 MetricRegistry (com.codahale.metrics.MetricRegistry)6 CloudStorageException (com.github.ambry.cloud.CloudStorageException)6 ChangeFeedOptions (com.microsoft.azure.cosmosdb.ChangeFeedOptions)6 DocumentClientException (com.microsoft.azure.cosmosdb.DocumentClientException)6 VcrMetrics (com.github.ambry.cloud.VcrMetrics)5