(trunk) #5168 'make libtransmission's public funcs nonblocking when possible' -- first attempt.

This commit is contained in:
Jordan Lee 2012-12-12 20:22:57 +00:00
parent 84f2cf8fa2
commit 079c78981c
12 changed files with 489 additions and 414 deletions

View File

@ -1376,7 +1376,7 @@ refreshWebseedList (struct DetailsImpl * di, tr_torrent ** torrents, int n)
/* step 3: update the webseeds */
for (i=0; i<n; ++i) {
int j;
const tr_torrent * tor = torrents[i];
tr_torrent * tor = torrents[i];
const tr_info * inf = tr_torrentInfo (tor);
double * speeds_KBps = tr_torrentWebSpeeds_KBps (tor);
for (j=0; j<inf->webseedCount; ++j) {

View File

@ -40,10 +40,10 @@ enum
***/
static void
getProgressString (GString * gstr,
const tr_torrent * tor,
const tr_info * info,
const tr_stat * st)
getProgressString (GString * gstr,
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;
const tr_torrent * tor = p->tor;
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;
@ -525,33 +525,34 @@ typedef GdkRGBA GtrColor;
static void
get_text_color (GtkWidget * w, const tr_stat * st, GtrColor * setme)
{
static const GdkRGBA red = { 1.0, 0, 0, 0 };
if (st->error)
*setme = red;
else if (st->activity == TR_STATUS_STOPPED)
gtk_style_context_get_color (gtk_widget_get_style_context (w), GTK_STATE_FLAG_INSENSITIVE, setme);
else
gtk_style_context_get_color (gtk_widget_get_style_context (w), GTK_STATE_FLAG_NORMAL, setme);
static const GdkRGBA red = { 1.0, 0, 0, 0 };
if (st->error)
*setme = red;
else if (st->activity == TR_STATUS_STOPPED)
gtk_style_context_get_color (gtk_widget_get_style_context (w), GTK_STATE_FLAG_INSENSITIVE, setme);
else
gtk_style_context_get_color (gtk_widget_get_style_context (w), GTK_STATE_FLAG_NORMAL, setme);
}
static double
get_percent_done (const tr_torrent * tor, const tr_stat * st, bool * seed)
get_percent_done (tr_torrent * tor, const tr_stat * st, bool * seed)
{
double d;
double d;
if ((st->activity == TR_STATUS_SEED) && tr_torrentGetSeedRatio (tor, &d))
if ((st->activity == TR_STATUS_SEED) && tr_torrentGetSeedRatio (tor, &d))
{
*seed = true;
d = MAX (0.0, st->seedRatioPercentDone);
*seed = true;
d = MAX (0.0, st->seedRatioPercentDone);
}
else
else
{
*seed = false;
d = MAX (0.0, st->percentDone);
*seed = false;
d = MAX (0.0, st->percentDone);
}
return d;
return d;
}
typedef cairo_t GtrDrawable;
@ -587,7 +588,7 @@ render_compact (TorrentCellRenderer * cell,
bool seed;
struct TorrentCellRendererPrivate * p = cell->priv;
const tr_torrent * tor = p->tor;
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);
@ -665,7 +666,7 @@ render_full (TorrentCellRenderer * cell,
bool seed;
struct TorrentCellRendererPrivate * p = cell->priv;
const tr_torrent * tor = p->tor;
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,12 +1129,9 @@ gotError (tr_peerIo * io,
tr_peerIoGetTorrentHash (io)) :
NULL;
/* Don't mark a peer as non-uTP unless it's really a connect failure. */
if (tor && (errcode == ETIMEDOUT || errcode == ECONNREFUSED)) {
tr_torrentLock (tor);
tr_peerMgrSetUtpFailed (tor,
tr_peerIoGetAddress (io, NULL),
true);
tr_torrentUnlock (tor);
if ((errcode == ETIMEDOUT || errcode == ECONNREFUSED) && tr_torrentRef(tor)) {
tr_peerMgrSetUtpFailed (tor, tr_peerIoGetAddress (io, NULL), true);
tr_torrentUnref (tor);
}
if (!tr_peerIoReconnect (handshake->io)) {

View File

@ -2549,36 +2549,42 @@ tr_peerMgrOnTorrentGotMetainfo (tr_torrent * tor)
}
void
tr_peerMgrTorrentAvailability (const tr_torrent * tor, int8_t * tab, unsigned int tabCount)
tr_peerMgrTorrentAvailability (tr_torrent * tor, int8_t * tab, unsigned int tabCount)
{
assert (tr_isTorrent (tor));
assert (torrentIsLocked (tor->torrentPeers));
assert (tab != NULL);
assert (tabCount > 0);
assert (tab != NULL);
assert (tabCount > 0);
memset (tab, 0, tabCount);
if (tr_torrentHasMetadata (tor))
if (tr_torrentRef (tor))
{
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;
memset (tab, 0, tabCount);
for (i=0; i<tabCount; ++i)
if (tr_torrentHasMetadata (tor))
{
const int piece = i * interval;
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 (isSeed || tr_cpPieceIsComplete (&tor->completion, piece))
tab[i] = -1;
else if (peerCount) {
int j;
for (j=0; j<peerCount; ++j)
for (i=0; i<tabCount; ++i)
{
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];
}
}
}
tr_torrentUnref (tor);
}
}
@ -2643,69 +2649,76 @@ tr_peerMgrTorrentStats (tr_torrent * tor,
int * setmePeersGettingFromUs,
int * setmePeersFrom)
{
int i, size;
const Torrent * t = tor->torrentPeers;
const tr_peer ** peers;
*setmePeersConnected = 0;
*setmePeersGettingFromUs = 0;
*setmePeersSendingToUs = 0;
*setmeWebseedsSendingToUs = 0;
assert (tr_torrentIsLocked (tor));
if (tr_torrentRef (tor))
{
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);
peers = (const tr_peer **) tr_ptrArrayBase (&t->peers);
size = tr_ptrArraySize (&t->peers);
*setmePeersConnected = 0;
*setmePeersGettingFromUs = 0;
*setmePeersSendingToUs = 0;
*setmeWebseedsSendingToUs = 0;
for (i=0; i<TR_PEER_FROM__MAX; ++i)
for (i=0; i<TR_PEER_FROM__MAX; ++i)
setmePeersFrom[i] = 0;
for (i=0; i<size; ++i)
{
const tr_peer * peer = peers[i];
const struct peer_atom * atom = peer->atom;
for (i=0; i<size; ++i)
{
const tr_peer * peer = peers[i];
const struct peer_atom * atom = peer->atom;
if (peer->io == NULL) /* not connected */
if (peer->io == NULL) /* not connected */
continue;
++*setmePeersConnected;
++*setmePeersConnected;
++setmePeersFrom[atom->fromFirst];
++setmePeersFrom[atom->fromFirst];
if (clientIsDownloadingFrom (tor, peer))
if (clientIsDownloadingFrom (tor, peer))
++*setmePeersSendingToUs;
if (clientIsUploadingTo (peer))
if (clientIsUploadingTo (peer))
++*setmePeersGettingFromUs;
}
}
*setmeWebseedsSendingToUs = countActiveWebseeds (t);
*setmeWebseedsSendingToUs = countActiveWebseeds (t);
tr_torrentUnref (tor);
}
}
double*
tr_peerMgrWebSpeeds_KBps (const tr_torrent * tor)
tr_peerMgrWebSpeeds_KBps (tr_torrent * tor)
{
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 ();
double * ret = tr_new0 (double, webseedCount);
double * ret = NULL;
assert (tr_isTorrent (tor));
assert (tr_torrentIsLocked (tor));
assert (t->manager != NULL);
assert (webseedCount == tor->info.webseedCount);
if (tr_torrentRef (tor))
{
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 ();
for (i=0; i<webseedCount; ++i) {
unsigned int Bps;
if (tr_webseedGetSpeed_Bps (webseeds[i], now, &Bps))
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
else
ret[i] = -1.0;
}
tr_torrentUnref (tor);
}
return ret;
return ret;
}
unsigned int
@ -2715,73 +2728,78 @@ tr_peerGetPieceSpeed_Bps (const tr_peer * peer, uint64_t now, tr_direction direc
}
struct tr_peer_stat *
tr_peerMgrPeerStats (const tr_torrent * tor, int * setmeCount)
tr_peerMgrPeerStats (tr_torrent * tor, int * setmeCount)
{
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 uint64_t now_msec = tr_time_msec ();
const time_t now = tr_time ();
tr_peer_stat * ret = tr_new0 (tr_peer_stat, size);
int size = 0;
tr_peer_stat * ret = NULL;
assert (tr_isTorrent (tor));
assert (tr_torrentIsLocked (tor));
assert (t->manager);
for (i=0; i<size; ++i)
if (tr_torrentRef (tor))
{
char * pch;
const tr_peer * peer = peers[i];
const struct peer_atom * atom = peer->atom;
tr_peer_stat * stat = ret + 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 ();
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);
assert (t->manager != NULL);
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);
size = tr_ptrArraySize (&t->peers);
ret = tr_new0 (tr_peer_stat, size);
stat->pendingReqsToPeer = peer->pendingReqsToPeer;
stat->pendingReqsToClient = peer->pendingReqsToClient;
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;
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_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);
}
*setmeCount = size;
return ret;
*setmeCount = size;
return ret;
}
/***
@ -2808,24 +2826,24 @@ tr_peerMgrClearInterest (tr_torrent * tor)
/* does this peer have any pieces that we want? */
static bool
isPeerInteresting (const tr_torrent * const tor,
const bool * const piece_is_interesting,
const tr_peer * const peer)
isPeerInteresting (tr_torrent * const tor,
const bool * const piece_is_interesting,
const tr_peer * const peer)
{
tr_piece_index_t i, n;
tr_piece_index_t i, n;
/* these cases should have already been handled by the calling code... */
assert (!tr_torrentIsSeed (tor));
assert (tr_torrentIsPieceTransferAllowed (tor, TR_PEER_TO_CLIENT));
/* these cases should have already been handled by the calling code... */
assert (!tr_torrentIsSeed (tor));
assert (tr_torrentIsPieceTransferAllowed (tor, TR_PEER_TO_CLIENT));
if (peerIsSeed (peer))
return true;
if (peerIsSeed (peer))
return true;
for (i=0, n=tor->info.pieceCount; i<n; ++i)
if (piece_is_interesting[i] && tr_bitfieldHas (&peer->have, i))
return true;
for (i=0, n=tor->info.pieceCount; i<n; ++i)
if (piece_is_interesting[i] && tr_bitfieldHas (&peer->have, i))
return true;
return false;
return false;
}
typedef enum

