Example #1
0
        public async Task<bool> TryLock()
        {
            try
            {
                _lease = _blobLeaseFactory.CreateLease(_blob);
                _leaseId = await _lease.TryAcquireLease();
                if (_leaseId == null)
                {
                    DisposeLease();
                    return false;
                }
                await _blob.FetchAttributesAsync();

                if (_blob.Metadata.ContainsKey(UpdateDomainInstancesKey))
                {
                    string[] instanceIds = _blob.Metadata[UpdateDomainInstancesKey].Split(',');
                    _instanceIds = new HashSet<string>(instanceIds);
                }
                _updateDomain = _blob.Metadata.ContainsKey(UpdateDomainKey) ? _blob.Metadata[UpdateDomainKey] : string.Empty;

                return true;
            }
            catch (Exception e)
            {
                if (e is StorageException || e is WebException)
                {
                    DisposeLease();
                    Trace.TraceInformation($"Failed to acquire the lease on blob {_blob.Name}", e);
                    return false;
                }
                throw;
            }
        }
Example #2
0
        public async Task <bool> TryLock()
        {
            try
            {
                _lease   = _blobLeaseFactory.CreateLease(_blob);
                _leaseId = await _lease.TryAcquireLease();

                if (_leaseId == null)
                {
                    DisposeLease();
                    return(false);
                }
                await _blob.FetchAttributesAsync();

                if (_blob.Metadata.ContainsKey(UpdateDomainInstancesKey))
                {
                    string[] instanceIds = _blob.Metadata[UpdateDomainInstancesKey].Split(',');
                    _instanceIds = new HashSet <string>(instanceIds);
                }
                _updateDomain = _blob.Metadata.ContainsKey(UpdateDomainKey) ? _blob.Metadata[UpdateDomainKey] : string.Empty;

                return(true);
            }
            catch (StorageException e)
            {
                DisposeLease();
                Trace.TraceInformation($"Failed to acquire the lease on blob {_blob.Name}", e);
                return(false);
            }
        }
Example #3
0
        private async Task TestThatLockFailsIfBlobLeaseCantBeAcquired(IBlobLease blobLeaseStub)
        {

            var leaseFactoryMock = new StubIBlobLeaseFactory
            {
                CreateLease_ICloudBlob = blob => blobLeaseStub
            };
            var testBlob = _container.GetBlockBlobReference("testBlob");
            await BlobUtils.CreateEmptyBlob(testBlob);
            UpdateBlob updateBlob = new UpdateBlob(testBlob, leaseFactoryMock);
            Assert.False(await updateBlob.TryLock());
        }
Example #4
0
 private void DisposeLease()
 {
     _leaseId = null;
     _lease.Dispose();
     _lease = null;
 }
        public async Task <bool> TryStartUpdateSession(string applicationId)
        {
            string updateBlobName = GetUpdateBlobName(applicationId);
            bool   started        = false;

            try
            {
                ICloudBlob updateBlob = GetBlob(updateBlobName);
                await CreateBlobIfNoneExists(updateBlob);

                IBlobLease blobLease = _blobLeaseFactory.CreateLease(updateBlob);

                ExceptionDispatchInfo capturedException = null;
                string leaseId = await blobLease.TryAcquireLease();

                // allow this instance to update only if it can acquire a lease on the blob.
                if (leaseId == null)
                {
                    Trace.TraceInformation("Cannot start update session because unable to acquire the lease on the blob");
                    return(false);
                }

                try
                {
                    var updateBlobWrapper = await UpdateBlobWrapper.Create(updateBlob);

                    var updateDomain = updateBlobWrapper.GetUpdateDomain();
                    HashSet <string> updateDomainInstancesHashset = updateBlobWrapper.GetInstanceIds();

                    // allow this instance to try updating only if either one of the following conditions are true:
                    // 1. no update domain is set,
                    // 2. the current instance is in the same update domain
                    // 3. no instances are set for the current update domain
                    if (string.IsNullOrEmpty(updateDomain) ||
                        _config.InstanceUpdateDomain == updateDomain ||
                        updateDomainInstancesHashset.Count == 0)
                    {
                        Trace.TraceInformation(
                            "Instance {0} acquired a lock on update blob {1} and will attempt to enlist itself",
                            _config.InstanceId, updateBlobName);

                        updateDomainInstancesHashset.Add(_config.InstanceId);
                        await
                        updateBlobWrapper.SetData(leaseId, _config.InstanceUpdateDomain,
                                                  updateDomainInstancesHashset);

                        Trace.TraceInformation("Instance {0} enlisted itself in the update blob", _config.InstanceId);
                        started = true;
                    }
                }
                catch (Exception e)
                {
                    capturedException = ExceptionDispatchInfo.Capture(e);
                }

                await blobLease.ReleaseLease();

                Trace.TraceInformation("Instance {0} released the lock on update blob {1}", _config.InstanceId, updateBlobName);

                if (capturedException != null)
                {
                    capturedException.Throw();
                }

                return(started);
            }
            catch (Exception ex)
            {
                throw new Exception("Failed to start update session ", ex);
            }
        }
        public async Task EndUpdateSession(string applicationId)
        {
            string updateBlobName         = GetUpdateBlobName(applicationId);
            var    retryAttemptsRemaining = 10;
            var    retryAttempts          = retryAttemptsRemaining;
            bool   failed = false;

            do
            {
                if (retryAttemptsRemaining-- == 0)
                {
                    throw new Exception(
                              string.Format("Instance {0} failed to update the update blob {1} after trying {2} times",
                                            _config.InstanceId,
                                            updateBlobName,
                                            retryAttempts));
                }

                try
                {
                    ICloudBlob updateBlob = GetBlob(updateBlobName);
                    IBlobLease blobLease  = _blobLeaseFactory.CreateLease(updateBlob);

                    ExceptionDispatchInfo capturedException = null;
                    string leaseId = await blobLease.TryAcquireLease();

                    if (leaseId != null)
                    {
                        Trace.TraceInformation(
                            "Instance {0} acquired a lock on update blob {1} and will attempt to delist itself",
                            _config.InstanceId, updateBlobName);
                        try
                        {
                            UpdateBlobWrapper updateBlobWrapper = await UpdateBlobWrapper.Create(updateBlob);

                            var updateDomain = updateBlobWrapper.GetUpdateDomain();
                            var updateDomainInstancesHashset = updateBlobWrapper.GetInstanceIds();

                            updateDomainInstancesHashset.Remove(_config.InstanceId);
                            await updateBlobWrapper.SetData(leaseId, updateDomain, updateDomainInstancesHashset);

                            Trace.TraceInformation("Instance {0} delisted itself from the update blob", _config.InstanceId);
                        }
                        catch (Exception e)
                        {
                            capturedException = ExceptionDispatchInfo.Capture(e);
                        }
                        finally
                        {
                            Trace.TraceInformation("Instance {0} released the lock on update blob {1}",
                                                   _config.InstanceId, updateBlobName);
                        }

                        await blobLease.ReleaseLease();

                        if (capturedException != null)
                        {
                            capturedException.Throw();
                        }
                    }
                    else
                    {
                        throw new Exception(
                                  "Update session manager failed to end update session because it cannot Acquire the lease");
                    }
                }
                catch (Exception ex)
                {
                    Trace.TraceError("Instance {0} failed to update the update blob {1}. Exception was: {2}",
                                     _config.InstanceId, updateBlobName, ex);
                    failed = true;
                }
                if (failed)
                {
                    await Task.Delay(1000); // allowing 1s between retries
                }
            } while (failed);
        }
Example #7
0
 private void DisposeLease()
 {
     _leaseId = null;
     _lease.Dispose();
     _lease = null;
 }