public Downloader Add(ResourceLocation rl, ResourceLocation[] mirrors, string localFile, List <Segment> segments, RemoteFileInfo remoteInfo, int requestedSegmentCount, bool autoStart, DateTime createdDateTime) { Downloader d = new Downloader(rl, mirrors, localFile, segments, remoteInfo, requestedSegmentCount, createdDateTime); Add(d, autoStart); return(d); }
private void RestartDownload() { int currentTry = 0; Stream stream; RemoteFileInfo newInfo; do { lastError = null; SetState(DownloaderState.Preparing); currentTry++; try { newInfo = defaultDownloadProvider.GetFileInfo(this.ResourceLocation, out stream); break; } catch (Exception ex) { lastError = ex; if (currentTry < Settings.Default.InitialMaxRetries) { SetState(DownloaderState.WaitingForReconnect); Thread.Sleep(TimeSpan.FromSeconds(Settings.Default.InitialRetryDelay)); } else { lastError = ex; SetState(DownloaderState.EndedWithError); return; } } }while (true); SetState(DownloaderState.Prepared); try { // check if the file changed on the server if (!newInfo.AcceptRanges || newInfo.LastModified > RemoteFileInfo.LastModified || newInfo.FileSize != RemoteFileInfo.FileSize) { this.remoteFileInfo = newInfo; StartSegments(this.RequestedSegments, stream); } else { if (stream != null) { stream.Dispose(); } RunSegments(); } } catch (ThreadAbortException) { throw; } catch (Exception ex) { lastError = ex; SetState(DownloaderState.EndedWithError); } }
private void SegmentThreadProc(object objSegment) { Segment segment = (Segment)objSegment; segment.LastError = null; try { if (segment.EndPosition > 0 && segment.StartPosition >= segment.EndPosition) { segment.State = SegmentState.Finished; // raise the event OnSegmentStoped(segment); return; } int buffSize = 8192; byte[] buffer = new byte[buffSize]; segment.State = SegmentState.Connecting; // raise the event OnSegmentStarting(segment); if (segment.InputStream == null) { // get the next URL (It can the the main url or some mirror) ResourceLocation location = this.MirrorSelector.GetNextResourceLocation(); // get the protocol provider for that mirror IProtocolProvider provider = location.BindProtocolProviderInstance(this); while (location != this.ResourceLocation) { Stream tempStream; // get the remote file info on mirror RemoteFileInfo tempRemoteInfo = provider.GetFileInfo(location, out tempStream); if (tempStream != null) { tempStream.Dispose(); } // check if the file on mirror is the same if (tempRemoteInfo.FileSize == remoteFileInfo.FileSize && tempRemoteInfo.AcceptRanges == remoteFileInfo.AcceptRanges) { // if yes, stop looking for the mirror break; } lock (mirrors) { // the file on the mirror is not the same, so remove from the mirror list mirrors.Remove(location); } // the file on the mirror is different // so get other mirror to use in the segment location = this.MirrorSelector.GetNextResourceLocation(); provider = location.BindProtocolProviderInstance(this); } // get the input stream from start position segment.InputStream = provider.CreateStream(location, segment.StartPosition, segment.EndPosition); // change the segment URL to the mirror URL segment.CurrentURL = location.URL; } else { // change the segment URL to the main URL segment.CurrentURL = this.resourceLocation.URL; } using (segment.InputStream) { // raise the event OnSegmentStarted(segment); // change the segment state segment.State = SegmentState.Downloading; segment.CurrentTry = 0; long readSize; do { // reads the buffer from input stream readSize = segment.InputStream.Read(buffer, 0, buffSize); // check if the segment has reached the end if (segment.EndPosition > 0 && segment.StartPosition + readSize > segment.EndPosition) { // adjust the 'readSize' to write only necessary bytes readSize = (segment.EndPosition - segment.StartPosition); if (readSize <= 0) { segment.StartPosition = segment.EndPosition; break; } } // locks the stream to avoid that other threads changes // the position of stream while this thread is writing into the stream lock (segment.OutputStream) { segment.OutputStream.Position = segment.StartPosition; segment.OutputStream.Write(buffer, 0, (int)readSize); } // increse the start position of the segment and also calculates the rate segment.IncreaseStartPosition(readSize); // check if the stream has reached its end if (segment.EndPosition > 0 && segment.StartPosition >= segment.EndPosition) { segment.StartPosition = segment.EndPosition; break; } // check if the user have requested to pause the download if (state == DownloaderState.Pausing) { segment.State = SegmentState.Paused; break; } //Thread.Sleep(1500); }while (readSize > 0); // Fix from code project: // http://www.codeproject.com/Messages/4730070/A-bug-fix.aspx if (segment.State == SegmentState.Downloading && segment.StartPosition != segment.EndPosition) { Debug.WriteLine("Probably stream read has been timeout."); throw new Exception("Probably stream read has been timeout."); } if (segment.State == SegmentState.Downloading) { segment.State = SegmentState.Finished; // try to create other segment, // spliting the missing bytes from one existing segment AddNewSegmentIfNeeded(); } } // raise the event OnSegmentStoped(segment); } catch (Exception ex) { // store the error information segment.State = SegmentState.Error; segment.LastError = ex; Debug.WriteLine(ex.ToString()); // raise the event OnSegmentFailed(segment); } finally { // clean up the segment segment.InputStream = null; } }
private void StartDownloadThreadProc(object objSegmentCount) { SetState(DownloaderState.Preparing); int segmentCount = Math.Min((int)objSegmentCount, Settings.Default.MaxSegments); Stream inputStream = null; int currentTry = 0; do { lastError = null; if (state == DownloaderState.Pausing) { SetState(DownloaderState.NeedToPrepare); return; } SetState(DownloaderState.Preparing); currentTry++; try { remoteFileInfo = defaultDownloadProvider.GetFileInfo(this.ResourceLocation, out inputStream); break; } catch (ThreadAbortException) { SetState(DownloaderState.NeedToPrepare); return; } catch (Exception ex) { lastError = ex; if (currentTry < Settings.Default.InitialMaxRetries) { SetState(DownloaderState.WaitingForReconnect); Thread.Sleep(TimeSpan.FromSeconds(Settings.Default.InitialRetryDelay)); } else { lastError = ex; SetState(DownloaderState.EndedWithError); return; } } }while (true); try { lastError = null; StartSegments(segmentCount, inputStream); } catch (ThreadAbortException) { throw; } catch (Exception ex) { lastError = ex; SetState(DownloaderState.EndedWithError); } }