Changeset 7888


Ignore:
Timestamp:
Feb 13, 2009, 6:23:56 PM (12 years ago)
Author:
charles
Message:

(trunk) #1787: add support for seeding ratio limiting in libtransmission

Location:
trunk
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/daemon/remote.c

    r7865 r7888  
    8686    { 931, "global-peers",         "Set the global maximum number of peers", "gpr", 1, "<max>" },
    8787    { 'R', "remove-and-delete",    "Remove the current torrent(s) and delete local data", NULL, 0, NULL },
     88    { 950, "seedratio",            "Let the current torrent(s) seed until a specific ratio", "sr", 1, "ratio" },
     89    { 951, "seedratio-default",    "Let the current torrent(s) use the global seedratio settings", "srd", 0, NULL },
     90    { 952, "no-seedratio",         "Let the current torrent(s) seed regardless of ratio", "SR", 0, NULL },
     91    { 953, "global-seedratio",     "All torrents, unless overridden by a per-torrent setting, should seed until a specific ratio", "gsr", 1, "ratio" },
     92    { 954, "no-global-seedratio",  "All torrents, unless overridden by a per-torrent setting, should seed regardless of ratio", "GSR", 0, NULL },
    8893    { 's', "start",                "Start the current torrent(s)", "s",  0, NULL },
    8994    { 'S', "stop",                 "Stop the current torrent(s)", "S",  0, NULL },
     
    534539                break;
    535540
     541            case 950:
     542                tr_bencDictAddStr( &top, "method", "torrent-set" );
     543                tr_bencDictAddDouble( args, "ratio-limit", atof(optarg) );
     544                tr_bencDictAddInt( args, "ratio-limit-mode", TR_RATIOLIMIT_SINGLE );
     545                addIdArg( args, id );
     546                break;
     547
     548            case 951:
     549                tr_bencDictAddStr( &top, "method", "torrent-set" );
     550                tr_bencDictAddInt( args, "ratio-limit-mode", TR_RATIOLIMIT_GLOBAL );
     551                addIdArg( args, id );
     552                break;
     553
     554            case 952:
     555                tr_bencDictAddStr( &top, "method", "torrent-set" );
     556                tr_bencDictAddInt( args, "ratio-limit-mode", TR_RATIOLIMIT_UNLIMITED );
     557                addIdArg( args, id );
     558                break;
     559
     560            case 953:
     561                tr_bencDictAddStr( &top, "method", "session-set" );
     562                tr_bencDictAddDouble( args, "ratio-limit", atof(optarg) );
     563                tr_bencDictAddInt( args, "ratio-limit-enabled", 1 );
     564                break;
     565
     566            case 954:
     567                tr_bencDictAddStr( &top, "method", "session-set" );
     568                tr_bencDictAddInt( args, "ratio-limit-enabled", 0 );
     569                break;
     570
    536571            case TR_OPT_ERR:
    537572                fprintf( stderr, "invalid option\n" );
  • trunk/daemon/transmission-remote.1

    r7865 r7888  
    2020.Op Fl gpr Ar peers
    2121.Op Fl G Ar files
     22.Op Fl gsr Ar ratio
     23.Op Fl GSR
    2224.Op Fl h
    2325.Op Fl i
     
    3436.Op Fl R
    3537.Op Fl s | S
     38.Op Fl sr Ar ratio
     39.Op Fl SR
     40.Op Fl srd
    3641.Op Fl si
    3742.Op Fl t Ar all | Ar id | Ar hash
     
    9499Mark file(s) for not downloading.
    95100
     101.It Fl gsr Fl -global-seedratio Ar ratio
     102All torrents, unless overridden by a per-torrent setting, should seed until a specific
     103.Ar ratio
     104
     105.It Fl GSR Fl -no-global-seedratio
     106All torrents, unless overridden by a per-torrent setting, should seed regardless of ratio
     107
    96108.It Fl h Fl -help
    97109Print command-line option descriptions.
     
    155167.It Fl -remove-and-delete
    156168Remove the current torrent(s) and delete their downloaded data.
     169
     170.It Fl sr Fl -seedratio Ar ratio
     171Let the current torrent(s) seed until a specific
     172.Ar ratio
     173
     174.It Fl SR Fl -no-seedratio
     175Let the current torrent(s) seed regardless of ratio
     176
     177.It Fl srd Fl -seedratio-default
     178Let the current torrent(s) use the global seedratio settings
    157179
    158180.It Fl s Fl -start
  • trunk/gtk/conf.c

    r7390 r7888  
    201201}
    202202
     203double
     204pref_double_get( const char * key )
     205{
     206    double d = 0.0;
     207
     208    tr_bencDictFindDouble( getPrefs( ), key, &d );
     209    return d;
     210}
     211
     212void
     213pref_double_set( const char * key,
     214                 double       value )
     215{
     216    tr_bencDictAddDouble( getPrefs( ), key, value );
     217}
     218
     219void
     220pref_double_set_default( const char * key,
     221                         double       value )
     222{
     223    if ( !tr_bencDictFind( getPrefs( ), key ) )
     224         pref_double_set( key, value );
     225}
     226
    203227/***
    204228****
  • trunk/gtk/conf.h

    r7708 r7888  
    3232void             pref_int_set           ( const char * key, int64_t value );
    3333void             pref_int_set_default   ( const char * key, int64_t value );
     34
     35double           pref_double_get        ( const char * key );
     36void             pref_double_set        ( const char * key, double value );
     37void             pref_double_set_default( const char * key, double value );
    3438
    3539gboolean         pref_flag_get          ( const char * key );
  • trunk/gtk/details.c

    r7686 r7888  
    3131
    3232#define UPDATE_INTERVAL_SECONDS 2
     33typedef struct
     34{
     35    gpointer    gtor;
     36    TrCore    * core;
     37    guint       handler;
     38} ResponseData;
     39
    3340
    3441/****
     
    11711178}
    11721179
     1180#define RATIO_MODE_KEY "ratio-mode"
     1181
     1182static void
     1183ratio_mode_changed_cb( GtkToggleButton * tb, gpointer gtor )
     1184{
     1185    if( gtk_toggle_button_get_active( tb ) )
     1186    {
     1187        tr_torrent * tor = tr_torrent_handle( gtor );
     1188        const int mode = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( tb ), RATIO_MODE_KEY ) );
     1189        tr_torrentSetRatioMode( tor, mode );
     1190    }
     1191}
     1192
    11731193static void
    11741194sensitize_from_check_cb( GtkToggleButton *toggle,
     
    12051225
    12061226static void
     1227ratio_spun_cb( GtkSpinButton *spin,
     1228               gpointer       gtor )
     1229{
     1230    tr_torrent * tor = tr_torrent_handle ( gtor );
     1231    float        ratio = gtk_spin_button_get_value ( spin );
     1232
     1233    tr_torrentSetRatioLimit( tor, ratio );
     1234}
     1235
     1236static void
    12071237max_peers_spun_cb( GtkSpinButton * spin,
    12081238                   gpointer        gtor )
     
    12131243}
    12141244
     1245static char*
     1246get_global_ratio_radiobutton_string( void )
     1247{
     1248    char * s;
     1249    const gboolean b = pref_flag_get( TR_PREFS_KEY_RATIO_ENABLED );
     1250    const double d = pref_double_get( TR_PREFS_KEY_RATIO );
     1251
     1252    if( b )
     1253        s = g_strdup_printf( _( "Use _Global setting  (currently: stop seeding when a torrent's ratio reaches %.2f)" ), d );
     1254    else
     1255        s = g_strdup( _( "Use _Global setting  (currently: seed regardless of ratio)" ) );
     1256
     1257    return s;
     1258}
     1259
     1260static void
     1261prefsChanged( TrCore * core UNUSED, const char *  key, gpointer rb )
     1262{
     1263    if( !strcmp( key, TR_PREFS_KEY_RATIO_ENABLED ) || !strcmp( key, TR_PREFS_KEY_RATIO ) )
     1264    {
     1265        char * s = get_global_ratio_radiobutton_string( );
     1266        gtk_button_set_label( GTK_BUTTON( rb ), s );
     1267        g_free( s );
     1268    }
     1269}
     1270
    12151271static GtkWidget*
    1216 options_page_new( TrTorrent * gtor )
     1272options_page_new( ResponseData * data )
    12171273{
    12181274    uint16_t     maxConnectedPeers;
    12191275    int          i, row;
     1276    double       d;
    12201277    gboolean     b;
    1221     GtkWidget *  t, *w, *tb;
     1278    char       * s;
     1279    GSList     * group;
     1280    GtkWidget  * t, *w, *tb, *h;
     1281    tr_ratiolimit mode;
     1282    TrCore     * core = data->core;
     1283    TrTorrent  * gtor = data->gtor;
    12221284    tr_torrent * tor = tr_torrent_handle ( gtor );
    12231285
     
    12651327
    12661328    hig_workarea_add_section_divider ( t, &row );
     1329    hig_workarea_add_section_title ( t, &row, _( "Seed-Until Ratio" ) );
     1330
     1331
     1332        group = NULL;
     1333        mode = tr_torrentGetRatioMode( tor );
     1334        s = get_global_ratio_radiobutton_string( );
     1335        w = gtk_radio_button_new_with_mnemonic( group, s );
     1336        data->handler = g_signal_connect( core, "prefs-changed", G_CALLBACK( prefsChanged ), w );
     1337        group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( w ) );
     1338        gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON( w ), mode == TR_RATIOLIMIT_GLOBAL);
     1339        hig_workarea_add_wide_control( t, &row, w );
     1340        g_free( s );
     1341        g_object_set_data( G_OBJECT( w ), RATIO_MODE_KEY, GINT_TO_POINTER( TR_RATIOLIMIT_GLOBAL ) );
     1342        g_signal_connect( w, "toggled", G_CALLBACK( ratio_mode_changed_cb ), gtor );
     1343
     1344        w = gtk_radio_button_new_with_mnemonic( group, _( "Seed _regardless of ratio" ) );
     1345        group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( w ) );
     1346        gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON( w ), mode == TR_RATIOLIMIT_UNLIMITED);
     1347        hig_workarea_add_wide_control( t, &row, w );
     1348        g_object_set_data( G_OBJECT( w ), RATIO_MODE_KEY, GINT_TO_POINTER( TR_RATIOLIMIT_UNLIMITED ) );
     1349        g_signal_connect( w, "toggled", G_CALLBACK( ratio_mode_changed_cb ), gtor );
     1350
     1351        h = gtk_hbox_new ( FALSE, GUI_PAD );
     1352        w = gtk_radio_button_new_with_mnemonic( group, _( "_Stop seeding when a torrent's ratio reaches" ) );
     1353        g_object_set_data( G_OBJECT( w ), RATIO_MODE_KEY, GINT_TO_POINTER( TR_RATIOLIMIT_SINGLE ) );
     1354        gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON( w ), mode == TR_RATIOLIMIT_SINGLE);
     1355        g_signal_connect( w, "toggled", G_CALLBACK( ratio_mode_changed_cb ), gtor );
     1356        group = gtk_radio_button_get_group( GTK_RADIO_BUTTON( w ) );
     1357        gtk_box_pack_start ( GTK_BOX( h ), w, FALSE, FALSE, 0 );
     1358        d = tr_torrentGetRatioLimit( tor );
     1359        w = gtk_spin_button_new_with_range( 0.5, INT_MAX, .05 );
     1360        gtk_spin_button_set_digits( GTK_SPIN_BUTTON( w ), 2 );
     1361        gtk_spin_button_set_value( GTK_SPIN_BUTTON( w ), d );
     1362        g_signal_connect ( w, "value-changed", G_CALLBACK( ratio_spun_cb ), gtor );
     1363        gtk_box_pack_start ( GTK_BOX( h ), w, FALSE, FALSE, 0 );
     1364        hig_workarea_add_wide_control( t, &row, h );
     1365   
     1366    hig_workarea_add_section_divider ( t, &row );
    12671367    hig_workarea_add_section_title ( t, &row, _( "Peer Connections" ) );
    12681368
     
    14591559response_cb( GtkDialog *  dialog,
    14601560             int response UNUSED,
    1461              gpointer     gtor )
    1462 {
    1463     g_object_weak_unref ( G_OBJECT( gtor ), torrent_destroyed, dialog );
     1561             gpointer     data )
     1562{
     1563    ResponseData *rd = data;
     1564    TrCore * core = rd->core;
     1565    gulong handler = rd-> handler;
     1566
     1567    g_signal_handler_disconnect( core, handler );
     1568    g_object_weak_unref ( G_OBJECT( rd->gtor ), torrent_destroyed, dialog );
    14641569    gtk_widget_destroy ( GTK_WIDGET( dialog ) );
     1570
     1571    g_free ( rd );
    14651572}
    14661573
     
    14781585GtkWidget*
    14791586torrent_inspector_new( GtkWindow * parent,
     1587                       TrCore    * core,
    14801588                       TrTorrent * gtor )
    14811589{
     
    14851593    char            title[512];
    14861594    const tr_info * info = tr_torrent_info ( gtor );
     1595    ResponseData  * rd;
    14871596
    14881597    /* create the dialog */
     1598    rd = g_new0(ResponseData, 1);
     1599    rd->gtor = gtor;
     1600    rd->core = core;
    14891601    g_snprintf( title, sizeof( title ), _( "%s Properties" ), info->name );
    14901602    d = gtk_dialog_new_with_buttons ( title, parent, 0,
     
    14921604                                      NULL );
    14931605    gtk_window_set_role ( GTK_WINDOW( d ), "tr-info" );
    1494     g_signal_connect ( d, "response", G_CALLBACK ( response_cb ), gtor );
     1606    g_signal_connect ( d, "response", G_CALLBACK ( response_cb ), rd );
    14951607    gtk_dialog_set_has_separator( GTK_DIALOG( d ), FALSE );
    14961608    gtk_container_set_border_width( GTK_CONTAINER( d ), GUI_PAD );
     
    15271639                              gtk_label_new ( _( "Files" ) ) );
    15281640
    1529     w = options_page_new ( gtor );
     1641    w = options_page_new ( rd );
    15301642    g_object_set_data ( G_OBJECT( d ), "options-top", w );
    15311643    gtk_notebook_append_page ( GTK_NOTEBOOK( n ), w,
    1532                               gtk_label_new ( _( "Options" ) ) );
     1644                               gtk_label_new ( _( "Options" ) ) );
    15331645
    15341646    gtk_box_pack_start( GTK_BOX( GTK_DIALOG( d )->vbox ), n, TRUE, TRUE, 0 );
  • trunk/gtk/details.h

    r7658 r7888  
    1515
    1616#include <gtk/gtk.h>
     17#include "tr-core.h"
    1718#include "tr-torrent.h"
    1819
    1920GtkWidget* torrent_inspector_new( GtkWindow * parent,
     21                                  TrCore    * core,
    2022                                  TrTorrent * tor );
    2123
  • trunk/gtk/main.c

    r7746 r7888  
    10831083        tr_sessionSetSpeedLimit( tr, TR_UP, limit );
    10841084    }
     1085    else if( !strcmp( key, TR_PREFS_KEY_RATIO_ENABLED ) )
     1086    {
     1087        const gboolean b = pref_flag_get( key );
     1088        tr_sessionSetRatioLimited( tr, b );
     1089    }
     1090    else if( !strcmp( key, TR_PREFS_KEY_RATIO ) )
     1091    {
     1092        const double limit = pref_double_get( key );
     1093        tr_sessionSetRatioLimit( tr, limit );
     1094    }
    10851095    else if( !strncmp( key, "sched-", 6 ) )
    10861096    {
     
    13171327    else
    13181328    {
    1319         w = torrent_inspector_new( GTK_WINDOW( data->wind ), tor );
     1329        w = torrent_inspector_new( GTK_WINDOW( data->wind ), data->core, tor );
    13201330        gtk_widget_show( w );
    13211331        g_hash_table_insert( data->tor2details, (gpointer)hashString, w );
  • trunk/gtk/tr-core.c

    r7860 r7888  
    12711271}
    12721272
     1273void
     1274tr_core_set_pref_double( TrCore *     self,
     1275                         const char * key,
     1276                         double       newval )
     1277{
     1278    const double oldval = pref_double_get( key );
     1279
     1280    if( oldval != newval )
     1281    {
     1282        pref_double_set( key, newval );
     1283        commitPrefsChange( self, key );
     1284    }
     1285}
     1286
  • trunk/gtk/tr-core.h

    r6978 r7888  
    205205                               int          val );
    206206
     207/* Set a double preference value, save the prefs file, and emit the
     208   "prefs-changed" signal */
     209void     tr_core_set_pref_double( TrCore *     self,
     210                                  const char * key,
     211                                  double       val );
    207212
    208213/**
  • trunk/gtk/tr-prefs.c

    r7818 r7888  
    146146    gpointer    core;
    147147    GTimer *    last_change;
     148    gboolean    isDouble;
    148149};
    149150
     
    169170        /* update the core */
    170171        const char * key = g_object_get_data( o, PREF_KEY );
    171         const int    value = gtk_spin_button_get_value_as_int(
    172              GTK_SPIN_BUTTON( spin ) );
    173         tr_core_set_pref_int( TR_CORE( data->core ), key, value );
     172        if (data->isDouble)
     173        {
     174            const double value = gtk_spin_button_get_value( GTK_SPIN_BUTTON( spin ) );
     175            tr_core_set_pref_double( TR_CORE( data->core ), key, value );
     176        }
     177        else
     178        {
     179            const int    value = gtk_spin_button_get_value_as_int(
     180                                 GTK_SPIN_BUTTON( spin ) );
     181            tr_core_set_pref_int( TR_CORE( data->core ), key, value );
     182        }
    174183
    175184        /* cleanup */
     
    184193static void
    185194spun_cb( GtkSpinButton * w,
    186          gpointer        core )
     195         gpointer        core,
     196         gboolean        isDouble )
    187197{
    188198    /* user may be spinning through many values, so let's hold off
     
    196206        data->core = core;
    197207        data->last_change = g_timer_new( );
     208        data->isDouble = isDouble;
    198209        g_object_set_data_full( o, IDLE_DATA, data, spin_idle_data_free );
    199210        g_object_ref( G_OBJECT( o ) );
     
    201212    }
    202213    g_timer_start( data->last_change );
     214}
     215
     216static void
     217spun_cb_int( GtkSpinButton * w,
     218             gpointer        core )
     219{
     220    spun_cb( w, core, FALSE );
     221}
     222
     223static void
     224spun_cb_double( GtkSpinButton * w,
     225                gpointer        core )
     226{
     227    spun_cb( w, core, TRUE );
    203228}
    204229
     
    216241    gtk_spin_button_set_digits( GTK_SPIN_BUTTON( w ), 0 );
    217242    gtk_spin_button_set_value( GTK_SPIN_BUTTON( w ), pref_int_get( key ) );
    218     g_signal_connect( w, "value-changed", G_CALLBACK( spun_cb ), core );
     243    g_signal_connect( w, "value-changed", G_CALLBACK( spun_cb_int ), core );
     244    return w;
     245}
     246
     247static GtkWidget*
     248new_spin_button_double( const char * key,
     249                       gpointer      core,
     250                       double        low,
     251                       double        high,
     252                       double        step )
     253{
     254    GtkWidget * w = gtk_spin_button_new_with_range( low, high, step );
     255
     256    g_object_set_data_full( G_OBJECT( w ), PREF_KEY, g_strdup(
     257                                key ), g_free );
     258    gtk_spin_button_set_digits( GTK_SPIN_BUTTON( w ), 2 );
     259    gtk_spin_button_set_value( GTK_SPIN_BUTTON( w ), pref_double_get( key ) );
     260    g_signal_connect( w, "value-changed", G_CALLBACK( spun_cb_double ), core );
    219261    return w;
    220262}
     
    11181160    w2 = new_spin_button( TR_PREFS_KEY_USPEED, core, 0, INT_MAX, 5 );
    11191161    gtk_widget_set_sensitive( GTK_WIDGET( w2 ), pref_flag_get( TR_PREFS_KEY_USPEED_ENABLED ) );
     1162    g_signal_connect( w, "toggled", G_CALLBACK( target_cb ), w2 );
     1163    hig_workarea_add_row_w( t, &row, w, w2, NULL );
     1164
     1165    s = _( "_Stop seeding when a torrent's ratio reaches:" );
     1166    w = new_check_button( s, TR_PREFS_KEY_RATIO_ENABLED, core );
     1167    w2 = new_spin_button_double( TR_PREFS_KEY_RATIO, core, .5, INT_MAX, .05 );
     1168    gtk_widget_set_sensitive( GTK_WIDGET( w2 ), pref_flag_get( TR_PREFS_KEY_RATIO_ENABLED ) );
    11201169    g_signal_connect( w, "toggled", G_CALLBACK( target_cb ), w2 );
    11211170    hig_workarea_add_row_w( t, &row, w, w2, NULL );
  • trunk/libtransmission/peer-io.c

    r7811 r7888  
    8787didWriteWrapper( tr_peerIo * io, size_t bytes_transferred )
    8888{
    89     while( bytes_transferred )
    90     {
     89     while( bytes_transferred && tr_isPeerIo( io ) )
     90     {
    9191        struct tr_datatype * next = __tr_list_entry( io->outbuf_datatypes.next, struct tr_datatype, head );
    9292        const size_t payload = MIN( next->length, bytes_transferred );
     
    100100        if( io->didWrite )
    101101            io->didWrite( io, payload, next->isPieceData, io->userData );
    102 
    103         bytes_transferred -= payload;
    104         next->length -= payload;
    105         if( !next->length ) {
    106             __tr_list_remove( io->outbuf_datatypes.next );
    107             tr_free( next );
    108         }
     102       
     103        if( tr_isPeerIo( io ) )
     104        {
     105            bytes_transferred -= payload;
     106            next->length -= payload;
     107            if( !next->length ) {
     108                __tr_list_remove( io->outbuf_datatypes.next );
     109                tr_free( next );
     110            }
     111        }
    109112    }
    110113}
  • trunk/libtransmission/peer-mgr.c

    r7874 r7888  
    934934
    935935static void
     936fireRatioLimitHit( tr_torrent * tor )
     937{
     938    assert( tr_isTorrent( tor ) );
     939
     940    if( tor->ratio_limit_hit_func )
     941        tor->ratio_limit_hit_func( tor, tor->ratio_limit_hit_func_user_data );
     942}
     943
     944static void
    936945peerCallbackFunc( void * vpeer, void * vevent, void * vt )
    937946{
     
    964973            const time_t now = time( NULL );
    965974            tr_torrent * tor = t->tor;
     975            double seedRatio;
    966976
    967977            tor->activityDate = now;
     
    979989                if( e->wasPieceData )
    980990                    a->piece_data_time = now;
     991            }
     992
     993            /* if we're seeding and we've reached our seed ratio limit, stop the torrent */
     994            if( tr_torrentIsSeed( tor ) && tr_torrentGetSeedRatio( tor, &seedRatio ) ) {
     995                double up = (double)tor->uploadedCur + (double)tor->uploadedPrev;
     996                double down = (double)tor->downloadedCur + (double)tor->downloadedPrev;
     997                double ratio = tr_getRatio( up, down );
     998                if( ratio >= seedRatio ) {
     999                    tr_torrentStop( tor );
     1000                    fireRatioLimitHit( tor );
     1001                }
    9811002            }
    9821003
  • trunk/libtransmission/peer-msgs.c

    r7874 r7888  
    15971597    tr_peermsgs * msgs = vmsgs;
    15981598    firePeerGotData( msgs, bytesWritten, wasPieceData );
    1599     peerPulse( msgs );
     1599
     1600    if ( tr_isPeerIo( io ) && io->userData )
     1601        peerPulse( msgs );
    16001602}
    16011603
  • trunk/libtransmission/resume.c

    r7710 r7888  
    4040#define KEY_PROGRESS        "progress"
    4141#define KEY_SPEEDLIMIT      "speed-limit"
     42#define KEY_RATIOLIMIT      "ratio-limit"
    4243#define KEY_UPLOADED        "uploaded"
    4344
     
    4647#define KEY_SPEEDLIMIT_UP_SPEED   "up-speed"
    4748#define KEY_SPEEDLIMIT_UP_MODE    "up-mode"
     49#define KEY_RATIOLIMIT_RATIO      "ratio-limit"
     50#define KEY_RATIOLIMIT_MODE       "ratio-mode"
    4851
    4952#define KEY_PROGRESS_MTIMES   "mtimes"
     
    254257    tr_bencDictAddInt( d, KEY_SPEEDLIMIT_UP_MODE,
    255258                      tr_torrentGetSpeedMode( tor, TR_UP ) );
     259}
     260
     261static void
     262saveRatioLimits( tr_benc *          dict,
     263                 const tr_torrent * tor )
     264{
     265    tr_benc * d = tr_bencDictAddDict( dict, KEY_RATIOLIMIT, 4 );
     266
     267    tr_bencDictAddDouble( d, KEY_RATIOLIMIT_RATIO,
     268                      tr_torrentGetRatioLimit( tor ) );
     269    tr_bencDictAddInt( d, KEY_RATIOLIMIT_MODE,
     270                      tr_torrentGetRatioMode( tor ) );
    256271}
    257272
     
    280295}
    281296
     297static uint64_t
     298loadRatioLimits( tr_benc *    dict,
     299                 tr_torrent * tor )
     300{
     301    uint64_t  ret = 0;
     302    tr_benc * d;
     303
     304    if( tr_bencDictFindDict( dict, KEY_RATIOLIMIT, &d ) )
     305    {
     306        int64_t i;
     307        double dratio;
     308          if( tr_bencDictFindDouble( d, KEY_RATIOLIMIT_RATIO, &dratio ) )
     309            tr_torrentSetRatioLimit( tor, dratio );
     310        if( tr_bencDictFindInt( d, KEY_RATIOLIMIT_MODE, &i ) )
     311            tr_torrentSetRatioMode( tor, i );
     312      ret = TR_FR_RATIOLIMIT;
     313    }
     314
     315    return ret;
     316}
    282317/***
    283318****
     
    436471    saveProgress( &top, tor );
    437472    saveSpeedLimits( &top, tor );
     473    saveRatioLimits( &top, tor );
    438474
    439475    filename = getResumeFilename( tor );
     
    554590    if( fieldsToLoad & TR_FR_SPEEDLIMIT )
    555591        fieldsLoaded |= loadSpeedLimits( &top, tor );
     592   
     593    if( fieldsToLoad & TR_FR_RATIOLIMIT )
     594        fieldsLoaded |= loadRatioLimits( &top, tor );
    556595
    557596    tr_bencFree( &top );
  • trunk/libtransmission/resume.h

    r7658 r7888  
    3333    TR_FR_ADDED_DATE     = ( 1 << 11 ),
    3434    TR_FR_DONE_DATE      = ( 1 << 12 ),
    35     TR_FR_ACTIVITY_DATE  = ( 1 << 13 )
     35    TR_FR_ACTIVITY_DATE  = ( 1 << 13 ),
     36    TR_FR_RATIOLIMIT     = ( 1 << 14 )
    3637};
    3738
  • trunk/libtransmission/rpcimpl.c

    r7854 r7888  
    604604    {
    605605        int64_t      tmp;
     606        double       d;
    606607        tr_benc *    files;
    607608        tr_torrent * tor = torrents[i];
     
    630631            tr_torrentSetSpeedMode( tor, TR_UP, tmp ? TR_SPEEDLIMIT_SINGLE
    631632                                    : TR_SPEEDLIMIT_GLOBAL );
    632 
     633        if( tr_bencDictFindDouble( args_in, "ratio-limit", &d ) )
     634            tr_torrentSetRatioLimit( tor, d );
     635        if( tr_bencDictFindInt( args_in, "ratio-limit-mode", &tmp ) )
     636            tr_torrentSetRatioMode( tor, tmp );
    633637        notify( session, TR_RPC_TORRENT_CHANGED, tor );
    634638    }
     
    787791{
    788792    int64_t      i;
     793    double       d;
    789794    const char * str;
    790795
     
    809814    if( tr_bencDictFindInt( args_in, "speed-limit-up-enabled", &i ) )
    810815        tr_sessionSetSpeedLimitEnabled( session, TR_UP, i );
     816    if( tr_bencDictFindDouble( args_in, "ratio-limit", &d ) )
     817        tr_sessionSetRatioLimit( session, d );
     818    if( tr_bencDictFindInt( args_in, "ratio-limit-enabled", &i ) )
     819        tr_sessionSetRatioLimited( session, i );
    811820    if( tr_bencDictFindStr( args_in, "encryption", &str ) )
    812821    {
     
    893902    tr_bencDictAddInt( d, "speed-limit-down", tr_sessionGetSpeedLimit( session, TR_DOWN ) );
    894903    tr_bencDictAddInt( d, "speed-limit-down-enabled", tr_sessionIsSpeedLimitEnabled( session, TR_DOWN ) );
     904    tr_bencDictAddDouble( d, "ratio-limit", tr_sessionGetRatioLimit( session ) );
     905    tr_bencDictAddInt( d, "ratio-limit-enabled", tr_sessionIsRatioLimited( session ) );
    895906    tr_bencDictAddStr( d, "version", LONG_VERSION_STRING );
    896907    switch( tr_sessionGetEncryption( session ) ) {
  • trunk/libtransmission/session.c

    r7836 r7888  
    246246    tr_bencDictAddInt( d, TR_PREFS_KEY_PROXY_TYPE,               TR_PROXY_HTTP );
    247247    tr_bencDictAddStr( d, TR_PREFS_KEY_PROXY_USERNAME,           "" );
     248    tr_bencDictAddDouble( d, TR_PREFS_KEY_RATIO,                 2.0 );
     249    tr_bencDictAddInt( d, TR_PREFS_KEY_RATIO_ENABLED,            FALSE );
    248250    tr_bencDictAddInt( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED,        FALSE );
    249251    tr_bencDictAddInt( d, TR_PREFS_KEY_RPC_ENABLED,              TRUE );
     
    292294    tr_bencDictAddInt( d, TR_PREFS_KEY_PROXY_TYPE,               s->proxyType );
    293295    tr_bencDictAddStr( d, TR_PREFS_KEY_PROXY_USERNAME,           s->proxyUsername );
     296    tr_bencDictAddDouble( d, TR_PREFS_KEY_RATIO,                 s->desiredRatio );
     297    tr_bencDictAddInt( d, TR_PREFS_KEY_RATIO_ENABLED,            s->isRatioLimited );
    294298    tr_bencDictAddInt( d, TR_PREFS_KEY_RPC_AUTH_REQUIRED,        tr_sessionIsRPCPasswordEnabled( s ) );
    295299    tr_bencDictAddInt( d, TR_PREFS_KEY_RPC_ENABLED,              tr_sessionIsRPCEnabled( s ) );
     
    409413    int64_t i;
    410414    int64_t j;
     415    double  d;
    411416    tr_bool found;
    412417    const char * str;
     
    556561    tr_sessionSetSpeedLimitEnabled( session, TR_DOWN, j );
    557562
     563    found = tr_bencDictFindDouble( &settings, TR_PREFS_KEY_RATIO, &d )
     564         && tr_bencDictFindInt( &settings, TR_PREFS_KEY_RATIO_ENABLED, &j );
     565    assert( found );
     566    tr_sessionSetRatioLimit( session, d );
     567    tr_sessionSetRatioLimited( session, j );
     568
    558569    /* initialize the blocklist */
    559570    filename = tr_buildPath( session->configDir, "blocklists", NULL );
     
    739750
    740751void
     752tr_sessionSetRatioLimited( tr_session      * session,
     753                           tr_bool           isLimited )
     754{
     755    assert( tr_isSession( session ) );
     756   
     757    session->isRatioLimited = isLimited;
     758}
     759
     760void
    741761tr_sessionSetSpeedLimit( tr_session    * session,
    742762                         tr_direction    dir,
     
    750770}
    751771
     772void
     773tr_sessionSetRatioLimit( tr_session    * session,
     774                         double          desiredRatio )
     775{
     776    assert( tr_isSession( session ) );
     777
     778    session->desiredRatio = desiredRatio;
     779}
     780
    752781tr_bool
    753782tr_sessionIsSpeedLimitEnabled( const tr_session  * session,
     
    760789}
    761790
     791tr_bool
     792tr_sessionIsRatioLimited( const tr_session  * session )
     793{
     794    assert( tr_isSession( session ) );
     795
     796    return session->isRatioLimited;
     797}
     798
    762799int
    763800tr_sessionGetSpeedLimit( const tr_session  * session,
     
    768805
    769806    return session->speedLimit[dir];
     807}
     808
     809double
     810tr_sessionGetRatioLimit( const tr_session  * session )
     811{
     812    assert( tr_isSession( session ) );
     813
     814    return session->desiredRatio;
    770815}
    771816
  • trunk/libtransmission/session.h

    r7812 r7888  
    6767    tr_bool                      isWaiting;
    6868    tr_bool                      useLazyBitfield;
     69    tr_bool                      isRatioLimited;
    6970
    7071    tr_bool                      isSpeedLimited[2];
     
    129130
    130131    /* monitors the "global pool" speeds */
    131     struct tr_bandwidth       * bandwidth;
     132    struct tr_bandwidth        * bandwidth;
     133
     134    double                       desiredRatio;
    132135};
    133136
     
    141144tr_bool      tr_sessionIsAddressBlocked( const tr_session        * session,
    142145                                         const struct tr_address * addr );
    143 
    144146
    145147void         tr_globalLock( tr_session * );
  • trunk/libtransmission/torrent.c

    r7830 r7888  
    146146                         tr_direction       dir )
    147147{
     148    assert( tr_isTorrent( tor ) );
     149
    148150    return tr_bandwidthGetDesiredSpeed( tor->bandwidth, dir );
     151}
     152
     153void
     154tr_torrentSetRatioMode( tr_torrent *  tor,                   
     155                        tr_ratiolimit mode )
     156{
     157    assert( tr_isTorrent( tor ) );
     158    assert( mode==TR_RATIOLIMIT_GLOBAL || mode==TR_RATIOLIMIT_SINGLE || mode==TR_RATIOLIMIT_UNLIMITED  );
     159
     160    tor->ratioLimitMode = mode;
     161}
     162
     163tr_ratiolimit
     164tr_torrentGetRatioMode( const tr_torrent * tor )
     165{
     166    assert( tr_isTorrent( tor ) );
     167
     168    return tor->ratioLimitMode;
     169}
     170
     171void
     172tr_torrentSetRatioLimit( tr_torrent * tor,
     173                         double       desiredRatio )
     174{
     175    assert( tr_isTorrent( tor ) );
     176
     177    tor->desiredRatio = desiredRatio;   
     178}
     179
     180double
     181tr_torrentGetRatioLimit( const tr_torrent * tor )
     182{
     183    assert( tr_isTorrent( tor ) );
     184
     185    return tor->desiredRatio;
    149186}
    150187
     
    176213
    177214    return isEnabled;
     215}
     216
     217tr_bool
     218tr_torrentGetSeedRatio( const tr_torrent * tor, double * ratio )
     219{
     220    double r = 0;
     221    tr_bool isLimited;
     222
     223    switch( tr_torrentGetRatioMode( tor ) )
     224    {
     225        case TR_RATIOLIMIT_SINGLE:
     226            isLimited = TRUE;
     227            r = tr_torrentGetRatioLimit( tor );
     228            break;
     229
     230        case TR_RATIOLIMIT_GLOBAL:
     231            if(( isLimited = tr_sessionIsRatioLimited( tor->session )))
     232                r = tr_sessionGetRatioLimit( tor->session );
     233            break;
     234
     235        case TR_RATIOLIMIT_UNLIMITED:
     236            isLimited = FALSE;
     237            break;
     238    }
     239
     240    *ratio = r;
     241    return isLimited;
    178242}
    179243
     
    526590                                tr_sessionGetSpeedLimit( tor->session, TR_UP ) );
    527591        tr_torrentSetSpeedLimit( tor, TR_DOWN,
    528                                 tr_sessionGetSpeedLimit( tor->session,
    529                                                          TR_DOWN ) );
     592                                tr_sessionGetSpeedLimit( tor->session, TR_DOWN ) );
     593    }
     594
     595    if( !( loaded & TR_FR_RATIOLIMIT ) )
     596    {
     597        tr_torrentSetRatioMode( tor, tr_sessionIsRatioLimited( tor-> session )
     598                                     ? TR_RATIOLIMIT_GLOBAL : TR_RATIOLIMIT_UNLIMITED );
     599        tr_torrentSetRatioLimit( tor, tr_sessionGetRatioLimit( tor->session ) );
    530600    }
    531601
     
    12981368
    12991369void
     1370tr_torrentSetRatioLimitHitCallback( tr_torrent                     * tor,
     1371                                    tr_torrent_ratio_limit_hit_func  func,
     1372                                    void                           * user_data )
     1373{
     1374    assert( tr_isTorrent( tor ) );
     1375
     1376    tor->ratio_limit_hit_func = func;
     1377    tor->ratio_limit_hit_func_user_data = user_data;
     1378}
     1379
     1380void
    13001381tr_torrentClearCompletenessCallback( tr_torrent * torrent )
    13011382{
    13021383    tr_torrentSetCompletenessCallback( torrent, NULL, NULL );
     1384}
     1385
     1386void
     1387tr_torrentClearRatioLimitHitCallback( tr_torrent * torrent )
     1388{
     1389    tr_torrentSetRatioLimitHitCallback( torrent, NULL, NULL );
    13031390}
    13041391
  • trunk/libtransmission/torrent.h

    r7816 r7888  
    7171                                              tr_direction       direction );
    7272
     73tr_bool     tr_torrentGetSeedRatio( const tr_torrent * tor, double * ratio );
     74
     75
    7376
    7477#define tr_block( a, b ) _tr_block( tor, a, b )
     
    186189    void *                     completeness_func_user_data;
    187190
     191    tr_torrent_ratio_limit_hit_func * ratio_limit_hit_func;
     192    void *                     ratio_limit_hit_func_user_data;
     193
    188194    tr_bool                    isRunning;
    189195    tr_bool                    isDeleting;
     
    203209
    204210    struct tr_torrent_peers  * torrentPeers;
     211
     212    double                     desiredRatio;
     213    tr_ratiolimit              ratioLimitMode;
    205214};
    206215
  • trunk/libtransmission/tr-getopt.h

    r7783 r7888  
    3030typedef struct tr_option
    3131{
    32     int     val;          /* the value to return from tr_getopt() */
     32    int           val;          /* the value to return from tr_getopt() */
    3333    const char *  longName;     /* --long-form */
    3434    const char *  description;  /* option's description for tr_getopt_usage() */
    3535    const char *  shortName;    /* short form */
    36     int     has_arg;      /* 0 for no argument, 1 for argument */
     36    int           has_arg;      /* 0 for no argument, 1 for argument */
    3737    const char *  argName;      /* argument's description for tr_getopt_usage() */
    3838}
  • trunk/libtransmission/transmission.h

    r7720 r7888  
    177177#define TR_PREFS_KEY_PROXY_TYPE                 "proxy-type"
    178178#define TR_PREFS_KEY_PROXY_USERNAME             "proxy-auth-username"
     179#define TR_PREFS_KEY_RATIO                      "ratio-limit"
     180#define TR_PREFS_KEY_RATIO_ENABLED              "ratio-limit-enabled"
    179181#define TR_PREFS_KEY_RPC_AUTH_REQUIRED          "rpc-authentication-required"
    180182#define TR_PREFS_KEY_RPC_ENABLED                "rpc-enabled"
     
    561563                                            tr_direction        direction );
    562564
     565void       tr_sessionSetRatioLimited      ( tr_session        * session,
     566                                            tr_bool             isEnabled );
     567
     568tr_bool    tr_sessionIsRatioLimited       ( const tr_session  * session);
     569
     570void       tr_sessionSetRatioLimit        ( tr_session        * session,
     571                                            double              desiredRatio);
     572
     573double     tr_sessionGetRatioLimit        ( const tr_session  * session);
     574
    563575double     tr_sessionGetRawSpeed          ( const tr_session  * session,
    564576                                           tr_direction         direction );
     
    867879tr_speedlimit;
    868880
     881typedef enum
     882{
     883    TR_RATIOLIMIT_GLOBAL    = 0, /* follow the global settings */
     884    TR_RATIOLIMIT_SINGLE    = 1, /* override the global settings, seeding until a certain ratio */
     885    TR_RATIOLIMIT_UNLIMITED = 2  /* override the global settings, seeding regardless of ratio */
     886}
     887tr_ratiolimit;
     888
    869889void          tr_torrentSetSpeedMode( tr_torrent     * tor,
    870890                                      tr_direction     up_or_down,
     
    880900int           tr_torrentGetSpeedLimit( const tr_torrent  * tor,
    881901                                       tr_direction        direction );
     902
     903void          tr_torrentSetRatioMode( tr_torrent         * tor,
     904                                      tr_ratiolimit        mode );
     905
     906tr_ratiolimit tr_torrentGetRatioMode( const tr_torrent   * tor );
     907
     908void          tr_torrentSetRatioLimit( tr_torrent        * tor,
     909                                       double              ratio );
     910
     911double        tr_torrentGetRatioLimit( const tr_torrent  * tor );
    882912
    883913/****
     
    9951025                                               void             * user_data );
    9961026
     1027typedef void ( tr_torrent_ratio_limit_hit_func )( tr_torrent   * torrent,
     1028                                                  void         * user_data );
     1029
    9971030/**
    9981031 * Register to be notified whenever a torrent's "completeness"
     
    10141047
    10151048void tr_torrentClearCompletenessCallback( tr_torrent * torrent );
     1049
     1050
     1051/**
     1052 * Register to be notified whenever a torrent's ratio limit
     1053 * has been hit. This will be called when the torrent's
     1054 * ul/dl ratio has met or exceeded the designated ratio limit.
     1055 *
     1056 * Has the same restrictions as tr_torrentSetCompletenessCallback
     1057 */
     1058void tr_torrentSetRatioLimitHitCallback(
     1059     tr_torrent                     * torrent,
     1060     tr_torrent_ratio_limit_hit_func  func,
     1061     void                           * user_data );
     1062
     1063void tr_torrentClearRatioLimitHitCallback( tr_torrent * torrent );
    10161064
    10171065
Note: See TracChangeset for help on using the changeset viewer.