コード例 #1
0
        public static void GenerateNupkgMetadataFile(string nupkgPath, string installPath, string hashPath, string nupkgMetadataPath)
        {
            ConcurrencyUtilities.ExecuteWithFileLocked(nupkgPath,
                                                       action: () =>
            {
                // make sure new hash file doesn't exists within File lock before actually creating it.
                if (!File.Exists(nupkgMetadataPath))
                {
                    var tempNupkgMetadataFilePath = Path.Combine(installPath, Path.GetRandomFileName());
                    using (var stream = File.Open(nupkgPath, FileMode.Open, FileAccess.Read, FileShare.Read))
                        using (var packageReader = new PackageArchiveReader(stream))
                        {
                            // get hash of unsigned content of signed package
                            var packageHash = packageReader.GetContentHashForSignedPackage(CancellationToken.None);

                            // if null, then it's unsigned package so just read the existing sha512 file
                            if (string.IsNullOrEmpty(packageHash))
                            {
                                packageHash = File.ReadAllText(hashPath);
                            }

                            // write the new hash file
                            var hashFile = new NupkgMetadataFile()
                            {
                                ContentHash = packageHash
                            };

                            NupkgMetadataFileFormat.Write(tempNupkgMetadataFilePath, hashFile);
                            File.Move(tempNupkgMetadataFilePath, nupkgMetadataPath);
                        }
                }
            });
        }
コード例 #2
0
        public async Task ConcurrencyUtilityBlocksOutOfProc()
        {
            // Arrange
            string fileId = Guid.NewGuid().ToString();

            var timeout = new CancellationTokenSource(DefaultTimeOut);

            var tasks = new Task <int> [3];

            // Act
            using (var sync = await Run(fileId, shouldAbandon: false, token: timeout.Token, shareProcessObject: true, debug: false))
            {
                var result = sync.Result;

                await WaitForLockToEngage(sync);

                _value1 = 0;

                // We should now be blocked, so the value returned from here should not be returned until the process has terminated.
                tasks[0] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForInt1, timeout.Token);

                _value1 = 1;

                tasks[1] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForInt1, timeout.Token);

                Assert.False(result.Process.HasExited);

                await ReleaseLock(sync);

                using (result.Process)
                {
                    if (!result.Process.WaitForExit(10000))
                    {
                        throw new TimeoutException("Process timed out.");
                    }
                }

                var fileIdReturned = result.Item2.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)[0];

                Assert.Equal(fileId, fileIdReturned.Trim());
            }

            await tasks[0]; // let the first tasks pass
            await tasks[1]; // let the second tasks pass

            _value1 = 2;

            tasks[2] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForInt1, timeout.Token);

            await Task.WhenAll(tasks);

            Task.WaitAll(tasks);

            // Assert
            Assert.True(1 == tasks[0].Result, "task[0]");
            Assert.True(1 == tasks[1].Result, "task[1]");
            Assert.True(2 == tasks[2].Result, "task[2]");

            Assert.False(timeout.IsCancellationRequested);
        }
コード例 #3
0
        private void CreateBreadcrumbFile(string fileName)
        {
            string fullFilePath = Path.Combine(_breadcrumbsFolder, fileName);

            // Execute with file locked because multiple processes can run at the same time
            ConcurrencyUtilities.ExecuteWithFileLocked(fullFilePath, action: _ =>
            {
                try
                {
                    if (!File.Exists(fullFilePath))
                    {
                        File.Create(fullFilePath).Dispose();

                        Logger.TraceInformation(
                            "[{0}] Wrote servicing breadcrumb for {1}",
                            _logType,
                            fileName);
                    }
                }
                catch (UnauthorizedAccessException exception)
                {
                    LogBreadcrumbsCreationFailure(fileName, exception);
                }
                catch (DirectoryNotFoundException exception)
                {
                    LogBreadcrumbsCreationFailure(fileName, exception);
                }
            });
        }
コード例 #4
0
        private void ExecuteSynchronized(Action ioOperation)
        {
            ConcurrencyUtilities.ExecuteWithFileLocked(filePath: ConfigFilePath, action: () =>
            {
                try
                {
                    ioOperation();
                }
                catch (InvalidOperationException e)
                {
                    throw new NuGetConfigurationException(
                        string.Format(CultureInfo.CurrentCulture, Resources.ShowError_ConfigInvalidOperation, ConfigFilePath, e.Message), e);
                }

                catch (UnauthorizedAccessException e)
                {
                    throw new NuGetConfigurationException(
                        string.Format(CultureInfo.CurrentCulture, Resources.ShowError_ConfigUnauthorizedAccess, ConfigFilePath, e.Message), e);
                }

                catch (XmlException e)
                {
                    throw new NuGetConfigurationException(
                        string.Format(CultureInfo.CurrentCulture, Resources.ShowError_ConfigInvalidXml, ConfigFilePath, e.Message), e);
                }

                catch (Exception e)
                {
                    throw new NuGetConfigurationException(
                        string.Format(CultureInfo.CurrentCulture, Resources.Unknown_Config_Exception, ConfigFilePath, e.Message), e);
                }
            });
        }
