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();
        }
예제 #2
0
        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;
        }
예제 #3
0
        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;
        }
예제 #4
0
        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;
        }
예제 #5
0
        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;
            }
        }
예제 #6
0
        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);
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
        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);
            }
        }
예제 #10
0
        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;
        }
예제 #11
0
        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);
        }