예제 #1
0
        public async Task <IDistributedLock> TryLockAsync(
            string account,
            string lockId,
            string lockOwnerId,
            string proposedLeaseId,
            TimeSpan lockPeriod,
            CancellationToken cancellationToken)
        {
            IStorageBlobDirectory lockDirectory = GetLockDirectory(account);
            IStorageBlockBlob     lockBlob      = lockDirectory.GetBlockBlobReference(lockId);
            string leaseId = await TryAcquireLeaseAsync(lockBlob, lockPeriod, proposedLeaseId, cancellationToken);

            if (string.IsNullOrEmpty(leaseId))
            {
                return(null);
            }

            if (!string.IsNullOrEmpty(lockOwnerId))
            {
                await WriteLeaseBlobMetadata(lockBlob, leaseId, lockOwnerId, cancellationToken);
            }

            SingletonLockHandle lockHandle = new SingletonLockHandle(leaseId, lockId, lockBlob, lockPeriod);

            return(lockHandle);
        }
        private static async Task<string> GetOrCreateHostIdAsync(string sharedHostName, IStorageBlobDirectory directory,
            CancellationToken cancellationToken)
        {
            Debug.Assert(directory != null);

            IStorageBlockBlob blob = directory.GetBlockBlobReference(sharedHostName);
            Guid? possibleHostId = await TryGetExistingIdAsync(blob, cancellationToken);

            if (possibleHostId.HasValue)
            {
                return possibleHostId.Value.ToString("N");
            }

            Guid newHostId = Guid.NewGuid();

            if (await TryInitializeIdAsync(blob, newHostId, cancellationToken))
            {
                return newHostId.ToString("N");
            }

            possibleHostId = await TryGetExistingIdAsync(blob, cancellationToken);

            if (possibleHostId.HasValue)
            {
                return possibleHostId.Value.ToString("N");
            }

            // Not expected - valid host ID didn't exist before, couldn't be created, and still didn't exist after.
            throw new InvalidOperationException("Unable to determine host ID.");
        }
예제 #3
0
        private static async Task <string> GetOrCreateHostIdAsync(string sharedHostName, IStorageBlobDirectory directory,
                                                                  CancellationToken cancellationToken)
        {
            Debug.Assert(directory != null);

            IStorageBlockBlob blob = directory.GetBlockBlobReference(sharedHostName);
            Guid?possibleHostId    = await TryGetExistingIdAsync(blob, cancellationToken);

            if (possibleHostId.HasValue)
            {
                return(possibleHostId.Value.ToString("N"));
            }

            Guid newHostId = Guid.NewGuid();

            if (await TryInitializeIdAsync(blob, newHostId, cancellationToken))
            {
                return(newHostId.ToString("N"));
            }

            possibleHostId = await TryGetExistingIdAsync(blob, cancellationToken);

            if (possibleHostId.HasValue)
            {
                return(possibleHostId.Value.ToString("N"));
            }

            // Not expected - valid host ID didn't exist before, couldn't be created, and still didn't exist after.
            throw new InvalidOperationException("Unable to determine host ID.");
        }
