public void PageBlobReadLockToETagTest() { byte[] outBuffer = new byte[1 * 1024 * 1024]; byte[] buffer = GetRandomBuffer(2 * outBuffer.Length); CloudBlobContainer container = GetRandomContainerReference(); try { container.Create(); CloudPageBlob blob = container.GetPageBlobReference("blob1"); blob.StreamMinimumReadSizeInBytes = outBuffer.Length; using (MemoryStream wholeBlob = new MemoryStream(buffer)) { blob.UploadFromStream(wholeBlob); } using (Stream blobStream = blob.OpenRead()) { blob.SetMetadata(); blobStream.Read(outBuffer, 0, outBuffer.Length); blob.SetMetadata(); TestHelper.ExpectedException( () => blobStream.Read(outBuffer, 0, outBuffer.Length), "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } using (Stream blobStream = blob.OpenRead()) { blob.SetMetadata(); long length = blobStream.Length; blob.SetMetadata(); TestHelper.ExpectedException( () => blobStream.Read(outBuffer, 0, outBuffer.Length), "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } AccessCondition accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(DateTimeOffset.Now); using (Stream blobStream = blob.OpenRead(accessCondition)) { blob.SetMetadata(); blobStream.Read(outBuffer, 0, outBuffer.Length); blob.SetMetadata(); TestHelper.ExpectedException( () => blobStream.Read(outBuffer, 0, outBuffer.Length), "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } } finally { container.DeleteIfExists(); } }
private static async Task DeleteOldBlobs() { var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["BlobStorage"]); var blobClient = storageAccount.CreateCloudBlobClient(); var container = blobClient.GetContainerReference("vk2tg"); var blobs = container.ListBlobs("", true).OfType <CloudBlockBlob>().Where(b => b.Properties.LastModified.Value.DateTime < DateTime.UtcNow.AddDays(-DaysToKeepBlobs)).ToList(); foreach (var blob in blobs) { await blob.DeleteIfExistsAsync(DeleteSnapshotsOption.None, AccessCondition.GenerateIfNotModifiedSinceCondition(DateTime.Now.AddDays(-DaysToKeepBlobs)), null, null); } }
public void BlockBlobReadLockToETagTestTask() { byte[] outBuffer = new byte[1 * 1024 * 1024]; byte[] buffer = GetRandomBuffer(2 * outBuffer.Length); CloudBlobContainer container = GetRandomContainerReference(); try { container.CreateAsync().Wait(); CloudBlockBlob blob = container.GetBlockBlobReference("blob1"); blob.StreamMinimumReadSizeInBytes = outBuffer.Length; using (MemoryStream wholeBlob = new MemoryStream(buffer)) { blob.UploadFromStreamAsync(wholeBlob).Wait(); } using (Stream blobStream = blob.OpenReadAsync().Result) { blobStream.Read(outBuffer, 0, outBuffer.Length); blob.SetMetadataAsync().Wait(); TestHelper.ExpectedException( () => blobStream.Read(outBuffer, 0, outBuffer.Length), "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } using (Stream blobStream = blob.OpenReadAsync().Result) { long length = blobStream.Length; blob.SetMetadataAsync().Wait(); TestHelper.ExpectedException( () => blobStream.Read(outBuffer, 0, outBuffer.Length), "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } AccessCondition accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(DateTimeOffset.Now.Subtract(TimeSpan.FromHours(1))); blob.SetMetadataAsync().Wait(); TestHelper.ExpectedExceptionTask( blob.OpenReadAsync(accessCondition, null, null), "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } finally { container.DeleteIfExistsAsync().Wait(); } }
/// <summary> /// Replace the contents of the file with the given Stream if the /// stored file has not been modified since a given time. /// </summary> /// <param name="Stream">Supplies the Stream to write into the file. /// The original contents of the file are replaced.</param> /// <param name="Time">Supplies the modified time cutoff.</param> public void WriteIfNotModifiedSince(Stream Stream, DateTimeOffset Time) { try { Blob.UploadFromStream(Stream, AccessCondition.GenerateIfNotModifiedSinceCondition(Time)); } catch (StorageException Ex) { if (Ex.RequestInformation.HttpStatusMessage == AzureFileStoreStatusCodes.ConditionNotMet) { throw new FileStoreConditionNotMetException(Ex); } throw; } }
private async Task CleanupContainer(CloudBlobContainer container, DateTimeOffset tresholdtime) { IEnumerable <IListBlobItem> blobs = container.ListBlobs(null, true, BlobListingDetails.None); foreach (IListBlobItem blob in blobs) { CloudBlockBlob block = (CloudBlockBlob)blob; try { await block.DeleteIfExistsAsync(DeleteSnapshotsOption.None, AccessCondition.GenerateIfNotModifiedSinceCondition(tresholdtime), new BlobRequestOptions(), new OperationContext()); } catch (StorageException ex) { if (!ex.Message.Contains("(412)")) { throw; } } } }
public async Task PageBlobReadLockToETagTestAsync() { byte[] outBuffer = new byte[1 * 1024 * 1024]; byte[] buffer = GetRandomBuffer(2 * outBuffer.Length); CloudBlobContainer container = GetRandomContainerReference(); try { await container.CreateAsync(); CloudPageBlob blob = container.GetPageBlobReference("blob1"); blob.StreamMinimumReadSizeInBytes = outBuffer.Length; using (MemoryStream wholeBlob = new MemoryStream(buffer)) { await blob.UploadFromStreamAsync(wholeBlob.AsInputStream()); } OperationContext opContext = new OperationContext(); using (IRandomAccessStreamWithContentType blobStream = await blob.OpenReadAsync(null, null, opContext)) { Stream blobStreamForRead = blobStream.AsStreamForRead(); await blob.SetMetadataAsync(); await blobStreamForRead.ReadAsync(outBuffer, 0, outBuffer.Length); await blob.SetMetadataAsync(); await TestHelper.ExpectedExceptionAsync( async() => await blobStreamForRead.ReadAsync(outBuffer, 0, outBuffer.Length), opContext, "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } opContext = new OperationContext(); using (IRandomAccessStreamWithContentType blobStream = await blob.OpenReadAsync(null, null, opContext)) { Stream blobStreamForRead = blobStream.AsStreamForRead(); await blob.SetMetadataAsync(); long length = blobStreamForRead.Length; await blob.SetMetadataAsync(); await TestHelper.ExpectedExceptionAsync( async() => await blobStreamForRead.ReadAsync(outBuffer, 0, outBuffer.Length), opContext, "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } opContext = new OperationContext(); AccessCondition accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(DateTimeOffset.Now); using (IRandomAccessStreamWithContentType blobStream = await blob.OpenReadAsync(accessCondition, null, opContext)) { Stream blobStreamForRead = blobStream.AsStreamForRead(); await blob.SetMetadataAsync(); await blobStreamForRead.ReadAsync(outBuffer, 0, outBuffer.Length); await blob.SetMetadataAsync(); await TestHelper.ExpectedExceptionAsync( async() => await blobStreamForRead.ReadAsync(outBuffer, 0, outBuffer.Length), opContext, "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } } finally { container.DeleteIfExistsAsync().AsTask().Wait(); } }
public void PageBlobReadLockToETagTestAPM() { byte[] outBuffer = new byte[1 * 1024 * 1024]; byte[] buffer = GetRandomBuffer(2 * outBuffer.Length); CloudBlobContainer container = GetRandomContainerReference(); try { container.Create(); CloudPageBlob blob = container.GetPageBlobReference("blob1"); blob.StreamMinimumReadSizeInBytes = outBuffer.Length; using (MemoryStream wholeBlob = new MemoryStream(buffer)) { blob.UploadFromStream(wholeBlob); } using (AutoResetEvent waitHandle = new AutoResetEvent(false)) { IAsyncResult result = blob.BeginOpenRead( ar => waitHandle.Set(), null); waitHandle.WaitOne(); using (Stream blobStream = blob.EndOpenRead(result)) { blobStream.Read(outBuffer, 0, outBuffer.Length); blob.SetMetadata(); TestHelper.ExpectedException( () => blobStream.Read(outBuffer, 0, outBuffer.Length), "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } result = blob.BeginOpenRead( ar => waitHandle.Set(), null); waitHandle.WaitOne(); using (Stream blobStream = blob.EndOpenRead(result)) { long length = blobStream.Length; blob.SetMetadata(); TestHelper.ExpectedException( () => blobStream.Read(outBuffer, 0, outBuffer.Length), "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } AccessCondition accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(DateTimeOffset.Now.Subtract(TimeSpan.FromHours(1))); blob.SetMetadata(); result = blob.BeginOpenRead( accessCondition, null, null, ar => waitHandle.Set(), null); waitHandle.WaitOne(); TestHelper.ExpectedException( () => blob.EndOpenRead(result), "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } } finally { container.DeleteIfExists(); } }
public async Task PageBlobWriteStreamOpenWithAccessConditionAsync() { CloudBlobContainer container = GetRandomContainerReference(); await container.CreateAsync(); try { OperationContext context = new OperationContext(); CloudPageBlob existingBlob = container.GetPageBlobReference("blob"); await existingBlob.CreateAsync(1024); CloudPageBlob blob = container.GetPageBlobReference("blob2"); AccessCondition accessCondition = AccessCondition.GenerateIfMatchCondition(existingBlob.Properties.ETag); await TestHelper.ExpectedExceptionAsync( async() => await blob.OpenWriteAsync(1024, accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.PreconditionFailed); blob = container.GetPageBlobReference("blob3"); accessCondition = AccessCondition.GenerateIfNoneMatchCondition(existingBlob.Properties.ETag); IOutputStream blobStream = await blob.OpenWriteAsync(1024, accessCondition, null, context); blobStream.Dispose(); blob = container.GetPageBlobReference("blob4"); accessCondition = AccessCondition.GenerateIfNoneMatchCondition("*"); blobStream = await blob.OpenWriteAsync(1024, accessCondition, null, context); blobStream.Dispose(); blob = container.GetPageBlobReference("blob5"); accessCondition = AccessCondition.GenerateIfModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(1)); blobStream = await blob.OpenWriteAsync(1024, accessCondition, null, context); blobStream.Dispose(); blob = container.GetPageBlobReference("blob6"); accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(-1)); blobStream = await blob.OpenWriteAsync(1024, accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfMatchCondition(existingBlob.Properties.ETag); blobStream = await existingBlob.OpenWriteAsync(1024, accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfMatchCondition(blob.Properties.ETag); await TestHelper.ExpectedExceptionAsync( async() => await existingBlob.OpenWriteAsync(1024, accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.PreconditionFailed); accessCondition = AccessCondition.GenerateIfNoneMatchCondition(blob.Properties.ETag); blobStream = await existingBlob.OpenWriteAsync(1024, accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfNoneMatchCondition(existingBlob.Properties.ETag); await TestHelper.ExpectedExceptionAsync( async() => await existingBlob.OpenWriteAsync(1024, accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.PreconditionFailed); accessCondition = AccessCondition.GenerateIfNoneMatchCondition("*"); await TestHelper.ExpectedExceptionAsync( async() => await existingBlob.OpenWriteAsync(1024, accessCondition, null, context), context, "BlobWriteStream.Dispose with a non-met condition should fail", HttpStatusCode.Conflict); accessCondition = AccessCondition.GenerateIfModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(-1)); blobStream = await existingBlob.OpenWriteAsync(1024, accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(1)); await TestHelper.ExpectedExceptionAsync( async() => await existingBlob.OpenWriteAsync(1024, accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.PreconditionFailed); accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(1)); blobStream = await existingBlob.OpenWriteAsync(1024, accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(-1)); await TestHelper.ExpectedExceptionAsync( async() => await existingBlob.OpenWriteAsync(1024, accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.PreconditionFailed); } finally { container.DeleteAsync().AsTask().Wait(); } }
public async Task CloudBlockBlobConditionalAccessAsync() { OperationContext operationContext = new OperationContext(); CloudBlobContainer container = GetRandomContainerReference(); try { await container.CreateAsync(); CloudBlockBlob blob = container.GetBlockBlobReference("blob1"); await CreateForTestAsync(blob, 2, 1024); await blob.FetchAttributesAsync(); string currentETag = blob.Properties.ETag; DateTimeOffset currentModifiedTime = blob.Properties.LastModified.Value; // ETag conditional tests blob.Metadata["ETagConditionalName"] = "ETagConditionalValue"; await blob.SetMetadataAsync(AccessCondition.GenerateIfMatchCondition(currentETag), null, null); await blob.FetchAttributesAsync(); string newETag = blob.Properties.ETag; Assert.AreNotEqual(newETag, currentETag, "ETage should be modified on write metadata"); blob.Metadata["ETagConditionalName"] = "ETagConditionalValue2"; await TestHelper.ExpectedExceptionAsync( async() => await blob.SetMetadataAsync(AccessCondition.GenerateIfNoneMatchCondition(newETag), null, operationContext), operationContext, "If none match on conditional test should throw", HttpStatusCode.PreconditionFailed, "ConditionNotMet"); string invalidETag = "\"0x10101010\""; await TestHelper.ExpectedExceptionAsync( async() => await blob.SetMetadataAsync(AccessCondition.GenerateIfMatchCondition(invalidETag), null, operationContext), operationContext, "Invalid ETag on conditional test should throw", HttpStatusCode.PreconditionFailed, "ConditionNotMet"); currentETag = blob.Properties.ETag; await blob.SetMetadataAsync(AccessCondition.GenerateIfNoneMatchCondition(invalidETag), null, null); await blob.FetchAttributesAsync(); newETag = blob.Properties.ETag; // LastModifiedTime tests currentModifiedTime = blob.Properties.LastModified.Value; blob.Metadata["DateConditionalName"] = "DateConditionalValue"; await TestHelper.ExpectedExceptionAsync( async() => await blob.SetMetadataAsync(AccessCondition.GenerateIfModifiedSinceCondition(currentModifiedTime), null, operationContext), operationContext, "IfModifiedSince conditional on current modified time should throw", HttpStatusCode.PreconditionFailed, "ConditionNotMet"); DateTimeOffset pastTime = currentModifiedTime.Subtract(TimeSpan.FromMinutes(5)); await blob.SetMetadataAsync(AccessCondition.GenerateIfModifiedSinceCondition(pastTime), null, null); pastTime = currentModifiedTime.Subtract(TimeSpan.FromHours(5)); await blob.SetMetadataAsync(AccessCondition.GenerateIfModifiedSinceCondition(pastTime), null, null); pastTime = currentModifiedTime.Subtract(TimeSpan.FromDays(5)); await blob.SetMetadataAsync(AccessCondition.GenerateIfModifiedSinceCondition(pastTime), null, null); currentModifiedTime = blob.Properties.LastModified.Value; pastTime = currentModifiedTime.Subtract(TimeSpan.FromMinutes(5)); await TestHelper.ExpectedExceptionAsync( async() => await blob.SetMetadataAsync(AccessCondition.GenerateIfNotModifiedSinceCondition(pastTime), null, operationContext), operationContext, "IfNotModifiedSince conditional on past time should throw", HttpStatusCode.PreconditionFailed, "ConditionNotMet"); pastTime = currentModifiedTime.Subtract(TimeSpan.FromHours(5)); await TestHelper.ExpectedExceptionAsync( async() => await blob.SetMetadataAsync(AccessCondition.GenerateIfNotModifiedSinceCondition(pastTime), null, operationContext), operationContext, "IfNotModifiedSince conditional on past time should throw", HttpStatusCode.PreconditionFailed, "ConditionNotMet"); pastTime = currentModifiedTime.Subtract(TimeSpan.FromDays(5)); await TestHelper.ExpectedExceptionAsync( async() => await blob.SetMetadataAsync(AccessCondition.GenerateIfNotModifiedSinceCondition(pastTime), null, operationContext), operationContext, "IfNotModifiedSince conditional on past time should throw", HttpStatusCode.PreconditionFailed, "ConditionNotMet"); blob.Metadata["DateConditionalName"] = "DateConditionalValue2"; currentETag = blob.Properties.ETag; await blob.SetMetadataAsync(AccessCondition.GenerateIfNotModifiedSinceCondition(currentModifiedTime), null, null); await blob.FetchAttributesAsync(); newETag = blob.Properties.ETag; Assert.AreNotEqual(newETag, currentETag, "ETage should be modified on write metadata"); } finally { container.DeleteIfExistsAsync().AsTask().Wait(); } }
public async Task BlockBlobWriteStreamOpenWithAccessConditionAsync() { CloudBlobContainer container = GetRandomContainerReference(); await container.CreateAsync(); try { OperationContext context = new OperationContext(); CloudBlockBlob existingBlob = container.GetBlockBlobReference("blob"); await existingBlob.PutBlockListAsync(new List <string>()); CloudBlockBlob blob = container.GetBlockBlobReference("blob2"); AccessCondition accessCondition = AccessCondition.GenerateIfMatchCondition(existingBlob.Properties.ETag); await TestHelper.ExpectedExceptionAsync( async() => await blob.OpenWriteAsync(accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.NotFound); blob = container.GetBlockBlobReference("blob3"); accessCondition = AccessCondition.GenerateIfNoneMatchCondition(existingBlob.Properties.ETag); var blobStream = await blob.OpenWriteAsync(accessCondition, null, context); blobStream.Dispose(); blob = container.GetBlockBlobReference("blob4"); accessCondition = AccessCondition.GenerateIfNoneMatchCondition("*"); blobStream = await blob.OpenWriteAsync(accessCondition, null, context); blobStream.Dispose(); blob = container.GetBlockBlobReference("blob5"); accessCondition = AccessCondition.GenerateIfModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(1)); blobStream = await blob.OpenWriteAsync(accessCondition, null, context); blobStream.Dispose(); blob = container.GetBlockBlobReference("blob6"); accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(-1)); blobStream = await blob.OpenWriteAsync(accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfMatchCondition(existingBlob.Properties.ETag); blobStream = await existingBlob.OpenWriteAsync(accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfMatchCondition(blob.Properties.ETag); await TestHelper.ExpectedExceptionAsync( async() => await existingBlob.OpenWriteAsync(accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.PreconditionFailed); accessCondition = AccessCondition.GenerateIfNoneMatchCondition(blob.Properties.ETag); blobStream = await existingBlob.OpenWriteAsync(accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfNoneMatchCondition(existingBlob.Properties.ETag); await TestHelper.ExpectedExceptionAsync( async() => await existingBlob.OpenWriteAsync(accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.NotModified); accessCondition = AccessCondition.GenerateIfNoneMatchCondition("*"); blobStream = await existingBlob.OpenWriteAsync(accessCondition, null, context); await TestHelper.ExpectedExceptionAsync( () => { blobStream.Dispose(); return(Task.FromResult(true)); }, context, "BlobWriteStream.Dispose with a non-met condition should fail", HttpStatusCode.Conflict); accessCondition = AccessCondition.GenerateIfModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(-1)); blobStream = await existingBlob.OpenWriteAsync(accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(1)); await TestHelper.ExpectedExceptionAsync( async() => await existingBlob.OpenWriteAsync(accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.NotModified); accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(1)); blobStream = await existingBlob.OpenWriteAsync(accessCondition, null, context); blobStream.Dispose(); accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(existingBlob.Properties.LastModified.Value.AddMinutes(-1)); await TestHelper.ExpectedExceptionAsync( async() => await existingBlob.OpenWriteAsync(accessCondition, null, context), context, "OpenWriteAsync with a non-met condition should fail", HttpStatusCode.PreconditionFailed); accessCondition = AccessCondition.GenerateIfMatchCondition(existingBlob.Properties.ETag); blobStream = await existingBlob.OpenWriteAsync(accessCondition, null, context); await existingBlob.SetPropertiesAsync(); await TestHelper.ExpectedExceptionAsync( () => { blobStream.Dispose(); return(Task.FromResult(true)); }, context, "BlobWriteStream.Dispose with a non-met condition should fail", HttpStatusCode.PreconditionFailed); blob = container.GetBlockBlobReference("blob7"); accessCondition = AccessCondition.GenerateIfNoneMatchCondition("*"); blobStream = await blob.OpenWriteAsync(accessCondition, null, context); await blob.PutBlockListAsync(new List <string>()); await TestHelper.ExpectedExceptionAsync( () => { blobStream.Dispose(); return(Task.FromResult(true)); }, context, "BlobWriteStream.Dispose with a non-met condition should fail", HttpStatusCode.Conflict); blob = container.GetBlockBlobReference("blob8"); accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(existingBlob.Properties.LastModified.Value); blobStream = await existingBlob.OpenWriteAsync(accessCondition, null, context); #if ASPNET_K Thread.Sleep(1000); //Make the condition invalid for sure #endif await existingBlob.SetPropertiesAsync(); await TestHelper.ExpectedExceptionAsync( () => { blobStream.Dispose(); return(Task.FromResult(true)); }, context, "BlobWriteStream.Dispose with a non-met condition should fail", HttpStatusCode.PreconditionFailed); } finally { container.DeleteAsync().AsTask().Wait(); } }
/// <summary>Ensures that 1 machine will execute an operation periodically.</summary> /// <param name="startTime">The base time; all machines should use the same exact base time.</param> /// <param name="period">Indicates how frequently you want the operation performed.</param> /// <param name="timeBetweenLeaseRetries">Indicates how frequently a machine that is not elected to perform the work should retry the work in case the elected machine crashes while performing the work.</param> /// <param name="blob">The blob that all the machines should be using to acquire a lease.</param> /// <param name="cancellationToken">Indicates when the operation should no longer be performed in the future.</param> /// <param name="winnerWorker">A method that is called periodically by whatever machine wins the election.</param> /// <returns>A Task which you can use to catch an exception or known then this method has been canceled.</returns> public static async Task RunAsync(DateTimeOffset startTime, TimeSpan period, TimeSpan timeBetweenLeaseRetries, ICloudBlob blob, CancellationToken cancellationToken, Func <Task> winnerWorker) { var bro = new BlobRequestOptions { RetryPolicy = new ExponentialRetry() }; const Int32 leaseDurationSeconds = 60; // 15-60 seconds DateTimeOffset nextElectionTime = NextElectionTime(startTime, period); while (true) { TimeSpan timeToWait = nextElectionTime - DateTimeOffset.UtcNow; timeToWait = (timeToWait < TimeSpan.Zero) ? TimeSpan.Zero : timeToWait; await Task.Delay(timeToWait, cancellationToken).ConfigureAwait(false); // Wait until time to check ElectionError electionError = ElectionError.Unknown; try { // Try to acquire lease & check metadata to see if this period has been processed String leaseId = await blob.AcquireLeaseAsync(TimeSpan.FromSeconds(leaseDurationSeconds), null, AccessCondition.GenerateIfNotModifiedSinceCondition(nextElectionTime), bro, null, CancellationToken.None).ConfigureAwait(false); try { // Got lease: do elected work (periodically renew lease) Task winnerWork = Task.Run(winnerWorker); while (true) { // Verify if winnerWork throws, we exit this loop & release the lease to try again Task wakeUp = await Task.WhenAny(Task.Delay(TimeSpan.FromSeconds(leaseDurationSeconds - 15)), winnerWork).ConfigureAwait(false); if (wakeUp == winnerWork) // Winner work is done { if (winnerWork.IsFaulted) { throw winnerWork.Exception; } else { break; } } await blob.RenewLeaseAsync(AccessCondition.GenerateLeaseCondition(leaseId)).ConfigureAwait(false); } // After work done, write to blob to indicate elected winner sucessfully did work blob.UploadFromByteArray(new Byte[1], 0, 1, AccessCondition.GenerateLeaseCondition(leaseId), bro, null); nextElectionTime = NextElectionTime(nextElectionTime + period, period); } finally { blob.ReleaseLease(AccessCondition.GenerateLeaseCondition(leaseId)); } } catch (StorageException ex) { if (ex.Matches(HttpStatusCode.Conflict, BlobErrorCodeStrings.LeaseAlreadyPresent)) { electionError = ElectionError.LeaseAlreadyPresent; } else if (ex.Matches(HttpStatusCode.PreconditionFailed)) { electionError = ElectionError.ElectionOver; } else { throw; } } switch (electionError) { case ElectionError.ElectionOver: // If access condition failed, the election is over, wait until next election time nextElectionTime = NextElectionTime(nextElectionTime + period, period); break; case ElectionError.LeaseAlreadyPresent: // if failed to get lease, wait a bit and retry again await Task.Delay(timeBetweenLeaseRetries).ConfigureAwait(false); break; } } // We never get here }
public async Task AppendBlobReadLockToETagTestAsync() { byte[] outBuffer = new byte[1 * 1024 * 1024]; byte[] buffer = GetRandomBuffer(2 * outBuffer.Length); CloudBlobContainer container = GetRandomContainerReference(); try { await container.CreateAsync(); CloudAppendBlob blob = container.GetAppendBlobReference("blob1"); await blob.CreateOrReplaceAsync(); blob.StreamMinimumReadSizeInBytes = outBuffer.Length; using (MemoryStream wholeBlob = new MemoryStream(buffer)) { #if !FACADE_NETCORE await blob.AppendBlockAsync(wholeBlob); #else await blob.AppendBlockAsync(wholeBlob, string.Empty, null, null, null, CancellationToken.None); #endif } OperationContext opContext = new OperationContext(); using (Stream blobStream = await blob.OpenReadAsync(null, null, opContext)) { Stream blobStreamForRead = blobStream; await blobStreamForRead.ReadAsync(outBuffer, 0, outBuffer.Length); await blob.SetMetadataAsync(); await TestHelper.ExpectedExceptionAsync( async() => await blobStreamForRead.ReadAsync(outBuffer, 0, outBuffer.Length), opContext, "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } opContext = new OperationContext(); using (Stream blobStream = await blob.OpenReadAsync(null, null, opContext)) { Stream blobStreamForRead = blobStream; long length = blobStreamForRead.Length; await blob.SetMetadataAsync(); await TestHelper.ExpectedExceptionAsync( async() => await blobStreamForRead.ReadAsync(outBuffer, 0, outBuffer.Length), opContext, "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } opContext = new OperationContext(); AccessCondition accessCondition = AccessCondition.GenerateIfNotModifiedSinceCondition(DateTimeOffset.Now.Subtract(TimeSpan.FromHours(1))); await blob.SetMetadataAsync(); await TestHelper.ExpectedExceptionAsync( async() => await blob.OpenReadAsync(accessCondition, null, opContext), opContext, "Blob read stream should fail if blob is modified during read", HttpStatusCode.PreconditionFailed); } finally { container.DeleteIfExistsAsync().Wait(); } }