Пример #1
0
 /// <summary>
 /// 内容に変更があっても、表示の更新及びChanged イベントが発生しない様にします。
 /// </summary>
 public System.IDisposable Lock()
 {
     if (this.locked == 0)
     {
         this.sbuffer = new System.Text.StringBuilder();
     }
     this.locked++;
     return(lock_rel ?? (lock_rel = new LockReleaser(this)));
 }
Пример #2
0
 public void TestDoubleRelease()
 {
     using (AsyncLocker locker = new AsyncLocker())
     {
         using (LockReleaser l = locker.Lock())
         {
             l.Dispose();
         }
     }
 }
Пример #3
0
            internal void DequeueAndEnter(LockReleaser releaser)
            {
                Debug.Assert(Monitor.IsEntered(_context._syncObj), "Выполнять можно только в блокировке");
                Debug.Assert(_queue.Count > 0);

                // Взять первый поток в очереди.
                var tcs = _queue.Dequeue();

                bool success = tcs.TrySetResult(releaser);

                Debug.Assert(success);
            }
Пример #4
0
        public async Task <ManagedToken> AddManagedTokenAsync(string key, ManagedToken managedToken)
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                return(await AddUnSafeManagedTokenAsync(key, managedToken));
            }
            finally
            {
                releaser.Dispose();
            }
        }
Пример #5
0
        public async Task RemoveManagedTokenAsync(string key)
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                await _tokenStorage.RemoveManagedTokenAsync(key);
            }
            finally
            {
                releaser.Dispose();
            }
        }
        public async Task RemoveConcurrentManagedTokenAsync(string key)
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                _managedTokens.TryRemove(key, out _);
            }
            finally
            {
                releaser.Dispose();
            }
        }
        public async Task RemoveAllConcurrentManagedTokenAsync()
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                _managedTokens.Clear();
            }
            finally
            {
                releaser.Dispose();
            }
        }
Пример #8
0
        public async Task AddCredentialsAsync(string key, OAuth2Credentials creds)
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                var memKey = $"{PreKeyName}.{key}";
                _memoryCache.Set(memKey, creds);
            }
            finally
            {
                releaser.Dispose();
            }
        }
        public async Task <ManagedToken> AddConcurrentManagedTokenAsync(string key, ManagedToken managedToken)
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                managedToken.StartDate      = DateTimeOffset.UtcNow;
                managedToken.ExpirationDate = managedToken.StartDate.AddSeconds(managedToken.ExpiresIn);
                _managedTokens[key]         = managedToken;
                return(managedToken);
            }
            finally
            {
                releaser.Dispose();
            }
        }
Пример #10
0
        public async Task <OAuth2Credentials> GetOAuth2CredentialsAsync(string key)
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                var memKey = $"{PreKeyName}.{key}";
                OAuth2Credentials creds;
                if (_memoryCache.TryGetValue(memKey, out creds))
                {
                    if (creds.DiscoveryDocumentResponse == null)
                    {
                        // pull it.
                        HttpClient client = null;
                        if (string.IsNullOrEmpty(creds.HttpClientName))
                        {
                            client = new HttpClient();
                        }
                        else
                        {
                            client = _clientFactory.CreateClient(creds.HttpClientName);
                        }
                        var disco = await client.GetDiscoveryDocumentAsync(creds.Authority);

                        if (disco.IsError)
                        {
                            throw new Exception(disco.Error);
                        }
                        creds.DiscoveryDocumentResponse = disco;
                        _memoryCache.Set(memKey, creds);
                    }
                    return(creds);
                }
                _logger.LogError($"OAuth2 Credentials is not in cache: key={key}");
                return(null);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                return(null);
            }
            finally
            {
                releaser.Dispose();
            }
        }
        private async Task <ManagedToken> GetConcurrentManagedTokenAsync(string key)
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                ManagedToken managedToken;
                if (_managedTokens.TryGetValue(key, out managedToken))
                {
                    return(managedToken);
                }
                return(null);
            }
            finally
            {
                releaser.Dispose();
            }
        }
