source: trunk/libtransmission/ratecontrol.c @ 92

Last change on this file since 92 was 92, checked in by titer, 16 years ago

Force rates to 0 when paused, and download rate to 0 when seeding.
Increased OS X UI update interval to 1 second.

File size: 4.1 KB
Line 
1/******************************************************************************
2 * Copyright (c) 2006 Eric Petit
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
21 *****************************************************************************/
22
23#include "transmission.h"
24
25#define MAX_HISTORY 30
26
27typedef struct tr_transfer_s tr_transfer_t;
28struct tr_ratecontrol_s
29{
30    tr_lock_t       lock;
31    int             limit;
32    tr_transfer_t * first;
33    tr_transfer_t * last;
34};
35struct tr_transfer_s
36{
37    uint64_t        date;
38    int             size;
39    tr_transfer_t * next;
40    tr_transfer_t * prev;
41};
42
43/***********************************************************************
44 * rateForInterval
45 ***********************************************************************
46 * Returns the transfer rate on the last 'interval' milliseconds
47 **********************************************************************/
48static inline float rateForInterval( tr_ratecontrol_t * r, int interval )
49{
50    tr_transfer_t * t;
51    uint64_t        start = tr_date() - interval;
52    int             total = 0;
53
54    for( t = r->first; t && t->date > start; t = t->next )
55    {
56        total += t->size;
57    }
58
59    return ( 1000.0 / 1024.0 ) * total / interval;
60}
61
62static inline void cleanOldTransfers( tr_ratecontrol_t * r )
63{
64    tr_transfer_t * t, * prev;
65    uint64_t        old = tr_date() - MAX_HISTORY * 1000;
66
67    for( t = r->last; t && t->date < old; )
68    {
69        prev = t->prev;
70        if( prev )
71            prev->next = NULL;
72        else
73            r->first = NULL;
74        free( t );
75        t       = prev;
76        r->last = prev;
77    }
78}
79
80tr_ratecontrol_t * tr_rcInit()
81{
82    tr_ratecontrol_t * r;
83
84    r        = calloc( sizeof( tr_ratecontrol_t ), 1 );
85    r->limit = -1;
86    tr_lockInit( &r->lock );
87
88    return r;
89}
90
91void tr_rcSetLimit( tr_ratecontrol_t * r, int limit )
92{
93    tr_lockLock( &r->lock );
94    r->limit = limit;
95    tr_lockUnlock( &r->lock );
96}
97
98int tr_rcCanTransfer( tr_ratecontrol_t * r )
99{
100    int ret;
101
102    tr_lockLock( &r->lock );
103    ret = ( r->limit < 0 ) || ( rateForInterval( r, 1000 ) < r->limit );
104    tr_lockUnlock( &r->lock );
105
106    return ret;
107}
108
109void tr_rcTransferred( tr_ratecontrol_t * r, int size )
110{
111    tr_transfer_t * t;
112
113    if( size < 100 )
114    {
115        return;
116    }
117   
118    tr_lockLock( &r->lock );
119    t = malloc( sizeof( tr_transfer_t ) );
120
121    if( r->first )
122        r->first->prev = t;
123    if( !r->last )
124        r->last = t;
125    t->next  = r->first;
126    t->prev  = NULL;
127    r->first = t;
128
129    t->date  = tr_date();
130    t->size  = size;
131
132    cleanOldTransfers( r );
133    tr_lockUnlock( &r->lock );
134}
135
136float tr_rcRate( tr_ratecontrol_t * r )
137{
138    float ret;
139
140    tr_lockLock( &r->lock );
141    ret = rateForInterval( r, MAX_HISTORY * 1000 );
142    tr_lockUnlock( &r->lock );
143
144    return ret;
145}
146
147void tr_rcReset( tr_ratecontrol_t * r )
148{
149    tr_transfer_t * t, * next;
150
151    tr_lockLock( &r->lock );
152    for( t = r->first; t; )
153    {
154        next = t->next;
155        free( t );
156        t = next;
157    }
158    r->first = NULL;
159    r->last  = NULL;
160    tr_lockUnlock( &r->lock );
161}
162
163void tr_rcClose( tr_ratecontrol_t * r )
164{
165    tr_rcReset( r );
166    tr_lockClose( &r->lock );
167    free( r );
168}
Note: See TracBrowser for help on using the repository browser.