コード例 #5
0
        public async Task ConcurrencyUtilities_WaitAcquiresLock()
        {
            // Arrange
            var fileId = Guid.NewGuid().ToString();

            var ctsA     = new CancellationTokenSource(DefaultTimeOut);
            var ctsB     = new CancellationTokenSource(TimeSpan.Zero);
            var expected = 3;

            // Act
            var actual = await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                fileId,
                async tA =>
            {
                try
                {
                    await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                        fileId,
                        tB => Task.FromResult(0),
                        ctsB.Token);
                    Assert.False(true, "Waiting with a timeout for a lock that has not been released should fail.");
                }
                catch (OperationCanceledException)
                {
                }

                return(expected);
            },
                ctsA.Token);

            // Assert
            Assert.Equal(expected, actual);
        }
コード例 #6
0
ファイル: PackageFeed.cs プロジェクト: spoiledsport/XRE
        public async Task <Stream> OpenNupkgStreamAsync(PackageInfo package)
        {
            Task <NupkgEntry> task;

            lock (_cache2)
            {
                if (!_cache2.TryGetValue(package.ContentUri, out task))
                {
                    task = _cache2[package.ContentUri] = _OpenNupkgStreamAsync(package);
                }
            }
            var result = await task;

            if (result == null)
            {
                return(null);
            }

            // Acquire the lock on a file before we open it to prevent this process
            // from opening a file deleted by the logic in HttpSource.GetAsync() in another process
            return(await ConcurrencyUtilities.ExecuteWithFileLocked(result.TempFileName, _ =>
            {
                return Task.FromResult(
                    new FileStream(result.TempFileName, FileMode.Open, FileAccess.Read,
                                   FileShare.ReadWrite | FileShare.Delete));
            }));
        }
コード例 #7
0
        private async Task <Stream> OpenNupkgStreamAsync(PackageInfo package, CancellationToken cancellationToken)
        {
            Task <NupkgEntry> task;

            lock (_nupkgCache)
            {
                if (!_nupkgCache.TryGetValue(package.ContentUri, out task))
                {
                    task = _nupkgCache[package.ContentUri] = OpenNupkgStreamAsyncCore(package, cancellationToken);
                }
            }

            var result = await task;

            if (result == null)
            {
                return(null);
            }

            // Acquire the lock on a file before we open it to prevent this process
            // from opening a file deleted by the logic in HttpSource.GetAsync() in another process
            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(result.TempFileName,
                                                                         action : token =>
            {
                return Task.FromResult(
                    new FileStream(result.TempFileName,
                                   FileMode.Open,
                                   FileAccess.Read,
                                   FileShare.ReadWrite | FileShare.Delete));
            },
                                                                         token : cancellationToken));
        }
コード例 #8
0
        private async Task <bool> ProcessCacheEntryAsync(
            CacheEntry cacheEntry,
            Func <Stream, Task> processStreamAsync,
            CancellationToken token)
        {
            if (cacheEntry.AlreadyProcessed)
            {
                return(true);
            }

            if (cacheEntry.CacheFile == null)
            {
                return(false);
            }

            // Acquire the lock on a file before we open it to prevent this process
            // from opening a file deleted by another HTTP request.
            using (var cacheStream = await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       cacheEntry.CacheFile,
                       lockedToken =>
            {
                return(Task.FromResult(new FileStream(
                                           cacheEntry.CacheFile,
                                           FileMode.Open,
                                           FileAccess.Read,
                                           FileShare.ReadWrite | FileShare.Delete,
                                           StreamExtensions.BufferSize)));
            },
                       token))
            {
                await processStreamAsync(cacheStream);

                return(true);
            }
        }
