Exemplo n.º 1
0
        public void StartDownload(long slotno, ConcurrentDictionary <long, MemoryStreamSlot> slot, BlockingCollection <KeyValuePair <long, MemoryStreamSlot> > SlotBuffer)
        {
            int  timeout = (int)(1000 * (double)SeekableStreamConfig.shortbuflen / (128 * 1024));
            long start   = slotno * SeekableStreamConfig.slotsize;
            long length  = SeekableStreamConfig.slotsize;

            if (start + length > (targetItem.Size ?? 0))
            {
                length = (targetItem.Size ?? 0) - start;
            }
            if (length <= 0)
            {
                return;
            }
            done     = false;
            readslot = slotno;
            //CancellationTokenSource cancel_cts = new CancellationTokenSource();
            //var cts_1 = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, cancel_cts.Token);

            //Config.Log.LogOut(string.Format("AmazonDriveStream : start to download slot {0} offset {1:#,0} - ", slotno, start));
            var cjob = new JobForToken(cts.Token);

            djob?.Cancel();
            djob = targetItem.DownloadItemRawJob(start, hidden: true, prevJob: cjob as Job);

            var job = JobControler.CreateNewJob <Stream>(JobClass.RemoteDownload, depends: djob);

            job.DisplayName = "Download slot :" + slotno + " item : " + targetItem.Name;
            job.ProgressStr = "wait for prepare...";
            job.ForceHidden = true;
            job.DoAlways    = true;
            var cts_1 = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, job.Ct);

            JobControler.Run <Stream>(job, (j) =>
            {
                var result = j.ResultOfDepend[0];
                if (result == null || !result.TryGetTarget(out var stream))
                {
                    return;
                }
                using (stream)
                {
                    if ((j as Job <Stream>).IsError)
                    {
                        (j as Job <Stream>).Cancel();
                        StartDownload(slotno, slot, SlotBuffer);
                        return;
                    }
                    if ((j as Job <Stream>).IsCanceled)
                    {
                        done = true;
                        return;
                    }

                    while (slotno <= lastslot)
                    {
                        //Config.Log.LogOut(string.Format("AmazonDriveStream : download slot {0}", slotno));
                        cts_1.Token.ThrowIfCancellationRequested();

                        // すでに取得済みかチェック
                        MemoryStreamSlot o;
                        if (slot.TryGetValue(slotno, out o))
                        {
                            cts.Cancel();
                            (j as Job <Stream>).Cancel();
                        }

                        readslot      = slotno;
                        byte[] buffer = new byte[(length > SeekableStreamConfig.shortbuflen) ? SeekableStreamConfig.shortbuflen : length];
                        var mem       = new MemoryStream();
                        var stime     = DateTime.Now;
                        int loopdelay = 0;
                        while (length > 0)
                        {
                            cts_1.Token.ThrowIfCancellationRequested();
                            var tret = stream.ReadAsync(buffer, 0, buffer.Length).ContinueWith(task2 =>
                            {
                                if (!task2.Wait(timeout, cts_1.Token))
                                {
                                    cts_1.Token.ThrowIfCancellationRequested();
                                    //Config.Log.LogOut(string.Format("AmazonDriveStream : wait timeout slot {0}", slotno));
                                    throw new IOException("transfer timeout1");
                                }
                                var ret = task2.Result;
                                mem.Write(buffer, 0, ret);
                                length    -= ret;
                                loopdelay += 5;
                                if ((DateTime.Now - stime).TotalMilliseconds > timeout + loopdelay)
                                {
                                    //Config.Log.LogOut(string.Format("AmazonDriveStream : transfer timeout slot {0}", slotno));
                                    throw new IOException("transfer timeout2");
                                }
                                if (buffer.Length > length)
                                {
                                    buffer = new byte[length];
                                }
                            }, cts_1.Token, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnCanceled, TaskScheduler.Default)
                                       .Wait(timeout, cts_1.Token);
                            if (!tret)
                            {
                                //Config.Log.LogOut(string.Format("AmazonDriveStream : wait2 timeout slot {0}", slotno));
                                throw new IOException("transfer timeout3");
                            }
                        }
                        cts_1.Token.ThrowIfCancellationRequested();
                        var newslot = new MemoryStreamSlot(mem, start);
                        if (leadThread)
                        {
                            while (leadThread)
                            {
                                cts_1.Token.ThrowIfCancellationRequested();
                                if (SlotBuffer.TryAdd(new KeyValuePair <long, MemoryStreamSlot>(slotno, newslot), 500, cts_1.Token))
                                {
                                    break;
                                }
                            }
                            if (!leadThread)
                            {
                                cts_1.Token.ThrowIfCancellationRequested();
                                if (slot.GetOrAdd(slotno, newslot) != newslot)
                                {
                                    cts.Cancel();
                                    (j as Job <Stream>).Cancel();
                                }
                            }
                        }
                        else
                        {
                            if (slot.GetOrAdd(slotno, newslot) != newslot)
                            {
                                cts.Cancel();
                                (j as Job <Stream>).Cancel();
                            }
                        }
                        cts_1.Token.ThrowIfCancellationRequested();

                        start  = ++slotno * SeekableStreamConfig.slotsize;
                        length = SeekableStreamConfig.slotsize;
                        if (start + length > (targetItem.Size ?? 0))
                        {
                            length = (targetItem.Size ?? 0) - start;
                        }
                        if (length <= 0)
                        {
                            return;
                        }
                    }
                }
            });