Пример #12
0
        public async Task <string> AcquireAccessTokenAsync()
        {
            var utcNow = DateTime.UtcNow;
            int result = DateTime.Compare(_expiration, utcNow);

            if (string.IsNullOrWhiteSpace(_token) || result <= 0)
            {
                LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

                try
                {
                    var clientId       = Environment.GetEnvironmentVariable("ARM_CLIENT_ID");
                    var clientSecret   = Environment.GetEnvironmentVariable("ARM_CLIENT_SECRET");
                    var subscriptionId = Environment.GetEnvironmentVariable("ARM_SUBSCRIPTION_ID");
                    var tenantId       = Environment.GetEnvironmentVariable("ARM_TENANT_ID");
                    var client         = new HttpClient();

                    var response = await client.RequestTokenAsync(new TokenRequest
                    {
                        Address      = $"https://login.microsoftonline.com/{tenantId}/oauth2/token?api-version=1.0",
                        GrantType    = "client_credentials",
                        ClientId     = clientId,
                        ClientSecret = clientSecret,
                        Parameters   =
                        {
                            { "resource", "https://management.core.windows.net/" }
                        }
                    });

                    _token      = response.AccessToken;
                    _expiration = DateTime.UtcNow.AddSeconds(response.ExpiresIn - 60);  // 1 minute grace.
                }
                finally
                {
                    releaser.Dispose();
                }
            }
            return(_token);
        }
        public async Task <OpenIdConnectConfiguration> GetOpenIdConnectConfigurationAsync(string issuer)
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                OpenIdConnectConfiguration openIdConfig;
                if (_cache.TryGetValue(issuer, out openIdConfig))
                {
                    return(openIdConfig);
                }
                IConfigurationManager <OpenIdConnectConfiguration> configurationManager = new ConfigurationManager <OpenIdConnectConfiguration>($"{issuer}/.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
                openIdConfig = await configurationManager.GetConfigurationAsync(CancellationToken.None);

                _cache.Set(issuer, openIdConfig, new TimeSpan(1, 0, 0, 0));  // cache for 1 day
                return(openIdConfig);
            }
            finally
            {
                releaser.Dispose();
            }
        }
Пример #14
0
        public void ReleaseLocks()
        {
            if (this.ContextLocks != null)
            {
                foreach (var entityId in this.ContextLocks)
                {
                    var instance = new OrchestrationInstance()
                    {
                        InstanceId = EntityId.GetSchedulerIdFromEntityId(entityId)
                    };
                    var message = new ReleaseMessage()
                    {
                        ParentInstanceId = this.InstanceId,
                        LockRequestId    = this.LockRequestId,
                    };
                    this.SendEntityMessage(instance, "release", message);
                }

                this.ContextLocks  = null;
                this.lockReleaser  = null;
                this.LockRequestId = null;
            }
        }
Пример #15
0
 public AsyncLock()
 {
     _semaphore    = new SemaphoreSlim(1, 1);
     _lockReleaser = new LockReleaser(_semaphore);
 }
