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;
 }
Beispiel #8
0
        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;
                }
            }
        }
Beispiel #11
0
        /// <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);
        }
Beispiel #12
0
 public Initialized(BlobLease lease, IndexFat fat)
 {
     Lease = lease;
     Fat   = fat;
 }
Beispiel #13
0
        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;
        }