public async Task <string> TryAcquireLeaseAsync(BlockBlobClient blob, CancellationToken cancellationToken) { try { BlobLease lease = await blob.GetBlobLeaseClient().AcquireAsync(LeasePeriod, cancellationToken: cancellationToken).ConfigureAwait(false); return(lease.LeaseId); } catch (RequestFailedException exception) { if (exception.IsConflictLeaseAlreadyPresent()) { return(null); } else if (exception.IsNotFoundBlobOrContainerNotFound()) { // If someone deleted the receipt, there's no lease to acquire. return(null); } else { throw; } } }
public async Task <bool> TryLockOrRenew(CancellationToken cancellationToken = default) { await EnsureContainerExists(cancellationToken).ConfigureAwait(false); if (lease == null) { try { lease = await blobLeaseClient.AcquireAsync(span, null, cancellationToken).ConfigureAwait(false); return(true); } catch (RequestFailedException ex) when(ex.Status == (int)HttpStatusCode.Conflict) { // someone else raced for the lease and got it return(false); } } try { await blobLeaseClient.RenewAsync(null, cancellationToken).ConfigureAwait(false); return(true); } catch (RequestFailedException ex) when(ex.Status == (int)HttpStatusCode.Conflict) { // someone else raced for the lease and got it so we have to try to re-acquire it lease = null; return(false); } }
public async Task Lease_CanAcquireAndRelease() { string id = $"test/{nameof(Lease_CanAcquireAndRelease)}.lck"; using (BlobLease lease = await _native.AcquireBlobLeaseAsync(id, TimeSpan.FromSeconds(20))) { } }
public virtual void Initialize() { this.cancellationToken = new CancellationTokenSource().Token; this.blobLeaseHelper = new Mock <IBlobLeaseHelper>(MockBehavior.Strict); this.timestampCreator = new Mock <ITimestampCreator>(MockBehavior.Strict); this.target = new BlobLease(this.timestampCreator.Object, this.blobLeaseHelper.Object, this.cancellationToken, LeaseObjectName); }
public async Task Lease_WaitsToReleaseAcquiredLease() { string id = $"test/{nameof(Lease_WaitsToReleaseAcquiredLease)}.lck"; using (BlobLease lease1 = await _native.AcquireBlobLeaseAsync(id, TimeSpan.FromSeconds(20))) { await _native.AcquireBlobLeaseAsync(id, TimeSpan.FromSeconds(20), true); } }
public async Task Lease_FailsOnAcquiredLeasedBlob() { string id = $"test/{nameof(Lease_FailsOnAcquiredLeasedBlob)}.lck"; using (BlobLease lease1 = await _native.AcquireBlobLeaseAsync(id, TimeSpan.FromSeconds(20))) { await Assert.ThrowsAsync <StorageException>(() => _native.AcquireBlobLeaseAsync(id, TimeSpan.FromSeconds(20))); } }
//TODO consider removing this. public async Task<string> SetupContainerLeaseCondition(BlobContainerClient container, string leaseId, string garbageLeaseId) { BlobLease lease = null; if (leaseId == ReceivedLeaseId || leaseId == garbageLeaseId) { lease = await InstrumentClient(container.GetBlobLeaseClient(Recording.Random.NewGuid().ToString())).AcquireAsync(BlobLeaseClient.InfiniteLeaseDuration); } return leaseId == ReceivedLeaseId ? lease.LeaseId : leaseId; }
protected override async Task <string> SetupLeaseAsync(TBlobClient client, string leaseId, string garbageLeaseId) { BlobLease lease = null; if (leaseId == Conditions.ReceivedLeaseId || leaseId == garbageLeaseId) { lease = await InstrumentClient(client.GetBlobLeaseClient(Recording.Random.NewGuid().ToString())).AcquireAsync(BlobLeaseClient.InfiniteLeaseDuration); } return(leaseId == Conditions.ReceivedLeaseId ? lease.LeaseId : leaseId); }
//TODO consider removing this. public async Task <string> SetupBlobLeaseCondition(BlobBaseClient blob, string leaseId, string garbageLeaseId) { BlobLease lease = null; if (leaseId == ReceivedLeaseId || leaseId == garbageLeaseId) { lease = await InstrumentClient(blob.GetLeaseClient(Recording.Random.NewGuid().ToString())).AcquireAsync(LeaseClient.InfiniteLeaseDuration); } return(leaseId == ReceivedLeaseId ? lease.LeaseId : leaseId); }
public async Task TryRelease(CancellationToken cancellationToken = default) { await EnsureContainerExists(cancellationToken).ConfigureAwait(false); if (lease != null) { try { await blobLeaseClient.ReleaseAsync(null, cancellationToken).ConfigureAwait(false); } catch (RequestFailedException) { } finally { lease = null; } } }
/// <inheritdoc/> public async Task <string> TryAcquireBlobLease(string filepath) { BlobClient blobClient = CreateBlobClient(filepath); BlobLeaseClient blobLeaseClient = blobClient.GetBlobLeaseClient(); try { BlobLease blobLease = await blobLeaseClient.AcquireAsync(TimeSpan.FromSeconds(_storageConfig.BlobLeaseTimeout)); return(blobLease.LeaseId); } catch (RequestFailedException ex) { _logger.LogError(ex, "Failed to acquire blob lease for policy file at {filepath}. RequestFailedException", filepath); } catch (Exception ex) { _logger.LogError(ex, "Failed to acquire blob lease for policy file at {filepath}. Unexpected error", filepath); } return(null); }
public Initialized(BlobLease lease, IndexFat fat) { Lease = lease; Fat = fat; }
public AzureBlobsLogWriter(BlobContainerClient blobsContainerClient, string fileName, bool appendOpen = false) { fileName = AzureBlobsLogsInterface.PathFixer(fileName); _blobsContainerClient = blobsContainerClient; _logClient = _blobsContainerClient.GetAppendBlobClient(fileName); ETag currentETag; if (_previousOpenAttempts.ContainsKey(fileName) && appendOpen) { // We've opened this blob before and want to be non-destructive. We don't need to CreateIfNotExists, which could be VERY slow. currentETag = _logClient.GetProperties().Value.ETag; } else { try { // Create the file non-destructively if needed, guaranteeing write continuity on creation by grabbing the etag of the create, if needed if (appendOpen) { var response = _logClient.CreateIfNotExists(); if (response != null) { currentETag = response.Value.ETag; } else { currentETag = _logClient.GetProperties().Value.ETag; } } else { currentETag = _logClient.Create().Value.ETag; } } catch { currentETag = _logClient.GetProperties().Value.ETag; } } // Try to grab the blob lease _leaseClient = _logClient.GetBlobLeaseClient(); // The blob hasn't be touched since the last time. This is a candidate for breaking the lease. if (_previousOpenAttempts.ContainsKey(fileName) && (_previousOpenAttempts[fileName].ToString().Equals(currentETag.ToString()))) { _previousOpenAttempts[fileName] = currentETag; // The blob hasn't been updated. Try to break the lease and reacquire var requestConditions = new BlobRequestConditions(); requestConditions = new BlobRequestConditions(); requestConditions.IfMatch = currentETag; // If the condition fails in the break, it's because someone else managed to touch the file, so give up ETag newETag; try { newETag = _leaseClient.Break(null, requestConditions).Value.ETag; } catch (Exception e) { newETag = currentETag; } var etagCondition = new RequestConditions(); etagCondition.IfMatch = newETag; // If the condition fails, someone snuck in and grabbed the lock before we could. Give up. _curLease = _leaseClient.Acquire(TimeSpan.FromSeconds(-1), etagCondition).Value; } else { // Not a candidate for breaking the lease. Just try to acquire. _previousOpenAttempts[fileName] = currentETag; _curLease = _leaseClient.Acquire(TimeSpan.FromSeconds(-1)).Value; } _leaseCondition = new AppendBlobRequestConditions(); _leaseCondition.LeaseId = _curLease.LeaseId; // We got the lease! Set up thread to periodically touch the blob to prevent others from breaking the lease. _blobMetadata = _logClient.GetProperties().Value.Metadata; _stopRelockThread = false; _relockThreadStopped = false; _leaseRenewThread = new Thread(() => { while (!_stopRelockThread) { Thread.Sleep(100); var response = _logClient.SetMetadata(_blobMetadata, _leaseCondition); } _relockThreadStopped = true; }) { IsBackground = true }; _leaseRenewThread.Start(); _bytesToSend = new MemoryStream(); Debug.Assert(_logClient.Exists()); }
// </Snippet_DemonstrateOptimisticConcurrencyBlob> #endregion #region DemonstratePessimisticConcurrencyBlob //------------------------------------------------- // Demonstrate pessimistic concurrency for write operations to a blob //------------------------------------------------- // <Snippet_DemonstratePessimisticConcurrencyBlob> public static async Task DemonstratePessimisticConcurrencyBlob(BlobClient blobClient) { Console.WriteLine("Demonstrate pessimistic concurrency"); BlobContainerClient containerClient = blobClient.GetParentBlobContainerClient(); BlobLeaseClient blobLeaseClient = blobClient.GetBlobLeaseClient(); try { // Create the container if it does not exist. await containerClient.CreateIfNotExistsAsync(); // Upload text to a blob. string blobContents1 = "First update. Overwrite blob if it exists."; byte[] byteArray = Encoding.ASCII.GetBytes(blobContents1); using (MemoryStream stream = new MemoryStream(byteArray)) { BlobContentInfo blobContentInfo = await blobClient.UploadAsync(stream, overwrite : true); } // Acquire a lease on the blob. BlobLease blobLease = await blobLeaseClient.AcquireAsync(TimeSpan.FromSeconds(15)); Console.WriteLine("Blob lease acquired. LeaseId = {0}", blobLease.LeaseId); // Set the request condition to include the lease ID. BlobUploadOptions blobUploadOptions = new BlobUploadOptions() { Conditions = new BlobRequestConditions() { LeaseId = blobLease.LeaseId } }; // Write to the blob again, providing the lease ID on the request. // The lease ID was provided, so this call should succeed. string blobContents2 = "Second update. Lease ID provided on request."; byteArray = Encoding.ASCII.GetBytes(blobContents2); using (MemoryStream stream = new MemoryStream(byteArray)) { BlobContentInfo blobContentInfo = await blobClient.UploadAsync(stream, blobUploadOptions); } // This code simulates an update by another client. // The lease ID is not provided, so this call fails. string blobContents3 = "Third update. No lease ID provided."; byteArray = Encoding.ASCII.GetBytes(blobContents3); using (MemoryStream stream = new MemoryStream(byteArray)) { // This call should fail with error code 412 (Precondition Failed). BlobContentInfo blobContentInfo = await blobClient.UploadAsync(stream); } } catch (RequestFailedException e) { if (e.Status == (int)HttpStatusCode.PreconditionFailed) { Console.WriteLine( @"Precondition failure as expected. The lease ID was not provided."); } else { Console.WriteLine(e.Message); throw; } } finally { await blobLeaseClient.ReleaseAsync(); } }
/// <summary> /// Lease a blob stored in a container. /// </summary> /// <param name="containerName">Container name</param> /// <param name="blobName">Blob name, including paths</param> /// <returns>An azureResults showing the results of the request.</returns> public azureResults LeaseBlob(string containerName, string blobName, BlobLease leaseType, string leaseGuid) { //if (leaseGuid.Trim() == string.Empty) // leaseGuid = Guid.NewGuid().ToString(); azureResults retVal = new azureResults(); Hashtable ht = new Hashtable(); ht.Add("If-Match", "*"); string leaseTypeString = string.Empty; switch (leaseType) { case BlobLease.acquireLease: leaseTypeString = "acquire"; break; case BlobLease.breakLease: leaseTypeString = "break"; break; case BlobLease.releaseLease: leaseTypeString = "release"; break; case BlobLease.renewLease: leaseTypeString = "renew"; break; } ht.Add("x-ms-lease-action", leaseTypeString ); if (leaseGuid.Trim() != string.Empty) ht.Add("x-ms-lease-id", leaseGuid); retVal = Blobs(cmdType.put , containerName, blobName, ht, "comp=lease"); retVal.Succeeded = (retVal.StatusCode == HttpStatusCode.OK || retVal.StatusCode == HttpStatusCode.Accepted || retVal.StatusCode == HttpStatusCode.Created ); return retVal; }