예제 #1
0
        protected override async Task <IFtpClientConnection> GetConnection(CancellationToken ctk = default)
        {
            IFtpClientConnection result = null;
            await _semaphore.WaitAsync(ctk);

            try
            {
                while (_pool.TryPop(out var candidate))
                {
                    if (await candidate.IsConnectedAsync(ctk))
                    {
                        result = candidate;
                        break;
                    }

                    candidate.Dispose();
                }

                if (result == null)
                {
                    result = _createNewConnection();
                    await result.ConnectAsync(ctk);
                }

                var pooled = new PooledFtpConnection(result);
                pooled.Disposing += _pooled_Disposing;
                return(pooled);
            } catch
            {
                result?.Dispose();
                _semaphore.Release();
                throw;
            }
        }
        public override async Task <IEnumerable <FtpEntry> > ListFilesRecursiveAsync(string startPath = null, Predicate <FtpEntry> skipFolder = null, CancellationToken ctk = default)
        {
            IFtpClientConnection conn = null;

            try
            {
                _logger.Trace("List files starting from path: {0}", startPath);

                conn = await GetConnection(ctk);

                await conn.ConnectAsync(ctk);

                if (skipFolder == null)
                {
                    skipFolder = x => false;
                }

                Stack <FtpEntry>       pendingFolders = new Stack <FtpEntry>();
                IEnumerable <FtpEntry> files          = new List <FtpEntry>();

                Func <string, CancellationToken, Task> listFolderAsync = async(string path, CancellationToken ct) =>
                {
                    var retrier = Policy
                                  .Handle <Exception>()
                                  .WaitAndRetryAsync(new[]
                    {
                        TimeSpan.FromSeconds(1),
                        TimeSpan.FromSeconds(1),
                    }, (ex, ts) =>
                    {
                        _logger.Warn(ex, "Failed to list folder {0}. Try again soon ...", path);
                    });

                    var list = await retrier.ExecuteAsync(async ct1 =>
                    {
                        if (!await conn.IsConnectedAsync(ctk))
                        {
                            conn.Dispose();
                            conn = await GetConnection(ctk);
                            await conn.ConnectAsync(ctk);
                        }
                        return(await conn.ListDirectoryAsync(path, ct1));
                    }, ct);

                    foreach (var d in list.Where(x => x.IsDirectory && !x.Name.Equals(".") && !x.Name.Equals("..")))
                    {
                        if (skipFolder.Invoke(d))
                        {
                            _logger.Info("Skipping folder: {0}", d.FullPath);
                        }
                        else
                        {
                            pendingFolders.Push(d);
                        }
                    }

                    files = files.Concat(list.Where(x => !x.IsDirectory).ToList());
                };

                await listFolderAsync(startPath, ctk);

                while (pendingFolders.Count > 0)
                {
                    await listFolderAsync(pendingFolders.Pop().FullPath, ctk);
                }

                return(files);
            } finally
            {
                conn?.Dispose();
            }
        }
예제 #3
0
 public PooledFtpConnection(IFtpClientConnection inner)
 {
     Inner = inner;
 }