コード例 #9
0
ファイル: PluginManager.cs プロジェクト: dslzuha/nugetclient
        /// <summary>
        /// Creates a plugin from the discovered plugin.
        /// We firstly check the cache for the operation claims for the given request key.
        /// If there is a valid cache entry, and it does contain the requested operation claim, then we start the plugin, and if need be update the cache value itself.
        /// If there is a valid cache entry, and it does NOT contain the requested operation claim, then we return a null.
        /// If there is no valid cache entry or an invalid one, we start the plugin as normally, return an active plugin even if the requested claim is not available, and write a cache entry.
        /// </summary>
        /// <param name="result">plugin discovery result</param>
        /// <param name="requestedOperationClaim">The requested operation claim</param>
        /// <param name="requestKey">plugin request key</param>
        /// <param name="packageSourceRepository">package source repository</param>
        /// <param name="serviceIndex">service index</param>
        /// <param name="cancellationToken">cancellation token</param>
        /// <returns>A plugin creation result, null if the requested plugin cannot handle the given operation claim</returns>
        private async Task <Tuple <bool, PluginCreationResult> > TryCreatePluginAsync(
            PluginDiscoveryResult result,
            OperationClaim requestedOperationClaim,
            PluginRequestKey requestKey,
            string packageSourceRepository,
            JObject serviceIndex,
            CancellationToken cancellationToken)
        {
            PluginCreationResult pluginCreationResult = null;
            var cacheEntry = new PluginCacheEntry(_pluginsCacheDirectory.Value, result.PluginFile.Path, requestKey.PackageSourceRepository);

            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       cacheEntry.CacheFileName,
                       action : async lockedToken =>
            {
                if (cacheEntry.OperationClaims == null || cacheEntry.OperationClaims.Contains(requestedOperationClaim))
                {
                    if (result.PluginFile.State.Value == PluginFileState.Valid)
                    {
                        var plugin = await _pluginFactory.GetOrCreateAsync(
                            result.PluginFile.Path,
                            PluginConstants.PluginArguments,
                            new RequestHandlers(),
                            _connectionOptions,
                            cancellationToken);

                        var utilities = await PerformOneTimePluginInitializationAsync(plugin, cancellationToken);

                        // We still make the GetOperationClaims call even if we have the operation claims cached. This is a way to self-update the cache.
                        var operationClaims = await _pluginOperationClaims.GetOrAdd(
                            requestKey,
                            key => new Lazy <Task <IReadOnlyList <OperationClaim> > >(() =>
                                                                                      GetPluginOperationClaimsAsync(
                                                                                          plugin,
                                                                                          packageSourceRepository,
                                                                                          serviceIndex,
                                                                                          cancellationToken))).Value;

                        if (!EqualityUtility.SequenceEqualWithNullCheck(operationClaims, cacheEntry.OperationClaims))
                        {
                            cacheEntry.OperationClaims = operationClaims;
                            await cacheEntry.UpdateCacheFileAsync();
                        }

                        pluginCreationResult = new PluginCreationResult(
                            plugin,
                            utilities.Value,
                            operationClaims);
                    }
                    else
                    {
                        pluginCreationResult = new PluginCreationResult(result.Message);
                    }
                }
                return new Tuple <bool, PluginCreationResult>(pluginCreationResult != null, pluginCreationResult);
            },
                       token : cancellationToken
                       ));
        }
コード例 #10
0
        public async Task ConcurrencyUtilities_LockStress()
        {
            // Arrange
            using (var testDirectory = TestDirectory.Create())
            {
                // This is the path that uniquely identifies the system-wide mutex.
                var path = Path.Combine(testDirectory, "ConcurrencyUtilities_LockStress_Verification");

                // This is a semaphore use to verify the lock.
                var verificationSemaphore = new SemaphoreSlim(1);

                // Iterate a lot, to increase confidence.
                const int threads    = 50;
                const int iterations = 10;

                // This is the action that is execute inside of the lock.
                Func <CancellationToken, Task <bool> > lockedActionAsync = async lockedToken =>
                {
                    var acquired = await verificationSemaphore.WaitAsync(0);

                    if (!acquired)
                    {
                        return(false);
                    }

                    // Hold the lock for a little bit.
                    await Task.Delay(TimeSpan.FromMilliseconds(1));

                    verificationSemaphore.Release();
                    return(true);
                };

                // Loop the same action, over and over.
                Func <int, Task <List <bool> > > loopAsync = async thread =>
                {
                    var loopResults = new List <bool>();
                    foreach (var iteration in Enumerable.Range(0, iterations))
                    {
                        var result = await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                            path,
                            lockedActionAsync,
                            CancellationToken.None);

                        loopResults.Add(result);
                    }

                    return(loopResults);
                };

                // Act
                var tasks   = Enumerable.Range(0, threads).Select(loopAsync);
                var results = (await Task.WhenAll(tasks)).SelectMany(r => r).ToArray();

                // Assert
                Assert.Equal(threads * iterations, results.Length);
                Assert.DoesNotContain(false, results);
            }
        }