Пример #16
0
        public async Task <ManagedToken> GetManagedTokenAsync(string key, bool forceRefresh = false, CancellationToken cancellationToken = default)
        {
            LockReleaser releaser = await _lock.Lock(new TimeSpan(0, 0, 30));

            try
            {
                var managedToken = await GetUnSafeManagedTokenAsync(key);

                if (managedToken == null)
                {
                    return(null);
                }
                if (string.IsNullOrEmpty(managedToken.RefreshToken))
                {
                    if (forceRefresh)
                    {
                        var func = _customTokenRequest.GetTokenRequestFunc(managedToken.RequestFunctionKey);
                        if (func == null)
                        {
                            throw new Exception($"forceRefresh requested, but no token request function exists. RequestFunctionKey={managedToken.RequestFunctionKey}");
                        }
                        var mT = await func(managedToken, _serviceProvider, _oAuth2CredentialManager, cancellationToken);

                        if (mT == null)
                        {
                            throw new Exception($"Custom Token Request function return a null. RequestFunctionKey={managedToken.RequestFunctionKey}");
                        }
                        managedToken = await AddUnSafeManagedTokenAsync(key, mT);
                    }
                    return(managedToken);
                }

                DateTimeOffset now = DateTimeOffset.UtcNow;
                if (!forceRefresh)
                {
                    if (managedToken.ExpirationDate > now || string.IsNullOrWhiteSpace(managedToken.RefreshToken))
                    {
                        return(managedToken);
                    }
                }
                var creds = await _oAuth2CredentialManager.GetOAuth2CredentialsAsync(managedToken.CredentialsKey);

                if (creds == null)
                {
                    throw new Exception($"GetOAuth2CredentialsAsync failed: key={managedToken.CredentialsKey}");
                }
                var client   = new HttpClient();
                var response = await client.RequestRefreshTokenAsync(new RefreshTokenRequest
                {
                    Address      = creds.DiscoveryDocumentResponse.TokenEndpoint,
                    ClientId     = creds.ClientId,
                    ClientSecret = creds.ClientSecret,
                    RefreshToken = managedToken.RefreshToken
                });

                if (response.IsError)
                {
                    // REMOVE the managed token, because the refresh failed
                    await _tokenStorage.RemoveManagedTokensAsync();

                    throw new Exception($"RequestRefreshTokenAsync failed for key={key}",
                                        new Exception(response.Error));
                }
                managedToken.RefreshToken = response.RefreshToken;
                managedToken.AccessToken  = response.AccessToken;
                managedToken.ExpiresIn    = response.ExpiresIn;
                managedToken = await AddUnSafeManagedTokenAsync(key, managedToken);

                return(managedToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                return(null);
            }
            finally
            {
                releaser.Dispose();
            }
        }
Пример #17
0
        /// <inheritdoc/>
        async Task <IDisposable> IDurableOrchestrationContext.LockAsync(params EntityId[] entities)
        {
            this.ThrowIfInvalidAccess();
            if (this.ContextLocks != null)
            {
                throw new LockingRulesViolationException("Cannot acquire more locks when already holding some locks.");
            }

            if (entities == null || entities.Length == 0)
            {
                throw new ArgumentException("The list of entities to lock must not be null or empty.", nameof(entities));
            }

            // acquire the locks in a globally fixed order to avoid deadlocks
            Array.Sort(entities);

            // remove duplicates if necessary. Probably quite rare, so no need to optimize more.
            for (int i = 0; i < entities.Length - 1; i++)
            {
                if (entities[i].Equals(entities[i + 1]))
                {
                    entities = entities.Distinct().ToArray();
                    break;
                }
            }

            // use a deterministically replayable unique ID for this lock request, and to receive the response
            var lockRequestId = this.NewGuid();

            // All the entities in entity[] need to be locked, but to avoid deadlock, the locks have to be acquired
            // sequentially, in order. So, we send the lock request to the first entity; when the first lock
            // is granted by the first entity, the first entity will forward the lock request to the second entity,
            // and so on; after the last entity grants the last lock, a response is sent back here.

            // send lock request to first entity in the lock set
            var target = new OrchestrationInstance()
            {
                InstanceId = EntityId.GetSchedulerIdFromEntityId(entities[0])
            };
            var request = new RequestMessage()
            {
                Id = lockRequestId,
                ParentInstanceId = this.InstanceId,
                LockSet          = entities,
                Position         = 0,
            };

            this.LockRequestId = lockRequestId.ToString();

            this.SendEntityMessage(target, "op", request);

            // wait for the response from the last entity in the lock set
            await this.WaitForExternalEvent <ResponseMessage>(this.LockRequestId, "LockAcquisitionCompleted");

            this.ContextLocks = new List <EntityId>(entities);

            // return an IDisposable that releases the lock
            this.lockReleaser = new LockReleaser(this);

            return(this.lockReleaser);
        }