public bool TryGetSlot(long slotno, out MemoryStreamSlot mem) { mem = null; if (slotno < 0 || slotno > lastslot) { return(false); } TouchSlot(slotno); return(slot.TryGetValue(slotno, out mem)); }
public void StartDownload(long slotno, ConcurrentDictionary <long, MemoryStreamSlot> slot, BlockingCollection <KeyValuePair <long, MemoryStreamSlot> > SlotBuffer) { int timeout = (int)(1000 * (double)AmazonDriveStreamConfig.shortbuflen / (Config.FFmodule_TransferLimit * 1024)); long start = slotno * AmazonDriveStreamConfig.slotsize; long length = AmazonDriveStreamConfig.slotsize; if (start + length > (targetItem.OrignalLength ?? 0)) { length = (targetItem.OrignalLength ?? 0) - start; } if (length <= 0) { return; } readslot = slotno; done = false; 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)); Drive.downloadFile(targetItem, start, ct: cts_1.Token) .ContinueWith(task => { if (!task.Wait(timeout, cts_1.Token)) { cts_1.Token.ThrowIfCancellationRequested(); //Config.Log.LogOut(string.Format("AmazonDriveStream : wait timeout slot {0}", slotno)); throw new IOException("transfer timeout0"); } using (var stream = task.Result) { 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(); } readslot = slotno; byte[] buffer = new byte[(length > AmazonDriveStreamConfig.shortbuflen) ? AmazonDriveStreamConfig.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) { if (SlotBuffer.TryAdd(new KeyValuePair <long, MemoryStreamSlot>(slotno, newslot), 500, cts_1.Token)) { break; } } if (!leadThread) { if (slot.GetOrAdd(slotno, newslot) != newslot) { cts.Cancel(); } } } else { if (slot.GetOrAdd(slotno, newslot) != newslot) { cts.Cancel(); } } cts_1.Token.ThrowIfCancellationRequested(); start = ++slotno * AmazonDriveStreamConfig.slotsize; length = AmazonDriveStreamConfig.slotsize; if (start + length > (targetItem.OrignalLength ?? 0)) { length = (targetItem.OrignalLength ?? 0) - start; } if (length <= 0) { return; } } } }, cts_1.Token, TaskContinuationOptions.LongRunning, TaskScheduler.Default) .ContinueWith(task => { leadThread = false; if (task.IsFaulted) { var e = task.Exception; e.Flatten().Handle(ex => { Config.Log.LogOut(string.Format("AmazonDriveStream : ERROR {0}", ex.Message)); return(true); }); e.Handle(ex => { return(true); }); if (++failcount < 10) { Config.Log.LogOut(string.Format("AmazonDriveStream : ERROR restart to download {0} - ", slotno)); cancel_cts.Cancel(true); StartDownload(slotno, slot, SlotBuffer); } else { Config.Log.LogOut(string.Format("AmazonDriveStream : ERROR too much fail stop. {0}", slotno)); done = true; } } else if (task.IsCanceled) { //Config.Log.LogOut(string.Format("AmazonDriveStream : cancel to download {0}", slotno)); done = true; } else if (task.IsCompleted) { //Config.Log.LogOut(string.Format("AmazonDriveStream : finish download {0}", slotno)); done = true; } cancel_cts.Cancel(true); }); }