(trunk) #5168 'make libtransmission's public funcs nonblocking when possible' -- first attempt.
This commit is contained in:
parent
84f2cf8fa2
commit
079c78981c
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue