source: trunk/libtransmission/bandwidth.h @ 11599

Last change on this file since 11599 was 11599, checked in by charles, 11 years ago

(trunk) Join the 21st century and use only 1 space at the end sentences. This commit is nearly as important as the semi-annual ones that remove trailing spaces from the ends of lines of code... :)

  • Property svn:keywords set to Date Rev Author Id
File size: 9.2 KB
Line 
1/*
2 * This file Copyright (C) 2008-2010 Mnemosyne LLC
3 *
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
9 *
10 * $Id: bandwidth.h 11599 2010-12-27 19:18:17Z charles $
11 */
12
13#ifndef __TRANSMISSION__
14#error only libtransmission should #include this header.
15#endif
16
17#ifndef TR_BANDWIDTH_H
18#define TR_BANDWIDTH_H
19
20#include "transmission.h"
21#include "ptrarray.h"
22#include "utils.h" /* tr_new(), tr_free() */
23
24struct tr_peerIo;
25
26/**
27 * @addtogroup networked_io Networked IO
28 * @{
29 */
30
31/* these are PRIVATE IMPLEMENTATION details that should not be touched.
32 * it's included in the header for inlining and composition. */
33enum
34{
35    HISTORY_MSEC = 2000u,
36    INTERVAL_MSEC = HISTORY_MSEC,
37    GRANULARITY_MSEC = 200,
38    HISTORY_SIZE = ( INTERVAL_MSEC / GRANULARITY_MSEC ),
39    MAGIC_NUMBER = 43143
40};
41
42/* these are PRIVATE IMPLEMENTATION details that should not be touched.
43 * it's included in the header for inlining and composition. */
44struct bratecontrol
45{
46    int newest;
47    struct { uint64_t date, size; } transfers[HISTORY_SIZE];
48};
49
50/* these are PRIVATE IMPLEMENTATION details that should not be touched.
51 * it's included in the header for inlining and composition. */
52struct tr_band
53{
54    tr_bool isLimited;
55    tr_bool honorParentLimits;
56    unsigned int bytesLeft;
57    unsigned int desiredSpeed_Bps;
58    struct bratecontrol raw;
59    struct bratecontrol piece;
60};
61
62/**
63 * Bandwidth is an object for measuring and constraining bandwidth speeds.
64 *
65 * Bandwidth objects can be "stacked" so that a peer can be made to obey
66 * multiple constraints (for example, obeying the global speed limit and a
67 * per-torrent speed limit).
68 *
69 * HIERARCHY
70 *
71 *   Transmission's bandwidth hierarchy is a tree.
72 *   At the top is the global bandwidth object owned by tr_session.
73 *   Its children are per-torrent bandwidth objects owned by tr_torrent.
74 *   Underneath those are per-peer bandwidth objects owned by tr_peer.
75 *
76 *   tr_session also owns a tr_handshake's bandwidths, so that the handshake
77 *   I/O can be counted in the global raw totals. When the handshake is done,
78 *   the bandwidth's ownership passes to a tr_peer.
79 *
80 * MEASURING
81 *
82 *   When you ask a bandwidth object for its speed, it gives the speed of the
83 *   subtree underneath it as well. So you can get Transmission's overall
84 *   speed by quering tr_session's bandwidth, per-torrent speeds by asking
85 *   tr_torrent's bandwidth, and per-peer speeds by asking tr_peer's bandwidth.
86 *
87 * CONSTRAINING
88 *
89 *   Call tr_bandwidthAllocate() periodically. tr_bandwidth knows its current
90 *   speed and will decide how many bytes to make available over the
91 *   user-specified period to reach the user-specified desired speed.
92 *   If appropriate, it notifies its peer-ios that new bandwidth is available.
93 *
94 *   tr_bandwidthAllocate() operates on the tr_bandwidth subtree, so usually
95 *   you'll only need to invoke it for the top-level tr_session bandwidth.
96 *
97 *   The peer-ios all have a pointer to their associated tr_bandwidth object,
98 *   and call tr_bandwidthClamp() before performing I/O to see how much
99 *   bandwidth they can safely use.
100 */
101typedef struct tr_bandwidth
102{
103    /* these are PRIVATE IMPLEMENTATION details that should not be touched.
104     * it's included in the header for inlining and composition. */
105
106    struct tr_band band[2];
107    struct tr_bandwidth * parent;
108    tr_priority_t priority;
109    int magicNumber;
110    tr_session * session;
111    tr_ptrArray children; /* struct tr_bandwidth */
112    struct tr_peerIo * peer;
113}
114tr_bandwidth;
115
116
117/**
118***
119**/
120
121tr_bandwidth* tr_bandwidthConstruct( tr_bandwidth * bandwidth,
122                                     tr_session   * session,
123                                     tr_bandwidth * parent );
124
125/** @brief create a new tr_bandwidth object */
126static inline tr_bandwidth* tr_bandwidthNew( tr_session * session, tr_bandwidth * parent )
127{
128    return tr_bandwidthConstruct( tr_new0( tr_bandwidth, 1 ), session, parent );
129}
130
131tr_bandwidth* tr_bandwidthDestruct( tr_bandwidth * bandwidth );
132
133/** @brief free a tr_bandwidth object */
134static inline void tr_bandwidthFree( tr_bandwidth * bandwidth )
135{
136    tr_free( tr_bandwidthDestruct( bandwidth ) );
137}
138
139/** @brief test to see if the pointer refers to a live bandwidth object */
140static inline tr_bool tr_isBandwidth( const tr_bandwidth  * b )
141{
142    return ( b != NULL ) && ( b->magicNumber == MAGIC_NUMBER );
143}
144
145/******
146*******
147******/
148
149/**
150 * @brief Set the desired speed for this bandwidth subtree.
151 * @see tr_bandwidthAllocate
152 * @see tr_bandwidthGetDesiredSpeed
153 */
154static inline tr_bool tr_bandwidthSetDesiredSpeed_Bps( tr_bandwidth        * bandwidth,
155                                                       tr_direction          dir,
156                                                       unsigned int          desiredSpeed )
157{
158    unsigned int * value = &bandwidth->band[dir].desiredSpeed_Bps;
159    const tr_bool didChange = desiredSpeed != *value;
160    *value = desiredSpeed;
161    return didChange;
162}
163
164/**
165 * @brief Get the desired speed for the bandwidth subtree.
166 * @see tr_bandwidthSetDesiredSpeed
167 */
168static inline double
169tr_bandwidthGetDesiredSpeed_Bps( const tr_bandwidth  * bandwidth, tr_direction dir )
170{
171    return bandwidth->band[dir].desiredSpeed_Bps;
172}
173
174/**
175 * @brief Set whether or not this bandwidth should throttle its peer-io's speeds
176 */
177static inline tr_bool tr_bandwidthSetLimited( tr_bandwidth        * bandwidth,
178                                                 tr_direction          dir,
179                                                 tr_bool               isLimited )
180{
181    tr_bool * value = &bandwidth->band[dir].isLimited;
182    const tr_bool didChange = isLimited != *value;
183    *value = isLimited;
184    return didChange;
185}
186
187/**
188 * @return nonzero if this bandwidth throttles its peer-ios speeds
189 */
190static inline tr_bool tr_bandwidthIsLimited( const tr_bandwidth  * bandwidth,
191                                                tr_direction          dir )
192{
193    return bandwidth->band[dir].isLimited;
194}
195
196/**
197 * @brief allocate the next period_msec's worth of bandwidth for the peer-ios to consume
198 */
199void    tr_bandwidthAllocate          ( tr_bandwidth        * bandwidth,
200                                        tr_direction          direction,
201                                        unsigned int          period_msec );
202
203/**
204 * @brief clamps byteCount down to a number that this bandwidth will allow to be consumed
205 */
206unsigned int  tr_bandwidthClamp       ( const tr_bandwidth  * bandwidth,
207                                        tr_direction          direction,
208                                        unsigned int          byteCount );
209
210/******
211*******
212******/
213
214/** @brief Get the raw total of bytes read or sent by this bandwidth subtree. */
215unsigned int tr_bandwidthGetRawSpeed_Bps( const tr_bandwidth  * bandwidth,
216                                           const uint64_t        now,
217                                           const tr_direction    direction );
218
219/** @brief Get the number of piece data bytes read or sent by this bandwidth subtree. */
220unsigned int tr_bandwidthGetPieceSpeed_Bps( const tr_bandwidth  * bandwidth,
221                                            const uint64_t        now,
222                                            const tr_direction    direction );
223
224/**
225 * @brief Notify the bandwidth object that some of its allocated bandwidth has been consumed.
226 * This is is usually invoked by the peer-io after a read or write.
227 */
228void    tr_bandwidthUsed              ( tr_bandwidth        * bandwidth,
229                                        tr_direction          direction,
230                                        size_t                byteCount,
231                                        tr_bool               isPieceData,
232                                        uint64_t              now );
233
234/******
235*******
236******/
237
238void    tr_bandwidthSetParent         ( tr_bandwidth        * bandwidth,
239                                        tr_bandwidth        * parent );
240
241/**
242 * Almost all the time we do want to honor a parents' bandwidth cap, so that
243 * (for example) a peer is constrained by a per-torrent cap and the global cap.
244 * But when we set a torrent's speed mode to TR_SPEEDLIMIT_UNLIMITED, then
245 * in that particular case we want to ignore the global speed limit...
246 */
247static inline tr_bool tr_bandwidthHonorParentLimits ( tr_bandwidth        * bandwidth,
248                                                         tr_direction          direction,
249                                                         tr_bool               isEnabled )
250{
251    tr_bool * value = &bandwidth->band[direction].honorParentLimits;
252    const tr_bool didChange = isEnabled != *value;
253    *value = isEnabled;
254    return didChange;
255}
256
257static inline tr_bool tr_bandwidthAreParentLimitsHonored( tr_bandwidth  * bandwidth,
258                                                             tr_direction    direction )
259{
260    assert( tr_isBandwidth( bandwidth ) );
261    assert( tr_isDirection( direction ) );
262
263    return bandwidth->band[direction].honorParentLimits;
264}
265
266/******
267*******
268******/
269
270void tr_bandwidthSetPeer( tr_bandwidth        * bandwidth,
271                          struct tr_peerIo    * peerIo );
272
273/* @} */
274#endif
Note: See TracBrowser for help on using the repository browser.