source: trunk/libtransmission/ratecontrol.c @ 346

Last change on this file since 346 was 261, checked in by titer, 15 years ago

Updated svn:keywords

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