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.");
        }
Example #2
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);
        }
Example #3
0
        public async Task <string> GetHostIdAsync(CancellationToken cancellationToken)
        {
            IStorageAccount account;

            try
            {
                account = await _storageAccountProvider.GetStorageAccountAsync(cancellationToken);
            }
            catch (InvalidOperationException exception)
            {
                throw new InvalidOperationException(
                          "A host ID is required. Either set JobHostConfiguration.HostId or provide a valid storage " +
                          "connection string.", exception);
            }

            IFunctionIndex index = await _getFunctionIndexProvider.Invoke().GetAsync(cancellationToken);

            IEnumerable <MethodInfo> indexedMethods = index.ReadAllMethods();

            string sharedHostName           = GetSharedHostName(indexedMethods, account);
            IStorageBlobDirectory directory = account.CreateBlobClient().GetContainerReference(
                HostContainerNames.Hosts).GetDirectoryReference(HostDirectoryNames.Ids);

            return(await GetOrCreateHostIdAsync(sharedHostName, directory, cancellationToken));
        }
 public SingletonManager(IStorageBlobClient blobClient, IBackgroundExceptionDispatcher backgroundExceptionDispatcher, SingletonConfiguration config, TraceWriter trace)
 {
     _backgroundExceptionDispatcher = backgroundExceptionDispatcher;
     _directory = blobClient.GetContainerReference(HostContainerNames.Hosts)
                            .GetDirectoryReference(HostDirectoryNames.SingletonLocks);
     _config = config;
     _trace = trace;
 }
Example #5
0
 public SingletonManager(IStorageBlobClient blobClient, IBackgroundExceptionDispatcher backgroundExceptionDispatcher, SingletonConfiguration config, TraceWriter trace)
 {
     _backgroundExceptionDispatcher = backgroundExceptionDispatcher;
     _directory = blobClient.GetContainerReference(HostContainerNames.Hosts)
                  .GetDirectoryReference(HostDirectoryNames.SingletonLocks);
     _config = config;
     _trace  = trace;
 }
Example #6
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);
        }
        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
            };
        }
Example #9
0
        public void GetLockDirectory_HandlesMultipleAccounts()
        {
            IStorageBlobDirectory directory = _core.GetLockDirectory(ConnectionStringNames.Storage);
            Assert.Same(_mockBlobDirectory.Object, directory);

            directory = _core.GetLockDirectory(null);
            Assert.Same(_mockBlobDirectory.Object, directory);

            directory = _core.GetLockDirectory(Secondary);
            Assert.Same(_mockSecondaryBlobDirectory.Object, directory);
        }
Example #10
0
        internal IStorageBlobDirectory GetLockDirectory(string accountName)
        {
            if (string.IsNullOrEmpty(accountName))
            {
                accountName = ConnectionStringNames.Storage;
            }

            IStorageBlobDirectory storageDirectory = null;

            if (!_lockDirectoryMap.TryGetValue(accountName, out storageDirectory))
            {
                IStorageBlobContainer container = this.GetContainer(accountName);

                storageDirectory = container.GetDirectoryReference(HostDirectoryNames.SingletonLocks);
                _lockDirectoryMap[accountName] = storageDirectory;
            }

            return(storageDirectory);
        }
Example #11
0
        internal IStorageBlobDirectory GetLockDirectory(string accountName)
        {
            if (string.IsNullOrEmpty(accountName))
            {
                accountName = ConnectionStringNames.Storage;
            }

            IStorageBlobDirectory storageDirectory = null;

            if (!_lockDirectoryMap.TryGetValue(accountName, out storageDirectory))
            {
                Task <IStorageAccount> task           = _accountProvider.GetAccountAsync(accountName, CancellationToken.None);
                IStorageAccount        storageAccount = task.Result;
                IStorageBlobClient     blobClient     = storageAccount.CreateBlobClient();
                storageDirectory = blobClient.GetContainerReference(HostContainerNames.Hosts)
                                   .GetDirectoryReference(HostDirectoryNames.SingletonLocks);
                _lockDirectoryMap[accountName] = storageDirectory;
            }

            return(storageDirectory);
        }
Example #12
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);
        }
Example #13
0
        public StorageBlobScanInfoManager(string hostId, IStorageBlobClient blobClient)
        {
            if (string.IsNullOrEmpty(hostId))
            {
                throw new ArgumentNullException("hostId");
            }
            if (blobClient == null)
            {
                throw new ArgumentNullException("blobClient");
            }

            _hostId = hostId;
            JsonSerializerSettings settings = new JsonSerializerSettings
            {
                DateFormatHandling = DateFormatHandling.IsoDateFormat
            };

            _serializer = JsonSerializer.Create(settings);

            string blobScanInfoDirectoryPath = string.Format(CultureInfo.InvariantCulture, "blobscaninfo/{0}", _hostId);

            _blobScanInfoDirectory = blobClient.GetContainerReference(HostContainerNames.Hosts).GetDirectoryReference(blobScanInfoDirectoryPath);
        }
Example #14
0
        internal IStorageBlobDirectory GetLockDirectory(string accountName)
        {
            if (string.IsNullOrEmpty(accountName))
            {
                accountName = ConnectionStringNames.Storage;
            }

            IStorageBlobDirectory storageDirectory = null;

            if (!_lockDirectoryMap.TryGetValue(accountName, out storageDirectory))
            {
                Task <IStorageAccount> task           = _accountProvider.GetStorageAccountAsync(accountName, CancellationToken.None);
                IStorageAccount        storageAccount = task.Result;
                // singleton requires block blobs, cannot be premium
                storageAccount.AssertTypeOneOf(StorageAccountType.GeneralPurpose, StorageAccountType.BlobOnly);
                IStorageBlobClient blobClient = storageAccount.CreateBlobClient();
                storageDirectory = blobClient.GetContainerReference(HostContainerNames.Hosts)
                                   .GetDirectoryReference(HostDirectoryNames.SingletonLocks);
                _lockDirectoryMap[accountName] = storageDirectory;
            }

            return(storageDirectory);
        }
 private BlobReceiptManager(IStorageBlobDirectory directory)
 {
     _directory = directory;
 }
Example #16
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.");
        }
Example #17
0
 private BlobReceiptManager(IStorageBlobDirectory directory)
 {
     _directory = directory;
 }
 private BlobFunctionOutputLogger(IStorageBlobDirectory outputLogDirectory)
 {
     _outputLogDirectory = outputLogDirectory;
 }
 private BlobFunctionOutputLogger(IStorageBlobDirectory outputLogDirectory)
 {
     _outputLogDirectory = outputLogDirectory;
 }