View File

@ -225,9 +225,9 @@ void tr_peerMgrAddTorrent (tr_peerMgr * manager,
void tr_peerMgrRemoveTorrent (tr_torrent * tor);
void tr_peerMgrTorrentAvailability (const tr_torrent * tor,
int8_t * tab,
unsigned int tabCount);
void tr_peerMgrTorrentAvailability (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 (const tr_torrent * tor,
int * setmeCount);
struct tr_peer_stat* tr_peerMgrPeerStats (tr_torrent * tor,
int * setmeCount);
double* tr_peerMgrWebSpeeds_KBps (const tr_torrent * tor);
double* tr_peerMgrWebSpeeds_KBps (tr_torrent * tor);
unsigned int tr_peerGetPieceSpeed_Bps (const tr_peer * peer,

View File

@ -1666,7 +1666,7 @@ tr_peerMsgsIsReadingBlock (const tr_peermsgs * msgs, tr_block_index_t block)
static void
updateDesiredRequestCount (tr_peermsgs * msgs)
{
const tr_torrent * const torrent = msgs->torrent;
tr_torrent * const torrent = msgs->torrent;
/* there are lots of reasons we might not want to request any blocks... */
if (tr_torrentIsSeed (torrent) || !tr_torrentHasMetadata (torrent)

View File

@ -263,7 +263,7 @@ loadFilePriorities (tr_benc * dict, tr_torrent * tor)
***/
static void
saveSingleSpeedLimit (tr_benc * d, const tr_torrent * tor, tr_direction dir)
saveSingleSpeedLimit (tr_benc * d, tr_torrent * tor, tr_direction dir)
{
tr_bencDictReserve (d, 3);
tr_bencDictAddInt (d, KEY_SPEED_Bps, tr_torrentGetSpeedLimit_Bps (tor, dir));
@ -272,14 +272,14 @@ saveSingleSpeedLimit (tr_benc * d, const tr_torrent * tor, tr_direction dir)
}
static void
saveSpeedLimits (tr_benc * dict, const tr_torrent * tor)
saveSpeedLimits (tr_benc * dict, tr_torrent * tor)
{
saveSingleSpeedLimit (tr_bencDictAddDict (dict, KEY_SPEEDLIMIT_DOWN, 0), tor, TR_DOWN);
saveSingleSpeedLimit (tr_bencDictAddDict (dict, KEY_SPEEDLIMIT_UP, 0), tor, TR_UP);
}
static void
saveRatioLimits (tr_benc * dict, const tr_torrent * tor)
saveRatioLimits (tr_benc * dict, tr_torrent * tor)
{
tr_benc * d = tr_bencDictAddDict (dict, KEY_RATIOLIMIT, 2);
tr_bencDictAddReal (d, KEY_RATIOLIMIT_RATIO, tr_torrentGetRatioLimit (tor));
@ -287,7 +287,7 @@ saveRatioLimits (tr_benc * dict, const tr_torrent * tor)
}
static void
saveIdleLimits (tr_benc * dict, const tr_torrent * tor)
saveIdleLimits (tr_benc * dict, tr_torrent * tor)
{
tr_benc * d = tr_bencDictAddDict (dict, KEY_IDLELIMIT, 2);
tr_bencDictAddInt (d, KEY_IDLELIMIT_MINS, tr_torrentGetIdleLimit (tor));

View File

@ -512,16 +512,15 @@ addTrackerStats (const tr_tracker_stat * st, int n, tr_benc * list)
}
static void
addPeers (const tr_torrent * tor,
tr_benc * list)
addPeers (tr_torrent * tor, tr_benc * list)
{
int i;
int peerCount;
tr_peer_stat * peers = tr_torrentPeers (tor, &peerCount);
int i;
int peerCount;
tr_peer_stat * peers = tr_torrentPeers (tor, &peerCount);
tr_bencInitList (list, peerCount);
tr_bencInitList (list, peerCount);
for (i = 0; i < peerCount; ++i)
for (i=0; i<peerCount; ++i)
{
tr_benc * d = tr_bencListAddDict (list, 16);
const tr_peer_stat * peer = peers + i;
@ -552,7 +551,7 @@ addPeers (const tr_torrent * tor,
#define tr_streq(a,alen,b)((alen+1==sizeof (b)) && !memcmp (a,b,alen))
static void
addField (const tr_torrent * const tor,
addField (tr_torrent * const tor,
const tr_info * const inf,
const tr_stat * const st,
tr_benc * const d,
@ -734,7 +733,7 @@ addField (const tr_torrent * const tor,
}
static void
addInfo (const tr_torrent * tor, tr_benc * d, tr_benc * fields)
addInfo (tr_torrent * tor, tr_benc * d, tr_benc * fields)
{
const char * str;
const int n = tr_bencListSize (fields);

View File

@ -1766,7 +1766,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_torrentFree (torrents[i]);
tr_torrentUnref (torrents[i]);
tr_free (torrents);
/* Close the announcer *after* closing the torrents

View File

@ -152,22 +152,30 @@ tr_torrentFindFromObfuscatedHash (tr_session * session,
}
bool
tr_torrentIsPieceTransferAllowed (const tr_torrent * tor,
tr_direction direction)
tr_torrentIsPieceTransferAllowed (tr_torrent * tor,
tr_direction direction)
{
unsigned int limit;
bool allowed = true;
bool allowed = false;
if (tr_torrentUsesSpeedLimit (tor, direction))
assert (tr_isDirection (direction));
if (tr_torrentRef (tor))
{
unsigned int limit;
allowed = true;
if (tr_torrentUsesSpeedLimit (tor, direction))
if (tr_torrentGetSpeedLimit_Bps (tor, direction) <= 0)
allowed = false;
allowed = false;
if (tr_torrentUsesSessionLimits (tor))
if (tr_torrentUsesSessionLimits (tor))
if (tr_sessionGetActiveSpeedLimit_Bps (tor->session, direction, &limit))
if (limit <= 0)
allowed = false;
if (limit <= 0)
allowed = false;
}
return allowed;
return allowed;
}
/***
@ -198,50 +206,71 @@ tr_torrentGetSpeedLimit_Bps (const tr_torrent * tor, tr_direction dir)
return tr_bandwidthGetDesiredSpeed_Bps (&tor->bandwidth, dir);
}
unsigned int
tr_torrentGetSpeedLimit_KBps (const tr_torrent * tor, tr_direction dir)
tr_torrentGetSpeedLimit_KBps (tr_torrent * tor, tr_direction dir)
{
return toSpeedKBps (tr_torrentGetSpeedLimit_Bps (tor, dir));
unsigned int limit = 0;
assert (tr_isDirection (dir));
if (tr_torrentRef (tor))
{
limit = toSpeedKBps (tr_torrentGetSpeedLimit_Bps (tor, dir));
tr_torrentUnref (tor);
}
return limit;
}
void
tr_torrentUseSpeedLimit (tr_torrent * tor, tr_direction dir, bool do_use)
{
assert (tr_isTorrent (tor));
assert (tr_isDirection (dir));
assert (tr_isTorrent (tor));
assert (tr_isDirection (dir));
if (tr_bandwidthSetLimited (&tor->bandwidth, dir, do_use))
tr_torrentSetDirty (tor);
if (tr_bandwidthSetLimited (&tor->bandwidth, dir, do_use))
tr_torrentSetDirty (tor);
}
bool
tr_torrentUsesSpeedLimit (const tr_torrent * tor, tr_direction dir)
tr_torrentUsesSpeedLimit (tr_torrent * tor, tr_direction dir)
{
assert (tr_isTorrent (tor));
assert (tr_isDirection (dir));
bool limited = false;
return tr_bandwidthIsLimited (&tor->bandwidth, dir);
if (tr_torrentRef (tor))
{
limited = tr_bandwidthIsLimited (&tor->bandwidth, dir);
tr_torrentUnref (tor);
}
return limited;
}
void
tr_torrentUseSessionLimits (tr_torrent * tor, bool doUse)
{
bool changed;
bool changed;
assert (tr_isTorrent (tor));
assert (tr_isTorrent (tor));
changed = tr_bandwidthHonorParentLimits (&tor->bandwidth, TR_UP, doUse);
changed |= tr_bandwidthHonorParentLimits (&tor->bandwidth, TR_DOWN, doUse);
changed = tr_bandwidthHonorParentLimits (&tor->bandwidth, TR_UP, doUse);
changed |= tr_bandwidthHonorParentLimits (&tor->bandwidth, TR_DOWN, doUse);
if (changed)
tr_torrentSetDirty (tor);
if (changed)
tr_torrentSetDirty (tor);
}
bool
tr_torrentUsesSessionLimits (const tr_torrent * tor)
tr_torrentUsesSessionLimits (tr_torrent * tor)
{
assert (tr_isTorrent (tor));
bool limited = false;
return tr_bandwidthAreParentLimitsHonored (&tor->bandwidth, TR_UP);
if (tr_torrentRef (tor))
{
limited = tr_bandwidthAreParentLimitsHonored (&tor->bandwidth, TR_UP);
tr_torrentUnref (tor);
}
return limited;
}
/***
@ -251,71 +280,82 @@ tr_torrentUsesSessionLimits (const tr_torrent * tor)
void
tr_torrentSetRatioMode (tr_torrent * tor, tr_ratiolimit mode)
{
assert (tr_isTorrent (tor));
assert (mode==TR_RATIOLIMIT_GLOBAL || mode==TR_RATIOLIMIT_SINGLE || mode==TR_RATIOLIMIT_UNLIMITED);
assert (tr_isTorrent (tor));
assert (mode==TR_RATIOLIMIT_GLOBAL || mode==TR_RATIOLIMIT_SINGLE || mode==TR_RATIOLIMIT_UNLIMITED);
if (mode != tor->ratioLimitMode)
if (mode != tor->ratioLimitMode)
{
tor->ratioLimitMode = mode;
tor->ratioLimitMode = mode;
tr_torrentSetDirty (tor);
tr_torrentSetDirty (tor);
}
}
tr_ratiolimit
tr_torrentGetRatioMode (const tr_torrent * tor)
{
assert (tr_isTorrent (tor));
assert (tr_isTorrent (tor));
return tor->ratioLimitMode;
return tor->ratioLimitMode;
}
void
tr_torrentSetRatioLimit (tr_torrent * tor, double desiredRatio)
{
assert (tr_isTorrent (tor));
assert (tr_isTorrent (tor));
if ((int)(desiredRatio*100.0) != (int)(tor->desiredRatio*100.0))
if ((int)(desiredRatio*100.0) != (int)(tor->desiredRatio*100.0))
{
tor->desiredRatio = desiredRatio;
tor->desiredRatio = desiredRatio;
tr_torrentSetDirty (tor);
tr_torrentSetDirty (tor);
}
}
double
tr_torrentGetRatioLimit (const tr_torrent * tor)
tr_torrentGetRatioLimit (tr_torrent * tor)
{
assert (tr_isTorrent (tor));
double limit = 0;
return tor->desiredRatio;
if (tr_torrentRef (tor))
{
limit = tor->desiredRatio;
tr_torrentUnref (tor);
}
return limit;
}
bool
tr_torrentGetSeedRatio (const tr_torrent * tor, double * ratio)
tr_torrentGetSeedRatio (tr_torrent * tor, double * ratio)
{
bool isLimited;
bool isLimited = false;
switch (tr_torrentGetRatioMode (tor))
if (tr_torrentRef (tor))
{
case TR_RATIOLIMIT_SINGLE:
switch (tr_torrentGetRatioMode (tor))
{
case TR_RATIOLIMIT_SINGLE:
isLimited = true;
if (ratio)
*ratio = tr_torrentGetRatioLimit (tor);
*ratio = tr_torrentGetRatioLimit (tor);
break;
case TR_RATIOLIMIT_GLOBAL:
case TR_RATIOLIMIT_GLOBAL:
isLimited = tr_sessionIsRatioLimited (tor->session);
if (isLimited && ratio)
*ratio = tr_sessionGetRatioLimit (tor->session);
*ratio = tr_sessionGetRatioLimit (tor->session);
break;
default: /* TR_RATIOLIMIT_UNLIMITED */
default: /* TR_RATIOLIMIT_UNLIMITED */
isLimited = false;
break;
}
tr_torrentUnref (tor);
}
return isLimited;
return isLimited;
}
/* returns true if the seed ratio applies --
@ -808,6 +848,7 @@ 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);
@ -1096,45 +1137,41 @@ tr_torrentSetVerifyState (tr_torrent * tor, tr_verify_state state)
tor->anyDate = tr_time ();
}
static tr_torrent_activity
torrentGetActivity (const tr_torrent * tor)
tr_torrent_activity
tr_torrentGetActivity (const tr_torrent * tor)
{
const bool is_seed = tr_torrentIsSeed (tor);
assert (tr_isTorrent (tor));
tr_torrent_activity ret = TR_STATUS_STOPPED;
if (tor->verifyState == TR_VERIFY_NOW)
return TR_STATUS_CHECK;
const bool is_seed = tr_torrentIsSeed (tor);
if (tor->verifyState == TR_VERIFY_WAIT)
return TR_STATUS_CHECK_WAIT;
if (tor->isRunning)
return is_seed ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
if (tr_torrentIsQueued (tor)) {
if (is_seed && tr_sessionGetQueueEnabled (tor->session, TR_UP))
return TR_STATUS_SEED_WAIT;
if (!is_seed && tr_sessionGetQueueEnabled (tor->session, TR_DOWN))
return TR_STATUS_DOWNLOAD_WAIT;
if (tor->verifyState == TR_VERIFY_NOW)
{
ret = TR_STATUS_CHECK;
}
else if (tor->verifyState == TR_VERIFY_WAIT)
{
ret = TR_STATUS_CHECK_WAIT;
}
else if (tor->isRunning)
{
ret = is_seed ? TR_STATUS_SEED : TR_STATUS_DOWNLOAD;
}
else if (tr_torrentIsQueued (tor))
{
if (is_seed && tr_sessionGetQueueEnabled (tor->session, TR_UP))
ret = TR_STATUS_SEED_WAIT;
else if (!is_seed && tr_sessionGetQueueEnabled (tor->session, TR_DOWN))
ret = TR_STATUS_DOWNLOAD_WAIT;
}
return TR_STATUS_STOPPED;
}
tr_torrent_activity
tr_torrentGetActivity (tr_torrent * tor)
{
/* FIXME: is this call still needed? */
tr_torrentRecheckCompleteness (tor);
return torrentGetActivity (tor);
return ret;
}
static time_t
torrentGetIdleSecs (const tr_torrent * tor)
{
int idle_secs;
const tr_torrent_activity activity = torrentGetActivity (tor);
const tr_torrent_activity activity = tr_torrentGetActivity (tor);
if ((activity == TR_STATUS_DOWNLOAD || activity == TR_STATUS_SEED) && tor->startDate != 0)
idle_secs = difftime (tr_time (), MAX (tor->startDate, tor->activityDate));
@ -1153,25 +1190,28 @@ tr_torrentIsStalled (const tr_torrent * tor)
static double
getVerifyProgress (const tr_torrent * tor)
getVerifyProgress (tr_torrent * tor)
{
double d = 0;
double d = 0;
assert (tr_isTorrent (tor));
if (tr_torrentHasMetadata (tor))
if (tr_torrentRef (tor))
{
tr_piece_index_t i, n;
tr_piece_index_t checked = 0;
if (tr_torrentHasMetadata (tor))
{
tr_piece_index_t i, n;
tr_piece_index_t checked = 0;
for (i=0, n=tor->info.pieceCount; i!=n; ++i)
for (i=0, n=tor->info.pieceCount; i!=n; ++i)
if (tor->info.pieces[i].timeChecked)
++checked;
++checked;
d = checked / (double)tor->info.pieceCount;
d = checked / (double)tor->info.pieceCount;
}
tr_torrentUnref (tor);
}
return d;
return d;
}
const tr_stat *
@ -1184,12 +1224,9 @@ tr_torrentStat (tr_torrent * tor)
bool seedRatioApplies;
uint16_t seedIdleMinutes;
if (!tor)
if (!tr_torrentRef(tor))
return NULL;
assert (tr_isTorrent (tor));
tr_torrentLock (tor);
tor->lastStatTime = tr_time ();
s = &tor->stats;
@ -1308,12 +1345,13 @@ tr_torrentStat (tr_torrent * tor)
else
s->seedRatioPercentDone = (double)(seedRatioBytesGoal - seedRatioBytesLeft) / seedRatioBytesGoal;
tr_torrentUnlock (tor);
/* 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;
}
@ -1396,54 +1434,51 @@ tr_torrentFilesFree (tr_file_stat * files,
***/
double*
tr_torrentWebSpeeds_KBps (const tr_torrent * tor)
tr_torrentWebSpeeds_KBps (tr_torrent * tor)
{
double * ret = NULL;
double * ret = NULL;
if (tr_isTorrent (tor))
if (tr_torrentRef (tor))
{
tr_torrentLock (tor);
ret = tr_peerMgrWebSpeeds_KBps (tor);
tr_torrentUnlock (tor);
ret = tr_peerMgrWebSpeeds_KBps (tor);
tr_torrentUnref (tor);
}
return ret;
return ret;
}
tr_peer_stat *
tr_torrentPeers (const tr_torrent * tor, int * peerCount)
tr_torrentPeers (tr_torrent * tor, int * peerCount)
{
tr_peer_stat * ret = NULL;
tr_peer_stat * ret = NULL;
if (tr_isTorrent (tor))
if (tr_torrentRef (tor))
{
tr_torrentLock (tor);
ret = tr_peerMgrPeerStats (tor, peerCount);
tr_torrentUnlock (tor);
ret = tr_peerMgrPeerStats (tor, peerCount);
tr_torrentUnref (tor);
}
return ret;
return ret;
}
void
tr_torrentPeersFree (tr_peer_stat * peers, int peerCount UNUSED)
{
tr_free (peers);
tr_free (peers);
}
tr_tracker_stat *
tr_torrentTrackers (const tr_torrent * torrent, int * setmeTrackerCount)
tr_torrentTrackers (tr_torrent * torrent, int * setmeTrackerCount)
{
tr_tracker_stat * ret = NULL;
tr_tracker_stat * ret = NULL;
if (tr_isTorrent (torrent))
if (tr_torrentRef (torrent))
{
tr_torrentLock (torrent);
ret = tr_announcerStats (torrent, setmeTrackerCount);
tr_torrentUnlock (torrent);
ret = tr_announcerStats (torrent, setmeTrackerCount);
tr_torrentUnref (torrent);
}
return ret;
return ret;
}
void
@ -1453,26 +1488,23 @@ tr_torrentTrackersFree (tr_tracker_stat * trackers, int trackerCount)
}
void
tr_torrentAvailability (const tr_torrent * tor, int8_t * tab, int size)
tr_torrentAvailability (tr_torrent * tor, int8_t * tab, int size)
{
if (tr_isTorrent (tor) && (tab != NULL) && (size > 0))
if ((tab != NULL) && (size > 0) && tr_torrentRef (tor))
{
tr_torrentLock (tor);
tr_peerMgrTorrentAvailability (tor, tab, size);
tr_torrentUnlock (tor);
tr_peerMgrTorrentAvailability (tor, tab, size);
tr_torrentUnref (tor);
}
}
void
tr_torrentAmountFinished (const tr_torrent * tor,
float * tab,
int size)
tr_torrentAmountFinished (tr_torrent * tor, float * tab, int size)
{
assert (tr_isTorrent (tor));
tr_torrentLock (tor);
tr_cpGetAmountDone (&tor->completion, tab, size);
tr_torrentUnlock (tor);
if (tr_torrentRef (tor))
{
tr_cpGetAmountDone (&tor->completion, tab, size);
tr_torrentUnref (tor);
}
}
static void
@ -1636,7 +1668,7 @@ torrentShouldQueue (const tr_torrent * tor)
static void
torrentStart (tr_torrent * tor, bool bypass_queue)
{
switch (torrentGetActivity (tor))
switch (tr_torrentGetActivity (tor))
{
case TR_STATUS_SEED:
case TR_STATUS_DOWNLOAD:
@ -1775,25 +1807,24 @@ tr_torrentSave (tr_torrent * tor)
static void
stopTorrent (void * vtor)
{
tr_torrent * tor = vtor;
tr_torinf (tor, "Pausing");
tr_torrent * tor = vtor;
tr_torinf (tor, "Pausing");
assert (tr_isTorrent (tor));
if (tr_torrentLock (tor))
{
tr_verifyRemove (tor);
torrentSetQueued (tor, false);
tr_peerMgrStopTorrent (tor);
tr_announcerTorrentStopped (tor);
tr_cacheFlushTorrent (tor->session->cache, tor);
tr_torrentLock (tor);
tr_fdTorrentClose (tor->session, tor->uniqueId);
tr_verifyRemove (tor);
torrentSetQueued (tor, false);
tr_peerMgrStopTorrent (tor);
tr_announcerTorrentStopped (tor);
tr_cacheFlushTorrent (tor->session->cache, tor);
tr_fdTorrentClose (tor->session, tor->uniqueId);
if (!tor->isDeleting)
if (!tor->isDeleting)
tr_torrentSave (tor);
tr_torrentUnlock (tor);
tr_torrentUnlock (tor);
}
}
void
@ -1841,21 +1872,41 @@ closeTorrent (void * vtor)
}
void
tr_torrentFree (tr_torrent * tor)
tr_torrentUnref (tr_torrent * tor)
{
if (tr_isTorrent (tor))
assert (tr_isTorrent (tor));
if (--tor->refCount == 0)
{
tr_session * session = tor->session;
assert (tr_isSession (session));
tr_sessionLock (session);
tr_session * session = tor->session;
tr_torrentClearCompletenessCallback (tor);
tr_runInEventThread (session, closeTorrent, tor);
tr_sessionUnlock (session);
tr_sessionLock (session);
tr_torrentClearCompletenessCallback (tor);
tr_runInEventThread (session, closeTorrent, tor);
tr_sessionUnlock (session);
}
}
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;
}
struct remove_data
{
tr_torrent * tor;
@ -2037,60 +2088,55 @@ torrentCallScript (const tr_torrent * tor, const char * script)
void
tr_torrentRecheckCompleteness (tr_torrent * tor)
{
tr_completeness completeness;
assert (tr_isTorrent (tor));
tr_torrentLock (tor);
completeness = tr_cpGetStatus (&tor->completion);
if (completeness != tor->completeness)
if (tr_torrentLock (tor))
{
const int recentChange = tor->downloadedCur != 0;
const bool wasLeeching = !tr_torrentIsSeed (tor);
const bool wasRunning = tor->isRunning;
const tr_completeness completeness = tr_cpGetStatus (&tor->completion);
if (recentChange)
if (completeness != tor->completeness)
{
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));
}
getCompletionString (tor->completeness),
getCompletionString (completeness));
tor->completeness = completeness;
tr_fdTorrentClose (tor->session, tor->uniqueId);
tor->completeness = completeness;
tr_fdTorrentClose (tor->session, tor->uniqueId);
fireCompletenessChange (tor, completeness, wasRunning);
fireCompletenessChange (tor, completeness, wasRunning);
if (tr_torrentIsSeed (tor))
{
if (recentChange)
if (tr_torrentIsSeed (tor))
{
tr_announcerTorrentCompleted (tor);
tor->doneDate = tor->anyDate = tr_time ();
}
if (recentChange)
{
tr_announcerTorrentCompleted (tor);
tor->doneDate = tor->anyDate = tr_time ();
}
if (wasLeeching && wasRunning)
{
/* clear interested flag on all peers */
tr_peerMgrClearInterest (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 completeness was TR_LEECH then the seed limit check will have been skipped in bandwidthPulse */
tr_torrentCheckSeedLimit (tor);
}
if (tor->currentDir == tor->incompleteDir)
if (tor->currentDir == tor->incompleteDir)
tr_torrentSetLocation (tor, tor->downloadDir, true, NULL, NULL);
if (tr_sessionIsTorrentDoneScriptEnabled (tor->session))
if (tr_sessionIsTorrentDoneScriptEnabled (tor->session))
torrentCallScript (tor, tr_sessionGetTorrentDoneScript (tor->session));
}
tr_torrentSetDirty (tor);
}
tr_torrentSetDirty (tor);
tr_torrentUnlock (tor);
}
tr_torrentUnlock (tor);
}
/***
@ -2160,20 +2206,22 @@ tr_torrentSetFilePriorities (tr_torrent * tor,
}
tr_priority_t*
tr_torrentGetFilePriorities (const tr_torrent * tor)
tr_torrentGetFilePriorities (tr_torrent * tor)
{
tr_file_index_t i;
tr_priority_t * p;
tr_file_index_t i;
tr_priority_t * p = NULL;
assert (tr_isTorrent (tor));
if (tr_torrentRef (tor))
{
p = tr_new0 (tr_priority_t, tor->info.fileCount);
tr_torrentLock (tor);
p = tr_new0 (tr_priority_t, tor->info.fileCount);
for (i = 0; i < tor->info.fileCount; ++i)
for (i=0; i<tor->info.fileCount; ++i)
p[i] = tor->info.files[i].priority;
tr_torrentUnlock (tor);
return p;
tr_torrentUnref (tor);
}
return p;
}
/**

View File

@ -62,8 +62,8 @@ tr_torrent* tr_torrentFindFromHashString (tr_session * session,
tr_torrent* tr_torrentFindFromObfuscatedHash (tr_session * session,
const uint8_t * hash);
bool tr_torrentIsPieceTransferAllowed (const tr_torrent * torrent,
tr_direction direction);
bool tr_torrentIsPieceTransferAllowed (tr_torrent * torrent,
tr_direction direction);
@ -127,7 +127,7 @@ tr_verify_state;
void tr_torrentSetVerifyState (tr_torrent * tor,
tr_verify_state state);
tr_torrent_activity tr_torrentGetActivity (tr_torrent * tor);
tr_torrent_activity tr_torrentGetActivity (const tr_torrent * tor);
struct tr_incomplete_metadata;
@ -139,6 +139,8 @@ struct tr_torrent
int magicNumber;
size_t refCount;
tr_stat_errtype error;
char errorString[128];
char errorTracker[128];
@ -300,10 +302,7 @@ tr_torBlockCountBytes (const tr_torrent * tor, const tr_block_index_t block)
: tor->blockSize;
}
static inline void tr_torrentLock (const tr_torrent * tor)
{
tr_sessionLock (tor->session);
}
bool tr_torrentLock (const tr_torrent * tor);
static inline bool tr_torrentIsLocked (const tr_torrent * tor)
{
@ -366,6 +365,7 @@ 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

@ -1147,9 +1147,21 @@ tr_torrent * tr_torrentNew (const tr_ctor * ctor,
/** @addtogroup tr_torrent Torrents
@{ */
/** @brief Frees memory allocated by tr_torrentNew ().
Running torrents are stopped first. */
void tr_torrentFree (tr_torrent * torrent);
/**
* @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);
@ -1228,13 +1240,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 (const tr_torrent *, tr_direction);
unsigned int tr_torrentGetSpeedLimit_KBps (tr_torrent *, tr_direction);
void tr_torrentUseSpeedLimit (tr_torrent *, tr_direction, bool);
bool tr_torrentUsesSpeedLimit (const tr_torrent *, tr_direction);
void tr_torrentUseSpeedLimit (tr_torrent *, tr_direction, bool);
bool tr_torrentUsesSpeedLimit (tr_torrent *, tr_direction);
void tr_torrentUseSessionLimits (tr_torrent *, bool);
bool tr_torrentUsesSessionLimits (const tr_torrent *);
void tr_torrentUseSessionLimits (tr_torrent *, bool);
bool tr_torrentUsesSessionLimits (tr_torrent *);
/****
@ -1262,10 +1274,10 @@ tr_ratiolimit tr_torrentGetRatioMode (const tr_torrent * tor);
void tr_torrentSetRatioLimit (tr_torrent * tor,
double ratio);
double tr_torrentGetRatioLimit (const tr_torrent * tor);
double tr_torrentGetRatioLimit (tr_torrent * tor);
bool tr_torrentGetSeedRatio (const tr_torrent *, double * ratio);
bool tr_torrentGetSeedRatio (tr_torrent *, double * ratio);
/****
@ -1334,7 +1346,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 (const tr_torrent * torrent);
tr_priority_t* tr_torrentGetFilePriorities (tr_torrent * torrent);
/** @brief Set a batch of files to be downloaded or not. */
void tr_torrentSetFileDLs (tr_torrent * torrent,
@ -1569,8 +1581,8 @@ typedef struct tr_peer_stat
}
tr_peer_stat;
tr_peer_stat * tr_torrentPeers (const tr_torrent * torrent,
int * peerCount);
tr_peer_stat * tr_torrentPeers (tr_torrent * torrent,
int * peerCount);
void tr_torrentPeersFree (tr_peer_stat * peerStats,
int peerCount);
@ -1692,8 +1704,8 @@ typedef struct
}
tr_tracker_stat;
tr_tracker_stat * tr_torrentTrackers (const tr_torrent * torrent,
int * setmeTrackerCount);
tr_tracker_stat * tr_torrentTrackers (tr_torrent * torrent,
int * setmeTrackerCount);
void tr_torrentTrackersFree (tr_tracker_stat * trackerStats,
int trackerCount);
@ -1710,7 +1722,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 (const tr_torrent * torrent);
double* tr_torrentWebSpeeds_KBps (tr_torrent * torrent);
typedef struct tr_file_stat
{
@ -1734,13 +1746,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 (const tr_torrent * torrent,
int8_t * tab,
int size);
void tr_torrentAvailability (tr_torrent * torrent,
int8_t * tab,
int size);
void tr_torrentAmountFinished (const tr_torrent * torrent,
float * tab,
int size);
void tr_torrentAmountFinished (tr_torrent * torrent,
float * tab,
int size);
void tr_torrentVerify (tr_torrent * torrent);