コード例 #11
0
        internal static async Task InstallFromStream(Stream stream, Library library, string packagesDirectory,
                                                     SHA512 sha512)
        {
            var packagePathResolver = new DefaultPackagePathResolver(packagesDirectory);

            var targetPath   = packagePathResolver.GetInstallPath(library.Name, library.Version);
            var targetNuspec = packagePathResolver.GetManifestFilePath(library.Name, library.Version);
            var targetNupkg  = packagePathResolver.GetPackageFilePath(library.Name, library.Version);
            var hashPath     = packagePathResolver.GetHashPath(library.Name, library.Version);

            // Acquire the lock on a nukpg before we extract it to prevent the race condition when multiple
            // processes are extracting to the same destination simultaneously
            await ConcurrencyUtilities.ExecuteWithFileLocked(targetNupkg, async createdNewLock =>
            {
                // If this is the first process trying to install the target nupkg, go ahead
                // After this process successfully installs the package, all other processes
                // waiting on this lock don't need to install it again
                if (createdNewLock)
                {
                    Directory.CreateDirectory(targetPath);
                    using (var nupkgStream = new FileStream(targetNupkg, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete))
                    {
                        await stream.CopyToAsync(nupkgStream);
                        nupkgStream.Seek(0, SeekOrigin.Begin);

                        ExtractPackage(targetPath, nupkgStream);
                    }

                    //// Fixup the casing of the nuspec on disk to match what we expect
                    //var nuspecFile = Directory.EnumerateFiles(targetPath, "*" + Constants.ManifestExtension).Single();

                    //if (!string.Equals(nuspecFile, targetNuspec, StringComparison.Ordinal))
                    //{
                    //    Manifest manifest = null;
                    //    using (var nuspecStream = File.OpenRead(nuspecFile))
                    //    {
                    //        manifest = Manifest.ReadFrom(nuspecStream, validateSchema: false);
                    //        manifest.Metadata.Id = library.Name;
                    //    }

                    //    // Delete the previous nuspec file
                    //    File.Delete(nuspecFile);

                    //    // Write the new manifest
                    //    using (var targetNuspecStream = File.OpenWrite(targetNuspec))
                    //    {
                    //        manifest.Save(targetNuspecStream);
                    //    }
                    //}

                    stream.Seek(0, SeekOrigin.Begin);
                    var nupkgSHA = Convert.ToBase64String(sha512.ComputeHash(stream));
                    File.WriteAllText(hashPath, nupkgSHA);
                }

                return(0);
            });
        }
コード例 #12
0
        public async Task ConcurrencyUtilities_LockStressSynchronous()
        {
            // Arrange
            using (var testDirectory = TestDirectory.Create())
            {
                // This is the path that uniquely identifies the system-wide mutex.
                var path = Path.Combine(testDirectory, "ConcurrencyUtilities_LockStress_Verification_Synchronous");

                // This is a semaphore use to verify the lock.
                var verificationSemaphore = new SemaphoreSlim(1);

                // Iterate a lot, to increase confidence.
                const int threads    = 50;
                const int iterations = 10;

                // This is the action that is execute inside of the lock.
                Action lockedActionSync = () =>
                {
                    var acquired = verificationSemaphore.Wait(0);
                    Assert.True(acquired, "Unable to acquire the lock on the semaphore within the file lock");

                    // Hold the lock for a little bit.
                    Thread.Sleep(TimeSpan.FromMilliseconds(1));

                    verificationSemaphore.Release();
                };


                // Loop the same action, over and over.
                Func <int, Task <List <bool> > > loopAsync = async thread =>
                {
                    var loopResults = new List <bool>();
                    await Task.Run(() =>
                    {
                        foreach (var iteration in Enumerable.Range(0, iterations))
                        {
                            ConcurrencyUtilities.ExecuteWithFileLocked(
                                path,
                                lockedActionSync);
                            loopResults.Add(true);
                        }
                    });

                    return(loopResults);
                };

                // Act
                var tasks   = Enumerable.Range(0, threads).Select(loopAsync);
                var results = (await Task.WhenAll(tasks)).SelectMany(r => r).ToArray();

                // Assert
                Assert.Equal(threads * iterations, results.Length);
            }
        }
コード例 #13
0
ファイル: TestAssetInfo.cs プロジェクト: sidsharma27/cli
 public static void Do(DirectoryInfo directory, Action <ExclusiveFolderAccess> action)
 {
     Task.Run(async() => await ConcurrencyUtilities.ExecuteWithFileLockedAsync <object>(
                  directory.FullName,
                  lockedToken =>
     {
         action(new ExclusiveFolderAccess(directory));
         return(Task.FromResult(new Object()));
     },
                  CancellationToken.None)).Wait();
 }
コード例 #14
0
        private static async Task CommitAsync(
            LockFileFormat lockFileFormat,
            IRestoreResult result,
            ILogger log,
            bool forceWrite,
            bool toolCommit,
            CancellationToken token)
        {
            // Don't write the lock file if it is Locked AND we're not re-locking the file
            if (!result.LockFile.IsLocked || result.RelockFile || toolCommit)
            {
                // Avoid writing out the lock file if it is the same to avoid triggering an intellisense
                // update on a restore with no actual changes.
                if (forceWrite ||
                    result.PreviousLockFile == null ||
                    !result.PreviousLockFile.Equals(result.LockFile))
                {
                    if (toolCommit)
                    {
                        log.LogDebug($"Writing tool lock file to disk. Path: {result.LockFilePath}");

                        await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                            result.LockFilePath,
                            lockedToken =>
                        {
                            var lockFileDirectory = Path.GetDirectoryName(result.LockFilePath);
                            Directory.CreateDirectory(lockFileDirectory);

                            lockFileFormat.Write(result.LockFilePath, result.LockFile);

                            return(Task.FromResult(0));
                        },
                            token);
                    }
                    else
                    {
                        log.LogMinimal($"Writing lock file to disk. Path: {result.LockFilePath}");

                        lockFileFormat.Write(result.LockFilePath, result.LockFile);
                    }
                }
                else
                {
                    if (toolCommit)
                    {
                        log.LogDebug($"Tool lock file has not changed. Skipping lock file write. Path: {result.LockFilePath}");
                    }
                    else
                    {
                        log.LogMinimal($"Lock file has not changed. Skipping lock file write. Path: {result.LockFilePath}");
                    }
                }
            }
        }
