Skip to content

Commit

Permalink
Merge pull request Azure#81 from jofriedm-msft/archivesupport
Browse files Browse the repository at this point in the history
Added support for setting the standard blob tier on block blobs
  • Loading branch information
jofriedm-msft authored Aug 18, 2017
2 parents 37ffe37 + ca01bc0 commit a4d7b9c
Show file tree
Hide file tree
Showing 13 changed files with 435 additions and 60 deletions.
3 changes: 3 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
2017.XX.XX Version X.X.X
* For Standard Storage Accounts only, added the ability to set the tier of individual block blobs. The tier can currently only be set through uploadTier()

2017.07.12 Version 5.4.0
* Added ErrorReceivingResponseEvent which fires when a network error occurs before the responseReceivedEvent fires. If the responseReceivedEvent fires sucessfully, this new event will not fire.
* For Premium Accounts only, added support for getting and setting the tier on a page blob. The tier can also be set when creating or copying from an existing page blob.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,7 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumSet;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TimeZone;
import java.util.*;

import com.microsoft.azure.storage.StorageErrorCodeStrings;
import com.microsoft.azure.storage.TestRunners.CloudTests;
Expand Down Expand Up @@ -1942,4 +1934,82 @@ private void doCloudBlockBlobCopy(boolean sourceIsSas, boolean destinationIsSas)
destination.delete();
source.delete();
}

@Test
@Category({ DevFabricTests.class, DevStoreTests.class })
public void testCloudBlockBlobUploadStandardTier() throws StorageException, IOException, URISyntaxException {
for (StandardBlobTier standardBlobTier : StandardBlobTier.values()) {
if (standardBlobTier == StandardBlobTier.UNKNOWN) {
continue;
}

final String blobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlob");
final CloudBlockBlob blob = this.container.getBlockBlobReference(blobName);
blob.uploadText("text");

blob.uploadStandardBlobTier(standardBlobTier);
assertEquals(standardBlobTier, blob.getProperties().getStandardBlobTier());
assertNull(blob.getProperties().getPremiumPageBlobTier());
assertNull(blob.getProperties().getRehydrationStatus());

CloudBlockBlob blob2 = this.container.getBlockBlobReference(blobName);
blob2.downloadAttributes();
assertEquals(standardBlobTier, blob2.getProperties().getStandardBlobTier());
assertNull(blob2.getProperties().getPremiumPageBlobTier());
assertNull(blob2.getProperties().getRehydrationStatus());

CloudBlockBlob blob3 = (CloudBlockBlob)this.container.listBlobs().iterator().next();
assertEquals(standardBlobTier, blob3.getProperties().getStandardBlobTier());
assertNull(blob3.getProperties().getPremiumPageBlobTier());
assertNull(blob3.getProperties().getRehydrationStatus());

blob.deleteIfExists();
}
}

