(trunk libT) #3026 "Recent T doesn't honor weekend speed limit setting" -- fixed in trunk for 2.00

This commit is contained in:
Charles Kerr 2010-03-10 22:19:31 +00:00
parent 2b6b193a43
commit af3736dbd3
2 changed files with 57 additions and 71 deletions

View 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 );
tr_bitfieldClear( b );
next_begin = today_began_at + ( t->beginMinute * 60 );
if( next_begin <= now )
next_begin += SECONDS_PER_DAY;
for( day=0; day<7; ++day )
{
if( t->days & (1<<day) )
{
int i;
const time_t begin = t->beginMinute;
time_t end = t->endMinute;
next_end = today_began_at + ( t->endMinute * 60 );
if( next_end <= now )
next_end += SECONDS_PER_DAY;
if( end <= begin )
end += MINUTES_PER_DAY;
if( next_begin < next_end ) {
t->_nextChangeAt = next_begin;
t->_nextChangeValue = TRUE;
} else {
t->_nextChangeAt = next_end;
t->_nextChangeValue = FALSE;
}
/* 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( 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 tr_bool
testTurtleTime( const struct tr_turtle_info * t )
{
struct tm tm;
size_t minute_of_the_week;
const time_t now = tr_time( );
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 );
}
static void
turtleCheckClock( tr_session * session, struct tr_turtle_info * t, tr_bool byUser )
{
const time_t now = tr_time( );
const tr_bool hit = ( t->testedAt < t->_nextChangeAt ) && ( t->_nextChangeAt <= tr_time( ));
t->testedAt = now;
if( hit )
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 );

View 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 */