コード例 #15
0
        public static async Task <LockFile> ReadWithLock(this LockFileFormat subject, string path)
        {
            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       path,
                       lockedToken =>
            {
                var lockFile = FileAccessRetrier.RetryOnFileAccessFailure(() => subject.Read(path));

                return lockFile;
            },
                       CancellationToken.None));
        }
コード例 #16
0
ファイル: HttpSource.cs プロジェクト: anthrax3/NuGet3
        private async Task <HttpSourceResult> TryCache(string uri, string cacheKey, TimeSpan cacheAgeLimit)
        {
            var baseFolderName = RemoveInvalidFileNameChars(ComputeHash(_baseUri));
            var baseFileName   = RemoveInvalidFileNameChars(cacheKey) + ".dat";

#if DNX451
            var localAppDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
#else
            var localAppDataFolder = Environment.GetEnvironmentVariable("LocalAppData");
#endif
            var cacheFolder = Path.Combine(localAppDataFolder, "kpm", "cache", baseFolderName);
            var cacheFile   = Path.Combine(cacheFolder, baseFileName);

            if (!Directory.Exists(cacheFolder) && !cacheAgeLimit.Equals(TimeSpan.Zero))
            {
                Directory.CreateDirectory(cacheFolder);
            }

            // Acquire the lock on a file before we open it to prevent this process
            // from opening a file deleted by the logic in HttpSource.GetAsync() in another process
            return(await ConcurrencyUtilities.ExecuteWithFileLocked(cacheFile, _ =>
            {
                if (File.Exists(cacheFile))
                {
                    var fileInfo = new FileInfo(cacheFile);
#if DNX451
                    var age = DateTime.UtcNow.Subtract(fileInfo.LastWriteTimeUtc);
#else
                    var age = DateTime.Now.Subtract(fileInfo.LastWriteTime);
#endif
                    if (age < cacheAgeLimit)
                    {
                        var stream = CreateAsyncFileStream(
                            cacheFile,
                            FileMode.Open,
                            FileAccess.Read,
                            FileShare.Read | FileShare.Delete);

                        return Task.FromResult(new HttpSourceResult
                        {
                            CacheFileName = cacheFile,
                            Stream = stream,
                        });
                    }
                }

                return Task.FromResult(new HttpSourceResult
                {
                    CacheFileName = cacheFile,
                });
            }));
        }
コード例 #17
0
        public async Task ConcurrencyUtilities_NormalizePaths()
        {
            // Arrange
            var token         = CancellationToken.None;
            var path1         = "/tmp/packageA/1.0.0";
            var path2         = "/tmp/sub/../packageA/1.0.0";
            var action1HitSem = new ManualResetEventSlim();
            var action1Sem    = new ManualResetEventSlim();
            var action2Sem    = new ManualResetEventSlim();

            Func <CancellationToken, Task <bool> > action1 = (ct) =>
            {
                action1HitSem.Set();
                action1Sem.Wait();
                return(Task.FromResult(true));
            };

            Func <CancellationToken, Task <bool> > action2 = (ct) =>
            {
                action2Sem.Set();
                return(Task.FromResult(true));
            };

            // Act
            var task1 = Task.Run(async() => await ConcurrencyUtilities.ExecuteWithFileLockedAsync <bool>(
                                     path1,
                                     action1,
                                     token));

            var task2Started = action1HitSem.Wait(60 * 1000 * 5, token);

            Assert.True(task2Started);

            var task2 = Task.Run(async() => await ConcurrencyUtilities.ExecuteWithFileLockedAsync <bool>(
                                     path2,
                                     action2,
                                     token));

            // Wait 1s to verify that task2 has not started
            await Task.Delay(1000);

            var task2blocked = !action2Sem.IsSet;

            action1Sem.Set();

            await task1;
            var   result = await task2;

            // Assert
            Assert.True(task2blocked);
            Assert.True(result);
        }
