3 Copyright (c) 2003, Arvid Norberg
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
15 * Neither the name of the author nor the names of its
16 contributors may be used to endorse or promote products derived
17 from this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
33 #ifndef TORRENT_STAT_HPP_INCLUDED
34 #define TORRENT_STAT_HPP_INCLUDED
41 #include "libtorrent/size_type.hpp"
42 #include "libtorrent/invariant_check.hpp"
43 #include "libtorrent/config.hpp"
44 #include "libtorrent/assert.hpp"
48 class TORRENT_EXPORT stat_channel
50 friend class invariant_access
;
52 enum { history
= 10 };
59 std::memset(m_rate_history
, 0, sizeof(m_rate_history
));
62 void operator+=(stat_channel
const& s
)
64 m_counter
+= s
.m_counter
;
65 m_total_counter
+= s
.m_counter
;
70 TORRENT_ASSERT(count
>= 0);
73 m_total_counter
+= count
;
76 // should be called once every second
77 void second_tick(float tick_interval
);
78 float rate() const { return m_rate_sum
/ float(history
); }
79 size_type
rate_sum() const { return m_rate_sum
; }
80 size_type
total() const { return m_total_counter
; }
82 void offset(size_type counter
)
84 TORRENT_ASSERT(counter
>= 0);
85 m_total_counter
+= counter
;
88 size_type
counter() const { return m_counter
; }
93 void check_invariant() const
96 for (int i
= 0; i
< history
; ++i
) sum
+= m_rate_history
[i
];
97 TORRENT_ASSERT(m_rate_sum
== sum
);
98 TORRENT_ASSERT(m_total_counter
>= 0);
102 // history of rates a few seconds back
103 int m_rate_history
[history
];
105 // the accumulator for this second.
109 size_type m_total_counter
;
111 // sum of all elements in m_rate_history
112 size_type m_rate_sum
;
115 class TORRENT_EXPORT stat
117 friend class invariant_access
;
119 void operator+=(const stat
& s
)
121 for (int i
= 0; i
< num_channels
; ++i
)
122 m_stat
[i
] += s
.m_stat
[i
];
125 void received_bytes(int bytes_payload
, int bytes_protocol
)
127 TORRENT_ASSERT(bytes_payload
>= 0);
128 TORRENT_ASSERT(bytes_protocol
>= 0);
130 m_stat
[download_payload
].add(bytes_payload
);
131 m_stat
[download_protocol
].add(bytes_protocol
);
134 void sent_bytes(int bytes_payload
, int bytes_protocol
)
136 TORRENT_ASSERT(bytes_payload
>= 0);
137 TORRENT_ASSERT(bytes_protocol
>= 0);
139 m_stat
[upload_payload
].add(bytes_payload
);
140 m_stat
[upload_protocol
].add(bytes_protocol
);
143 // calculate ip protocol overhead
144 void calc_ip_overhead()
146 int uploaded
= m_stat
[upload_protocol
].counter()
147 + m_stat
[upload_payload
].counter();
148 int downloaded
= m_stat
[download_protocol
].counter()
149 + m_stat
[download_payload
].counter();
151 // IP + TCP headers are 40 bytes per MTU (1460)
152 // bytes of payload, but at least 40 bytes
153 m_stat
[upload_ip_protocol
].add((std::max
)(uploaded
/ 1460, uploaded
>0?40:0));
154 m_stat
[download_ip_protocol
].add((std::max
)(downloaded
/ 1460, downloaded
>0?40:0));
156 // also account for ACK traffic. That adds to the transfers
157 // in the opposite direction. Even on connections with symmetric
158 // transfer rates, it seems to add a penalty.
159 m_stat
[upload_ip_protocol
].add((std::max
)(downloaded
* 40 / 1460, downloaded
>0?40:0));
160 m_stat
[download_ip_protocol
].add((std::max
)(uploaded
* 40 / 1460, uploaded
>0?40:0));
163 int upload_ip_overhead() const { return m_stat
[upload_ip_protocol
].counter(); }
164 int download_ip_overhead() const { return m_stat
[download_ip_protocol
].counter(); }
166 // should be called once every second
167 void second_tick(float tick_interval
)
169 for (int i
= 0; i
< num_channels
; ++i
)
170 m_stat
[i
].second_tick(tick_interval
);
173 float upload_rate() const
175 return (m_stat
[upload_payload
].rate_sum()
176 + m_stat
[upload_protocol
].rate_sum()
177 + m_stat
[upload_ip_protocol
].rate_sum())
178 / float(stat_channel::history
);
181 float download_rate() const
183 return (m_stat
[download_payload
].rate_sum()
184 + m_stat
[download_protocol
].rate_sum()
185 + m_stat
[download_ip_protocol
].rate_sum())
186 / float(stat_channel::history
);
189 float upload_payload_rate() const
190 { return m_stat
[upload_payload
].rate(); }
192 float download_payload_rate() const
193 { return m_stat
[download_payload
].rate(); }
195 size_type
total_payload_upload() const
196 { return m_stat
[upload_payload
].total(); }
197 size_type
total_payload_download() const
198 { return m_stat
[download_payload
].total(); }
200 size_type
total_protocol_upload() const
201 { return m_stat
[upload_protocol
].total(); }
202 size_type
total_protocol_download() const
203 { return m_stat
[download_protocol
].total(); }
205 // this is used to offset the statistics when a
206 // peer_connection is opened and have some previous
207 // transfers from earlier connections.
208 void add_stat(size_type downloaded
, size_type uploaded
)
210 TORRENT_ASSERT(downloaded
>= 0);
211 TORRENT_ASSERT(uploaded
>= 0);
212 m_stat
[download_payload
].offset(downloaded
);
213 m_stat
[upload_payload
].offset(uploaded
);
216 size_type
last_payload_downloaded() const
217 { return m_stat
[download_payload
].counter(); }
218 size_type
last_payload_uploaded() const
219 { return m_stat
[upload_payload
].counter(); }
223 // these are the channels we keep stats for
231 download_ip_protocol
,
235 stat_channel m_stat
[num_channels
];
240 #endif // TORRENT_STAT_HPP_INCLUDED