(trunk, libT) #5168 'make libtransmission's public funcs nonblocking when possible' -- remove tr_torrentRef() and tr_torrentUnref() as discussed in https://trac.transmissionbt.com/ticket/5168#comment:8
This commit is contained in:
parent
c5ff0c0308
commit
aea6d7cd6f
|
@ -2,5 +2,6 @@
|
|||
export G_SLICE=always-malloc
|
||||
export G_DEBUG=gc-friendly
|
||||
export GLIBCXX_FORCE_NEW=1
|
||||
valgrind --tool=cachegrind ./transmission-gtk 2>&1 | tee runlog
|
||||
#valgrind --tool=cachegrind ./transmission-gtk -p -g /tmp/transmission-test 2>&1 | tee runlog
|
||||
valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=48 --log-file=x-valgrind --show-reachable=no ./transmission-gtk -p 2>&1 | tee runlog
|
||||
#valgrind --tool=memcheck --leak-check=full --leak-resolution=high --num-callers=48 --log-file=x-valgrind --show-reachable=no ./transmission-gtk -p 2>&1 | tee runlog
|
||||
|
|
|
@ -40,10 +40,10 @@ enum
|
|||
***/
|
||||
|
||||
static void
|
||||
getProgressString (GString * gstr,
|
||||
tr_torrent * tor,
|
||||
const tr_info * info,
|
||||
const tr_stat * st)
|
||||
getProgressString (GString * gstr,
|
||||
const tr_torrent * tor,
|
||||
const tr_info * info,
|
||||
const tr_stat * st)
|
||||
{
|
||||
const int isDone = st->leftUntilDone == 0;
|
||||
const uint64_t haveTotal = st->haveUnchecked + st->haveValid;
|
||||
|
@ -443,7 +443,7 @@ get_size_full (TorrentCellRenderer * cell,
|
|||
GdkPixbuf * icon;
|
||||
|
||||
struct TorrentCellRendererPrivate * p = cell->priv;
|
||||
tr_torrent * tor = p->tor;
|
||||
const tr_torrent * tor = p->tor;
|
||||
const tr_stat * st = tr_torrentStatCached ((tr_torrent*)tor);
|
||||
const tr_info * inf = tr_torrentInfo (tor);
|
||||
GString * gstr_prog = p->gstr1;
|
||||
|
@ -537,7 +537,7 @@ get_text_color (GtkWidget * w, const tr_stat * st, GtrColor * setme)
|
|||
|
||||
|
||||
static double
|
||||
get_percent_done (tr_torrent * tor, const tr_stat * st, bool * seed)
|
||||
get_percent_done (const tr_torrent * tor, const tr_stat * st, bool * seed)
|
||||
{
|
||||
double d;
|
||||
|
||||
|
@ -588,7 +588,7 @@ render_compact (TorrentCellRenderer * cell,
|
|||
bool seed;
|
||||
|
||||
struct TorrentCellRendererPrivate * p = cell->priv;
|
||||
tr_torrent * tor = p->tor;
|
||||
const tr_torrent * tor = p->tor;
|
||||
const tr_stat * st = tr_torrentStatCached ((tr_torrent*)tor);
|
||||
const gboolean active = (st->activity != TR_STATUS_STOPPED) && (st->activity != TR_STATUS_DOWNLOAD_WAIT) && (st->activity != TR_STATUS_SEED_WAIT);
|
||||
const double percentDone = get_percent_done (tor, st, &seed);
|
||||
|
@ -666,7 +666,7 @@ render_full (TorrentCellRenderer * cell,
|
|||
bool seed;
|
||||
|
||||
struct TorrentCellRendererPrivate * p = cell->priv;
|
||||
tr_torrent * tor = p->tor;
|
||||
const tr_torrent * tor = p->tor;
|
||||
const tr_stat * st = tr_torrentStatCached ((tr_torrent*)tor);
|
||||
const tr_info * inf = tr_torrentInfo (tor);
|
||||
const gboolean active = (st->activity != TR_STATUS_STOPPED) && (st->activity != TR_STATUS_DOWNLOAD_WAIT) && (st->activity != TR_STATUS_SEED_WAIT);
|
||||
|
|
|
@ -1129,10 +1129,8 @@ gotError (tr_peerIo * io,
|
|||
tr_peerIoGetTorrentHash (io)) :
|
||||
NULL;
|
||||
/* Don't mark a peer as non-uTP unless it's really a connect failure. */
|
||||
if ((errcode == ETIMEDOUT || errcode == ECONNREFUSED) && tr_torrentRef(tor)) {
|
||||
if ((errcode == ETIMEDOUT || errcode == ECONNREFUSED) && tr_isTorrent(tor))
|
||||
tr_peerMgrSetUtpFailed (tor, tr_peerIoGetAddress (io, NULL), true);
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
|
||||
if (!tr_peerIoReconnect (handshake->io)) {
|
||||
uint8_t msg[HANDSHAKE_SIZE];
|
||||
|
|
|
@ -2548,42 +2548,40 @@ tr_peerMgrOnTorrentGotMetainfo (tr_torrent * tor)
|
|||
}
|
||||
|
||||
void
|
||||
tr_peerMgrTorrentAvailability (tr_torrent * tor, int8_t * tab, unsigned int tabCount)
|
||||
tr_peerMgrTorrentAvailability (const tr_torrent * tor,
|
||||
int8_t * tab,
|
||||
unsigned int tabCount)
|
||||
{
|
||||
assert (tr_isTorrent (tor));
|
||||
assert (tab != NULL);
|
||||
assert (tabCount > 0);
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
memset (tab, 0, tabCount);
|
||||
|
||||
if (tr_torrentHasMetadata (tor))
|
||||
{
|
||||
memset (tab, 0, tabCount);
|
||||
tr_piece_index_t i;
|
||||
const int peerCount = tr_ptrArraySize (&tor->torrentPeers->peers);
|
||||
const tr_peer ** peers = (const tr_peer**) tr_ptrArrayBase (&tor->torrentPeers->peers);
|
||||
const float interval = tor->info.pieceCount / (float)tabCount;
|
||||
const bool isSeed = tr_cpGetStatus (&tor->completion) == TR_SEED;
|
||||
|
||||
if (tr_torrentHasMetadata (tor))
|
||||
for (i=0; i<tabCount; ++i)
|
||||
{
|
||||
tr_piece_index_t i;
|
||||
const int peerCount = tr_ptrArraySize (&tor->torrentPeers->peers);
|
||||
const tr_peer ** peers = (const tr_peer**) tr_ptrArrayBase (&tor->torrentPeers->peers);
|
||||
const float interval = tor->info.pieceCount / (float)tabCount;
|
||||
const bool isSeed = tr_cpGetStatus (&tor->completion) == TR_SEED;
|
||||
const int piece = i * interval;
|
||||
|
||||
for (i=0; i<tabCount; ++i)
|
||||
if (isSeed || tr_cpPieceIsComplete (&tor->completion, piece))
|
||||
{
|
||||
const int piece = i * interval;
|
||||
|
||||
if (isSeed || tr_cpPieceIsComplete (&tor->completion, piece))
|
||||
{
|
||||
tab[i] = -1;
|
||||
}
|
||||
else if (peerCount)
|
||||
{
|
||||
int j;
|
||||
for (j=0; j<peerCount; ++j)
|
||||
if (tr_bitfieldHas (&peers[j]->have, piece))
|
||||
++tab[i];
|
||||
}
|
||||
tab[i] = -1;
|
||||
}
|
||||
else if (peerCount)
|
||||
{
|
||||
int j;
|
||||
for (j=0; j<peerCount; ++j)
|
||||
if (tr_bitfieldHas (&peers[j]->have, piece))
|
||||
++tab[i];
|
||||
}
|
||||
}
|
||||
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2648,73 +2646,74 @@ tr_peerMgrTorrentStats (tr_torrent * tor,
|
|||
int * setmePeersGettingFromUs,
|
||||
int * setmePeersFrom)
|
||||
{
|
||||
int i;
|
||||
int size;
|
||||
Torrent * t;
|
||||
const tr_peer ** peers;
|
||||
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
*setmePeersConnected = 0;
|
||||
*setmePeersGettingFromUs = 0;
|
||||
*setmePeersSendingToUs = 0;
|
||||
*setmeWebseedsSendingToUs = 0;
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
t = tor->torrentPeers;
|
||||
size = tr_ptrArraySize (&t->peers);
|
||||
peers = (const tr_peer **) tr_ptrArrayBase (&t->peers);
|
||||
|
||||
for (i=0; i<TR_PEER_FROM__MAX; ++i)
|
||||
setmePeersFrom[i] = 0;
|
||||
|
||||
for (i=0; i<size; ++i)
|
||||
{
|
||||
int i;
|
||||
const Torrent * t = tor->torrentPeers;
|
||||
const int size = tr_ptrArraySize (&t->peers);
|
||||
const tr_peer ** peers = (const tr_peer **) tr_ptrArrayBase (&t->peers);
|
||||
const tr_peer * peer = peers[i];
|
||||
const struct peer_atom * atom = peer->atom;
|
||||
|
||||
for (i=0; i<TR_PEER_FROM__MAX; ++i)
|
||||
setmePeersFrom[i] = 0;
|
||||
if (peer->io == NULL) /* not connected */
|
||||
continue;
|
||||
|
||||
for (i=0; i<size; ++i)
|
||||
{
|
||||
const tr_peer * peer = peers[i];
|
||||
const struct peer_atom * atom = peer->atom;
|
||||
++*setmePeersConnected;
|
||||
|
||||
if (peer->io == NULL) /* not connected */
|
||||
continue;
|
||||
++setmePeersFrom[atom->fromFirst];
|
||||
|
||||
++*setmePeersConnected;
|
||||
if (clientIsDownloadingFrom (tor, peer))
|
||||
++*setmePeersSendingToUs;
|
||||
|
||||
++setmePeersFrom[atom->fromFirst];
|
||||
|
||||
if (clientIsDownloadingFrom (tor, peer))
|
||||
++*setmePeersSendingToUs;
|
||||
|
||||
if (clientIsUploadingTo (peer))
|
||||
++*setmePeersGettingFromUs;
|
||||
}
|
||||
|
||||
*setmeWebseedsSendingToUs = countActiveWebseeds (t);
|
||||
tr_torrentUnref (tor);
|
||||
if (clientIsUploadingTo (peer))
|
||||
++*setmePeersGettingFromUs;
|
||||
}
|
||||
|
||||
*setmeWebseedsSendingToUs = countActiveWebseeds (t);
|
||||
}
|
||||
|
||||
double*
|
||||
tr_peerMgrWebSpeeds_KBps (tr_torrent * tor)
|
||||
tr_peerMgrWebSpeeds_KBps (const tr_torrent * tor)
|
||||
{
|
||||
int i;
|
||||
int webseedCount;
|
||||
const Torrent * t;
|
||||
const tr_webseed ** webseeds;
|
||||
double * ret = NULL;
|
||||
const uint64_t now = tr_time_msec ();
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
t = tor->torrentPeers;
|
||||
webseedCount = tr_ptrArraySize (&t->webseeds);
|
||||
webseeds = (const tr_webseed**) tr_ptrArrayBase (&t->webseeds);
|
||||
ret = tr_new0 (double, webseedCount);
|
||||
|
||||
assert (t->manager != NULL);
|
||||
assert (webseedCount == tor->info.webseedCount);
|
||||
|
||||
for (i=0; i<webseedCount; ++i)
|
||||
{
|
||||
int i;
|
||||
const Torrent * t = tor->torrentPeers;
|
||||
const int webseedCount = tr_ptrArraySize (&t->webseeds);
|
||||
const tr_webseed ** webseeds = (const tr_webseed**) tr_ptrArrayBase (&t->webseeds);
|
||||
const uint64_t now = tr_time_msec ();
|
||||
|
||||
ret = tr_new0 (double, webseedCount);
|
||||
|
||||
assert (t->manager != NULL);
|
||||
assert (webseedCount == tor->info.webseedCount);
|
||||
|
||||
for (i=0; i<webseedCount; ++i)
|
||||
{
|
||||
unsigned int Bps;
|
||||
if (tr_webseedGetSpeed_Bps (webseeds[i], now, &Bps))
|
||||
ret[i] = Bps / (double)tr_speed_K;
|
||||
else
|
||||
ret[i] = -1.0;
|
||||
}
|
||||
|
||||
tr_torrentUnref (tor);
|
||||
unsigned int Bps;
|
||||
if (tr_webseedGetSpeed_Bps (webseeds[i], now, &Bps))
|
||||
ret[i] = Bps / (double)tr_speed_K;
|
||||
else
|
||||
ret[i] = -1.0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -2723,78 +2722,75 @@ tr_peerMgrWebSpeeds_KBps (tr_torrent * tor)
|
|||
unsigned int
|
||||
tr_peerGetPieceSpeed_Bps (const tr_peer * peer, uint64_t now, tr_direction direction)
|
||||
{
|
||||
return peer->io ? tr_peerIoGetPieceSpeed_Bps (peer->io, now, direction) : 0.0;
|
||||
return peer->io ? tr_peerIoGetPieceSpeed_Bps (peer->io, now, direction) : 0.0;
|
||||
}
|
||||
|
||||
struct tr_peer_stat *
|
||||
tr_peerMgrPeerStats (tr_torrent * tor, int * setmeCount)
|
||||
tr_peerMgrPeerStats (const tr_torrent * tor, int * setmeCount)
|
||||
{
|
||||
int i;
|
||||
int size = 0;
|
||||
tr_peer_stat * ret = NULL;
|
||||
tr_peer_stat * ret;
|
||||
const Torrent * t;
|
||||
const tr_peer ** peers;
|
||||
const time_t now = tr_time ();
|
||||
const uint64_t now_msec = tr_time_msec ();
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
assert (tr_isTorrent (tor));
|
||||
assert (tor->torrentPeers->manager != NULL);
|
||||
|
||||
t = tor->torrentPeers;
|
||||
peers = (const tr_peer**) tr_ptrArrayBase (&t->peers);
|
||||
size = tr_ptrArraySize (&t->peers);
|
||||
ret = tr_new0 (tr_peer_stat, size);
|
||||
|
||||
for (i=0; i<size; ++i)
|
||||
{
|
||||
int i;
|
||||
const Torrent * t = tor->torrentPeers;
|
||||
const tr_peer ** peers = (const tr_peer**) tr_ptrArrayBase (&t->peers);
|
||||
const uint64_t now_msec = tr_time_msec ();
|
||||
const time_t now = tr_time ();
|
||||
char * pch;
|
||||
const tr_peer * peer = peers[i];
|
||||
const struct peer_atom * atom = peer->atom;
|
||||
tr_peer_stat * stat = ret + i;
|
||||
|
||||
assert (t->manager != NULL);
|
||||
tr_address_to_string_with_buf (&atom->addr, stat->addr, sizeof (stat->addr));
|
||||
tr_strlcpy (stat->client, (peer->client ? peer->client : ""), sizeof (stat->client));
|
||||
stat->port = ntohs (peer->atom->port);
|
||||
stat->from = atom->fromFirst;
|
||||
stat->progress = peer->progress;
|
||||
stat->isUTP = peer->io->utp_socket != NULL;
|
||||
stat->isEncrypted = tr_peerIoIsEncrypted (peer->io) ? 1 : 0;
|
||||
stat->rateToPeer_KBps = toSpeedKBps (tr_peerGetPieceSpeed_Bps (peer, now_msec, TR_CLIENT_TO_PEER));
|
||||
stat->rateToClient_KBps = toSpeedKBps (tr_peerGetPieceSpeed_Bps (peer, now_msec, TR_PEER_TO_CLIENT));
|
||||
stat->peerIsChoked = peer->peerIsChoked;
|
||||
stat->peerIsInterested = peer->peerIsInterested;
|
||||
stat->clientIsChoked = peer->clientIsChoked;
|
||||
stat->clientIsInterested = peer->clientIsInterested;
|
||||
stat->isIncoming = tr_peerIoIsIncoming (peer->io);
|
||||
stat->isDownloadingFrom = clientIsDownloadingFrom (tor, peer);
|
||||
stat->isUploadingTo = clientIsUploadingTo (peer);
|
||||
stat->isSeed = peerIsSeed (peer);
|
||||
|
||||
size = tr_ptrArraySize (&t->peers);
|
||||
ret = tr_new0 (tr_peer_stat, size);
|
||||
stat->blocksToPeer = tr_historyGet (&peer->blocksSentToPeer, now, CANCEL_HISTORY_SEC);
|
||||
stat->blocksToClient = tr_historyGet (&peer->blocksSentToClient, now, CANCEL_HISTORY_SEC);
|
||||
stat->cancelsToPeer = tr_historyGet (&peer->cancelsSentToPeer, now, CANCEL_HISTORY_SEC);
|
||||
stat->cancelsToClient = tr_historyGet (&peer->cancelsSentToClient, now, CANCEL_HISTORY_SEC);
|
||||
|
||||
for (i=0; i<size; ++i)
|
||||
{
|
||||
char * pch;
|
||||
const tr_peer * peer = peers[i];
|
||||
const struct peer_atom * atom = peer->atom;
|
||||
tr_peer_stat * stat = ret + i;
|
||||
stat->pendingReqsToPeer = peer->pendingReqsToPeer;
|
||||
stat->pendingReqsToClient = peer->pendingReqsToClient;
|
||||
|
||||
tr_address_to_string_with_buf (&atom->addr, stat->addr, sizeof (stat->addr));
|
||||
tr_strlcpy (stat->client, (peer->client ? peer->client : ""), sizeof (stat->client));
|
||||
stat->port = ntohs (peer->atom->port);
|
||||
stat->from = atom->fromFirst;
|
||||
stat->progress = peer->progress;
|
||||
stat->isUTP = peer->io->utp_socket != NULL;
|
||||
stat->isEncrypted = tr_peerIoIsEncrypted (peer->io) ? 1 : 0;
|
||||
stat->rateToPeer_KBps = toSpeedKBps (tr_peerGetPieceSpeed_Bps (peer, now_msec, TR_CLIENT_TO_PEER));
|
||||
stat->rateToClient_KBps = toSpeedKBps (tr_peerGetPieceSpeed_Bps (peer, now_msec, TR_PEER_TO_CLIENT));
|
||||
stat->peerIsChoked = peer->peerIsChoked;
|
||||
stat->peerIsInterested = peer->peerIsInterested;
|
||||
stat->clientIsChoked = peer->clientIsChoked;
|
||||
stat->clientIsInterested = peer->clientIsInterested;
|
||||
stat->isIncoming = tr_peerIoIsIncoming (peer->io);
|
||||
stat->isDownloadingFrom = clientIsDownloadingFrom (tor, peer);
|
||||
stat->isUploadingTo = clientIsUploadingTo (peer);
|
||||
stat->isSeed = peerIsSeed (peer);
|
||||
|
||||
stat->blocksToPeer = tr_historyGet (&peer->blocksSentToPeer, now, CANCEL_HISTORY_SEC);
|
||||
stat->blocksToClient = tr_historyGet (&peer->blocksSentToClient, now, CANCEL_HISTORY_SEC);
|
||||
stat->cancelsToPeer = tr_historyGet (&peer->cancelsSentToPeer, now, CANCEL_HISTORY_SEC);
|
||||
stat->cancelsToClient = tr_historyGet (&peer->cancelsSentToClient, now, CANCEL_HISTORY_SEC);
|
||||
|
||||
stat->pendingReqsToPeer = peer->pendingReqsToPeer;
|
||||
stat->pendingReqsToClient = peer->pendingReqsToClient;
|
||||
|
||||
pch = stat->flagStr;
|
||||
if (stat->isUTP) *pch++ = 'T';
|
||||
if (t->optimistic == peer) *pch++ = 'O';
|
||||
if (stat->isDownloadingFrom) *pch++ = 'D';
|
||||
else if (stat->clientIsInterested) *pch++ = 'd';
|
||||
if (stat->isUploadingTo) *pch++ = 'U';
|
||||
else if (stat->peerIsInterested) *pch++ = 'u';
|
||||
if (!stat->clientIsChoked && !stat->clientIsInterested) *pch++ = 'K';
|
||||
if (!stat->peerIsChoked && !stat->peerIsInterested) *pch++ = '?';
|
||||
if (stat->isEncrypted) *pch++ = 'E';
|
||||
if (stat->from == TR_PEER_FROM_DHT) *pch++ = 'H';
|
||||
else if (stat->from == TR_PEER_FROM_PEX) *pch++ = 'X';
|
||||
if (stat->isIncoming) *pch++ = 'I';
|
||||
*pch = '\0';
|
||||
}
|
||||
|
||||
tr_torrentUnref (tor);
|
||||
pch = stat->flagStr;
|
||||
if (stat->isUTP) *pch++ = 'T';
|
||||
if (t->optimistic == peer) *pch++ = 'O';
|
||||
if (stat->isDownloadingFrom) *pch++ = 'D';
|
||||
else if (stat->clientIsInterested) *pch++ = 'd';
|
||||
if (stat->isUploadingTo) *pch++ = 'U';
|
||||
else if (stat->peerIsInterested) *pch++ = 'u';
|
||||
if (!stat->clientIsChoked && !stat->clientIsInterested) *pch++ = 'K';
|
||||
if (!stat->peerIsChoked && !stat->peerIsInterested) *pch++ = '?';
|
||||
if (stat->isEncrypted) *pch++ = 'E';
|
||||
if (stat->from == TR_PEER_FROM_DHT) *pch++ = 'H';
|
||||
else if (stat->from == TR_PEER_FROM_PEX) *pch++ = 'X';
|
||||
if (stat->isIncoming) *pch++ = 'I';
|
||||
*pch = '\0';
|
||||
}
|
||||
|
||||
*setmeCount = size;
|
||||
|
|
|
@ -225,9 +225,9 @@ void tr_peerMgrAddTorrent (tr_peerMgr * manager,
|
|||
|
||||
void tr_peerMgrRemoveTorrent (tr_torrent * tor);
|
||||
|
||||
void tr_peerMgrTorrentAvailability (tr_torrent * tor,
|
||||
int8_t * tab,
|
||||
unsigned int tabCount);
|
||||
void tr_peerMgrTorrentAvailability (const tr_torrent * tor,
|
||||
int8_t * tab,
|
||||
unsigned int tabCount);
|
||||
|
||||
uint64_t tr_peerMgrGetDesiredAvailable (const tr_torrent * tor);
|
||||
|
||||
|
@ -242,10 +242,10 @@ void tr_peerMgrTorrentStats (tr_torrent * tor,
|
|||
int * setmePeersGettingFromUs,
|
||||
int * setmePeersFrom); /* TR_PEER_FROM__MAX */
|
||||
|
||||
struct tr_peer_stat* tr_peerMgrPeerStats (tr_torrent * tor,
|
||||
int * setmeCount);
|
||||
struct tr_peer_stat* tr_peerMgrPeerStats (const tr_torrent * tor,
|
||||
int * setmeCount);
|
||||
|
||||
double* tr_peerMgrWebSpeeds_KBps (tr_torrent * tor);
|
||||
double* tr_peerMgrWebSpeeds_KBps (const tr_torrent * tor);
|
||||
|
||||
|
||||
unsigned int tr_peerGetPieceSpeed_Bps (const tr_peer * peer,
|
||||
|
|
|
@ -1769,7 +1769,7 @@ sessionCloseImpl (void * vsession)
|
|||
torrents[i] = tor = tr_torrentNext (session, tor);
|
||||
qsort (torrents, n, sizeof (tr_torrent*), compareTorrentByCur);
|
||||
for (i = 0; i < n; ++i)
|
||||
tr_torrentUnref (torrents[i]);
|
||||
tr_torrentFree (torrents[i]);
|
||||
tr_free (torrents);
|
||||
|
||||
/* Close the announcer *after* closing the torrents
|
||||
|
|
|
@ -152,30 +152,23 @@ tr_torrentFindFromObfuscatedHash (tr_session * session,
|
|||
}
|
||||
|
||||
bool
|
||||
tr_torrentIsPieceTransferAllowed (tr_torrent * tor,
|
||||
tr_direction direction)
|
||||
tr_torrentIsPieceTransferAllowed (const tr_torrent * tor,
|
||||
tr_direction direction)
|
||||
{
|
||||
bool allowed = false;
|
||||
bool allowed = true;
|
||||
unsigned int limit;
|
||||
|
||||
assert (tr_isTorrent (tor));
|
||||
assert (tr_isDirection (direction));
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
{
|
||||
unsigned int limit;
|
||||
if (tr_torrentUsesSpeedLimit (tor, direction))
|
||||
if (tr_torrentGetSpeedLimit_Bps (tor, direction) <= 0)
|
||||
allowed = false;
|
||||
|
||||
allowed = true;
|
||||
|
||||
if (tr_torrentUsesSpeedLimit (tor, direction))
|
||||
if (tr_torrentGetSpeedLimit_Bps (tor, direction) <= 0)
|
||||
allowed = false;
|
||||
|
||||
if (tr_torrentUsesSessionLimits (tor))
|
||||
if (tr_sessionGetActiveSpeedLimit_Bps (tor->session, direction, &limit))
|
||||
if (limit <= 0)
|
||||
allowed = false;
|
||||
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
if (tr_torrentUsesSessionLimits (tor))
|
||||
if (tr_sessionGetActiveSpeedLimit_Bps (tor->session, direction, &limit))
|
||||
if (limit <= 0)
|
||||
allowed = false;
|
||||
|
||||
return allowed;
|
||||
}
|
||||
|
@ -208,19 +201,12 @@ tr_torrentGetSpeedLimit_Bps (const tr_torrent * tor, tr_direction dir)
|
|||
return tr_bandwidthGetDesiredSpeed_Bps (&tor->bandwidth, dir);
|
||||
}
|
||||
unsigned int
|
||||
tr_torrentGetSpeedLimit_KBps (tr_torrent * tor, tr_direction dir)
|
||||
tr_torrentGetSpeedLimit_KBps (const tr_torrent * tor, tr_direction dir)
|
||||
{
|
||||
unsigned int limit = 0;
|
||||
|
||||
assert (tr_isTorrent (tor));
|
||||
assert (tr_isDirection (dir));
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
{
|
||||
limit = toSpeedKBps (tr_torrentGetSpeedLimit_Bps (tor, dir));
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
|
||||
return limit;
|
||||
return toSpeedKBps (tr_torrentGetSpeedLimit_Bps (tor, dir));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -234,17 +220,11 @@ tr_torrentUseSpeedLimit (tr_torrent * tor, tr_direction dir, bool do_use)
|
|||
}
|
||||
|
||||
bool
|
||||
tr_torrentUsesSpeedLimit (tr_torrent * tor, tr_direction dir)
|
||||
tr_torrentUsesSpeedLimit (const tr_torrent * tor, tr_direction dir)
|
||||
{
|
||||
bool limited = false;
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
{
|
||||
limited = tr_bandwidthIsLimited (&tor->bandwidth, dir);
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
|
||||
return limited;
|
||||
return tr_bandwidthIsLimited (&tor->bandwidth, dir);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -262,17 +242,11 @@ tr_torrentUseSessionLimits (tr_torrent * tor, bool doUse)
|
|||
}
|
||||
|
||||
bool
|
||||
tr_torrentUsesSessionLimits (tr_torrent * tor)
|
||||
tr_torrentUsesSessionLimits (const tr_torrent * tor)
|
||||
{
|
||||
bool limited = false;
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
{
|
||||
limited = tr_bandwidthAreParentLimitsHonored (&tor->bandwidth, TR_UP);
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
|
||||
return limited;
|
||||
return tr_bandwidthAreParentLimitsHonored (&tor->bandwidth, TR_UP);
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -315,46 +289,37 @@ tr_torrentSetRatioLimit (tr_torrent * tor, double desiredRatio)
|
|||
}
|
||||
|
||||
double
|
||||
tr_torrentGetRatioLimit (tr_torrent * tor)
|
||||
tr_torrentGetRatioLimit (const tr_torrent * tor)
|
||||
{
|
||||
double limit = 0;
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
{
|
||||
limit = tor->desiredRatio;
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
|
||||
return limit;
|
||||
return tor->desiredRatio;
|
||||
}
|
||||
|
||||
bool
|
||||
tr_torrentGetSeedRatio (tr_torrent * tor, double * ratio)
|
||||
tr_torrentGetSeedRatio (const tr_torrent * tor, double * ratio)
|
||||
{
|
||||
bool isLimited = false;
|
||||
bool isLimited;
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
switch (tr_torrentGetRatioMode (tor))
|
||||
{
|
||||
switch (tr_torrentGetRatioMode (tor))
|
||||
{
|
||||
case TR_RATIOLIMIT_SINGLE:
|
||||
isLimited = true;
|
||||
if (ratio)
|
||||
*ratio = tr_torrentGetRatioLimit (tor);
|
||||
break;
|
||||
case TR_RATIOLIMIT_SINGLE:
|
||||
isLimited = true;
|
||||
if (ratio)
|
||||
*ratio = tr_torrentGetRatioLimit (tor);
|
||||
break;
|
||||
|
||||
case TR_RATIOLIMIT_GLOBAL:
|
||||
isLimited = tr_sessionIsRatioLimited (tor->session);
|
||||
if (isLimited && ratio)
|
||||
*ratio = tr_sessionGetRatioLimit (tor->session);
|
||||
break;
|
||||
case TR_RATIOLIMIT_GLOBAL:
|
||||
isLimited = tr_sessionIsRatioLimited (tor->session);
|
||||
if (isLimited && ratio)
|
||||
*ratio = tr_sessionGetRatioLimit (tor->session);
|
||||
break;
|
||||
|
||||
default: /* TR_RATIOLIMIT_UNLIMITED */
|
||||
isLimited = false;
|
||||
break;
|
||||
}
|
||||
|
||||
tr_torrentUnref (tor);
|
||||
default: /* TR_RATIOLIMIT_UNLIMITED */
|
||||
isLimited = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return isLimited;
|
||||
|
@ -363,29 +328,31 @@ tr_torrentGetSeedRatio (tr_torrent * tor, double * ratio)
|
|||
/* returns true if the seed ratio applies --
|
||||
* it applies if the torrent's a seed AND it has a seed ratio set */
|
||||
static bool
|
||||
tr_torrentGetSeedRatioBytes (tr_torrent * tor,
|
||||
uint64_t * setmeLeft,
|
||||
uint64_t * setmeGoal)
|
||||
tr_torrentGetSeedRatioBytes (const tr_torrent * tor,
|
||||
uint64_t * setmeLeft,
|
||||
uint64_t * setmeGoal)
|
||||
{
|
||||
double seedRatio;
|
||||
bool seedRatioApplies = false;
|
||||
double seedRatio;
|
||||
bool seedRatioApplies = false;
|
||||
|
||||
if (tr_torrentGetSeedRatio (tor, &seedRatio))
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
if (tr_torrentGetSeedRatio (tor, &seedRatio))
|
||||
{
|
||||
const uint64_t u = tor->uploadedCur + tor->uploadedPrev;
|
||||
const uint64_t d = tor->downloadedCur + tor->downloadedPrev;
|
||||
const uint64_t baseline = d ? d : tr_cpSizeWhenDone (&tor->completion);
|
||||
const uint64_t goal = baseline * seedRatio;
|
||||
if (setmeLeft) *setmeLeft = goal > u ? goal - u : 0;
|
||||
if (setmeGoal) *setmeGoal = goal;
|
||||
seedRatioApplies = tr_torrentIsSeed (tor);
|
||||
const uint64_t u = tor->uploadedCur + tor->uploadedPrev;
|
||||
const uint64_t d = tor->downloadedCur + tor->downloadedPrev;
|
||||
const uint64_t baseline = d ? d : tr_cpSizeWhenDone (&tor->completion);
|
||||
const uint64_t goal = baseline * seedRatio;
|
||||
if (setmeLeft) *setmeLeft = goal > u ? goal - u : 0;
|
||||
if (setmeGoal) *setmeGoal = goal;
|
||||
seedRatioApplies = tr_torrentIsSeed (tor);
|
||||
}
|
||||
|
||||
return seedRatioApplies;
|
||||
return seedRatioApplies;
|
||||
}
|
||||
|
||||
static bool
|
||||
tr_torrentIsSeedRatioDone (tr_torrent * tor)
|
||||
tr_torrentIsSeedRatioDone (const tr_torrent * tor)
|
||||
{
|
||||
uint64_t bytesLeft;
|
||||
return tr_torrentGetSeedRatioBytes (tor, &bytesLeft, NULL) && !bytesLeft;
|
||||
|
@ -850,7 +817,6 @@ torrentInit (tr_torrent * tor, const tr_ctor * ctor)
|
|||
tor->session = session;
|
||||
tor->uniqueId = nextUniqueId++;
|
||||
tor->magicNumber = TORRENT_MAGIC_NUMBER;
|
||||
tor->refCount = 1;
|
||||
tor->queuePosition = session->torrentCount;
|
||||
|
||||
tr_peerIdInit (tor->peer_id);
|
||||
|
@ -1192,25 +1158,20 @@ tr_torrentIsStalled (const tr_torrent * tor)
|
|||
|
||||
|
||||
static double
|
||||
getVerifyProgress (tr_torrent * tor)
|
||||
getVerifyProgress (const tr_torrent * tor)
|
||||
{
|
||||
double d = 0;
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
if (tr_torrentHasMetadata (tor))
|
||||
{
|
||||
if (tr_torrentHasMetadata (tor))
|
||||
{
|
||||
tr_piece_index_t i, n;
|
||||
tr_piece_index_t checked = 0;
|
||||
tr_piece_index_t i, n;
|
||||
tr_piece_index_t checked = 0;
|
||||
|
||||
for (i=0, n=tor->info.pieceCount; i!=n; ++i)
|
||||
if (tor->info.pieces[i].timeChecked)
|
||||
++checked;
|
||||
for (i=0, n=tor->info.pieceCount; i!=n; ++i)
|
||||
if (tor->info.pieces[i].timeChecked)
|
||||
++checked;
|
||||
|
||||
d = checked / (double)tor->info.pieceCount;
|
||||
}
|
||||
|
||||
tr_torrentUnref (tor);
|
||||
d = checked / (double)tor->info.pieceCount;
|
||||
}
|
||||
|
||||
return d;
|
||||
|
@ -1219,142 +1180,142 @@ getVerifyProgress (tr_torrent * tor)
|
|||
const tr_stat *
|
||||
tr_torrentStat (tr_torrent * tor)
|
||||
{
|
||||
tr_stat * s;
|
||||
uint64_t now;
|
||||
uint64_t seedRatioBytesLeft;
|
||||
uint64_t seedRatioBytesGoal;
|
||||
bool seedRatioApplies;
|
||||
uint16_t seedIdleMinutes;
|
||||
tr_stat * s;
|
||||
uint64_t seedRatioBytesLeft;
|
||||
uint64_t seedRatioBytesGoal;
|
||||
bool seedRatioApplies;
|
||||
uint16_t seedIdleMinutes;
|
||||
const uint64_t now = tr_time_msec ();
|
||||
|
||||
if (!tr_torrentRef(tor))
|
||||
return NULL;
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
tor->lastStatTime = tr_time ();
|
||||
tor->lastStatTime = tr_time ();
|
||||
|
||||
s = &tor->stats;
|
||||
s->id = tor->uniqueId;
|
||||
s->activity = tr_torrentGetActivity (tor);
|
||||
s->error = tor->error;
|
||||
s->queuePosition = tor->queuePosition;
|
||||
s->isStalled = tr_torrentIsStalled (tor);
|
||||
tr_strlcpy (s->errorString, tor->errorString, sizeof (s->errorString));
|
||||
s = &tor->stats;
|
||||
s->id = tor->uniqueId;
|
||||
s->activity = tr_torrentGetActivity (tor);
|
||||
s->error = tor->error;
|
||||
s->queuePosition = tor->queuePosition;
|
||||
s->isStalled = tr_torrentIsStalled (tor);
|
||||
tr_strlcpy (s->errorString, tor->errorString, sizeof (s->errorString));
|
||||
|
||||
s->manualAnnounceTime = tr_announcerNextManualAnnounce (tor);
|
||||
s->manualAnnounceTime = tr_announcerNextManualAnnounce (tor);
|
||||
|
||||
tr_peerMgrTorrentStats (tor,
|
||||
&s->peersConnected,
|
||||
&s->webseedsSendingToUs,
|
||||
&s->peersSendingToUs,
|
||||
&s->peersGettingFromUs,
|
||||
s->peersFrom);
|
||||
tr_peerMgrTorrentStats (tor,
|
||||
&s->peersConnected,
|
||||
&s->webseedsSendingToUs,
|
||||
&s->peersSendingToUs,
|
||||
&s->peersGettingFromUs,
|
||||
s->peersFrom);
|
||||
|
||||
now = tr_time_msec ();
|
||||
s->rawUploadSpeed_KBps = toSpeedKBps (tr_bandwidthGetRawSpeed_Bps (&tor->bandwidth, now, TR_UP));
|
||||
s->pieceUploadSpeed_KBps = toSpeedKBps (tr_bandwidthGetPieceSpeed_Bps (&tor->bandwidth, now, TR_UP));
|
||||
s->rawDownloadSpeed_KBps = toSpeedKBps (tr_bandwidthGetRawSpeed_Bps (&tor->bandwidth, now, TR_DOWN));
|
||||
s->pieceDownloadSpeed_KBps = toSpeedKBps (tr_bandwidthGetPieceSpeed_Bps (&tor->bandwidth, now, TR_DOWN));
|
||||
s->rawUploadSpeed_KBps = toSpeedKBps (tr_bandwidthGetRawSpeed_Bps (&tor->bandwidth, now, TR_UP));
|
||||
s->pieceUploadSpeed_KBps = toSpeedKBps (tr_bandwidthGetPieceSpeed_Bps (&tor->bandwidth, now, TR_UP));
|
||||
s->rawDownloadSpeed_KBps = toSpeedKBps (tr_bandwidthGetRawSpeed_Bps (&tor->bandwidth, now, TR_DOWN));
|
||||
s->pieceDownloadSpeed_KBps = toSpeedKBps (tr_bandwidthGetPieceSpeed_Bps (&tor->bandwidth, now, TR_DOWN));
|
||||
|
||||
s->percentComplete = tr_cpPercentComplete (&tor->completion);
|
||||
s->metadataPercentComplete = tr_torrentGetMetadataPercent (tor);
|
||||
s->percentComplete = tr_cpPercentComplete (&tor->completion);
|
||||
s->metadataPercentComplete = tr_torrentGetMetadataPercent (tor);
|
||||
|
||||
s->percentDone = tr_cpPercentDone (&tor->completion);
|
||||
s->leftUntilDone = tr_cpLeftUntilDone (&tor->completion);
|
||||
s->sizeWhenDone = tr_cpSizeWhenDone (&tor->completion);
|
||||
s->recheckProgress = s->activity == TR_STATUS_CHECK ? getVerifyProgress (tor) : 0;
|
||||
s->activityDate = tor->activityDate;
|
||||
s->addedDate = tor->addedDate;
|
||||
s->doneDate = tor->doneDate;
|
||||
s->startDate = tor->startDate;
|
||||
s->secondsSeeding = tor->secondsSeeding;
|
||||
s->secondsDownloading = tor->secondsDownloading;
|
||||
s->idleSecs = torrentGetIdleSecs (tor);
|
||||
s->percentDone = tr_cpPercentDone (&tor->completion);
|
||||
s->leftUntilDone = tr_cpLeftUntilDone (&tor->completion);
|
||||
s->sizeWhenDone = tr_cpSizeWhenDone (&tor->completion);
|
||||
s->recheckProgress = s->activity == TR_STATUS_CHECK ? getVerifyProgress (tor) : 0;
|
||||
s->activityDate = tor->activityDate;
|
||||
s->addedDate = tor->addedDate;
|
||||
s->doneDate = tor->doneDate;
|
||||
s->startDate = tor->startDate;
|
||||
s->secondsSeeding = tor->secondsSeeding;
|
||||
s->secondsDownloading = tor->secondsDownloading;
|
||||
s->idleSecs = torrentGetIdleSecs (tor);
|
||||
|
||||
s->corruptEver = tor->corruptCur + tor->corruptPrev;
|
||||
s->downloadedEver = tor->downloadedCur + tor->downloadedPrev;
|
||||
s->uploadedEver = tor->uploadedCur + tor->uploadedPrev;
|
||||
s->haveValid = tr_cpHaveValid (&tor->completion);
|
||||
s->haveUnchecked = tr_cpHaveTotal (&tor->completion) - s->haveValid;
|
||||
s->desiredAvailable = tr_peerMgrGetDesiredAvailable (tor);
|
||||
s->corruptEver = tor->corruptCur + tor->corruptPrev;
|
||||
s->downloadedEver = tor->downloadedCur + tor->downloadedPrev;
|
||||
s->uploadedEver = tor->uploadedCur + tor->uploadedPrev;
|
||||
s->haveValid = tr_cpHaveValid (&tor->completion);
|
||||
s->haveUnchecked = tr_cpHaveTotal (&tor->completion) - s->haveValid;
|
||||
s->desiredAvailable = tr_peerMgrGetDesiredAvailable (tor);
|
||||
|
||||
s->ratio = tr_getRatio (s->uploadedEver,
|
||||
s->downloadedEver ? s->downloadedEver : s->haveValid);
|
||||
s->ratio = tr_getRatio (s->uploadedEver,
|
||||
s->downloadedEver ? s->downloadedEver : s->haveValid);
|
||||
|
||||
seedRatioApplies = tr_torrentGetSeedRatioBytes (tor, &seedRatioBytesLeft,
|
||||
&seedRatioBytesGoal);
|
||||
seedRatioApplies = tr_torrentGetSeedRatioBytes (tor, &seedRatioBytesLeft,
|
||||
&seedRatioBytesGoal);
|
||||
|
||||
switch (s->activity)
|
||||
switch (s->activity)
|
||||
{
|
||||
/* etaXLSpeed exists because if we use the piece speed directly,
|
||||
* brief fluctuations cause the ETA to jump all over the place.
|
||||
* so, etaXLSpeed is a smoothed-out version of the piece speed
|
||||
* to dampen the effect of fluctuations */
|
||||
/* etaXLSpeed exists because if we use the piece speed directly,
|
||||
* brief fluctuations cause the ETA to jump all over the place.
|
||||
* so, etaXLSpeed is a smoothed-out version of the piece speed
|
||||
* to dampen the effect of fluctuations */
|
||||
case TR_STATUS_DOWNLOAD:
|
||||
if ((tor->etaDLSpeedCalculatedAt + 800) < now)
|
||||
{
|
||||
tor->etaDLSpeed_KBps = ((tor->etaDLSpeedCalculatedAt + 4000) < now)
|
||||
? s->pieceDownloadSpeed_KBps /* if no recent previous speed, no need to smooth */
|
||||
: ((tor->etaDLSpeed_KBps*4.0) + s->pieceDownloadSpeed_KBps)/5.0; /* smooth across 5 readings */
|
||||
tor->etaDLSpeedCalculatedAt = now;
|
||||
}
|
||||
|
||||
case TR_STATUS_DOWNLOAD:
|
||||
if ((tor->etaDLSpeedCalculatedAt + 800) < now) {
|
||||
tor->etaDLSpeed_KBps = ((tor->etaDLSpeedCalculatedAt + 4000) < now)
|
||||
? s->pieceDownloadSpeed_KBps /* if no recent previous speed, no need to smooth */
|
||||
: ((tor->etaDLSpeed_KBps*4.0) + s->pieceDownloadSpeed_KBps)/5.0; /* smooth across 5 readings */
|
||||
tor->etaDLSpeedCalculatedAt = now;
|
||||
}
|
||||
if (s->leftUntilDone > s->desiredAvailable)
|
||||
s->eta = TR_ETA_NOT_AVAIL;
|
||||
else if (tor->etaDLSpeed_KBps < 1)
|
||||
s->eta = TR_ETA_UNKNOWN;
|
||||
else
|
||||
s->eta = s->leftUntilDone / toSpeedBytes (tor->etaDLSpeed_KBps);
|
||||
|
||||
if (s->leftUntilDone > s->desiredAvailable)
|
||||
s->eta = TR_ETA_NOT_AVAIL;
|
||||
else if (tor->etaDLSpeed_KBps < 1)
|
||||
s->eta = TR_ETA_UNKNOWN;
|
||||
else
|
||||
s->eta = s->leftUntilDone / toSpeedBytes (tor->etaDLSpeed_KBps);
|
||||
s->etaIdle = TR_ETA_NOT_AVAIL;
|
||||
break;
|
||||
|
||||
s->etaIdle = TR_ETA_NOT_AVAIL;
|
||||
break;
|
||||
|
||||
case TR_STATUS_SEED: {
|
||||
if (!seedRatioApplies)
|
||||
s->eta = TR_ETA_NOT_AVAIL;
|
||||
else {
|
||||
if ((tor->etaULSpeedCalculatedAt + 800) < now) {
|
||||
tor->etaULSpeed_KBps = ((tor->etaULSpeedCalculatedAt + 4000) < now)
|
||||
? s->pieceUploadSpeed_KBps /* if no recent previous speed, no need to smooth */
|
||||
: ((tor->etaULSpeed_KBps*4.0) + s->pieceUploadSpeed_KBps)/5.0; /* smooth across 5 readings */
|
||||
tor->etaULSpeedCalculatedAt = now;
|
||||
}
|
||||
if (tor->etaULSpeed_KBps < 1)
|
||||
s->eta = TR_ETA_UNKNOWN;
|
||||
else
|
||||
s->eta = seedRatioBytesLeft / toSpeedBytes (tor->etaULSpeed_KBps);
|
||||
}
|
||||
|
||||
if (tor->etaULSpeed_KBps < 1 && tr_torrentGetSeedIdle (tor, &seedIdleMinutes))
|
||||
s->etaIdle = seedIdleMinutes * 60 - s->idleSecs;
|
||||
else
|
||||
s->etaIdle = TR_ETA_NOT_AVAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
case TR_STATUS_SEED:
|
||||
if (!seedRatioApplies)
|
||||
{
|
||||
s->eta = TR_ETA_NOT_AVAIL;
|
||||
s->etaIdle = TR_ETA_NOT_AVAIL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tor->etaULSpeedCalculatedAt + 800) < now)
|
||||
{
|
||||
tor->etaULSpeed_KBps = ((tor->etaULSpeedCalculatedAt + 4000) < now)
|
||||
? s->pieceUploadSpeed_KBps /* if no recent previous speed, no need to smooth */
|
||||
: ((tor->etaULSpeed_KBps*4.0) + s->pieceUploadSpeed_KBps)/5.0; /* smooth across 5 readings */
|
||||
tor->etaULSpeedCalculatedAt = now;
|
||||
}
|
||||
|
||||
if (tor->etaULSpeed_KBps < 1)
|
||||
s->eta = TR_ETA_UNKNOWN;
|
||||
else
|
||||
s->eta = seedRatioBytesLeft / toSpeedBytes (tor->etaULSpeed_KBps);
|
||||
}
|
||||
|
||||
if (tor->etaULSpeed_KBps < 1 && tr_torrentGetSeedIdle (tor, &seedIdleMinutes))
|
||||
s->etaIdle = seedIdleMinutes * 60 - s->idleSecs;
|
||||
else
|
||||
s->etaIdle = TR_ETA_NOT_AVAIL;
|
||||
break;
|
||||
|
||||
default:
|
||||
s->eta = TR_ETA_NOT_AVAIL;
|
||||
s->etaIdle = TR_ETA_NOT_AVAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* s->haveValid is here to make sure a torrent isn't marked 'finished'
|
||||
* when the user hits "uncheck all" prior to starting the torrent... */
|
||||
s->finished = tor->finishedSeedingByIdle || (seedRatioApplies && !seedRatioBytesLeft && s->haveValid);
|
||||
/* s->haveValid is here to make sure a torrent isn't marked 'finished'
|
||||
* when the user hits "uncheck all" prior to starting the torrent... */
|
||||
s->finished = tor->finishedSeedingByIdle || (seedRatioApplies && !seedRatioBytesLeft && s->haveValid);
|
||||
|
||||
if (!seedRatioApplies || s->finished)
|
||||
s->seedRatioPercentDone = 1;
|
||||
else if (!seedRatioBytesGoal) /* impossible? safeguard for div by zero */
|
||||
s->seedRatioPercentDone = 0;
|
||||
else
|
||||
s->seedRatioPercentDone = (double)(seedRatioBytesGoal - seedRatioBytesLeft) / seedRatioBytesGoal;
|
||||
if (!seedRatioApplies || s->finished)
|
||||
s->seedRatioPercentDone = 1;
|
||||
else if (!seedRatioBytesGoal) /* impossible? safeguard for div by zero */
|
||||
s->seedRatioPercentDone = 0;
|
||||
else
|
||||
s->seedRatioPercentDone = (double)(seedRatioBytesGoal - seedRatioBytesLeft) / seedRatioBytesGoal;
|
||||
|
||||
/* test some of the constraints */
|
||||
assert (s->sizeWhenDone <= tor->info.totalSize);
|
||||
assert (s->leftUntilDone <= s->sizeWhenDone);
|
||||
assert (s->desiredAvailable <= s->leftUntilDone);
|
||||
/* test some of the constraints */
|
||||
assert (s->sizeWhenDone <= tor->info.totalSize);
|
||||
assert (s->leftUntilDone <= s->sizeWhenDone);
|
||||
assert (s->desiredAvailable <= s->leftUntilDone);
|
||||
|
||||
tr_torrentUnref (tor);
|
||||
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -1436,31 +1397,19 @@ tr_torrentFilesFree (tr_file_stat * files,
|
|||
***/
|
||||
|
||||
double*
|
||||
tr_torrentWebSpeeds_KBps (tr_torrent * tor)
|
||||
tr_torrentWebSpeeds_KBps (const tr_torrent * tor)
|
||||
{
|
||||
double * ret = NULL;
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
{
|
||||
ret = tr_peerMgrWebSpeeds_KBps (tor);
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return tr_peerMgrWebSpeeds_KBps (tor);
|
||||
}
|
||||
|
||||
tr_peer_stat *
|
||||
tr_torrentPeers (tr_torrent * tor, int * peerCount)
|
||||
tr_torrentPeers (const tr_torrent * tor, int * peerCount)
|
||||
{
|
||||
tr_peer_stat * ret = NULL;
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
{
|
||||
ret = tr_peerMgrPeerStats (tor, peerCount);
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return tr_peerMgrPeerStats (tor, peerCount);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1470,43 +1419,32 @@ tr_torrentPeersFree (tr_peer_stat * peers, int peerCount UNUSED)
|
|||
}
|
||||
|
||||
tr_tracker_stat *
|
||||
tr_torrentTrackers (tr_torrent * torrent, int * setmeTrackerCount)
|
||||
tr_torrentTrackers (const tr_torrent * tor, int * setmeTrackerCount)
|
||||
{
|
||||
tr_tracker_stat * ret = NULL;
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
if (tr_torrentRef (torrent))
|
||||
{
|
||||
ret = tr_announcerStats (torrent, setmeTrackerCount);
|
||||
tr_torrentUnref (torrent);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return tr_announcerStats (tor, setmeTrackerCount);
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentTrackersFree (tr_tracker_stat * trackers, int trackerCount)
|
||||
{
|
||||
tr_announcerStatsFree (trackers, trackerCount);
|
||||
tr_announcerStatsFree (trackers, trackerCount);
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentAvailability (tr_torrent * tor, int8_t * tab, int size)
|
||||
tr_torrentAvailability (const tr_torrent * tor, int8_t * tab, int size)
|
||||
{
|
||||
if ((tab != NULL) && (size > 0) && tr_torrentRef (tor))
|
||||
{
|
||||
tr_peerMgrTorrentAvailability (tor, tab, size);
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
if ((tab != NULL) && (size > 0))
|
||||
tr_peerMgrTorrentAvailability (tor, tab, size);
|
||||
}
|
||||
|
||||
void
|
||||
tr_torrentAmountFinished (tr_torrent * tor, float * tab, int size)
|
||||
tr_torrentAmountFinished (const tr_torrent * tor, float * tab, int size)
|
||||
{
|
||||
if (tr_torrentRef (tor))
|
||||
{
|
||||
tr_cpGetAmountDone (&tor->completion, tab, size);
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
tr_cpGetAmountDone (&tor->completion, tab, size);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1812,21 +1750,22 @@ stopTorrent (void * vtor)
|
|||
tr_torrent * tor = vtor;
|
||||
tr_torinf (tor, "%s", "Pausing");
|
||||
|
||||
if (tr_torrentLock (tor))
|
||||
{
|
||||
tr_verifyRemove (tor);
|
||||
torrentSetQueued (tor, false);
|
||||
tr_peerMgrStopTorrent (tor);
|
||||
tr_announcerTorrentStopped (tor);
|
||||
tr_cacheFlushTorrent (tor->session->cache, tor);
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
tr_fdTorrentClose (tor->session, tor->uniqueId);
|
||||
tr_torrentLock (tor);
|
||||
|
||||
if (!tor->isDeleting)
|
||||
tr_torrentSave (tor);
|
||||
tr_verifyRemove (tor);
|
||||
torrentSetQueued (tor, false);
|
||||
tr_peerMgrStopTorrent (tor);
|
||||
tr_announcerTorrentStopped (tor);
|
||||
tr_cacheFlushTorrent (tor->session->cache, tor);
|
||||
|
||||
tr_torrentUnlock (tor);
|
||||
}
|
||||
tr_fdTorrentClose (tor->session, tor->uniqueId);
|
||||
|
||||
if (!tor->isDeleting)
|
||||
tr_torrentSave (tor);
|
||||
|
||||
tr_torrentUnlock (tor);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1874,45 +1813,19 @@ closeTorrent (void * vtor)
|
|||
}
|
||||
|
||||
void
|
||||
tr_torrentUnref (tr_torrent * tor)
|
||||
tr_torrentFree (tr_torrent * tor)
|
||||
{
|
||||
assert (tr_isTorrent (tor));
|
||||
if (tr_isTorrent (tor))
|
||||
{
|
||||
tr_session * session = tor->session;
|
||||
assert (tr_isSession (session));
|
||||
tr_sessionLock (session);
|
||||
|
||||
if (tor->refCount > 1)
|
||||
{
|
||||
--tor->refCount;
|
||||
}
|
||||
else if (tor->refCount == 1)
|
||||
{
|
||||
tr_session * session = tor->session;
|
||||
tr_torrentClearCompletenessCallback (tor);
|
||||
tr_runInEventThread (session, closeTorrent, tor);
|
||||
|
||||
tr_sessionLock (session);
|
||||
tr_torrentClearCompletenessCallback (tor);
|
||||
tr_runInEventThread (session, closeTorrent, tor);
|
||||
tr_sessionUnlock (session);
|
||||
|
||||
--tor->refCount;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
tr_torrentLock (const tr_torrent * tor)
|
||||
{
|
||||
if (!tr_isTorrent (tor))
|
||||
return false;
|
||||
|
||||
tr_sessionLock (tor->session);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
tr_torrentRef (tr_torrent * tor)
|
||||
{
|
||||
if (!tr_isTorrent (tor))
|
||||
return false;
|
||||
|
||||
++tor->refCount;
|
||||
return true;
|
||||
tr_sessionUnlock (session);
|
||||
}
|
||||
}
|
||||
|
||||
struct remove_data
|
||||
|
@ -2096,55 +2009,55 @@ torrentCallScript (const tr_torrent * tor, const char * script)
|
|||
void
|
||||
tr_torrentRecheckCompleteness (tr_torrent * tor)
|
||||
{
|
||||
if (tr_torrentLock (tor))
|
||||
tr_completeness completeness;
|
||||
|
||||
tr_torrentLock (tor);
|
||||
|
||||
completeness = tr_cpGetStatus (&tor->completion);
|
||||
if (completeness != tor->completeness)
|
||||
{
|
||||
const tr_completeness completeness = tr_cpGetStatus (&tor->completion);
|
||||
const int recentChange = tor->downloadedCur != 0;
|
||||
const bool wasLeeching = !tr_torrentIsSeed (tor);
|
||||
const bool wasRunning = tor->isRunning;
|
||||
|
||||
if (completeness != tor->completeness)
|
||||
if (recentChange)
|
||||
tr_torinf (tor, _("State changed from \"%1$s\" to \"%2$s\""),
|
||||
getCompletionString (tor->completeness),
|
||||
getCompletionString (completeness));
|
||||
|
||||
tor->completeness = completeness;
|
||||
tr_fdTorrentClose (tor->session, tor->uniqueId);
|
||||
|
||||
fireCompletenessChange (tor, completeness, wasRunning);
|
||||
|
||||
if (tr_torrentIsSeed (tor))
|
||||
{
|
||||
const int recentChange = tor->downloadedCur != 0;
|
||||
const bool wasLeeching = !tr_torrentIsSeed (tor);
|
||||
const bool wasRunning = tor->isRunning;
|
||||
|
||||
if (recentChange)
|
||||
tr_torinf (tor, _("State changed from \"%1$s\" to \"%2$s\""),
|
||||
getCompletionString (tor->completeness),
|
||||
getCompletionString (completeness));
|
||||
|
||||
tor->completeness = completeness;
|
||||
tr_fdTorrentClose (tor->session, tor->uniqueId);
|
||||
|
||||
fireCompletenessChange (tor, completeness, wasRunning);
|
||||
|
||||
if (tr_torrentIsSeed (tor))
|
||||
{
|
||||
if (recentChange)
|
||||
{
|
||||
tr_announcerTorrentCompleted (tor);
|
||||
tor->doneDate = tor->anyDate = tr_time ();
|
||||
}
|
||||
|
||||
if (wasLeeching && wasRunning)
|
||||
{
|
||||
/* clear interested flag on all peers */
|
||||
tr_peerMgrClearInterest (tor);
|
||||
|
||||
/* if completeness was TR_LEECH then the seed limit check will have been skipped in bandwidthPulse */
|
||||
tr_torrentCheckSeedLimit (tor);
|
||||
}
|
||||
|
||||
if (tor->currentDir == tor->incompleteDir)
|
||||
tr_torrentSetLocation (tor, tor->downloadDir, true, NULL, NULL);
|
||||
|
||||
if (tr_sessionIsTorrentDoneScriptEnabled (tor->session))
|
||||
torrentCallScript (tor, tr_sessionGetTorrentDoneScript (tor->session));
|
||||
tr_announcerTorrentCompleted (tor);
|
||||
tor->doneDate = tor->anyDate = tr_time ();
|
||||
}
|
||||
|
||||
tr_torrentSetDirty (tor);
|
||||
if (wasLeeching && wasRunning)
|
||||
{
|
||||
/* clear interested flag on all peers */
|
||||
tr_peerMgrClearInterest (tor);
|
||||
|
||||
/* if completeness was TR_LEECH then the seed limit check will have been skipped in bandwidthPulse */
|
||||
tr_torrentCheckSeedLimit (tor);
|
||||
}
|
||||
|
||||
if (tor->currentDir == tor->incompleteDir)
|
||||
tr_torrentSetLocation (tor, tor->downloadDir, true, NULL, NULL);
|
||||
|
||||
if (tr_sessionIsTorrentDoneScriptEnabled (tor->session))
|
||||
torrentCallScript (tor, tr_sessionGetTorrentDoneScript (tor->session));
|
||||
}
|
||||
|
||||
tr_torrentUnlock (tor);
|
||||
tr_torrentSetDirty (tor);
|
||||
}
|
||||
|
||||
tr_torrentUnlock (tor);
|
||||
}
|
||||
|
||||
/***
|
||||
|
@ -2214,20 +2127,17 @@ tr_torrentSetFilePriorities (tr_torrent * tor,
|
|||
}
|
||||
|
||||
tr_priority_t*
|
||||
tr_torrentGetFilePriorities (tr_torrent * tor)
|
||||
tr_torrentGetFilePriorities (const tr_torrent * tor)
|
||||
{
|
||||
tr_file_index_t i;
|
||||
tr_priority_t * p = NULL;
|
||||
tr_priority_t * p;
|
||||
|
||||
if (tr_torrentRef (tor))
|
||||
{
|
||||
p = tr_new0 (tr_priority_t, tor->info.fileCount);
|
||||
assert (tr_isTorrent (tor));
|
||||
|
||||
for (i=0; i<tor->info.fileCount; ++i)
|
||||
p[i] = tor->info.files[i].priority;
|
||||
p = tr_new0 (tr_priority_t, tor->info.fileCount);
|
||||
|
||||
tr_torrentUnref (tor);
|
||||
}
|
||||
for (i=0; i<tor->info.fileCount; ++i)
|
||||
p[i] = tor->info.files[i].priority;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ struct tr_magnet_info;
|
|||
*** Package-visible ctor API
|
||||
**/
|
||||
|
||||
void tr_torrentFree (tr_torrent * tor);
|
||||
|
||||
void tr_ctorSetSave (tr_ctor * ctor,
|
||||
bool saveMetadataInOurTorrentsDir);
|
||||
|
||||
|
@ -62,8 +64,8 @@ tr_torrent* tr_torrentFindFromHashString (tr_session * session,
|
|||
tr_torrent* tr_torrentFindFromObfuscatedHash (tr_session * session,
|
||||
const uint8_t * hash);
|
||||
|
||||
bool tr_torrentIsPieceTransferAllowed (tr_torrent * torrent,
|
||||
tr_direction direction);
|
||||
bool tr_torrentIsPieceTransferAllowed (const tr_torrent * torrent,
|
||||
tr_direction direction);
|
||||
|
||||
|
||||
|
||||
|
@ -139,8 +141,6 @@ struct tr_torrent
|
|||
|
||||
int magicNumber;
|
||||
|
||||
size_t refCount;
|
||||
|
||||
tr_stat_errtype error;
|
||||
char errorString[128];
|
||||
char errorTracker[128];
|
||||
|
@ -302,16 +302,17 @@ tr_torBlockCountBytes (const tr_torrent * tor, const tr_block_index_t block)
|
|||
: tor->blockSize;
|
||||
}
|
||||
|
||||
bool tr_torrentLock (const tr_torrent * tor);
|
||||
|
||||
static inline void tr_torrentLock (const tr_torrent * tor)
|
||||
{
|
||||
tr_sessionLock (tor->session);
|
||||
}
|
||||
static inline bool tr_torrentIsLocked (const tr_torrent * tor)
|
||||
{
|
||||
return tr_sessionIsLocked (tor->session);
|
||||
return tr_sessionIsLocked (tor->session);
|
||||
}
|
||||
|
||||
static inline void tr_torrentUnlock (const tr_torrent * tor)
|
||||
{
|
||||
tr_sessionUnlock (tor->session);
|
||||
tr_sessionUnlock (tor->session);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
|
@ -365,7 +366,6 @@ static inline bool tr_isTorrent (const tr_torrent * tor)
|
|||
{
|
||||
return (tor != NULL)
|
||||
&& (tor->magicNumber == TORRENT_MAGIC_NUMBER)
|
||||
&& (tor->refCount > 0)
|
||||
&& (tr_isSession (tor->session));
|
||||
}
|
||||
|
||||
|
|
|
@ -1145,26 +1145,9 @@ tr_torrent * tr_torrentNew (const tr_ctor * ctor,
|
|||
/** @addtogroup tr_torrent Torrents
|
||||
@{ */
|
||||
|
||||
/**
|
||||
* @brief Decrements a torrent's refcount.
|
||||
*
|
||||
* If its refcount becomes zero, the torrent is stopped and its memory is freed.
|
||||
*/
|
||||
void tr_torrentUnref (tr_torrent * torrent);
|
||||
|
||||
/**
|
||||
* @brief Increments a torrent's refcount.
|
||||
*
|
||||
* @return true if the pointer is a live torrent object.
|
||||
* This is a convenience for validity checking before use:
|
||||
* if (tr_torrentRef (tor)) { foo(); bar(); tr_torrentUnref(tor); }
|
||||
*/
|
||||
bool tr_torrentRef (tr_torrent * torrent);
|
||||
|
||||
typedef int tr_fileFunc (const char * filename);
|
||||
|
||||
/** @brief Removes our .torrent and .resume files for
|
||||
this torrent, then calls tr_torrentFree (). */
|
||||
/** @brief Removes our .torrent and .resume files for this torrent */
|
||||
void tr_torrentRemove (tr_torrent * torrent,
|
||||
bool removeLocalData,
|
||||
tr_fileFunc removeFunc);
|
||||
|
@ -1238,13 +1221,13 @@ char* tr_torrentFindFile (const tr_torrent * tor, tr_file_index_t fileNo);
|
|||
***/
|
||||
|
||||
void tr_torrentSetSpeedLimit_KBps (tr_torrent *, tr_direction, unsigned int KBps);
|
||||
unsigned int tr_torrentGetSpeedLimit_KBps (tr_torrent *, tr_direction);
|
||||
unsigned int tr_torrentGetSpeedLimit_KBps (const tr_torrent *, tr_direction);
|
||||
|
||||
void tr_torrentUseSpeedLimit (tr_torrent *, tr_direction, bool);
|
||||
bool tr_torrentUsesSpeedLimit (tr_torrent *, tr_direction);
|
||||
bool tr_torrentUsesSpeedLimit (const tr_torrent *, tr_direction);
|
||||
|
||||
void tr_torrentUseSessionLimits (tr_torrent *, bool);
|
||||
bool tr_torrentUsesSessionLimits (tr_torrent *);
|
||||
bool tr_torrentUsesSessionLimits (const tr_torrent *);
|
||||
|
||||
|
||||
/****
|
||||
|
@ -1272,10 +1255,10 @@ tr_ratiolimit tr_torrentGetRatioMode (const tr_torrent * tor);
|
|||
void tr_torrentSetRatioLimit (tr_torrent * tor,
|
||||
double ratio);
|
||||
|
||||
double tr_torrentGetRatioLimit (tr_torrent * tor);
|
||||
double tr_torrentGetRatioLimit (const tr_torrent * tor);
|
||||
|
||||
|
||||
bool tr_torrentGetSeedRatio (tr_torrent *, double * ratio);
|
||||
bool tr_torrentGetSeedRatio (const tr_torrent *, double * ratio);
|
||||
|
||||
|
||||
/****
|
||||
|
@ -1344,7 +1327,7 @@ void tr_torrentSetFilePriorities (tr_torrent * torrent,
|
|||
* each holding a TR_PRI_NORMAL, TR_PRI_HIGH, or TR_PRI_LOW.
|
||||
* It's the caller's responsibility to free () this.
|
||||
*/
|
||||
tr_priority_t* tr_torrentGetFilePriorities (tr_torrent * torrent);
|
||||
tr_priority_t* tr_torrentGetFilePriorities (const tr_torrent * torrent);
|
||||
|
||||
/** @brief Set a batch of files to be downloaded or not. */
|
||||
void tr_torrentSetFileDLs (tr_torrent * torrent,
|
||||
|
@ -1579,8 +1562,8 @@ typedef struct tr_peer_stat
|
|||
}
|
||||
tr_peer_stat;
|
||||
|
||||
tr_peer_stat * tr_torrentPeers (tr_torrent * torrent,
|
||||
int * peerCount);
|
||||
tr_peer_stat * tr_torrentPeers (const tr_torrent * torrent,
|
||||
int * peerCount);
|
||||
|
||||
void tr_torrentPeersFree (tr_peer_stat * peerStats,
|
||||
int peerCount);
|
||||
|
@ -1702,8 +1685,8 @@ typedef struct
|
|||
}
|
||||
tr_tracker_stat;
|
||||
|
||||
tr_tracker_stat * tr_torrentTrackers (tr_torrent * torrent,
|
||||
int * setmeTrackerCount);
|
||||
tr_tracker_stat * tr_torrentTrackers (const tr_torrent * torrent,
|
||||
int * setmeTrackerCount);
|
||||
|
||||
void tr_torrentTrackersFree (tr_tracker_stat * trackerStats,
|
||||
int trackerCount);
|
||||
|
@ -1720,7 +1703,7 @@ void tr_torrentTrackersFree (tr_tracker_stat * trackerStats,
|
|||
* return -1 instead of 0 KiB/s.
|
||||
* NOTE: always free this array with tr_free () when you're done with it.
|
||||
*/
|
||||
double* tr_torrentWebSpeeds_KBps (tr_torrent * torrent);
|
||||
double* tr_torrentWebSpeeds_KBps (const tr_torrent * torrent);
|
||||
|
||||
typedef struct tr_file_stat
|
||||
{
|
||||
|
@ -1744,13 +1727,13 @@ void tr_torrentFilesFree (tr_file_stat * files,
|
|||
* to either -1 if we have the piece, otherwise it is set to the number
|
||||
* of connected peers who have the piece.
|
||||
**********************************************************************/
|
||||
void tr_torrentAvailability (tr_torrent * torrent,
|
||||
int8_t * tab,
|
||||
int size);
|
||||
void tr_torrentAvailability (const tr_torrent * torrent,
|
||||
int8_t * tab,
|
||||
int size);
|
||||
|
||||
void tr_torrentAmountFinished (tr_torrent * torrent,
|
||||
float * tab,
|
||||
int size);
|
||||
void tr_torrentAmountFinished (const tr_torrent * torrent,
|
||||
float * tab,
|
||||
int size);
|
||||
|
||||
void tr_torrentVerify (tr_torrent * torrent);
|
||||
|
||||
|
|
Loading…
Reference in New Issue