source: trunk/libtransmission/bandwidth.h

Last change on this file was 14724, checked in by jordan, 5 years ago

use '#pragma once' instead of #ifndef..#define..#endif guards

  • Property svn:keywords set to Date Rev Author Id
File size: 8.1 KB
Line 
1/*
2 * This file Copyright (C) 2008-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: bandwidth.h 14724 2016-03-29 16:37:21Z mikedld $
8 */
9
10#ifndef __TRANSMISSION__
11 #error only libtransmission should #include this header.
12#endif
13
14#pragma once
15
16#include <assert.h>
17
18#include "transmission.h"
19#include "ptrarray.h"
20#include "utils.h" /* tr_new (), tr_free () */
21
22struct tr_peerIo;
23
24/**
25 * @addtogroup networked_io Networked IO
26 * @{
27 */
28
29/* these are PRIVATE IMPLEMENTATION details that should not be touched.
30 * it's included in the header for inlining and composition. */
31enum
32{
33  HISTORY_MSEC = 2000u,
34  INTERVAL_MSEC = HISTORY_MSEC,
35  GRANULARITY_MSEC = 200,
36  HISTORY_SIZE = (INTERVAL_MSEC / GRANULARITY_MSEC),
37  BANDWIDTH_MAGIC_NUMBER = 43143
38};
39
40/* these are PRIVATE IMPLEMENTATION details that should not be touched.
41 * it's included in the header for inlining and composition. */
42struct bratecontrol
43{
44  int newest;
45  struct { uint64_t date, size; } transfers[HISTORY_SIZE];
46  uint64_t cache_time;
47  unsigned int cache_val;
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  bool isLimited;
55  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  unsigned int uniqueKey;
111  tr_session * session;
112  tr_ptrArray children; /* struct tr_bandwidth */
113  struct tr_peerIo * peer;
114}
115tr_bandwidth;
116
117
118/**
119***
120**/
121
122void tr_bandwidthConstruct (tr_bandwidth * bandwidth,
123                            tr_session   * session,
124                            tr_bandwidth * parent);
125
126void tr_bandwidthDestruct (tr_bandwidth * bandwidth);
127
128/** @brief test to see if the pointer refers to a live bandwidth object */
129static inline bool
130tr_isBandwidth (const tr_bandwidth  * b)
131{
132  return (b != NULL) && (b->magicNumber == BANDWIDTH_MAGIC_NUMBER);
133}
134
135/******
136*******
137******/
138
139/**
140 * @brief Set the desired speed for this bandwidth subtree.
141 * @see tr_bandwidthAllocate
142 * @see tr_bandwidthGetDesiredSpeed
143 */
144static inline bool
145tr_bandwidthSetDesiredSpeed_Bps (tr_bandwidth  * bandwidth,
146                                 tr_direction    dir,
147                                 unsigned int    desiredSpeed)
148{
149  unsigned int * value = &bandwidth->band[dir].desiredSpeed_Bps;
150  const bool didChange = desiredSpeed != *value;
151  *value = desiredSpeed;
152  return didChange;
153}
154
155/**
156 * @brief Get the desired speed for the bandwidth subtree.
157 * @see tr_bandwidthSetDesiredSpeed
158 */
159static inline double
160tr_bandwidthGetDesiredSpeed_Bps (const tr_bandwidth  * bandwidth, tr_direction dir)
161{
162  return bandwidth->band[dir].desiredSpeed_Bps;
163}
164
165/**
166 * @brief Set whether or not this bandwidth should throttle its peer-io's speeds
167 */
168static inline bool
169tr_bandwidthSetLimited (tr_bandwidth  * bandwidth,
170                        tr_direction    dir,
171                        bool            isLimited)
172{
173  bool * value = &bandwidth->band[dir].isLimited;
174  const bool didChange = isLimited != *value;
175  *value = isLimited;
176  return didChange;
177}
178
179/**
180 * @return nonzero if this bandwidth throttles its peer-ios speeds
181 */
182static inline bool
183tr_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
241tr_bandwidthHonorParentLimits (tr_bandwidth   * bandwidth,
242                               tr_direction     direction,
243                               bool             isEnabled)
244{
245  bool * value = &bandwidth->band[direction].honorParentLimits;
246  const bool didChange = isEnabled != *value;
247  *value = isEnabled;
248  return didChange;
249}
250
251static inline bool
252tr_bandwidthAreParentLimitsHonored (const tr_bandwidth  * bandwidth,
253                                    tr_direction          direction)
254{
255  assert (tr_isBandwidth (bandwidth));
256  assert (tr_isDirection (direction));
257
258  return bandwidth->band[direction].honorParentLimits;
259}
260
261/******
262*******
263******/
264
265void tr_bandwidthSetPeer (tr_bandwidth      * bandwidth,
266                          struct tr_peerIo  * peerIo);
267
268/* @} */
269
Note: See TracBrowser for help on using the repository browser.