コード例 #18
0
ファイル: TestAssetInfo.cs プロジェクト: siphillipson/cli
        private IEnumerable <FileInfo> GetInventory(
            FileInfo file,
            Func <IEnumerable <FileInfo> > beforeAction,
            Action action)
        {
            var inventory = Enumerable.Empty <FileInfo>();

            if (file.Exists)
            {
                inventory = LoadInventory(file);
            }

            if (inventory.Any())
            {
                return(inventory);
            }

            IEnumerable <FileInfo> preInventory;

            if (beforeAction == null)
            {
                preInventory = new List <FileInfo>();
            }
            else
            {
                preInventory = beforeAction();
            }

            Task.Run(async() => await ConcurrencyUtilities.ExecuteWithFileLockedAsync <object>(
                         _dataDirectory.FullName,
                         lockedToken =>
            {
                if (file.Exists)
                {
                    inventory = LoadInventory(file);
                }
                else
                {
                    action();

                    inventory = GetFileList().Where(i => !preInventory.Select(p => p.FullName).Contains(i.FullName));

                    SaveInventory(file, inventory);
                }

                return(Task.FromResult(new Object()));
            },
                         CancellationToken.None)).Wait();

            return(inventory);
        }
コード例 #19
0
            public FileInfoNuGetLock(FileInfo fileInfo)
            {
                _cancellationTokenSource = new CancellationTokenSource();

                _task = ConcurrencyUtilities.ExecuteWithFileLockedAsync <int>(
                    fileInfo.FullName,
                    lockedToken =>
                {
                    Task.Delay(60000, _cancellationTokenSource.Token).Wait();

                    return(Task.FromResult(0));
                },
                    _cancellationTokenSource.Token);
            }
コード例 #20
0
        public async Task ConcurrencyUtilities_ZeroTimeoutStillGetsLock()
        {
            // Arrange
            var fileId   = Guid.NewGuid().ToString();
            var cts      = new CancellationTokenSource(TimeSpan.Zero);
            var expected = 3;

            // Act
            var actual = await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                fileId,
                token => Task.FromResult(expected),
                cts.Token);

            // Assert
            Assert.Equal(actual, expected);
        }
コード例 #21
0
        public async Task ConcurrencyUtilityDoesntBlocksInProc()
        {
            // Arrange
            var fileId = nameof(ConcurrencyUtilityDoesntBlocksInProc);

            var timeout = new CancellationTokenSource(DefaultTimeOut * 2);
            var cts     = new CancellationTokenSource(DefaultTimeOut);

            var tasks = new Task <int> [4];

            // Act
            tasks[0] = ConcurrencyUtilities.ExecuteWithFileLockedAsync("x" + fileId, WaitForever, cts.Token);

            _value2 = 0;

            // We should now be blocked, so the value returned from here should not be
            // returned until the token is cancelled.
            tasks[1] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForInt2, timeout.Token);

            await tasks[1];

            _value2 = 1;

            tasks[2] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForInt2, timeout.Token);

            await tasks[2]; // let the first tasks pass we get a deadlock if there is a lock applied by the first task

            Assert.False(cts.IsCancellationRequested);
            cts.Cancel();

            _value2 = 2;

            tasks[3] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForInt2, timeout.Token);

            await tasks[3];

            await tasks[0];
            await Task.WhenAll(tasks);

            // Assert
            Assert.Equal(0, tasks[1].Result);
            Assert.Equal(1, tasks[2].Result);
            Assert.Equal(2, tasks[3].Result);

            Assert.False(timeout.IsCancellationRequested);
        }
コード例 #22
0
        public static int Main(string[] args)
        {
            if (args.Length == 0)
            {
                throw new InvalidOperationException($"usage: [{DebugSwitch}] filename port [{AbandonSwitch}]");
            }

            if (args[0].Equals(DebugSwitch, StringComparison.Ordinal))
            {
                args = args.Skip(1).ToArray();

                Debugger.Launch();
                Debugger.Break();
            }

            var filename = args[0];

            if (string.IsNullOrEmpty(filename))
            {
                throw new InvalidOperationException("Pass a filename");
            }

            _port = int.Parse(args[1]);

            _abandonLock = args.Length > 2 && args[2].Equals(AbandonSwitch, StringComparison.Ordinal);

            _reportStarted = !_abandonLock;

            _client = new TcpClient();

            var lockedTask = ConcurrencyUtilities.ExecuteWithFileLockedAsync(filename, WaitInALock, CancellationToken.None);

            try
            {
                lockedTask.Wait();
            }
            catch (AggregateException)
            {
                return(2);
            }

            Console.WriteLine(filename);

            return(0);
        }
コード例 #23
0
        public async Task ConcurrencyUtilityBlocksInProc()
        {
            // Arrange
            var fileId = nameof(ConcurrencyUtilityBlocksInProc);

            var timeout = new CancellationTokenSource(DefaultTimeOut * 2);
            var cts     = new CancellationTokenSource(DefaultTimeOut);

            var tasks = new Task <int> [4];

            // Act
            tasks[0] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForever1, cts.Token);

            await _waitForEverStarted.WaitAsync();

            // We should now be blocked, so the value returned from here should not be returned until the token is cancelled.
            tasks[1] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForInt1, timeout.Token);

            Assert.False(tasks[0].IsCompleted, $"task status: {tasks[0].Status}");

            _value1 = 1;

            tasks[2] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForInt1, timeout.Token);

            Assert.False(cts.Token.IsCancellationRequested);
            cts.Cancel();

            await tasks[1]; // let the first tasks pass
            await tasks[2]; // let the first tasks pass

            _value1 = 2;

            tasks[3] = ConcurrencyUtilities.ExecuteWithFileLockedAsync(fileId, WaitForInt1, timeout.Token);

            await tasks[3];

            // Assert
            Assert.Equal(TaskStatus.Canceled, tasks[0].Status);
            Assert.Equal(1, tasks[1].Result);
            Assert.Equal(1, tasks[2].Result);
            Assert.Equal(2, tasks[3].Result);

            Assert.False(timeout.IsCancellationRequested);
        }
