source: trunk/libtransmission/bandwidth.h @ 7579

Last change on this file since 7579 was 7579, checked in by charles, 12 years ago

(trunk libT) inline parts of peer-io and bandwidth, too

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