예제 #4
0
        public async virtual Task <object> TryLockAsync(string lockId, string functionInstanceId, SingletonAttribute attribute, CancellationToken cancellationToken, bool retry = true)
        {
            IStorageBlobDirectory lockDirectory = GetLockDirectory(attribute.Account);
            IStorageBlockBlob     lockBlob      = lockDirectory.GetBlockBlobReference(lockId);

            await TryCreateAsync(lockBlob, cancellationToken);

            _trace.Verbose(string.Format(CultureInfo.InvariantCulture, "Waiting for Singleton lock ({0})", lockId), source: TraceSource.Execution);

            TimeSpan lockPeriod = GetLockPeriod(attribute, _config);
            string   leaseId    = await TryAcquireLeaseAsync(lockBlob, lockPeriod, cancellationToken);

            if (string.IsNullOrEmpty(leaseId) && retry)
            {
                // Someone else has the lease. Continue trying to periodically get the lease for
                // a period of time
                TimeSpan acquisitionTimeout = attribute.LockAcquisitionTimeout != null
                    ? TimeSpan.FromSeconds(attribute.LockAcquisitionTimeout.Value) :
                                              _config.LockAcquisitionTimeout;

                double remainingWaitTime = acquisitionTimeout.TotalMilliseconds;
                while (string.IsNullOrEmpty(leaseId) && remainingWaitTime > 0)
                {
                    await Task.Delay(_config.LockAcquisitionPollingInterval);

                    leaseId = await TryAcquireLeaseAsync(lockBlob, lockPeriod, cancellationToken);

                    remainingWaitTime -= _config.LockAcquisitionPollingInterval.TotalMilliseconds;
                }
            }

            if (string.IsNullOrEmpty(leaseId))
            {
                _trace.Verbose(string.Format(CultureInfo.InvariantCulture, "Unable to acquire Singleton lock ({0}).", lockId), source: TraceSource.Execution);
                return(null);
            }

            _trace.Verbose(string.Format(CultureInfo.InvariantCulture, "Singleton lock acquired ({0})", lockId), source: TraceSource.Execution);

            if (!string.IsNullOrEmpty(functionInstanceId))
            {
                await WriteLeaseBlobMetadata(lockBlob, leaseId, functionInstanceId, cancellationToken);
            }

            SingletonLockHandle lockHandle = new SingletonLockHandle
            {
                LeaseId           = leaseId,
                LockId            = lockId,
                Blob              = lockBlob,
                LeaseRenewalTimer = CreateLeaseRenewalTimer(lockBlob, leaseId, lockId, lockPeriod, _backgroundExceptionDispatcher)
            };

            // start the renewal timer, which ensures that we maintain our lease until
            // the lock is released
            lockHandle.LeaseRenewalTimer.Start();

            return(lockHandle);
        }
예제 #5
0
        public IStorageBlockBlob CreateReference(string hostId, string functionId, string containerName,
                                                 string blobName, string eTag)
        {
            // Put the ETag before the blob name to prevent ambiguity since the blob name can contain embedded slashes.
            string receiptName = String.Format(CultureInfo.InvariantCulture, "{0}/{1}/{2}/{3}/{4}", hostId, functionId,
                                               eTag, containerName, blobName);

            return(_directory.GetBlockBlobReference(receiptName));
        }
        private static LocalBlobDescriptor CreateDescriptor(IStorageBlobDirectory directory, string name)
        {
            IStorageBlockBlob blob = directory.GetBlockBlobReference(name);

            return(new LocalBlobDescriptor
            {
                ContainerName = blob.Container.Name,
                BlobName = blob.Name
            });
        }
        private static LocalBlobDescriptor CreateDescriptor(IStorageBlobDirectory directory, string name)
        {
            IStorageBlockBlob blob = directory.GetBlockBlobReference(name);

            return new LocalBlobDescriptor
            {
                ContainerName = blob.Container.Name,
                BlobName = blob.Name
            };
        }
예제 #8
0
        public async virtual Task <string> GetLockOwnerAsync(SingletonAttribute attribute, string lockId, CancellationToken cancellationToken)
        {
            IStorageBlobDirectory lockDirectory = GetLockDirectory(attribute.Account);
            IStorageBlockBlob     lockBlob      = lockDirectory.GetBlockBlobReference(lockId);

            await ReadLeaseBlobMetadata(lockBlob, cancellationToken);

            // if the lease is Available, then there is no current owner
            // (any existing owner value is the last owner that held the lease)
            if (lockBlob.Properties.LeaseState == LeaseState.Available &&
                lockBlob.Properties.LeaseStatus == LeaseStatus.Unlocked)
            {
                return(null);
            }

            string owner = string.Empty;

            lockBlob.Metadata.TryGetValue(FunctionInstanceMetadataKey, out owner);

            return(owner);
        }