コード例 #24
0
        private static async Task <NuGetExe> DownloadNuGetExeAsync(
            string requestUri,
            string fileName,
            bool supportsIsolatedHttpCache)
        {
            var temp = NuGetEnvironment.GetFolderPath(NuGetFolderPath.Temp);
            var path = Path.Combine(temp, fileName);

            var verifiedPath = await _verifiedPaths.GetOrAdd(
                path,
                thisPath => ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                    thisPath,
                    async token =>
            {
                if (File.Exists(thisPath))
                {
                    // Make sure we can run the executable.
                    var helpResult = CommandRunner.Run(
                        thisPath,
                        ".",
                        "help",
                        waitForExit: true);

                    if (helpResult.ExitCode == 0)
                    {
                        return(thisPath);
                    }
                }

                // Download the executable.
                using (var httpClient = new System.Net.Http.HttpClient())
                    using (var stream = await httpClient.GetStreamAsync(requestUri))
                        using (var fileStream = new FileStream(thisPath, FileMode.Create))
                        {
                            await stream.CopyToAsync(fileStream);
                        }

                return(thisPath);
            },
                    CancellationToken.None));

            return(new NuGetExe(verifiedPath, supportsIsolatedHttpCache));
        }
コード例 #25
0
            public FileInfoNuGetLock(FileInfo fileInfo)
            {
                var taskCompletionSource = new TaskCompletionSource <string>();

                _cancellationTokenSource = new CancellationTokenSource();

                _task = Task.Run(async() => await ConcurrencyUtilities.ExecuteWithFileLockedAsync <int>(
                                     fileInfo.FullName,
                                     cancellationToken =>
                {
                    taskCompletionSource.SetResult("Lock is taken so test can continue");

                    Task.Delay(60000, cancellationToken).Wait();

                    return(Task.FromResult(0));
                },
                                     _cancellationTokenSource.Token));

                taskCompletionSource.Task.Wait();
            }
コード例 #26
0
        public static async Task <LockFile> ReadWithLock(this LockFileFormat subject, string path)
        {
            if (!File.Exists(path))
            {
                throw new GracefulException(string.Join(
                                                Environment.NewLine,
                                                string.Format(LocalizableStrings.FileNotFound, path),
                                                LocalizableStrings.ProjectNotRestoredOrRestoreFailed));
            }

            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       path,
                       lockedToken =>
            {
                var lockFile = FileAccessRetrier.RetryOnFileAccessFailure(() => subject.Read(path));

                return lockFile;
            },
                       CancellationToken.None));
        }
コード例 #27
0
        public static async Task <LockFile> ReadWithLock(this LockFileFormat subject, string path)
        {
            if (!File.Exists(path))
            {
                throw new GracefulException(string.Join(
                                                Environment.NewLine,
                                                $"File not found `{path}`.",
                                                "The project may not have been restored or restore failed - run `dotnet restore`"));
            }

            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       path,
                       lockedToken =>
            {
                var lockFile = FileAccessRetrier.RetryOnFileAccessFailure(() => subject.Read(path));

                return lockFile;
            },
                       CancellationToken.None));
        }
コード例 #28
0
        public static async Task <LockFile> ReadWithLock(this LockFileFormat subject, string path)
        {
            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       path,
                       lockedToken =>
            {
                if (!File.Exists(path))
                {
                    throw new GracefulException(string.Join(
                                                    Environment.NewLine,
                                                    string.Format(Resources.GetString("FileNotFound"), path),
                                                    Resources.GetString("ProjectNotRestoredOrRestoreFailed")));
                }

                var lockFile = FileAccessRetrier.RetryOnFileAccessFailure(() => subject.Read(path), Resources.GetString("CouldNotAccessAssetsFile"));

                return lockFile;
            },
                       CancellationToken.None));
        }
