Ticket #529: eta.diff

File eta.diff, 4.6 KB (added by MSN_Exploder, 13 years ago)
  • libtransmission/torrent.c

     
    3030#include <limits.h> /* INT_MAX */
    3131#include <string.h> /* memcmp */
    3232#include <stdlib.h> /* qsort */
     33#include <math.h> /* ETA */
    3334
    3435#include "transmission.h"
    3536#include "bencode.h"
     
    697698    return TR_STATUS_SEED;
    698699}
    699700
     701static int estimateWINX( float sampleSum, int count, uint64_t bytesLeft )
     702{
     703   
     704    if ( sampleSum > 0 && count > 0 )
     705        return (int) floor((double) bytesLeft / ((double) sampleSum / (double) count));
     706   
     707    return 0;
     708}
     709
     710static int estimateGASA( uint64_t downloaded, uint64_t bytesLeft, double runningTime )
     711{
     712    double avgSpeed;
     713   
     714    if (runningTime > 0 && downloaded > 0)
     715    {
     716        avgSpeed = (double) downloaded / runningTime;
     717        return (int) floor((double) bytesLeft / avgSpeed);
     718    }
     719   
     720    return 0;
     721}
     722
     723static int estimateMAVG( int mCount, float sampleSum, float first, float last, uint64_t bytesLeft )
     724{
     725    static int mLastAvg = 0;
     726    double lavg;
     727   
     728    if (mCount > 0)
     729    {
     730        if (mLastAvg == 0)
     731            lavg = (int) sampleSum / mCount;
     732        else
     733            lavg = mLastAvg - ((double) first / (double) mCount) + ((double) last / (double) mCount);
     734       
     735        mLastAvg = (int) floor(lavg);
     736       
     737        if (lavg > 0)
     738            return (int) floor((double) bytesLeft / ((lavg + (sampleSum / mCount)) / 2));
     739       
     740        return 0;
     741    }
     742   
     743    return 0;
     744}
     745
     746/**
     747 * more acurate ETA
     748 * shamelessly adopted from KTorrent
     749 */
     750
     751static int
     752calculateETA ( uint64_t leftUntilDone,
     753              uint64_t desiredAvailable,
     754              float rateDownload,
     755              float perc,
     756              uint64_t downloaded,
     757              uint64_t bytesLeft,
     758              time_t startDate )
     759{
     760    int i;
     761    int eta;
     762
     763#define MSIZE 20
     764   
     765    static int mStart = 0;
     766    static int mEnd = -1;
     767    static int mCount = 0;
     768    const static int mSize = MSIZE;
     769    static float mSamples[MSIZE];
     770    static double mPerc = -1;
     771   
     772    float sampleSum;
     773    int percentage;
     774    double delta;
     775    double runningTime;
     776   
     777    if (mCount < mSize)
     778    {
     779        /* it's not full yet */
     780        mSamples[(++mEnd) % mSize ] = rateDownload;
     781        mCount++;
     782    }
     783    else
     784    {
     785        /* since it's full I'll just replace the oldest value with new one and update all variables. */
     786        mEnd = (++mEnd) % mSize;
     787        mStart = (++mStart) % mSize;
     788        mSamples[mEnd] = rateDownload;
     789    }
     790   
     791    percentage = (int)(perc) * 100;
     792   
     793    /* calculate percentage increasement */
     794    delta = 1 - 1 / (perc / mPerc);
     795   
     796    /* calculate sampleSum */
     797    for (i = 0; i < mCount; ++i) {
     798        sampleSum += mSamples[i];
     799    }
     800   
     801    /* calculate running time */
     802    runningTime = difftime(time(NULL), startDate);
     803   
     804    /* remember last percentage */
     805    mPerc = perc;
     806   
     807    /* <100KB */
     808    if (downloaded < 1024*1024*100 && mSamples[mEnd] > 0)
     809    {
     810        eta = estimateGASA(downloaded, bytesLeft, runningTime);
     811        return eta;
     812    }
     813    /* 1% of a very large torrent could be hundreds of MB so limit it to 10MB */
     814    if (percentage >= 99 && mSamples[mEnd] > 0 && bytesLeft <= 10*1024*1024*1024LL)
     815    {
     816        if (mCount < mSize)
     817        {
     818            eta = estimateWINX(sampleSum, mCount, bytesLeft);
     819           
     820            if (eta == 0)
     821                eta = estimateGASA(downloaded, bytesLeft, runningTime);
     822           
     823            return eta;
     824        }
     825        else
     826        {
     827            eta = 0;
     828           
     829            if (delta > 0.0001)
     830                eta = estimateMAVG(mCount, sampleSum, mSamples[mStart], mSamples[mEnd], bytesLeft);
     831           
     832            if (eta == 0)
     833                eta = estimateGASA(downloaded, bytesLeft, runningTime);
     834        }
     835       
     836        return eta;
     837    }
     838   
     839    eta = estimateGASA(downloaded, bytesLeft, runningTime);
     840   
     841    return eta;
     842}
     843
    700844const tr_stat *
    701845tr_torrentStat( tr_torrent * tor )
    702846{
     
    791935    else if( s->rateDownload < 0.1 )
    792936        s->eta = TR_ETA_UNKNOWN;
    793937    else
    794         s->eta = s->leftUntilDone / s->rateDownload / 1024.0;
     938        s->eta = calculateETA( s->leftUntilDone, s->desiredAvailable, s->rateDownload,
     939                             s->percentDone, s->downloadedEver, s->leftUntilDone, s->startDate);
    795940
    796941    s->ratio = tr_getRatio( s->uploadedEver,
    797942                            s->downloadedEver ? s->downloadedEver : s->haveValid );