예제 #1
0
        private Downloader StartDownload(FSItem item, string path)
        {
            var downloader = new Downloader(item, path);

            lock (DownloadersLock)
            {
                Downloader result;
                if (Downloaders.TryGetValue(item.Path, out result))
                {
                    if (result.Task == null)
                    {
                        throw new Exception("Downloader Task is Null");
                    }

                    return(result);
                }

                Directory.CreateDirectory(cachePath);

                var fileinfo = new FileInfo(path);

                if (fileinfo.Exists && fileinfo.Length == item.Length)
                {
                    return(Downloader.CreateCompleted(item, path, item.Length));
                }

                Stream writer;

                if (!fileinfo.Exists || fileinfo.Length < item.Length)
                {
                    writer = new FileStream(
                        path,
                        FileMode.Append,
                        FileAccess.Write,
                        FileShare.ReadWrite,
                        4096,
                        FileOptions.Asynchronous | FileOptions.SequentialScan);
                    if (writer.Length > 0)
                    {
                        Log.Warn(
                            $"File was not totally downloaded before. Should be {item.Length} but was {writer.Length}: {item.Path} - {item.Id}");
                        downloader.Downloaded = writer.Length;
                    }
                }
                else
                {
                    writer = new FileStream(
                        path,
                        FileMode.Create,
                        FileAccess.Write,
                        FileShare.ReadWrite,
                        4096,
                        FileOptions.Asynchronous | FileOptions.SequentialScan);
                }

                downloader.Task = Task.Factory.StartNew(async() => await Download(item, writer, downloader), TaskCreationOptions.LongRunning);
                Downloaders.Add(item.Path, downloader);

                return(downloader);
            }
        }
예제 #2
0
        private async Task Download(FSItem item, Stream result, Downloader downloader)
        {
            try
            {
                Log.Trace($"Started download: {item.Name} - {item.Id}");
                var       start          = Stopwatch.StartNew();
                var       buf            = new byte[64 << 10];
                var       uncommitedSize = 0;
                const int commitSize     = 512 << 10;

                using (result)
                    using (var writer = new BufferedStream(result))
                    {
                        OnDownloadStarted?.Invoke(item);
                        while (writer.Length < item.Length)
                        {
                            var stream = await cloud.Files.Download(item.Id);

                            stream.Position = writer.Length;
                            int red;
                            do
                            {
                                red = await stream.ReadAsync(buf, 0, buf.Length);

                                if (writer.Length == 0)
                                {
                                    Log.Trace($"Got first part: {item.Name} - {item.Id} in {start.ElapsedMilliseconds}");
                                }

                                await writer.WriteAsync(buf, 0, red);

                                uncommitedSize += red;
                                if (uncommitedSize <= commitSize)
                                {
                                    continue;
                                }

                                uncommitedSize = 0;
                                await writer.FlushAsync();

                                downloader.Downloaded = writer.Length;
                            }while (red > 0);
                        }

                        await writer.FlushAsync();

                        downloader.Downloaded = writer.Length;
                    }

                Log.Trace($"Finished download: {item.Name} - {item.Id}");
                OnDownloaded?.Invoke(item);
                BoschHelper.Decrypt(downloader.Path);

                if (access.TryAdd(
                        item.Id,
                        new CacheEntry {
                    Id = item.Id, AccessTime = DateTime.UtcNow, Length = item.Length
                }))
                {
                    TotalSizeIncrease(item.Length);
                }

                if (TotalSize > CacheSize)
                {
                    var task = cleanSizeWorker.Run(TotalSize - CacheSize);
                }

                if (start.ElapsedMilliseconds > 29000)
                {
                    Log.Warn($"Downloading {item.Path} took: {start.ElapsedMilliseconds}");
                }
            }
            catch (Exception ex)
            {
                Log.ErrorTrace($"Download failed: {item.Name} - {item.Id}\r\n{ex}");
                await downloader.Failed();

                OnDownloadFailed?.Invoke(item);
            }
            finally
            {
                lock (DownloadersLock)
                {
                    Downloaders.Remove(item.Path);
                }
            }
        }