]> granicus.if.org Git - transmission/commitdiff
(trunk, libT) #5168 'make libtransmission's public funcs nonblocking when possible...
authorJordan Lee <jordan@transmissionbt.com>
Fri, 14 Dec 2012 20:04:37 +0000 (20:04 +0000)
committerJordan Lee <jordan@transmissionbt.com>
Fri, 14 Dec 2012 20:04:37 +0000 (20:04 +0000)
gtk/my-valgrind.sh
gtk/torrent-cell-renderer.c
libtransmission/handshake.c
libtransmission/peer-mgr.c
libtransmission/peer-mgr.h
libtransmission/session.c
libtransmission/torrent.c
libtransmission/torrent.h
libtransmission/transmission.h

index 146b7c02f5c702d5337d7d2a2e722ecc6f8ebab8..cd5ff98faa38bfd709b65e1f83a3cc5c5fecdc4c 100755 (executable)
@@ -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
index 4192bb50528d35d480d35cbfbd4777afbdd9583c..46f23c3e8ad2b2ad619f49676e1027536f55852e 100644 (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);
index c615e56f76ffd718cff653203faeceda2c266a64..fa11455e950caf130cd0b34873fab7a2e8553bd7 100644 (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];
index 84e9e584961122f01e2dd379855811fb8658e20b..aad3d7f2dc30ad1c5d944c19bad55854c9de2066 100644 (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))
-    {
-      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);
+  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<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;
-
-          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 (clientIsUploadingTo (peer))
-            ++*setmePeersGettingFromUs;
-        }
+      if (clientIsDownloadingFrom (tor, peer))
+        ++*setmePeersSendingToUs;
 
-      *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))
-    {
-      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 ();
+  assert (tr_isTorrent (tor));
 
-      ret = tr_new0 (double, webseedCount);
+  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)
-        {
-          unsigned int Bps;
-          if (tr_webseedGetSpeed_Bps (webseeds[i], now, &Bps))
-            ret[i] = Bps / (double)tr_speed_K;
-          else
-            ret[i] = -1.0;
-        }
+  assert (t->manager != NULL);
+  assert (webseedCount == tor->info.webseedCount);
 
-      tr_torrentUnref (tor);
+  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;
     }
 
   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;
-
-  if (tr_torrentRef (tor))
-    {
-      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_peer_stat * ret;
+  const Torrent * t;
+  const tr_peer ** peers;
+  const time_t now = tr_time ();
+  const uint64_t now_msec = tr_time_msec ();
 
-      assert (t->manager != NULL);
+  assert (tr_isTorrent (tor));
+  assert (tor->torrentPeers->manager != NULL);
 
-      size = tr_ptrArraySize (&t->peers);
-      ret = tr_new0 (tr_peer_stat, size);
+  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)
-        {
-          char *                   pch;
-          const tr_peer *          peer = peers[i];
-          const struct peer_atom * atom = peer->atom;
-          tr_peer_stat *           stat = ret + i;
-
-          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);
+  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;
+
+      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';
     }
 
   *setmeCount = size;
