]> granicus.if.org Git - transmission/commitdiff
(trunk libT) #3026 "Recent T doesn't honor weekend speed limit setting" -- fixed...
authorCharles Kerr <charles@transmissionbt.com>
Wed, 10 Mar 2010 22:19:31 +0000 (22:19 +0000)
committerCharles Kerr <charles@transmissionbt.com>
Wed, 10 Mar 2010 22:19:31 +0000 (22:19 +0000)
libtransmission/session.c
libtransmission/session.h

index b61dd6e12f9f099ae7b8ced0f48e54f3d0d4ddd8..8f662b1f78073071b42ec4f0edc6611e7e2978e8 100644 (file)
@@ -1094,51 +1094,35 @@ updateBandwidth( tr_session * session, tr_direction dir )
     tr_bandwidthSetDesiredSpeed( session->bandwidth, dir, limit );
 }
 
+enum
+{
+    MINUTES_PER_HOUR = 60,
+    MINUTES_PER_DAY = MINUTES_PER_HOUR * 24,
+    MINUTES_PER_WEEK = MINUTES_PER_DAY * 7
+};
+
 static void
-turtleFindNextChange( struct tr_turtle_info * t )
+turtleUpdateTable( struct tr_turtle_info * t )
 {
     int day;
-    struct tm tm;
-    time_t today_began_at;
-    time_t next_begin;
-    time_t next_end;
-    const time_t now = tr_time( );
-    const int SECONDS_PER_DAY = 86400;
+    tr_bitfield * b = &t->minutes;
 
-    tr_localtime_r( &now, &tm );
-    tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
-    today_began_at = mktime( &tm );
-
-    next_begin = today_began_at + ( t->beginMinute * 60 );
-    if( next_begin <= now )
-        next_begin += SECONDS_PER_DAY;
-
-    next_end = today_began_at + ( t->endMinute * 60 );
-    if( next_end <= now )
-        next_end += SECONDS_PER_DAY;
-
-    if( next_begin < next_end ) {
-        t->_nextChangeAt = next_begin;
-        t->_nextChangeValue = TRUE;
-    } else {
-        t->_nextChangeAt = next_end;
-        t->_nextChangeValue = FALSE;
-    }
+    tr_bitfieldClear( b );
 
-    /* if the next change is today, look for today in t->days.
-       if the next change is tomorrow to turn limits OFF, look for today in t->days.
-       if the next change is tomorrow to turn limits ON, look for tomorrow in t->days. */
-    if( t->_nextChangeValue && (( t->_nextChangeAt >= today_began_at + SECONDS_PER_DAY )))
-        day = ( tm.tm_wday + 1 ) % 7;
-    else
-        day = tm.tm_wday;
-    t->_nextChangeAllowed = ( t->days & (1<<day) ) != 0;
-
-    if( t->isClockEnabled && t->_nextChangeAllowed ) {
-        char buf[128];
-        tr_localtime_r( &t->_nextChangeAt, &tm );
-        strftime( buf, sizeof( buf ), "%a %b %d %T %Y", &tm );
-        tr_inf( "Turtle clock updated: at %s we'll turn limits %s", buf, (t->_nextChangeValue?"on":"off") );
+    for( day=0; day<7; ++day )
+    {
+        if( t->days & (1<<day) )
+        {
+            int i;
+            const time_t begin = t->beginMinute;
+            time_t end = t->endMinute;
+
+            if( end <= begin )
+                end += MINUTES_PER_DAY;
+
+            for( i=begin; i<end; ++i )
+                tr_bitfieldAdd( b, (i+day*MINUTES_PER_DAY) % MINUTES_PER_WEEK );
+        }
     }
 }
 
@@ -1152,7 +1136,6 @@ altSpeedToggled( void * vsession )
 
     updateBandwidth( session, TR_UP );
     updateBandwidth( session, TR_DOWN );
-    turtleFindNextChange( t );
 
     if( t->callback != NULL )
         (*t->callback)( session, t->isEnabled, t->changedByUser, t->callbackUserData );
@@ -1174,25 +1157,37 @@ useAltSpeed( tr_session * s, struct tr_turtle_info * t, tr_bool enabled, tr_bool
     }
 }
 
