public async Task ConcurrencyLimitIsRespected(SemaphoreOrder order)
        {
            var cycles = 4;

            for (var cycle = 0; cycle < cycles; cycle++)
            {
                var concurrencyLimit = 10;
                var semaphore        = new OrderedSemaphore(concurrencyLimit: concurrencyLimit, order, Context);

                // Use up the semaphore
                for (var i = 0; i < concurrencyLimit; i++)
                {
                    (await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None)).Should().BeTrue();
                }

                // Any more should not be immediatelly successful
                var task = semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None);
                await Task.Delay(TimeSpan.FromMilliseconds(1));

                task.IsCompleted.Should().BeFalse();

                // Releasing at least one space should free up a space.
                semaphore.Release();
                (await task).Should().BeTrue();

                // Clear the semaphore.
                for (var i = 0; i < concurrencyLimit; i++)
                {
                    semaphore.Release();
                }
            }
        }
        public DefaultCopyScheduler(DefaultCopySchedulerConfiguration configuration, Context tracingContext)
        {
            _configuration = configuration;

            _outboundPullGate = new OrderedSemaphore(
                configuration.OutboundPullConfiguration.MaximumConcurrency,
                configuration.OutboundPullConfiguration.SemaphoreOrder,
                tracingContext);

            _outboundPushGate = new OrderedSemaphore(
                configuration.OutboundPushConfiguration.MaximumConcurrency,
                configuration.OutboundPushConfiguration.SemaphoreOrder,
                tracingContext);
        }
        internal async Task AlreadyCancelledTokenIsRespected(SemaphoreOrder order)
        {
            var concurrencyLimit = 10;

            var semaphore = new OrderedSemaphore(concurrencyLimit: concurrencyLimit, order, Context);

            // Fill out the semaphore
            var tasks = Enumerable.Range(0, concurrencyLimit).Select(async num => await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None));

            (await Task.WhenAll(tasks)).Should().AllBeEquivalentTo(true);

            // Queue tasks which should be blocked by other running tasks
            var cts = new CancellationTokenSource();

            cts.Cancel();
            var blockedTasks = Enumerable.Range(0, concurrencyLimit).Select(async num => await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, cts.Token));

            blockedTasks.Select(t => Assert.ThrowsAsync <TaskCanceledException>(() => t)).ToArray();
        }
        public async Task CancellationTokenTimeoutIsDetected(SemaphoreOrder order)
        {
            var concurrencyLimit = 10;

            var semaphore = new OrderedSemaphore(concurrencyLimit: concurrencyLimit, order, Context);

            // Fill out the semaphore
            var tasks = Enumerable.Range(0, concurrencyLimit).Select(async num => await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None));

            (await Task.WhenAll(tasks)).Should().AllBeEquivalentTo(true);

            // Queue tasks which should be blocked by other running tasks
            var cts          = new CancellationTokenSource(delay: TimeSpan.FromMilliseconds(100));
            var blockedTasks = Enumerable.Range(0, concurrencyLimit).Select(async num => await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, cts.Token));

            await Task.Delay(TimeSpan.FromMilliseconds(1));

            // Should all be blocked
            blockedTasks.Select(t => t.IsCompleted.Should().BeFalse()).ToArray();

            blockedTasks.Select(t => Assert.ThrowsAsync <TaskCanceledException>(() => t)).ToArray();
        }
        public DistributedContentCopier(
            DistributedContentStoreSettings settings,
            IAbsFileSystem fileSystem,
            IRemoteFileCopier fileCopier,
            IContentCommunicationManager copyRequester,
            IClock clock,
            ILogger logger)
        {
            Contract.Requires(settings != null);
            Contract.Requires(settings.ParallelHashingFileSizeBoundary >= -1);

            _settings         = settings;
            _remoteFileCopier = fileCopier;
            _copyRequester    = copyRequester;
            FileSystem        = fileSystem;
            _clock            = clock;

            _ioGate = new OrderedSemaphore(_settings.MaxConcurrentCopyOperations, _settings.OrderForCopies, new Context(logger));
            _proactiveCopyIoGate             = new OrderedSemaphore(_settings.MaxConcurrentProactiveCopyOperations, _settings.OrderForProactiveCopies, new Context(logger));
            _retryIntervals                  = settings.RetryIntervalForCopies;
            _maxRetryCount                   = settings.MaxRetryCount;
            _ioGateTimeoutForProactiveCopies = settings.ProactiveCopyIOGateTimeout;
        }
        public async Task OrderIsRespected(SemaphoreOrder order)
        {
            var semaphore = new OrderedSemaphore(concurrencyLimit: 1, order, Context);

            var amountTasks = 10;
            var results     = new List <int>();

            // Block to make sure that we have time to create all tasks before they start executing; otherwise LIFO will be flaky.
            await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None);

            var tasks = Enumerable.Range(0, amountTasks).Select(async num =>
            {
                (await semaphore.WaitAsync(Timeout.InfiniteTimeSpan, CancellationToken.None)).Should().BeTrue();
                results.Add(num);
                semaphore.Release();
            }).ToArray();

            // Tasks should be blocked.
            results.Count.Should().Be(0);

            // Unblock tasks
            semaphore.Release();

            // Wait for tasks to complete and validate results.
            await Task.WhenAll(tasks);

            results.Count.Should().Be(amountTasks);
            for (var i = 0; i < results.Count; i++)
            {
                var expected = order == SemaphoreOrder.FIFO
                    ? i
                    : amountTasks - i - 1;

                results[i].Should().Be(expected);
            }
        }
        public async Task LongTimeoutIsRespected(SemaphoreOrder order)
        {
            var semaphore = new OrderedSemaphore(concurrencyLimit: 0, order, Context);

            (await semaphore.WaitAsync(timeout: TimeSpan.FromMilliseconds(10), CancellationToken.None)).Should().BeFalse();
        }