index 0d9f3d1b432ef8e9f779a61343ce1df7c3217615..6b88e3d5bf35472f9754b41ab4b47c8e9c129d76 100644 (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,
index 0ee85f30ec0c62d1b032f52238fa20ba05051a25..152c8f860741e426c8239629337623579f4096cd 100644 (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
index e306b3ab4b2f78fb3173e2030b127880c8e8fc4c..a2f817ff2c33e496362b8961ae859c2494f69e50 100644 (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;
-
-      allowed = true;
-
-      if (tr_torrentUsesSpeedLimit (tor, direction))
-        if (tr_torrentGetSpeedLimit_Bps (tor, direction) <= 0)
-          allowed = false;
+  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;
-
-  if (tr_torrentRef (tor))
-    {
-      limited = tr_bandwidthIsLimited (&tor->bandwidth, dir);
-      tr_torrentUnref (tor);
-    }
+  assert (tr_isTorrent (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;
-
-  if (tr_torrentRef (tor))
-    {
-      limited = tr_bandwidthAreParentLimitsHonored (&tor->bandwidth, TR_UP);
-      tr_torrentUnref (tor);
-    }
+  assert (tr_isTorrent (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;
-
-  if (tr_torrentRef (tor))
-    {
-      limit = tor->desiredRatio;
-      tr_torrentUnref (tor);
-    }
+  assert (tr_isTorrent (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;
+
+  assert (tr_isTorrent (tor));
 
-  if (tr_torrentRef (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;
+
+  assert (tr_isTorrent (tor));
 
-    if (tr_torrentGetSeedRatio (tor, &seedRatio))
+  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;
-
-    if (!tr_torrentRef(tor))
-        return NULL;
-
-    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->manualAnnounceTime = tr_announcerNextManualAnnounce (tor);
-
-    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->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->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);
-
-    seedRatioApplies = tr_torrentGetSeedRatioBytes (tor, &seedRatioBytesLeft,
-                                                         &seedRatioBytesGoal);
-
-    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 */
-
-        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;
-            }
+  tr_stat * s;
+  uint64_t seedRatioBytesLeft;
+  uint64_t seedRatioBytesGoal;
+  bool seedRatioApplies;
+  uint16_t seedIdleMinutes;
+  const uint64_t now = tr_time_msec ();
 
-            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);
+  assert (tr_isTorrent (tor));
 
-            s->etaIdle = TR_ETA_NOT_AVAIL;
-            break;
+  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->manualAnnounceTime = tr_announcerNextManualAnnounce (tor);
+
+  tr_peerMgrTorrentStats (tor,
+                          &s->peersConnected,
+                          &s->webseedsSendingToUs,
+                          &s->peersSendingToUs,
+                          &s->peersGettingFromUs,
+                          s->peersFrom);
+
+  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->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->ratio = tr_getRatio (s->uploadedEver,
+                          s->downloadedEver ? s->downloadedEver : s->haveValid);
+
+  seedRatioApplies = tr_torrentGetSeedRatioBytes (tor, &seedRatioBytesLeft,
+                                                       &seedRatioBytesGoal);
+
+  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 */
+      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);
 
-        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);
-            }
+        s->etaIdle = TR_ETA_NOT_AVAIL;
+        break;
 
-            if (tor->etaULSpeed_KBps < 1 && tr_torrentGetSeedIdle (tor, &seedIdleMinutes))
-                s->etaIdle = seedIdleMinutes * 60 - s->idleSecs;
+      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->etaIdle = TR_ETA_NOT_AVAIL;
-            break;
-        }
+              s->eta = seedRatioBytesLeft / toSpeedBytes (tor->etaULSpeed_KBps);
+          }
 
-        default:
-            s->eta = TR_ETA_NOT_AVAIL;
-            s->etaIdle = TR_ETA_NOT_AVAIL;
-            break;
-    }
+        if (tor->etaULSpeed_KBps < 1 && tr_torrentGetSeedIdle (tor, &seedIdleMinutes))
+          s->etaIdle = seedIdleMinutes * 60 - s->idleSecs;
+        else
+          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);
+      default:
+        s->eta = TR_ETA_NOT_AVAIL;
+        s->etaIdle = TR_ETA_NOT_AVAIL;
+        break;
+    }
 
-    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;
+  /* 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);
 
-    /* test some of the constraints */
-    assert (s->sizeWhenDone <= tor->info.totalSize);
-    assert (s->leftUntilDone <= s->sizeWhenDone);
-    assert (s->desiredAvailable <= s->leftUntilDone);
+  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;
 
-    tr_torrentUnref (tor);
+  /* test some of the constraints */
+  assert (s->sizeWhenDone <= tor->info.totalSize);
+  assert (s->leftUntilDone <= s->sizeWhenDone);
+  assert (s->desiredAvailable <= s->leftUntilDone);
 
