source: trunk/libtransmission/bandwidth.h @ 12204

Last change on this file since 12204 was 12204, checked in by jordan, 11 years ago

(trunk) #4138 "use stdbool.h instead of tr_bool" -- done.

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