@Test
@Category({ DevFabricTests.class, DevStoreTests.class })
public void testCloudBlockBlobRehydrateBlob() throws StorageException, IOException, URISyntaxException {
final String blobName1 = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlob1");
final String blobName2 = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlob2");
final CloudBlockBlob blob = this.container.getBlockBlobReference(blobName1);
blob.uploadText("text");
blob.uploadStandardBlobTier(StandardBlobTier.ARCHIVE);
final CloudBlockBlob blob2 = this.container.getBlockBlobReference(blobName2);
blob2.uploadText("text");
blob2.uploadStandardBlobTier(StandardBlobTier.ARCHIVE);

CloudBlockBlob blobRef1 = this.container.getBlockBlobReference(blobName1);
blobRef1.uploadStandardBlobTier(StandardBlobTier.COOL);
assertNull(blobRef1.getProperties().getRehydrationStatus());
assertEquals(StandardBlobTier.ARCHIVE, blobRef1.getProperties().getStandardBlobTier());
assertNull(blobRef1.getProperties().getPremiumPageBlobTier());

blob.downloadAttributes();
assertEquals(RehydrationStatus.PENDING_TO_COOL, blob.getProperties().getRehydrationStatus());
assertEquals(StandardBlobTier.ARCHIVE, blob.getProperties().getStandardBlobTier());
assertNull(blob.getProperties().getPremiumPageBlobTier());

CloudBlockBlob blobRef2 = this.container.getBlockBlobReference(blobName2);
blobRef2.uploadStandardBlobTier(StandardBlobTier.HOT);
assertNull(blobRef2.getProperties().getRehydrationStatus());
assertEquals(StandardBlobTier.ARCHIVE, blobRef2.getProperties().getStandardBlobTier());
assertNull(blobRef2.getProperties().getPremiumPageBlobTier());

blob2.downloadAttributes();
assertEquals(RehydrationStatus.PENDING_TO_HOT, blob2.getProperties().getRehydrationStatus());
assertEquals(StandardBlobTier.ARCHIVE, blob2.getProperties().getStandardBlobTier());
assertNull(blob2.getProperties().getPremiumPageBlobTier());

Iterator it = this.container.listBlobs().iterator();
CloudBlockBlob listBlob = (CloudBlockBlob)it.next();
assertEquals(RehydrationStatus.PENDING_TO_COOL, listBlob.getProperties().getRehydrationStatus());
assertEquals(StandardBlobTier.ARCHIVE, listBlob.getProperties().getStandardBlobTier());
assertNull(listBlob.getProperties().getPremiumPageBlobTier());

CloudBlockBlob listBlob2 = (CloudBlockBlob)it.next();
assertEquals(RehydrationStatus.PENDING_TO_HOT, listBlob2.getProperties().getRehydrationStatus());
assertEquals(StandardBlobTier.ARCHIVE, listBlob2.getProperties().getStandardBlobTier());
assertNull(listBlob2.getProperties().getPremiumPageBlobTier());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1246,18 +1246,24 @@ public void testCloudPageBlobSetPremiumBlobTierOnCreate() throws URISyntaxExcept
blob.create(1024, PremiumPageBlobTier.P4, null, null, null);
assertEquals(PremiumPageBlobTier.P4, blob.getProperties().getPremiumPageBlobTier());
assertFalse(blob.getProperties().getInferredBlobTier());
assertNull(blob.getProperties().getStandardBlobTier());
assertNull(blob.getProperties().getRehydrationStatus());

CloudPageBlob blob2 = container.getPageBlobReference(blobName);
blob2.downloadAttributes();
assertEquals(PremiumPageBlobTier.P4, blob2.getProperties().getPremiumPageBlobTier());
assertNull(blob2.getProperties().getInferredBlobTier());
assertNull(blob2.getProperties().getStandardBlobTier());
assertNull(blob2.getProperties().getRehydrationStatus());

// Test upload from byte array API
byte[] buffer = BlobTestHelper.getRandomBuffer(1024);
CloudPageBlob blob3 = container.getPageBlobReference("blob3");
blob3.uploadFromByteArray(buffer, 0, 1024, PremiumPageBlobTier.P6, null, null, null);
assertEquals(PremiumPageBlobTier.P6, blob3.getProperties().getPremiumPageBlobTier());
assertFalse(blob3.getProperties().getInferredBlobTier());
assertNull(blob3.getProperties().getStandardBlobTier());
assertNull(blob3.getProperties().getRehydrationStatus());

CloudPageBlob blob3Ref = container.getPageBlobReference("blob3");
blob3Ref.downloadAttributes();
Expand All @@ -1270,6 +1276,8 @@ public void testCloudPageBlobSetPremiumBlobTierOnCreate() throws URISyntaxExcept
blob4.upload(srcStream, 1024, PremiumPageBlobTier.P10, null, null, null);
assertEquals(PremiumPageBlobTier.P10, blob4.getProperties().getPremiumPageBlobTier());
assertFalse(blob4.getProperties().getInferredBlobTier());
assertNull(blob4.getProperties().getStandardBlobTier());
assertNull(blob4.getProperties().getRehydrationStatus());

CloudPageBlob blob4Ref = container.getPageBlobReference("blob4");
blob4Ref.downloadAttributes();
Expand All @@ -1287,6 +1295,8 @@ public void testCloudPageBlobSetPremiumBlobTierOnCreate() throws URISyntaxExcept
blob5.uploadFromFile(sourceFile.getAbsolutePath(), PremiumPageBlobTier.P20, null, null, null);
assertEquals(PremiumPageBlobTier.P20, blob5.getProperties().getPremiumPageBlobTier());
assertFalse(blob5.getProperties().getInferredBlobTier());
assertNull(blob5.getProperties().getStandardBlobTier());
assertNull(blob5.getProperties().getRehydrationStatus());

CloudPageBlob blob5Ref = container.getPageBlobReference("blob5");
blob5Ref.downloadAttributes();
Expand Down Expand Up @@ -1315,6 +1325,8 @@ public void testCloudPageBlobSetBlobTier() throws URISyntaxException, StorageExc
blob.uploadPremiumPageBlobTier(PremiumPageBlobTier.P40);
assertEquals(PremiumPageBlobTier.P40, blob.properties.getPremiumPageBlobTier());
assertFalse(blob.getProperties().getInferredBlobTier());
assertNull(blob.getProperties().getStandardBlobTier());
assertNull(blob.getProperties().getRehydrationStatus());

CloudPageBlob blob2 = container.getPageBlobReference(blobName);
blob2.downloadAttributes();
Expand All @@ -1329,6 +1341,8 @@ public void testCloudPageBlobSetBlobTier() throws URISyntaxException, StorageExc
// Check that the blob is found exactly once
assertEquals(PremiumPageBlobTier.P40, blob3.properties.getPremiumPageBlobTier());
assertFalse(blob3.getProperties().getInferredBlobTier());
assertNull(blob3.getProperties().getStandardBlobTier());
assertNull(blob3.getProperties().getRehydrationStatus());
pageBlobWithTierFound = true;
} else if (blob.getName().equals(blobName)) {
fail("Page blob found twice");
Expand Down Expand Up @@ -1381,6 +1395,10 @@ public void testCloudPageBlobSetBlobTierOnCopy() throws URISyntaxException, Stor
assertEquals(PremiumPageBlobTier.P10, source.getProperties().getPremiumPageBlobTier());
assertFalse(source.getProperties().getInferredBlobTier());
assertFalse(copy.getProperties().getInferredBlobTier());
assertNull(source.getProperties().getStandardBlobTier());
assertNull(source.getProperties().getRehydrationStatus());
assertNull(copy.getProperties().getStandardBlobTier());
assertNull(copy.getProperties().getRehydrationStatus());
BlobTestHelper.waitForCopy(copy);

CloudPageBlob copyRef = container.getPageBlobReference("copy");
Expand All @@ -1399,6 +1417,10 @@ public void testCloudPageBlobSetBlobTierOnCopy() throws URISyntaxException, Stor
assertNull(source2.getProperties().getPremiumPageBlobTier());
assertNull(source2.getProperties().getInferredBlobTier());
assertFalse(copy3.getProperties().getInferredBlobTier());
assertNull(source2.getProperties().getStandardBlobTier());
assertNull(source2.getProperties().getRehydrationStatus());
assertNull(copy3.getProperties().getStandardBlobTier());
assertNull(copy3.getProperties().getRehydrationStatus());
}
finally {
container.deleteIfExists();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,11 @@ public static class QueryConstants {
*/
public static final String ACCESS_TIER = "AccessTier";

/**
* XML element for the archive status.
*/
public static final String ARCHIVE_STATUS = "ArchiveStatus";

/**
* Buffer width used to copy data to output streams.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,17 @@ final class BlobConstants {
* The header that specifies if the access tier is inferred.
*/
public static final String ACCESS_TIER_INFERRED_HEADER = Constants.PREFIX_FOR_STORAGE_HEADER + "access-tier-inferred";

/**
* Specifies the append blob type.
*/
public static final String APPEND_BLOB = "AppendBlob";

/**
* The header that specifies the archive status.
*/
public static final String ARCHIVE_STATUS_HEADER = Constants.PREFIX_FOR_STORAGE_HEADER + "archive-status";

/**
* XML element for authentication error details.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,32 @@ else if (Constants.COPY_DESTINATION_SNAPSHOT_ID_ELEMENT.equals(currentNode)) {
this.copyState.setCopyDestinationSnapshotID(value);
}
else if (Constants.ACCESS_TIER.equals(currentNode)) {
PremiumPageBlobTier premiumPageBlobTier = PremiumPageBlobTier.parse(value);
this.properties.setPremiumPageBlobTier(premiumPageBlobTier);
this.properties.setBlobTierInferredTier(false);
if (properties.getBlobType().equals(BlobType.PAGE_BLOB)) {
PremiumPageBlobTier premiumPageBlobTier = PremiumPageBlobTier.parse(value);
this.properties.setPremiumPageBlobTier(premiumPageBlobTier);
this.properties.setBlobTierInferredTier(false);
}
else if (properties.getBlobType().equals(BlobType.BLOCK_BLOB)) {
StandardBlobTier standardBlobTier = StandardBlobTier.parse(value);
this.properties.setStandardBlobTier(standardBlobTier);
}
else if (properties.getBlobType().equals(BlobType.UNSPECIFIED)) {
PremiumPageBlobTier premiumPageBlobTier = PremiumPageBlobTier.parse(value);
StandardBlobTier standardBlobTier = StandardBlobTier.parse(value);
if (!premiumPageBlobTier.equals(PremiumPageBlobTier.UNKNOWN)) {
properties.setPremiumPageBlobTier(premiumPageBlobTier);
}
else if (!standardBlobTier.equals(StandardBlobTier.UNKNOWN)) {
properties.setStandardBlobTier(standardBlobTier);
}
else {
properties.setPremiumPageBlobTier(PremiumPageBlobTier.UNKNOWN);
properties.setStandardBlobTier(StandardBlobTier.UNKNOWN);
}
}
}
else if (Constants.ARCHIVE_STATUS.equals(currentNode)) {
this.properties.setRehydrationStatus(RehydrationStatus.parse(value));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,21 @@ public final class BlobProperties {
*/
private PremiumPageBlobTier premiumPageBlobTier;

/**
* Represents the tier on a blob on a standard storage account.
*/
private StandardBlobTier standardBlobTier;

/**
* Represents whether or not the blob tier is inferred.
*/
private Boolean isBlobTierInferredTier;


/**
* Represents the rehydration status if the blob is being rehydrated.
*/
private RehydrationStatus rehydrationStatus;

/**
* Creates an instance of the <code>BlobProperties</code> class.
*/
Expand All @@ -152,16 +162,18 @@ public BlobProperties(final BlobProperties other) {
this.contentType = other.contentType;
this.copyState = other.copyState;
this.etag = other.etag;
this.isBlobTierInferredTier = other.isBlobTierInferredTier;
this.isIncrementalCopy = other.isIncrementalCopy;
this.leaseStatus = other.leaseStatus;
this.leaseState = other.leaseState;
this.leaseDuration = other.leaseDuration;
this.length = other.length;
this.lastModified = other.lastModified;
this.pageBlobSequenceNumber = other.pageBlobSequenceNumber;
this.serverEncrypted = other.serverEncrypted;
this.isIncrementalCopy = other.isIncrementalCopy;
this.premiumPageBlobTier = other.premiumPageBlobTier;
this.isBlobTierInferredTier = other.isBlobTierInferredTier;
this.serverEncrypted = other.serverEncrypted;
this.standardBlobTier = other.standardBlobTier;
this.rehydrationStatus = other.rehydrationStatus;
}

/**
Expand Down Expand Up @@ -344,6 +356,22 @@ public PremiumPageBlobTier getPremiumPageBlobTier() {
return this.premiumPageBlobTier;
}

/**
* If using a standard account and the blob is a block blob, gets the tier of the blob.
* @return A {@link StandardBlobTier} object which represents the tier of the blob
* or <code>null</code> if the tier has not been set.
*/
public StandardBlobTier getStandardBlobTier() {
return this.standardBlobTier;
}

/**
* The rehydration status if the blob is being rehydrated
* and the tier of the blob once the rehydration from archive has completed.
* @return
*/
public RehydrationStatus getRehydrationStatus() { return this.rehydrationStatus; }

/**
* Gets the blob's server-side encryption status;
*
Expand Down Expand Up @@ -550,6 +578,15 @@ protected void setPremiumPageBlobTier(PremiumPageBlobTier premiumPageBlobTier) {
this.premiumPageBlobTier = premiumPageBlobTier;
}

/**
* Sets the tier of the block blob. This is only supported for standard storage accounts.
* @param standardBlobTier
* A {@link StandardBlobTier} object which represents the tier of the blob.
*/
protected void setStandardBlobTier(StandardBlobTier standardBlobTier) {
this.standardBlobTier = standardBlobTier;
}

/**
* Sets whether the blob tier is inferred.
* @param isBlobTierInferredTier
Expand All @@ -558,4 +595,13 @@ protected void setPremiumPageBlobTier(PremiumPageBlobTier premiumPageBlobTier) {
protected void setBlobTierInferredTier(Boolean isBlobTierInferredTier) {
this.isBlobTierInferredTier = isBlobTierInferredTier;
}

/**
* Sets the rehydration status of the blob.
* @param rehydrationStatus
* A {@Link RehydrationStatus} which specifies the rehydration status of the blob.
*/
protected void setRehydrationStatus(RehydrationStatus rehydrationStatus) {
this.rehydrationStatus = rehydrationStatus;
}
}
Loading

0 comments on commit a4d7b9c

Please sign in to comment.