-    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;
-
-  if (tr_torrentRef (tor))
-    {
-      ret = tr_peerMgrWebSpeeds_KBps (tor);
-      tr_torrentUnref (tor);
-    }
+  assert (tr_isTorrent (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;
-
-  if (tr_torrentRef (tor))
-    {
-      ret = tr_peerMgrPeerStats (tor, peerCount);
-      tr_torrentUnref (tor);
-    }
+  assert (tr_isTorrent (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;
-
-  if (tr_torrentRef (torrent))
-    {
-      ret = tr_announcerStats (torrent, setmeTrackerCount);
-      tr_torrentUnref (torrent);
-    }
+  assert (tr_isTorrent (tor));
 
-  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_sessionLock (session);
-      tr_torrentClearCompletenessCallback (tor);
-      tr_runInEventThread (session, closeTorrent, tor);
-      tr_sessionUnlock (session);
+      tr_torrentClearCompletenessCallback (tor); 
+      tr_runInEventThread (session, closeTorrent, tor); 
 
-      --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))
-    {
-      const tr_completeness completeness = tr_cpGetStatus (&tor->completion);
-
-      if (completeness != tor->completeness)
-        {
-          const int recentChange = tor->downloadedCur != 0;
-          const bool wasLeeching = !tr_torrentIsSeed (tor);
-          const bool wasRunning = tor->isRunning;
+  tr_completeness completeness;
 
-          if (recentChange)
-            tr_torinf (tor, _("State changed from \"%1$s\" to \"%2$s\""),
-                       getCompletionString (tor->completeness),
-                       getCompletionString (completeness));
+  tr_torrentLock (tor);
 
-          tor->completeness = completeness;
-          tr_fdTorrentClose (tor->session, tor->uniqueId);
+  completeness = tr_cpGetStatus (&tor->completion);
+  if (completeness != tor->completeness)
+    {
+      const int recentChange = tor->downloadedCur != 0;
+      const bool wasLeeching = !tr_torrentIsSeed (tor);
+      const bool wasRunning = tor->isRunning;
 
-          fireCompletenessChange (tor, completeness, wasRunning);
+      if (recentChange)
+        tr_torinf (tor, _("State changed from \"%1$s\" to \"%2$s\""),
+                   getCompletionString (tor->completeness),
+                   getCompletionString (completeness));
 
-          if (tr_torrentIsSeed (tor))
-            {
-              if (recentChange)
-                {
-                  tr_announcerTorrentCompleted (tor);
-                  tor->doneDate = tor->anyDate = tr_time ();
-                }
+      tor->completeness = completeness;
+      tr_fdTorrentClose (tor->session, tor->uniqueId);
 
-              if (wasLeeching && wasRunning)
-                {
-                  /* clear interested flag on all peers */
-                  tr_peerMgrClearInterest (tor);
+      fireCompletenessChange (tor, completeness, wasRunning);
 
-                  /* if completeness was TR_LEECH then the seed limit check will have been skipped in bandwidthPulse */
-                  tr_torrentCheckSeedLimit (tor);
-                }
+      if (tr_torrentIsSeed (tor))
+        {
+          if (recentChange)
+            {
+              tr_announcerTorrentCompleted (tor);
+              tor->doneDate = tor->anyDate = tr_time ();
+            }
 
-              if (tor->currentDir == tor->incompleteDir)
-                tr_torrentSetLocation (tor, tor->downloadDir, true, NULL, NULL);
+          if (wasLeeching && wasRunning)
+            {
+              /* clear interested flag on all peers */
+              tr_peerMgrClearInterest (tor);
 
-              if (tr_sessionIsTorrentDoneScriptEnabled (tor->session))
-                torrentCallScript (tor, tr_sessionGetTorrentDoneScript (tor->session));
+              /* if completeness was TR_LEECH then the seed limit check will have been skipped in bandwidthPulse */
+              tr_torrentCheckSeedLimit (tor);
             }
 
-          tr_torrentSetDirty (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;
 }
index bf6d3695f7c38a902c3cf97961c850314848eaab..01b73d3b3d36ec47ffce80aea4f39dfff21e424b 100644 (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));
 }
 
index ad8705da072cd0236ae7a2a4f9ab13a1d6c946a1..1ea57c24fec475df067162ff42dc40083d9ef439 100644 (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);