コード例 #29
0
ファイル: PortReserver.cs プロジェクト: dslzuha/nugetclient
        public async Task <T> ExecuteAsync <T>(
            Func <int, CancellationToken, Task <T> > action,
            CancellationToken token)
        {
            int port = _basePort - 1;

            while (true)
            {
                token.ThrowIfCancellationRequested();

                port++;

                if (port > 65535)
                {
                    throw new InvalidOperationException("Exceeded port range");
                }

                // ListUsedTCPPort prevents port contention with other apps.
                if (!IsTcpPortAvailable(port))
                {
                    continue;
                }

                // WaitForLockAsync prevents port contention with this app.
                string portLockName = $"NuGet-Port-{port}";
                var    tryOnceCts   = new CancellationTokenSource(TimeSpan.Zero);
                try
                {
                    var attemptedPort = port;
                    return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync <T>(
                               portLockName,
                               t => action(attemptedPort, token),
                               tryOnceCts.Token));
                }
                catch (OperationCanceledException)
                {
                }
            }
        }
コード例 #30
0
        /// <summary>
        /// Caching Get request.
        /// </summary>
        public async Task <T> GetAsync <T>(
            HttpSourceCachedRequest request,
            Func <HttpSourceResult, Task <T> > processAsync,
            ILogger log,
            CancellationToken token)
        {
            var cacheResult = HttpCacheUtility.InitializeHttpCacheResult(
                HttpCacheDirectory,
                _sourceUri,
                request.CacheKey,
                request.CacheContext);

            return(await ConcurrencyUtilities.ExecuteWithFileLockedAsync(
                       cacheResult.CacheFile,
                       action : async lockedToken =>
            {
                cacheResult.Stream = TryReadCacheFile(request.Uri, cacheResult.MaxAge, cacheResult.CacheFile);

                if (cacheResult.Stream != null)
                {
                    log.LogInformation(string.Format(CultureInfo.InvariantCulture, "  " + Strings.Http_RequestLog, "CACHE", request.Uri));

                    // Validate the content fetched from the cache.
                    try
                    {
                        request.EnsureValidContents?.Invoke(cacheResult.Stream);

                        cacheResult.Stream.Seek(0, SeekOrigin.Begin);

                        var httpSourceResult = new HttpSourceResult(
                            HttpSourceResultStatus.OpenedFromDisk,
                            cacheResult.CacheFile,
                            cacheResult.Stream);

                        return await processAsync(httpSourceResult);
                    }
                    catch (Exception e)
                    {
                        cacheResult.Stream.Dispose();
                        cacheResult.Stream = null;

                        string message = string.Format(CultureInfo.CurrentCulture, Strings.Log_InvalidCacheEntry, request.Uri)
                                         + Environment.NewLine
                                         + ExceptionUtilities.DisplayMessage(e);
                        log.LogWarning(message);
                    }
                }

                Func <HttpRequestMessage> requestFactory = () =>
                {
                    var requestMessage = HttpRequestMessageFactory.Create(HttpMethod.Get, request.Uri, log);

                    foreach (var acceptHeaderValue in request.AcceptHeaderValues)
                    {
                        requestMessage.Headers.Accept.Add(acceptHeaderValue);
                    }

                    return requestMessage;
                };

                Func <Task <ThrottledResponse> > throttledResponseFactory = () => GetThrottledResponse(
                    requestFactory,
                    request.RequestTimeout,
                    request.DownloadTimeout,
                    request.MaxTries,
                    log,
                    lockedToken);

                using (var throttledResponse = await throttledResponseFactory())
                {
                    if (request.IgnoreNotFounds && throttledResponse.Response.StatusCode == HttpStatusCode.NotFound)
                    {
                        var httpSourceResult = new HttpSourceResult(HttpSourceResultStatus.NotFound);

                        return await processAsync(httpSourceResult);
                    }

                    if (throttledResponse.Response.StatusCode == HttpStatusCode.NoContent)
                    {
                        // Ignore reading and caching the empty stream.
                        var httpSourceResult = new HttpSourceResult(HttpSourceResultStatus.NoContent);

                        return await processAsync(httpSourceResult);
                    }

                    throttledResponse.Response.EnsureSuccessStatusCode();

                    if (!request.CacheContext.DirectDownload)
                    {
                        await HttpCacheUtility.CreateCacheFileAsync(
                            cacheResult,
                            throttledResponse.Response,
                            request.EnsureValidContents,
                            lockedToken);

                        using (var httpSourceResult = new HttpSourceResult(
                                   HttpSourceResultStatus.OpenedFromDisk,
                                   cacheResult.CacheFile,
                                   cacheResult.Stream))
                        {
                            return await processAsync(httpSourceResult);
                        }
                    }
                    else
                    {
                        // Note that we do not execute the content validator on the response stream when skipping
                        // the cache. We cannot seek on the network stream and it is not valuable to download the
                        // content twice just to validate the first time (considering that the second download could
                        // be different from the first thus rendering the first validation meaningless).
                        using (var stream = await throttledResponse.Response.Content.ReadAsStreamAsync())
                            using (var httpSourceResult = new HttpSourceResult(
                                       HttpSourceResultStatus.OpenedFromNetwork,
                                       cacheFileName: null,
                                       stream: stream))
                            {
                                return await processAsync(httpSourceResult);
                            }
                    }
                }
            },
                       token : token));
        }