public CalculatedSegment[] GetSegments(int segmentCount, RemoteFileInfo remoteFileInfo) { long minSize = Settings.Default.MinSegmentSize; long segmentSize = remoteFileInfo.FileSize / (long)segmentCount; while (segmentCount > 1 && segmentSize < minSize) { segmentCount--; segmentSize = remoteFileInfo.FileSize / (long)segmentCount; } long startPosition = 0; List<CalculatedSegment> segments = new List<CalculatedSegment>(); for (int i = 0; i < segmentCount; i++) { if (segmentCount - 1 == i) { segments.Add(new CalculatedSegment(startPosition, remoteFileInfo.FileSize)); } else { segments.Add(new CalculatedSegment(startPosition, startPosition + (int)segmentSize)); } startPosition = segments[segments.Count - 1].EndPosition; } return segments.ToArray(); }
public RemoteFileInfo GetFileInfo(ResourceLocation rl, out Stream stream) { FtpWebRequest request; RemoteFileInfo result = new RemoteFileInfo(); result.AcceptRanges = true; stream = null; request = (FtpWebRequest)GetRequest(rl); request.Method = WebRequestMethods.Ftp.GetFileSize; FillCredentials(request, rl); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { result.FileSize = response.ContentLength; } request = (FtpWebRequest)GetRequest(rl); request.Method = WebRequestMethods.Ftp.GetDateTimestamp; FillCredentials(request, rl); using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()) { result.LastModified = response.LastModified; } return result; }
public virtual RemoteFileInfo GetFileInfo(ResourceLocation rl, out Stream stream) { HttpWebRequest request = (HttpWebRequest)GetRequest(rl); FillCredentials(request, rl); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); RemoteFileInfo result = new RemoteFileInfo(); result.MimeType = response.ContentType; result.LastModified = response.LastModified; result.FileSize = response.ContentLength; result.AcceptRanges = String.Compare(response.Headers["Accept-Ranges"], "bytes", true) == 0; stream = response.GetResponseStream(); return result; }
public Downloader( ResourceLocation rl, ResourceLocation[] mirrors, string localFile, List<Segment> segments, RemoteFileInfo remoteInfo, int requestedSegmentCount, DateTime createdDateTime) : this(rl, mirrors, localFile) { if (segments.Count > 0) { SetState(DownloaderState.Prepared); } else { SetState(DownloaderState.NeedToPrepare); } this.createdDateTime = createdDateTime; this.remoteFileInfo = remoteInfo; this.requestedSegmentCount = requestedSegmentCount; this.segments = segments; }
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); 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 RestartDownload() { int currentTry = 0; Stream stream; RemoteFileInfo newInfo; try { 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.MaxRetries) { SetState(DownloaderState.WaitingForReconnect); Thread.Sleep(TimeSpan.FromSeconds(Settings.Default.RetryDelay)); } else { return; } } }while (true); } finally { 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 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.MaxRetries) { SetState(DownloaderState.WaitingForReconnect); Thread.Sleep(TimeSpan.FromSeconds(Settings.Default.RetryDelay)); } else { SetState(DownloaderState.NeedToPrepare); return; } } }while (true); try { lastError = null; StartSegments(segmentCount, inputStream); } catch (ThreadAbortException) { throw; } catch (Exception ex) { lastError = ex; SetState(DownloaderState.EndedWithError); } }
private void RestartDownload() { int currentTry = 0; Stream stream; RemoteFileInfo newInfo; try { 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.MaxRetries) { SetState(DownloaderState.WaitingForReconnect); Thread.Sleep(TimeSpan.FromSeconds(Settings.Default.RetryDelay)); } else { return; } } } while (true); } finally { 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 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.MaxRetries) { SetState(DownloaderState.WaitingForReconnect); Thread.Sleep(TimeSpan.FromSeconds(Settings.Default.RetryDelay)); } else { SetState(DownloaderState.NeedToPrepare); return; } } } while (true); try { lastError = null; StartSegments(segmentCount, inputStream); } catch (ThreadAbortException) { throw; } catch (Exception ex) { lastError = ex; SetState(DownloaderState.EndedWithError); } }
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; }
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); }