Changeset 10593


Ignore:
Timestamp:
May 1, 2010, 1:40:42 PM (11 years ago)
Author:
charles
Message:

(1.9x libT) backport r10352 and r10366 for #3026 "Speed Limit mode not honoring limits on other days"

Location:
branches/1.9x/libtransmission
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/1.9x/libtransmission/session.c

    r10568 r10593  
    521521}
    522522
    523 static void turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser );
     523static void turtleCheckClock( tr_session * s, struct tr_turtle_info * t );
    524524
    525525static void
     
    545545    /* tr_session things to do once per second */
    546546    tr_timeUpdate( tv.tv_sec );
    547     turtleCheckClock( session, &session->turtle, FALSE );
     547    if( session->turtle.isClockEnabled )
     548        turtleCheckClock( session, &session->turtle );
    548549}
    549550
     
    10981099}
    10991100
    1100 static void
    1101 turtleFindNextChange( struct tr_turtle_info * t )
     1101enum
     1102{
     1103    MINUTES_PER_HOUR = 60,
     1104    MINUTES_PER_DAY = MINUTES_PER_HOUR * 24,
     1105    MINUTES_PER_WEEK = MINUTES_PER_DAY * 7
     1106};
     1107
     1108static void
     1109turtleUpdateTable( struct tr_turtle_info * t )
    11021110{
    11031111    int day;
    1104     struct tm tm;
    1105     time_t today_began_at;
    1106     time_t next_begin;
    1107     time_t next_end;
    1108     const time_t now = tr_time( );
    1109     const int SECONDS_PER_DAY = 86400;
    1110 
    1111     tr_localtime_r( &now, &tm );
    1112     tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
    1113     today_began_at = mktime( &tm );
    1114 
    1115     next_begin = today_began_at + ( t->beginMinute * 60 );
    1116     if( next_begin <= now )
    1117         next_begin += SECONDS_PER_DAY;
    1118 
    1119     next_end = today_began_at + ( t->endMinute * 60 );
    1120     if( next_end <= now )
    1121         next_end += SECONDS_PER_DAY;
    1122 
    1123     if( next_begin < next_end ) {
    1124         t->_nextChangeAt = next_begin;
    1125         t->_nextChangeValue = TRUE;
    1126     } else {
    1127         t->_nextChangeAt = next_end;
    1128         t->_nextChangeValue = FALSE;
    1129     }
    1130 
    1131     /* if the next change is today, look for today in t->days.
    1132        if the next change is tomorrow to turn limits OFF, look for today in t->days.
    1133        if the next change is tomorrow to turn limits ON, look for tomorrow in t->days. */
    1134     if( t->_nextChangeValue && (( t->_nextChangeAt >= today_began_at + SECONDS_PER_DAY )))
    1135         day = ( tm.tm_wday + 1 ) % 7;
    1136     else
    1137         day = tm.tm_wday;
    1138     t->_nextChangeAllowed = ( t->days & (1<<day) ) != 0;
    1139 
    1140     if( t->isClockEnabled && t->_nextChangeAllowed ) {
    1141         char buf[128];
    1142         tr_localtime_r( &t->_nextChangeAt, &tm );
    1143         strftime( buf, sizeof( buf ), "%a %b %d %T %Y", &tm );
    1144         tr_inf( "Turtle clock updated: at %s we'll turn limits %s", buf, (t->_nextChangeValue?"on":"off") );
     1112    tr_bitfield * b = &t->minutes;
     1113
     1114    tr_bitfieldClear( b );
     1115
     1116    for( day=0; day<7; ++day )
     1117    {
     1118        if( t->days & (1<<day) )
     1119        {
     1120            int i;
     1121            const time_t begin = t->beginMinute;
     1122            time_t end = t->endMinute;
     1123
     1124            if( end <= begin )
     1125                end += MINUTES_PER_DAY;
     1126
     1127            for( i=begin; i<end; ++i )
     1128                tr_bitfieldAdd( b, (i+day*MINUTES_PER_DAY) % MINUTES_PER_WEEK );
     1129        }
    11451130    }
    11461131}
     
    11561141    updateBandwidth( session, TR_UP );
    11571142    updateBandwidth( session, TR_DOWN );
    1158     turtleFindNextChange( t );
    11591143
    11601144    if( t->callback != NULL )
     
    11631147
    11641148static void
    1165 useAltSpeed( tr_session * s, struct tr_turtle_info * t, tr_bool enabled, tr_bool byUser )
     1149useAltSpeed( tr_session * s, struct tr_turtle_info * t,
     1150             tr_bool enabled, tr_bool byUser )
    11661151{
    11671152    assert( tr_isSession( s ) );
     
    11781163}
    11791164
    1180 static void
    1181 turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser )
    1182 {
     1165/**
     1166 * @param enabled whether turtle should be on/off according to the scheduler
     1167 * @param changed whether that's different from the previous minute
     1168 */
     1169static void
     1170testTurtleTime( const struct tr_turtle_info * t,
     1171                tr_bool * enabled,
     1172                tr_bool * changed )
     1173{
     1174    tr_bool e;
     1175    struct tm tm;
     1176    size_t minute_of_the_week;
    11831177    const time_t now = tr_time( );
    1184     const tr_bool hit = ( t->testedAt < t->_nextChangeAt ) && ( t->_nextChangeAt <= tr_time( ));
    1185 
    1186     t->testedAt = now;
    1187 
    1188     if( hit )
    1189     {
    1190         const tr_bool enabled = t->_nextChangeValue;
    1191 
    1192         if( t->isClockEnabled && t->_nextChangeAllowed )
    1193         {
    1194             tr_inf( "Time to turn %s turtle mode!", (enabled?"on":"off") );
    1195             useAltSpeed( session, t, enabled, byUser );
    1196         }
    1197 
    1198         turtleFindNextChange( t );
     1178
     1179    tr_localtime_r( &now, &tm );
     1180
     1181    minute_of_the_week = tm.tm_wday * MINUTES_PER_DAY
     1182                       + tm.tm_hour * MINUTES_PER_HOUR
     1183                       + tm.tm_min;
     1184    if( minute_of_the_week >= MINUTES_PER_WEEK ) /* leap minutes? */
     1185        minute_of_the_week = MINUTES_PER_WEEK - 1;
     1186
     1187    e = tr_bitfieldHasFast( &t->minutes, minute_of_the_week );
     1188    if( enabled != NULL )
     1189        *enabled = e;
     1190
     1191    if( changed != NULL )
     1192    {
     1193        const size_t prev = minute_of_the_week > 0 ? minute_of_the_week - 1
     1194                                                   : MINUTES_PER_WEEK - 1;
     1195        *changed = e != tr_bitfieldHasFast( &t->minutes, prev );
     1196    }
     1197}
     1198
     1199static void
     1200turtleCheckClock( tr_session * s, struct tr_turtle_info * t )
     1201{
     1202    tr_bool enabled;
     1203    tr_bool changed;
     1204
     1205    assert( t->isClockEnabled );
     1206
     1207    testTurtleTime( t, &enabled, &changed );
     1208
     1209    if( changed )
     1210    {
     1211        tr_inf( "Time to turn %s turtle mode!", (enabled?"on":"off") );
     1212        useAltSpeed( s, t, enabled, FALSE );
    11991213    }
    12001214}
     
    12061220turtleBootstrap( tr_session * session, struct tr_turtle_info * turtle )
    12071221{
    1208     turtleFindNextChange( turtle );
    1209 
    12101222    turtle->changedByUser = FALSE;
    12111223
     1224    tr_bitfieldConstruct( &turtle->minutes, MINUTES_PER_WEEK );
     1225
     1226    turtleUpdateTable( turtle );
     1227
    12121228    if( turtle->isClockEnabled )
    1213         turtle->isEnabled = !turtle->_nextChangeValue;
     1229        testTurtleTime( turtle, &turtle->isEnabled, NULL );
    12141230
    12151231    altSpeedToggled( session );
     
    12921308    tr_dbg( "Refreshing the turtle mode clock due to user changes" );
    12931309
    1294     t->testedAt = 0;
    1295     turtleFindNextChange( t );
    1296 
    1297     if( t->isClockEnabled && t->_nextChangeAllowed )
    1298         useAltSpeed( s, t, !t->_nextChangeValue, TRUE );
     1310    turtleUpdateTable( t );
     1311
     1312    if( t->isClockEnabled )
     1313    {
     1314        tr_bool enabled, changed;
     1315        testTurtleTime( t, &enabled, &changed );
     1316        useAltSpeed( s, t, enabled, TRUE );
     1317    }
    12991318}
    13001319
     
    15961615    tr_bencFree( &session->removedTorrents );
    15971616    tr_bandwidthFree( session->bandwidth );
     1617    tr_bitfieldDestruct( &session->turtle.minutes );
    15981618    tr_lockFree( session->lock );
    15991619    if( session->metainfoLookup ) {
  • branches/1.9x/libtransmission/session.h

    r10276 r10593  
    2929
    3030#include "bencode.h"
     31#include "bitfield.h"
    3132
    3233typedef enum { TR_NET_OK, TR_NET_ERROR, TR_NET_WAIT } tr_tristate_t;
     
    4243struct tr_fdInfo;
    4344
    44 /**
    45  * How clock mode works:
    46  *
    47  * ._nextChangeAt, ._nextChangeValue and ._nextChangeAllowed are private fields
    48  * that are derived from .days, .beginMinute, .endMinute and the current time.
    49  * They're rebuilt when either (a) the user changes the clock settings or
    50  * (b) when the time at ._nextChangeAt is reached.
    51  *
    52  * When ._nextChangeAt is reached, if .isClockEnabled and ._nextChangeAllowed
    53  * are both true, then turtle mode's flag is set to ._nextChangeValue.
    54  */
    5545struct tr_turtle_info
    5646{
     
    8373    tr_bool changedByUser;
    8474
    85     /* this is the next time the clock will set turtle mode */
    86     time_t _nextChangeAt;
    87 
    88     /* the clock will set turtle mode to this flag. */
    89     tr_bool _nextChangeValue;
    90 
    91     /* When clock mode is on, only toggle turtle mode if this is true.
    92      * This flag is used to filter out changes that fall on days when
    93      * clock mode is disabled. */
    94     tr_bool _nextChangeAllowed;
    95 
    96     /* The last time the clock tested to see if _nextChangeAt was reached */
    97     time_t testedAt;
     75    /* bitfield of all the minutes in a week.
     76     * Each bit's value indicates whether the scheduler wants turtle
     77     * limits on or off at that given minute in the week. */
     78    tr_bitfield minutes;
    9879};
    9980
Note: See TracChangeset for help on using the changeset viewer.