-static void
-turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser )
+static tr_bool
+testTurtleTime( const struct tr_turtle_info * t )
 {
+    struct tm tm;
+    size_t minute_of_the_week;
     const time_t now = tr_time( );
-    const tr_bool hit = ( t->testedAt < t->_nextChangeAt ) && ( t->_nextChangeAt <= tr_time( ));
 
-    t->testedAt = now;
+    tr_localtime_r( &now, &tm );
+
+    minute_of_the_week = tm.tm_wday * MINUTES_PER_DAY
+                       + tm.tm_hour * MINUTES_PER_HOUR
+                       + tm.tm_min;
+
+    if( minute_of_the_week >= MINUTES_PER_WEEK ) /* leap minutes? */
+        minute_of_the_week = MINUTES_PER_WEEK - 1;
+
+    return tr_bitfieldHasFast( &t->minutes, minute_of_the_week );
+}
 
-    if( hit )
+static void
+turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser )
+{
+    if( t->isClockEnabled )
     {
-        const tr_bool enabled = t->_nextChangeValue;
+        const tr_bool hit = testTurtleTime( t );
 
-        if( t->isClockEnabled && t->_nextChangeAllowed )
+        if( hit != t->isEnabled )
         {
-            tr_inf( "Time to turn %s turtle mode!", (enabled?"on":"off") );
-            useAltSpeed( session, t, enabled, byUser );
+            tr_inf( "Time to turn %s turtle mode!", (hit?"on":"off") );
+            useAltSpeed( session, t, hit, byUser );
         }
-
-        turtleFindNextChange( t );
     }
 }
 
@@ -1202,12 +1197,14 @@ turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUse
 static void
 turtleBootstrap( tr_session * session, struct tr_turtle_info * turtle )
 {
-    turtleFindNextChange( turtle );
-
     turtle->changedByUser = FALSE;
 
+    tr_bitfieldConstruct( &turtle->minutes, MINUTES_PER_WEEK );
+
+    turtleUpdateTable( turtle );
+
     if( turtle->isClockEnabled )
-        turtle->isEnabled = !turtle->_nextChangeValue;
+        turtle->isEnabled = testTurtleTime( turtle );
 
     altSpeedToggled( session );
 }
@@ -1288,11 +1285,10 @@ userPokedTheClock( tr_session * s, struct tr_turtle_info * t )
 {
     tr_dbg( "Refreshing the turtle mode clock due to user changes" );
 
-    t->testedAt = 0;
-    turtleFindNextChange( t );
+    turtleUpdateTable( t );
 
-    if( t->isClockEnabled && t->_nextChangeAllowed )
-        useAltSpeed( s, t, !t->_nextChangeValue, TRUE );
+    if( t->isClockEnabled )
+        useAltSpeed( s, t, testTurtleTime( t ), TRUE );
 }
 
 void
@@ -1592,6 +1588,7 @@ tr_sessionClose( tr_session * session )
     /* free the session memory */
     tr_bencFree( &session->removedTorrents );
     tr_bandwidthFree( session->bandwidth );
+    tr_bitfieldDestruct( &session->turtle.minutes );
     tr_lockFree( session->lock );
     if( session->metainfoLookup ) {
         tr_bencFree( session->metainfoLookup );
index cb3d2c61a7b1559e65a799bd23359238486ef505..6b71c2a14e28a8564c82979f676096ca68fb4353 100644 (file)
@@ -28,6 +28,7 @@
 #endif
 
 #include "bencode.h"
+#include "bitfield.h"
 
 typedef enum { TR_NET_OK, TR_NET_ERROR, TR_NET_WAIT } tr_tristate_t;
 
@@ -82,19 +83,7 @@ struct tr_turtle_info
      * indicates whether the change came from the user or from the clock. */
     tr_bool changedByUser;
 
-    /* this is the next time the clock will set turtle mode */
-    time_t _nextChangeAt;
-
-    /* the clock will set turtle mode to this flag. */
-    tr_bool _nextChangeValue;
-
-    /* When clock mode is on, only toggle turtle mode if this is true.
-     * This flag is used to filter out changes that fall on days when
-     * clock mode is disabled. */
-    tr_bool _nextChangeAllowed;
-
-    /* The last time the clock tested to see if _nextChangeAt was reached */
-    time_t testedAt;
+    tr_bitfield minutes;
 };
 
 /** @brief handle to an active libtransmission session */