• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/transmission/transmission-2.73/libtransmission/
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 12509 2011-06-19 18:34:10Z 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    unsigned int uniqueKey;
115    tr_session * session;
116    tr_ptrArray children; /* struct tr_bandwidth */
117    struct tr_peerIo * peer;
118}
119tr_bandwidth;
120
121
122/**
123***
124**/
125
126void tr_bandwidthConstruct( tr_bandwidth * bandwidth,
127                            tr_session   * session,
128                            tr_bandwidth * parent );
129
130void tr_bandwidthDestruct( tr_bandwidth * bandwidth );
131
132/** @brief test to see if the pointer refers to a live bandwidth object */
133static inline bool tr_isBandwidth( const tr_bandwidth  * b )
134{
135    return ( b != NULL ) && ( b->magicNumber == BANDWIDTH_MAGIC_NUMBER );
136}
137
138/******
139*******
140******/
141
142/**
143 * @brief Set the desired speed for this bandwidth subtree.
144 * @see tr_bandwidthAllocate
145 * @see tr_bandwidthGetDesiredSpeed
146 */
147static inline bool tr_bandwidthSetDesiredSpeed_Bps( tr_bandwidth        * bandwidth,
148                                                    tr_direction          dir,
149                                                    unsigned int          desiredSpeed )
150{
151    unsigned int * value = &bandwidth->band[dir].desiredSpeed_Bps;
152    const bool didChange = desiredSpeed != *value;
153    *value = desiredSpeed;
154    return didChange;
155}
156
157/**
158 * @brief Get the desired speed for the bandwidth subtree.
159 * @see tr_bandwidthSetDesiredSpeed
160 */
161static inline double
162tr_bandwidthGetDesiredSpeed_Bps( const tr_bandwidth  * bandwidth, tr_direction dir )
163{
164    return bandwidth->band[dir].desiredSpeed_Bps;
165}
166
167/**
168 * @brief Set whether or not this bandwidth should throttle its peer-io's speeds
169 */
170static inline bool tr_bandwidthSetLimited( tr_bandwidth  * bandwidth,
171                                           tr_direction    dir,
172                                           bool            isLimited )
173{
174    bool * value = &bandwidth->band[dir].isLimited;
175    const bool didChange = isLimited != *value;
176    *value = isLimited;
177    return didChange;
178}
179
180/**
181 * @return nonzero if this bandwidth throttles its peer-ios speeds
182 */
183static inline bool tr_bandwidthIsLimited( const tr_bandwidth  * bandwidth,
184                                          tr_direction          dir )
185{
186    return bandwidth->band[dir].isLimited;
187}
188
189/**
190 * @brief allocate the next period_msec's worth of bandwidth for the peer-ios to consume
191 */
192void    tr_bandwidthAllocate          ( tr_bandwidth        * bandwidth,
193                                        tr_direction          direction,
194                                        unsigned int          period_msec );
195
196/**
197 * @brief clamps byteCount down to a number that this bandwidth will allow to be consumed
198 */
199unsigned int  tr_bandwidthClamp       ( const tr_bandwidth  * bandwidth,
200                                        tr_direction          direction,
201                                        unsigned int          byteCount );
202
203/******
204*******
205******/
206
207/** @brief Get the raw total of bytes read or sent by this bandwidth subtree. */
208unsigned int tr_bandwidthGetRawSpeed_Bps( const tr_bandwidth  * bandwidth,
209                                           const uint64_t        now,
210                                           const tr_direction    direction );
211
212/** @brief Get the number of piece data bytes read or sent by this bandwidth subtree. */
213unsigned int tr_bandwidthGetPieceSpeed_Bps( const tr_bandwidth  * bandwidth,
214                                            const uint64_t        now,
215                                            const tr_direction    direction );
216
217/**
218 * @brief Notify the bandwidth object that some of its allocated bandwidth has been consumed.
219 * This is is usually invoked by the peer-io after a read or write.
220 */
221void    tr_bandwidthUsed              ( tr_bandwidth        * bandwidth,
222                                        tr_direction          direction,
223                                        size_t                byteCount,
224                                        bool                  isPieceData,
225                                        uint64_t              now );
226
227/******
228*******
229******/
230
231void    tr_bandwidthSetParent         ( tr_bandwidth        * bandwidth,
232                                        tr_bandwidth        * parent );
233
234/**
235 * Almost all the time we do want to honor a parents' bandwidth cap, so that
236 * (for example) a peer is constrained by a per-torrent cap and the global cap.
237 * But when we set a torrent's speed mode to TR_SPEEDLIMIT_UNLIMITED, then
238 * in that particular case we want to ignore the global speed limit...
239 */
240static inline bool tr_bandwidthHonorParentLimits ( tr_bandwidth   * bandwidth,
241                                                   tr_direction     direction,
242                                                   bool             isEnabled )
243{
244    bool * value = &bandwidth->band[direction].honorParentLimits;
245    const bool didChange = isEnabled != *value;
246    *value = isEnabled;
247    return didChange;
248}
249
250static inline bool tr_bandwidthAreParentLimitsHonored( const tr_bandwidth  * bandwidth,
251                                                       tr_direction          direction )
252{
253    assert( tr_isBandwidth( bandwidth ) );
254    assert( tr_isDirection( direction ) );
255
256    return bandwidth->band[direction].honorParentLimits;
257}
258
259/******
260*******
261******/
262
263void tr_bandwidthSetPeer( tr_bandwidth        * bandwidth,
264                          struct tr_peerIo    * peerIo );
265
266/* @} */
267#endif
268