source: branches/1.5x/libtransmission/bandwidth.h @ 7664

Last change on this file since 7664 was 7664, checked in by charles, 13 years ago

(1.5x) updates from trunk: all of build system & libtransmission; bugfixes in daemon, cli, and gtk; sync tr_sessionInit() changes. NOTE: mac end needs to add request-list.[ch] to its libtransmissio rules

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