(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:
Jordan Lee 2012-12-14 20:04:37 +00:00
parent c5ff0c0308
commit aea6d7cd6f
9 changed files with 442 additions and 554 deletions

View File

@ -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

View File

@ -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);

View File

@ -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];

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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;
}

View File

@ -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));
}

View File

@ -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);