mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-08-27 22:35:02 +00:00
collect and return unload/download rate stats
This commit is contained in:
@@ -305,6 +305,7 @@ namespace torrents
|
||||
m_Length (0), m_PieceLength (0), m_Interval (MIN_TRACKER_REQUESTS_INTERVAL),
|
||||
m_NextTrackerRequestTime (0), m_IsComplete (false), m_Uploaded (0)
|
||||
{
|
||||
ResetStats ();
|
||||
ParseDictionary (buf, [this](std::string_view key, std::string_view buf)->size_t
|
||||
{
|
||||
if (key == "announce")
|
||||
@@ -662,7 +663,9 @@ namespace torrents
|
||||
i2p::client::I2PServiceHandler (owner), m_Stream (stream), m_ReceiveBufferOffset (0),
|
||||
m_IsHandshakeSent (false), m_IsEstablished (false), m_IsChoked (true), m_IsRemoteChoked (true),
|
||||
m_IsInterested (false), m_IsRemoteInterested (false), m_LastReceiveTime (0), m_LastSendTime (0),
|
||||
m_NumRequests (0), m_NumPieces (0), m_LastRequestedPieceIndex (-1)
|
||||
m_NumRequests (0), m_NumPieces (0), m_LastRequestedPieceIndex (-1),
|
||||
m_DownloadRate (0), m_UploadRate (0), m_LastBlockDownloadTimestamp (0),
|
||||
m_LastBlockUploadTimestamp (0), m_ReceivedSinceLastTimestamp (0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1124,6 +1127,24 @@ namespace torrents
|
||||
}
|
||||
if (m_NumRequests > 0) m_NumRequests--;
|
||||
RequestNextBlocks ();
|
||||
// update stats
|
||||
auto ts = i2p::util::GetMonotonicMilliseconds ();
|
||||
if (m_LastBlockDownloadTimestamp)
|
||||
{
|
||||
m_ReceivedSinceLastTimestamp += REQUEST_BLOCK_SIZE;
|
||||
auto delta = ts - m_LastBlockDownloadTimestamp;
|
||||
if (delta >= BANDWIDTH_RATE_SAMPLING_INTERVAL)
|
||||
{
|
||||
if (m_DownloadRate)
|
||||
m_DownloadRate = (m_DownloadRate + m_ReceivedSinceLastTimestamp*1000/delta)/2;
|
||||
else
|
||||
m_DownloadRate = m_ReceivedSinceLastTimestamp*1000/delta;
|
||||
m_LastBlockDownloadTimestamp = ts;
|
||||
m_ReceivedSinceLastTimestamp = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
m_LastBlockDownloadTimestamp = ts;
|
||||
}
|
||||
|
||||
void PeerConnection::SendPieceMsg (uint32_t index, uint32_t offset, const uint8_t * data, size_t len)
|
||||
@@ -1154,6 +1175,20 @@ namespace torrents
|
||||
s->m_IsRemoteChoked = false;
|
||||
s->SendUnchokeMsg ();
|
||||
}
|
||||
// update status
|
||||
auto ts = i2p::util::GetMonotonicMilliseconds ();
|
||||
if (s->m_LastBlockUploadTimestamp)
|
||||
{
|
||||
auto delta = ts - s->m_LastBlockUploadTimestamp;
|
||||
if (delta)
|
||||
{
|
||||
if (s->m_UploadRate)
|
||||
s->m_UploadRate = (s->m_UploadRate + REQUEST_BLOCK_SIZE*1000/delta)/2;
|
||||
else
|
||||
s->m_UploadRate = REQUEST_BLOCK_SIZE*1000/delta;
|
||||
}
|
||||
}
|
||||
s->m_LastBlockUploadTimestamp = ts;
|
||||
}
|
||||
else
|
||||
s->Terminate ();
|
||||
@@ -1910,6 +1945,7 @@ namespace torrents
|
||||
{
|
||||
auto ts = i2p::util::GetMonotonicSeconds ();
|
||||
for (auto it: m_Torrents)
|
||||
{
|
||||
if (!it.second->IsComplete ())
|
||||
{
|
||||
if (it.second->UpdateStatus (ts))
|
||||
@@ -1917,6 +1953,8 @@ namespace torrents
|
||||
else
|
||||
UpdatePeersPerPiece (it.second);
|
||||
}
|
||||
}
|
||||
UpdateStats ();
|
||||
ScheduleStatusUpdate ();
|
||||
}
|
||||
}
|
||||
@@ -1990,5 +2028,24 @@ namespace torrents
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void TorrentsTunnel::UpdateStats ()
|
||||
{
|
||||
for (auto it: m_Torrents)
|
||||
it.second->ResetStats ();
|
||||
IterateHandlers ([](std::shared_ptr<i2p::client::I2PServiceHandler> handler) mutable
|
||||
{
|
||||
if (handler)
|
||||
{
|
||||
auto conn = std::static_pointer_cast<PeerConnection>(handler);
|
||||
auto torrent = conn->GetTorrent ();
|
||||
if (torrent)
|
||||
{
|
||||
torrent->SetDownloadRate (torrent->GetDownloadRate () + conn->GetDownloadRate ());
|
||||
torrent->SetUploadRate (torrent->GetUploadRate () + conn->GetUploadRate ());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace torrents
|
||||
constexpr int PIECE_INACTIVITY_TIMEOUT = 60; // in seconds
|
||||
constexpr int TORRENTS_STATUS_UPDATE_INTERVAL = 25; // in seconds
|
||||
constexpr int HANDSHAKE_RECEIVE_TIMEOUT = 20; // in seconds
|
||||
constexpr int BANDWIDTH_RATE_SAMPLING_INTERVAL = 20; // in milliseconds
|
||||
|
||||
constexpr size_t HANDSHAKE_MSG_LENGTH = 68;
|
||||
constexpr size_t INTERESTED_MSG_LENGTH = 5;
|
||||
@@ -196,6 +197,12 @@ namespace torrents
|
||||
void ApplyPeerRemoteBitfield (const boost::dynamic_bitset<>& peerRemoteBitfield);
|
||||
bool HasIncompletePieces (const boost::dynamic_bitset<>& peerRemoteBitfield) const; // if remote bitfie;d has incomplete pieces
|
||||
|
||||
void ResetStats () { m_DownloadRate = 0; m_UploadRate = 0; }
|
||||
uint64_t GetDownloadRate () const { return m_DownloadRate; }
|
||||
void SetDownloadRate (uint64_t downloadRate) { m_DownloadRate = downloadRate; }
|
||||
uint64_t GetUploadRate () const { return m_UploadRate; }
|
||||
void SetUploadRate (uint64_t uploadRate) { m_UploadRate = uploadRate; }
|
||||
|
||||
private:
|
||||
|
||||
size_t ParsePieces (std::string_view buf);
|
||||
@@ -216,6 +223,8 @@ namespace torrents
|
||||
bool m_IsComplete;
|
||||
std::list<std::pair<std::filesystem::path, size_t> > m_Files; // list of (path, length)
|
||||
size_t m_Uploaded;
|
||||
// stats
|
||||
uint64_t m_DownloadRate, m_UploadRate; // B/sec
|
||||
};
|
||||
|
||||
class TorrentsTunnel;
|
||||
@@ -247,6 +256,9 @@ namespace torrents
|
||||
int GetLastRequestedPieceIndex () const { return m_LastRequestedPieceIndex; }
|
||||
const boost::dynamic_bitset<>& GetRemoteBitfield () const { return m_RemoteBitfield;} ;
|
||||
|
||||
uint64_t GetDownloadRate () const { return m_DownloadRate; }
|
||||
uint64_t GetUploadRate () const { return m_UploadRate; }
|
||||
|
||||
private:
|
||||
|
||||
void Terminate ();
|
||||
@@ -281,7 +293,6 @@ namespace torrents
|
||||
bool RequestNextBlock ();
|
||||
void RequestNextBlock (uint32_t index, uint32_t offset, uint32_t len);
|
||||
bool RequestNextBlocks ();
|
||||
|
||||
bool SendRequestedBlock (const RequestedBlock& requestedBlock);
|
||||
|
||||
private:
|
||||
@@ -299,6 +310,10 @@ namespace torrents
|
||||
std::list<RequestedBlock> m_IncomingRequestsQueue;
|
||||
int m_LastRequestedPieceIndex;
|
||||
std::unique_ptr<boost::asio::steady_timer> m_HandshakeReceiveTimer;
|
||||
// stats
|
||||
uint64_t m_DownloadRate, m_UploadRate; // B/sec
|
||||
uint64_t m_LastBlockDownloadTimestamp, m_LastBlockUploadTimestamp; // monotonic milliseconds
|
||||
size_t m_ReceivedSinceLastTimestamp; // bytes
|
||||
};
|
||||
|
||||
class TorrentsTunnel final: public i2p::client::I2PService
|
||||
@@ -365,6 +380,7 @@ namespace torrents
|
||||
void ConnectToPeer (std::shared_ptr<Torrent> torrent, const i2p::data::IdentHash& peer);
|
||||
size_t ConnectToPeers (std::shared_ptr<Torrent> torrent);
|
||||
void UpdatePeersPerPiece (std::shared_ptr<Torrent> torrent);
|
||||
void UpdateStats ();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -152,9 +152,7 @@ namespace torrents
|
||||
{
|
||||
auto arguments = jsonRequest.at ("arguments").as_object ();
|
||||
bool deleteFiles = false;
|
||||
if (arguments.contains ("delete_local_data")) // for transmission >= 4.1
|
||||
deleteFiles = arguments.at ("delete_local_data").as_bool ();
|
||||
else if (arguments.contains ("delete-local-data")) // for transmission < 4.1
|
||||
if (arguments.contains ("delete-local-data"))
|
||||
deleteFiles = arguments.at ("delete-local-data").as_bool ();
|
||||
std::vector<int> torrentIds;
|
||||
if (arguments.contains ("ids"))
|
||||
@@ -204,9 +202,9 @@ namespace torrents
|
||||
t["is_finished"] = torrent->IsComplete ();
|
||||
t["size_when_done"] = torrent->GetLength ();
|
||||
t["left_until_done"] = torrent->GetLeft ();
|
||||
t["eta"] = 1; // TODO
|
||||
t["rate_download"] = 1000; // B/s TODO:
|
||||
t["rate_upload"] = 0; // B/s TODO:
|
||||
t["eta"] = 600; // TODO
|
||||
t["rate_download"] = torrent->GetDownloadRate ();
|
||||
t["rate_upload"] = torrent->GetUploadRate ();
|
||||
t["upload_ratio"] = 1; // TODO:
|
||||
if (torrentsRequested)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user