Ticket #6147: priority.patch

File priority.patch, 28.3 KB (added by EyeTolledEweSew, 6 years ago)

Initial patch for custom piece priorities

  • configure.ac

    diff --git a/configure.ac b/configure.ac
    index 8f9d0c8..92e4372 100644
    a b dnl STATUS: "X" for prerelease beta builds, 
    33dnl         "Z" for unsupported trunk builds,
    44dnl         "0" for stable, supported releases
    55dnl these should be the only two lines you need to change
    6 m4_define([user_agent_prefix],[2.92])
    7 m4_define([peer_id_prefix],[-TR2920-])
     6m4_define([user_agent_prefix],[2.92+])
     7m4_define([peer_id_prefix],[-TR292Z-])
    88
    99AC_INIT([transmission],[user_agent_prefix],[http://trac.transmissionbt.com/newticket])
    1010AC_SUBST(USERAGENT_PREFIX,[user_agent_prefix])
  • libtransmission/cache.c

    diff --git a/libtransmission/cache.c b/libtransmission/cache.c
    index 80efb7b..a21836c 100644
    a b tr_cacheFlushTorrent (tr_cache * cache, tr_torrent * torrent) 
    475475
    476476  return err;
    477477}
     478
     479void
     480tr_cacheGetTorrentBlockBitfieldStruct (tr_cache * cache, tr_torrent * torrent,
     481                                       tr_bitfield * blockInCache)
     482{
     483  tr_block_index_t n = torrent->blockCount;
     484  int pos = findBlockPos (cache, torrent, 0);
     485
     486  assert (tr_torrentHasMetadata (torrent));
     487
     488  tr_bitfieldConstruct (blockInCache, n);
     489
     490  while (pos < tr_ptrArraySize (&cache->blocks))
     491    {
     492      const struct cache_block * b = tr_ptrArrayNth (&cache->blocks, pos);
     493
     494      if (b->tor != torrent)
     495        break;
     496
     497      tr_bitfieldAdd (blockInCache, b->block);
     498      pos++;
     499    }
     500}
  • libtransmission/cache.h

    diff --git a/libtransmission/cache.h b/libtransmission/cache.h
    index 81a1992..e092e1f 100644
    a b  
    1515#define TR_CACHE_H
    1616
    1717struct evbuffer;
     18struct tr_bitfield;
    1819
     20typedef struct tr_bitfield tr_bitfield;
    1921typedef struct tr_cache tr_cache;
    2022
    2123/***
    int tr_cacheFlushFile (tr_cache * cache, 
    6769                       tr_torrent       * torrent,
    6870                       tr_file_index_t    file);
    6971
     72void tr_cacheGetTorrentBlockBitfieldStruct (tr_cache    * cache,
     73                                            tr_torrent  * torrent,
     74                                            tr_bitfield * blockInCache);
     75
    7076#endif
  • libtransmission/completion.c

    diff --git a/libtransmission/completion.c b/libtransmission/completion.c
    index 1ed6e68..229d908 100644
    a b tr_cpFileIsComplete (const tr_completion * cp, tr_file_index_t i) 
    288288    }
    289289}
    290290
    291 void *
    292 tr_cpCreatePieceBitfield (const tr_completion * cp, size_t * byte_count)
     291void
     292tr_cpCreatePieceBitfieldStruct (const tr_completion * cp, tr_bitfield * pieces)
    293293{
    294   void * ret;
    295294  tr_piece_index_t n;
    296   tr_bitfield pieces;
    297295
    298296  assert (tr_torrentHasMetadata (cp->tor));
    299297
    300298  n = cp->tor->info.pieceCount;
    301   tr_bitfieldConstruct (&pieces, n);
     299  tr_bitfieldConstruct (pieces, n);
    302300
    303301  if (tr_cpHasAll (cp))
    304302    {
    305       tr_bitfieldSetHasAll (&pieces);
     303      tr_bitfieldSetHasAll (pieces);
    306304    }
    307305  else if (!tr_cpHasNone (cp))
    308306    {
    tr_cpCreatePieceBitfield (const tr_completion * cp, size_t * byte_count) 
    310308      bool * flags = tr_new (bool, n);
    311309      for (i=0; i<n; ++i)
    312310        flags[i] = tr_cpPieceIsComplete (cp, i);
    313       tr_bitfieldSetFromFlags (&pieces, flags, n);
     311      tr_bitfieldSetFromFlags (pieces, flags, n);
    314312      tr_free (flags);
    315313    }
     314}
     315
     316void *
     317tr_cpCreatePieceBitfield (const tr_completion * cp, size_t * byte_count)
     318{
     319  void * ret;
     320  tr_bitfield pieces;
     321
     322  assert (tr_torrentHasMetadata (cp->tor));
    316323
     324  tr_cpCreatePieceBitfieldStruct (cp, &pieces);
    317325  ret = tr_bitfieldGetRaw (&pieces, byte_count);
    318326  tr_bitfieldDestruct (&pieces);
    319327  return ret;
  • libtransmission/completion.h

    diff --git a/libtransmission/completion.h b/libtransmission/completion.h
    index a36a112..4340882 100644
    a b tr_cpBlockIsComplete (const tr_completion * cp, tr_block_index_t i) 
    135135bool  tr_cpFileIsComplete (const tr_completion * cp, tr_file_index_t);
    136136
    137137void* tr_cpCreatePieceBitfield (const tr_completion * cp, size_t * byte_count);
     138void tr_cpCreatePieceBitfieldStruct (const tr_completion * cp,
     139                                     tr_bitfield         * pieces);
    138140
    139141static inline void
    140142tr_cpInvalidateDND (tr_completion * cp)
  • libtransmission/peer-mgr.c

    diff --git a/libtransmission/peer-mgr.c b/libtransmission/peer-mgr.c
    index 30e9036..93176e9 100644
    a b struct weighted_piece 
    171171  tr_piece_index_t index;
    172172  int16_t salt;
    173173  int16_t requestCount;
     174  int8_t maxRequestsPerBlock;
    174175};
    175176
    176177enum piece_sort_state
    typedef struct tr_swarm 
    218219  int                        maxPeers;
    219220  time_t                     lastCancel;
    220221
     222  /* are we in the endgame? */
     223  int                        endgame;
     224
    221225  /* Before the endgame this should be 0. In endgame, is contains the average
    222226   * number of pending requests per peer. Only peers which have more pending
    223227   * requests are considered 'fast' are allowed to request a block that's
    224228   * already been requested from another (slower?) peer. */
    225   int                        endgame;
     229  int                        avgRequestsPerDownloadingPeer;
    226230}
    227231tr_swarm;
    228232
    testForEndgame (const tr_swarm * s) 
    886890}
    887891
    888892static void
    889 updateEndgame (tr_swarm * s)
     893updateBlockRequestStats (tr_torrent * t)
    890894{
     895  tr_swarm * s = t->swarm;
    891896  assert (s->requestCount >= 0);
    892897
    893   if (!testForEndgame (s))
     898  /* if we'll issue multiple requests per block, get the average number of
     899   * requests per downloading peer */
     900  int i;
     901  int numDownloading = 0;
     902  const int n = tr_ptrArraySize (&s->peers);
     903
     904  s->endgame = testForEndgame(s);
     905
     906  /* add the active bittorrent peers... */
     907  for (i=0; i<n; ++i)
    894908    {
    895       /* not in endgame */
    896       s->endgame = 0;
     909      const tr_peer * p = tr_ptrArrayNth (&s->peers, i);
     910      if (p->pendingReqsToPeer > 0)
     911        ++numDownloading;
    897912    }
    898   else if (!s->endgame) /* only recalculate when endgame first begins */
    899     {
    900       int i;
    901       int numDownloading = 0;
    902       const int n = tr_ptrArraySize (&s->peers);
    903 
    904       /* add the active bittorrent peers... */
    905       for (i=0; i<n; ++i)
    906         {
    907           const tr_peer * p = tr_ptrArrayNth (&s->peers, i);
    908           if (p->pendingReqsToPeer > 0)
    909             ++numDownloading;
    910         }
    911913
    912       /* add the active webseeds... */
    913       numDownloading += countActiveWebseeds (s);
     914  /* add the active webseeds... */
     915  numDownloading += countActiveWebseeds (s);
    914916
    915       /* average number of pending requests per downloading peer */
    916       s->endgame = s->requestCount / MAX (numDownloading, 1);
    917     }
     917  /* average number of pending requests per downloading peer */
     918  s->avgRequestsPerDownloadingPeer = s->requestCount / MAX (numDownloading, 1);
    918919}
    919920
    920921
    pieceListRebuild (tr_swarm * s) 
    11021103          piece->index = pool[i];
    11031104          piece->requestCount = 0;
    11041105          piece->salt = tr_rand_int_weak (4096);
     1106          piece->maxRequestsPerBlock = inf->pieces[i].maxRequestsPerBlock;
    11051107        }
    11061108
    11071109      /* if we already had a list of pieces, merge it into
    tr_peerMgrGetNextRequests (tr_torrent * tor, 
    13541356  assertReplicationCountIsExact (s);
    13551357  assertWeightedPiecesAreSorted (s);
    13561358
    1357   updateEndgame (s);
     1359  updateBlockRequestStats (tor);
    13581360  pieces = s->pieces;
    13591361  for (i=0; i<s->pieceCount && got<numwant; ++i)
    13601362    {
    tr_peerMgrGetNextRequests (tr_torrent * tor, 
    13851387              peers = (tr_peer **) tr_ptrArrayPeek (&peerArr, &peerCount);
    13861388              if (peerCount != 0)
    13871389                {
    1388                   /* don't make a second block request until the endgame */
    1389                   if (!s->endgame)
    1390                     continue;
     1390                  int maxRequestsPerBlock;
    13911391
    1392                   /* don't have more than two peers requesting this block */
    1393                   if (peerCount > 1)
     1392                  if (p->maxRequestsPerBlock)
     1393                    maxRequestsPerBlock = p->maxRequestsPerBlock;
     1394                  else if (s->endgame)
     1395                    maxRequestsPerBlock = 2;
     1396                  else
     1397                    maxRequestsPerBlock = 1;
     1398
     1399                  /* limit the peers requesting this block */
     1400                  if (peerCount >= maxRequestsPerBlock)
    13941401                    continue;
    13951402
    13961403                  /* don't send the same request to the same peer twice */
    1397                   if (peer == peers[0])
    1398                     continue;
     1404                  {
     1405                    int j;
     1406                    bool found = false;
     1407                    for (j = 0; j < peerCount; j++)
     1408                      {
     1409                        if (peer == peers[j]) {
     1410                          found = true;
     1411                          break;
     1412                        }
     1413                      }
     1414                    if (found)
     1415                      continue;
     1416                  }
    13991417
    14001418                  /* in the endgame allow an additional peer to download a
    14011419                     block but only if the peer seems to be handling requests
    14021420                     relatively fast */
    1403                   if (peer->pendingReqsToPeer + numwant - got < s->endgame)
     1421                  if (peer->pendingReqsToPeer + numwant - got < s->avgRequestsPerDownloadingPeer)
    14041422                    continue;
    14051423                }
    14061424
  • libtransmission/quark.c

    diff --git a/libtransmission/quark.c b/libtransmission/quark.c
    index 30cc2bc..bed1779 100644
    a b static const struct tr_key_struct my_static[] = 
    148148  { "incomplete", 10 },
    149149  { "incomplete-dir", 14 },
    150150  { "incomplete-dir-enabled", 22 },
     151  { "indexes", 7 },
    151152  { "info", 4 },
    152153  { "info_hash", 9 },
    153154  { "inhibit-desktop-hibernation", 27 },
    static const struct tr_key_struct my_static[] = 
    240241  { "pex-enabled", 11 },
    241242  { "piece", 5 },
    242243  { "piece length", 12 },
     244  { "piece-get", 9 },
     245  { "piece-max-requests-per-block", 28 },
     246  { "piece-priority", 14 },
    243247  { "pieceCount", 10 },
    244248  { "pieceSize", 9 },
    245249  { "pieces", 6 },
     250  { "pieces-on-disk", 14 },
     251  { "pieces-unwanted", 15 },
     252  { "pieces-wanted", 13 },
    246253  { "play-download-complete-sound", 28 },
    247254  { "port", 4 },
    248255  { "port-forwarding-enabled", 23 },
    static const struct tr_key_struct my_static[] = 
    393400  { "ut_recommend", 12 },
    394401  { "utp-enabled", 11 },
    395402  { "v", 1 },
     403  { "values", 6 },
    396404  { "version", 7 },
    397405  { "wanted", 6 },
    398406  { "warning message", 15 },
  • libtransmission/quark.h

    diff --git a/libtransmission/quark.h b/libtransmission/quark.h
    index 7f52127..a0298c7 100644
    a b enum 
    150150  TR_KEY_incomplete,
    151151  TR_KEY_incomplete_dir,
    152152  TR_KEY_incomplete_dir_enabled,
     153  TR_KEY_indexes,
    153154  TR_KEY_info,
    154155  TR_KEY_info_hash,
    155156  TR_KEY_inhibit_desktop_hibernation,
    enum 
    242243  TR_KEY_pex_enabled,
    243244  TR_KEY_piece,
    244245  TR_KEY_piece_length,
     246  TR_KEY_piece_get,
     247  TR_KEY_piece_max_requests_per_block,
     248  TR_KEY_piece_priority,
    245249  TR_KEY_pieceCount,
    246250  TR_KEY_pieceSize,
    247251  TR_KEY_pieces,
     252  TR_KEY_pieces_on_disk,
     253  TR_KEY_pieces_unwanted,
     254  TR_KEY_pieces_wanted,
    248255  TR_KEY_play_download_complete_sound,
    249256  TR_KEY_port,
    250257  TR_KEY_port_forwarding_enabled,
    enum 
    395402  TR_KEY_ut_recommend,
    396403  TR_KEY_utp_enabled,
    397404  TR_KEY_v,
     405  TR_KEY_values,
    398406  TR_KEY_version,
    399407  TR_KEY_wanted,
    400408  TR_KEY_warning_message,
  • libtransmission/rpcimpl.c

    diff --git a/libtransmission/rpcimpl.c b/libtransmission/rpcimpl.c
    index 46fd319..8c82cf9 100644
    a b  
    1818#include <event2/buffer.h>
    1919
    2020#include "transmission.h"
     21#include "cache.h"
    2122#include "completion.h"
    2223#include "crypto-utils.h"
    2324#include "error.h"
    torrentVerify (tr_session * session, 
    426427  return NULL;
    427428}
    428429
     430static const char*
     431torrentFlush  (tr_session               * session,
     432               tr_variant               * args_in,
     433               tr_variant               * args_out UNUSED,
     434               struct tr_rpc_idle_data  * idle_data UNUSED)
     435{
     436  int i;
     437  int torrentCount;
     438  tr_torrent ** torrents = getTorrents (session, args_in, &torrentCount);
     439  tr_variant * list = tr_variantDictAddList (args_out, TR_KEY_torrents, torrentCount);
     440
     441  assert (idle_data == NULL);
     442
     443  for (i=0; i<torrentCount; ++i)
     444    {
     445      tr_torrent * tor = torrents[i];
     446      tr_variant * d = tr_variantListAdd (list);
     447      void * pieceBitfield;
     448      size_t pieceBitfieldLen;
     449      char * str;
     450
     451      tr_variantInitDict (d, 1);
     452      tr_torrentFlushCache (tor, &pieceBitfield, &pieceBitfieldLen);
     453
     454      str = tr_base64_encode (pieceBitfield, pieceBitfieldLen, NULL);
     455      tr_variantDictAddStr (d, TR_KEY_pieces, str ? str : "");
     456      tr_free (str);
     457      tr_free (pieceBitfield);
     458    }
     459
     460  tr_free (torrents);
     461  return NULL;
     462}
     463
    429464/***
    430465****
    431466***/
    addField (tr_torrent * const tor, 
    764799          }
    765800        break;
    766801
     802      case TR_KEY_pieces_on_disk:
     803        if (tr_torrentHasMetadata (tor))
     804          {
     805            tr_block_index_t i;
     806            tr_bitfield pieces, blockInCache;
     807            void * bytes;
     808            size_t byteCount;
     809            char * str;
     810
     811            tr_torrentCreatePieceBitfieldStruct (tor, &pieces);
     812            tr_cacheGetTorrentBlockBitfieldStruct (tor->session->cache, tor, &blockInCache);
     813
     814            for (i = 0; i < tor->blockCount; i++)
     815              if (tr_bitfieldHas (&blockInCache, i))
     816                tr_bitfieldRem (&pieces, tr_torBlockPiece (tor, i));
     817
     818            bytes = tr_bitfieldGetRaw (&pieces, &byteCount);
     819            tr_bitfieldDestruct (&pieces);
     820            tr_bitfieldDestruct (&blockInCache);
     821            str = tr_base64_encode (bytes, byteCount, NULL);
     822            tr_free (bytes);
     823
     824            tr_variantDictAddStr (d, key, str ? str : "");
     825
     826            tr_free (str);
     827          }
     828        else
     829          {
     830            tr_variantDictAddStr (d, key, "");
     831          }
     832        break;
     833
     834      case TR_KEY_piece_get:
     835        if (tr_torrentHasMetadata (tor))
     836          {
     837            void * raw;
     838            size_t raw_byte_count = 0;
     839            tr_bitfield piece_get_bitfield;
     840            tr_piece_index_t i;
     841            char * str;
     842
     843            tr_bitfieldConstruct (&piece_get_bitfield, inf->pieceCount);
     844
     845            for (i = 0; i < inf->pieceCount; i++) {
     846              if (!inf->pieces[i].dnd) {
     847                tr_bitfieldAdd(&piece_get_bitfield, i);
     848              }
     849            }
     850
     851            raw = tr_bitfieldGetRaw (&piece_get_bitfield, &raw_byte_count);
     852            tr_bitfieldDestruct (&piece_get_bitfield);
     853            str = tr_base64_encode(raw, raw_byte_count, NULL);
     854            tr_free(raw);
     855
     856            tr_variantDictAddStr(d, key, str ? str : "");
     857
     858            tr_free(str);
     859          }
     860        else
     861          {
     862            tr_variantDictAddStr (d, key, "");
     863          }
     864        break;
     865
     866      case TR_KEY_piece_priority:
     867        {
     868          tr_piece_index_t i;
     869          tr_variant * p = tr_variantDictAddList (d, key, inf->pieceCount);
     870          for (i = 0; i < inf->pieceCount; i++)
     871            tr_variantListAddInt (p, inf->pieces[i].priority);
     872        }
     873        break;
     874
     875      case TR_KEY_piece_max_requests_per_block:
     876        {
     877          tr_piece_index_t i;
     878          tr_variant * p = tr_variantDictAddList (d, key, inf->pieceCount);
     879          for (i = 0; i < inf->pieceCount; i++)
     880            tr_variantListAddInt (p, inf->pieces[i].maxRequestsPerBlock);
     881        }
     882        break;
     883
    767884      case TR_KEY_pieceCount:
    768885        tr_variantDictAddInt (d, key, inf->pieceCount);
    769886        break;
    setFilePriorities (tr_torrent * tor, 
    10051122  return errmsg;
    10061123}
    10071124
     1125static bool dictGetSparseList (tr_variant * d, int64_t ** setme_indexes,
     1126                               int64_t ** setme_values, size_t * setme_count)
     1127{
     1128  tr_variant * indexes, * values;
     1129  size_t i, n, nk, nv;
     1130
     1131  if (!tr_variantDictFindList (d, TR_KEY_indexes, &indexes))
     1132    return false;
     1133  if (!tr_variantDictFindList (d, TR_KEY_values, &values))
     1134    return false;
     1135
     1136  *setme_count = 0;
     1137
     1138  nk = tr_variantListSize (indexes);
     1139  nv = tr_variantListSize (values);
     1140  n = nk > nv ? nv : nk;
     1141
     1142  if (n == 0)
     1143    {
     1144      *setme_indexes = NULL;
     1145      *setme_values = NULL;
     1146      return true;
     1147    }
     1148
     1149  *setme_indexes = tr_new0 (int64_t, n);
     1150  *setme_values = tr_new0 (int64_t, n);
     1151
     1152  for (i = 0; i < n; i++)
     1153    {
     1154      tr_variant * k = tr_variantListChild (indexes, i);
     1155      tr_variant * v = tr_variantListChild (values, i);
     1156      if (!k || !v)
     1157        continue;
     1158      if (!tr_variantGetInt (k, *setme_indexes + *setme_count))
     1159        continue;
     1160      if (!tr_variantGetInt (v, *setme_values + *setme_count))
     1161        continue;
     1162      (*setme_count)++;
     1163    }
     1164
     1165  return true;
     1166}
     1167
     1168static const char *
     1169setPiecePriorities (tr_torrent * tor, tr_variant * d)
     1170{
     1171  const char * errmsg = NULL;
     1172  int64_t * indexes, * values;
     1173  size_t n;
     1174  tr_piece_index_t i;
     1175  tr_piece_index_t * pieces;
     1176  tr_priority_t * priorities;
     1177
     1178  if (!dictGetSparseList (d, &indexes, &values, &n))
     1179    {
     1180      return NULL;
     1181    }
     1182
     1183  pieces = tr_new0 (tr_piece_index_t, tor->info.pieceCount);
     1184  priorities = tr_new0 (tr_priority_t, tor->info.pieceCount);
     1185
     1186  if (n > 0)
     1187    {
     1188      for (i = 0; i < n; i++)
     1189        {
     1190          pieces[i] = indexes[i];
     1191          priorities[i] = values[i];
     1192        }
     1193    }
     1194  else /* if empty set, set all to equal priority */
     1195    {
     1196      n = tor->info.pieceCount;
     1197      for (i = 0; i < n; i++)
     1198        {
     1199          pieces[i] = i;
     1200          priorities[i] = TR_PRI_NORMAL;
     1201        }
     1202    }
     1203
     1204  if (indexes)
     1205    tr_free(indexes);
     1206  if (values)
     1207    tr_free(values);
     1208
     1209  if (n > 0)
     1210    tr_torrentSetPiecePriorities(tor, pieces, priorities, n);
     1211
     1212  tr_free(pieces);
     1213  tr_free(priorities);
     1214
     1215  return errmsg;
     1216}
     1217
     1218static const char*
     1219setPieceMaxRequestsPerBlock (tr_torrent * tor, tr_variant * d)
     1220{
     1221  const char * errmsg = NULL;
     1222  int64_t * indexes, * values;
     1223  size_t n;
     1224  tr_piece_index_t i;
     1225  tr_piece_index_t * pieces;
     1226  int8_t * max_requests;
     1227
     1228  if (!dictGetSparseList (d, &indexes, &values, &n))
     1229    {
     1230      return NULL;
     1231    }
     1232
     1233  pieces = tr_new0 (tr_piece_index_t, tor->info.pieceCount);
     1234  max_requests = tr_new0 (int8_t, tor->info.pieceCount);
     1235
     1236  if (n > 0)
     1237    {
     1238      for (i = 0; i < n; i++)
     1239        {
     1240          pieces[i] = indexes[i];
     1241          max_requests[i] = (int8_t) values[i];
     1242        }
     1243    }
     1244  else /* if empty set, set all to equal priority */
     1245    {
     1246      n = tor->info.pieceCount;
     1247      for (i = 0; i < n; i++)
     1248        {
     1249          pieces[i] = i;
     1250          max_requests[i] = 0;
     1251        }
     1252    }
     1253
     1254  if (indexes)
     1255    tr_free(indexes);
     1256  if (values)
     1257    tr_free(values);
     1258
     1259  if (n > 0)
     1260    tr_torrentSetPieceMaxRequests (tor, pieces, max_requests, n);
     1261
     1262  tr_free (pieces);
     1263  tr_free (max_requests);
     1264
     1265  return errmsg;
     1266}
     1267
    10081268static const char*
    10091269setFileDLs (tr_torrent * tor,
    10101270            bool         do_download,
    setFileDLs (tr_torrent * tor, 
    10451305  return errmsg;
    10461306}
    10471307
     1308static const char *
     1309setPieceDLs (tr_torrent * tor,
     1310             bool         do_download,
     1311             tr_variant * list)
     1312{
     1313  int i;
     1314  int64_t tmp;
     1315  int pieceCount = 0;
     1316  const int n = tr_variantListSize (list);
     1317  const char * errmsg = NULL;
     1318  tr_piece_index_t * pieces = tr_new0 (tr_piece_index_t, tor->info.pieceCount);
     1319
     1320  if (n) /* if argument list, process them */
     1321    {
     1322      for (i = 0; i < n; i++)
     1323        {
     1324          if (tr_variantGetInt (tr_variantListChild (list, i), &tmp))
     1325            {
     1326              if (0 <= tmp && tmp < tor->info.pieceCount)
     1327                pieces[pieceCount++] = tmp;
     1328              else
     1329                errmsg = "piece index out of range";
     1330            }
     1331        }
     1332    }
     1333  else /* if empty set, apply to all */
     1334    {
     1335      tr_piece_index_t p;
     1336      for (p = 0; p < tor->info.pieceCount; p++)
     1337        pieces[pieceCount++] = p;
     1338    }
     1339
     1340  if (pieceCount > 0)
     1341      tr_torrentSetPieceDLs (tor, pieces, pieceCount, do_download);
     1342
     1343  tr_free (pieces);
     1344  return errmsg;
     1345}
     1346
    10481347static bool
    10491348findAnnounceUrl (const tr_tracker_info * t, int n, const char * url, int * pos)
    10501349{
    torrentSet (tr_session * session, 
    12571556      double d;
    12581557      tr_variant * files;
    12591558      tr_variant * trackers;
     1559      tr_variant * pieces;
    12601560      bool boolVal;
    12611561      tr_torrent * tor;
    12621562
    torrentSet (tr_session * session, 
    12841584      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_priority_normal, &files))
    12851585        errmsg = setFilePriorities (tor, TR_PRI_NORMAL, files);
    12861586
     1587      if (!errmsg && tr_variantDictFindDict (args_in, TR_KEY_piece_priority, &pieces))
     1588        errmsg = setPiecePriorities (tor, pieces);
     1589
     1590      if (!errmsg && tr_variantDictFindDict (args_in, TR_KEY_piece_max_requests_per_block, &pieces))
     1591        errmsg = setPieceMaxRequestsPerBlock (tor, pieces);
     1592
     1593      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_pieces_unwanted, &pieces))
     1594        errmsg = setPieceDLs (tor, false, pieces);
     1595
     1596      if (!errmsg && tr_variantDictFindList (args_in, TR_KEY_pieces_wanted, &pieces))
     1597        errmsg = setPieceDLs (tor, true, pieces);
     1598
    12871599      if (tr_variantDictFindInt (args_in, TR_KEY_downloadLimit, &tmp))
    12881600        tr_torrentSetSpeedLimit_KBps (tor, TR_DOWN, tmp);
    12891601
    methods[] = 
    21872499  { "torrent-stop",          true,  torrentStop         },
    21882500  { "torrent-verify",        true,  torrentVerify       },
    21892501  { "torrent-reannounce",    true,  torrentReannounce   },
     2502  { "torrent-flush",         true,  torrentFlush        },
    21902503  { "queue-move-top",        true,  queueMoveTop        },
    21912504  { "queue-move-up",         true,  queueMoveUp         },
    21922505  { "queue-move-down",       true,  queueMoveDown       },
  • libtransmission/torrent.c

    diff --git a/libtransmission/torrent.c b/libtransmission/torrent.c
    index 54e3150..348659b 100644
    a b tr_torrentSetFileDLs (tr_torrent * tor, 
    24372437  tr_torrentUnlock (tor);
    24382438}
    24392439
     2440void tr_torrentSetPiecePriorities (tr_torrent             * torrent,
     2441                                   const tr_piece_index_t * pieces,
     2442                                   const tr_priority_t    * priorities,
     2443                                   tr_piece_index_t         pieceCount)
     2444{
     2445  tr_piece_index_t i;
     2446
     2447  assert (tr_isTorrent (torrent));
     2448  tr_torrentLock (torrent);
     2449
     2450  for (i=0; i<pieceCount; i++)
     2451    if (pieces[i] < torrent->info.pieceCount)
     2452      torrent->info.pieces[pieces[i]].priority = priorities[i];
     2453  tr_peerMgrRebuildRequests (torrent);
     2454
     2455  tr_torrentUnlock (torrent);
     2456}
     2457
     2458void tr_torrentSetPieceMaxRequests (tr_torrent             * torrent,
     2459                                    const tr_piece_index_t * pieces,
     2460                                    const int8_t           * max_requests,
     2461                                    tr_piece_index_t         pieceCount)
     2462{
     2463  tr_piece_index_t i;
     2464
     2465  assert (tr_isTorrent (torrent));
     2466  tr_torrentLock (torrent);
     2467
     2468  for (i=0; i<pieceCount; i++)
     2469    if (pieces[i] < torrent->info.pieceCount)
     2470      torrent->info.pieces[pieces[i]].maxRequestsPerBlock = max_requests[i];
     2471  tr_peerMgrRebuildRequests (torrent);
     2472
     2473  tr_torrentUnlock (torrent);
     2474}
     2475
     2476void tr_torrentSetPieceDLs (tr_torrent             * torrent,
     2477                            const tr_piece_index_t * pieces,
     2478                            tr_piece_index_t         pieceCount,
     2479                            bool                     do_download)
     2480{
     2481  tr_piece_index_t i;
     2482
     2483  assert (tr_isTorrent (torrent));
     2484  tr_torrentLock (torrent);
     2485
     2486  for (i=0; i<pieceCount; i++)
     2487    if (pieces[i] < torrent->info.pieceCount)
     2488      torrent->info.pieces[pieces[i]].dnd = !do_download;
     2489  tr_torrentRecheckCompleteness (torrent);
     2490  tr_peerMgrRebuildRequests (torrent);
     2491
     2492  tr_torrentUnlock (torrent);
     2493}
     2494
    24402495/***
    24412496****
    24422497***/
    tr_torrentRenamePath (tr_torrent * tor, 
    38733928
    38743929  tr_runInEventThread (tor->session, torrentRenamePath, data);
    38753930}
     3931
     3932void tr_torrentFlushCache (tr_torrent * tor, void ** piecesBitmask,
     3933                           size_t * piecesLength)
     3934{
     3935  tr_torrentLock (tor);
     3936
     3937  if (piecesBitmask && piecesLength)
     3938    *piecesBitmask = tr_torrentCreatePieceBitfield (tor, piecesLength);
     3939  tr_cacheFlushTorrent (tor->session->cache, tor);
     3940
     3941  tr_torrentUnlock (tor);
     3942}
  • libtransmission/torrent.h

    diff --git a/libtransmission/torrent.h b/libtransmission/torrent.h
    index 4a16fa9..65398ee 100644
    a b tr_torrentCreatePieceBitfield (const tr_torrent * tor, size_t * byte_count) 
    492492  return tr_cpCreatePieceBitfield (&tor->completion, byte_count);
    493493}
    494494
     495static inline void
     496tr_torrentCreatePieceBitfieldStruct (const tr_torrent * tor, tr_bitfield * bitfield)
     497{
     498  tr_cpCreatePieceBitfieldStruct (&tor->completion, bitfield);
     499}
     500
    495501static inline uint64_t
    496502tr_torrentHaveTotal (const tr_torrent * tor)
    497503{
  • libtransmission/transmission.h

    diff --git a/libtransmission/transmission.h b/libtransmission/transmission.h
    index 4f76adf..5f87973 100644
    a b typedef struct tr_session tr_session; 
    5959struct tr_error;
    6060struct tr_variant;
    6161
    62 typedef int8_t tr_priority_t;
     62typedef int32_t tr_priority_t;
    6363
    6464#define TR_RPC_SESSION_ID_HEADER "X-Transmission-Session-Id"
    6565
    bool tr_torrentUsesSpeedLimit (const tr_torrent *, tr_direction); 
    11971197void         tr_torrentUseSessionLimits   (tr_torrent *, bool);
    11981198bool         tr_torrentUsesSessionLimits  (const tr_torrent *);
    11991199
     1200void         tr_torrentSetMaxRequestsPerBlock (tr_torrent *, unsigned int requests);
     1201unsigned int tr_torrentGetMaxRequestsPerBlock (const tr_torrent *);
     1202
    12001203
    12011204/****
    12021205*****  Ratio Limits
    void tr_torrentSetFileDLs (tr_torrent * torrent, 
    13031306                           tr_file_index_t          fileCount,
    13041307                           bool                     do_download);
    13051308
     1309void tr_torrentSetPiecePriorities (tr_torrent             * torrent,
     1310                                   const tr_piece_index_t * pieces,
     1311                                   const tr_priority_t    * priorities,
     1312                                   tr_piece_index_t         pieceCount);
     1313
     1314void tr_torrentSetPieceMaxRequests (tr_torrent             * torrent,
     1315                                    const tr_piece_index_t * pieces,
     1316                                    const int8_t           * max_requests,
     1317                                    tr_piece_index_t         pieceCount);
     1318
     1319void tr_torrentSetPieceDLs (tr_torrent             * torrent,
     1320                            const tr_piece_index_t * pieces,
     1321                            tr_piece_index_t         pieceCount,
     1322                            bool                     do_download);
     1323
    13061324
    13071325const tr_info * tr_torrentInfo (const tr_torrent * torrent);
    13081326
    typedef struct tr_file 
    17361754{
    17371755    uint64_t          length;      /* Length of the file, in bytes */
    17381756    char *            name;        /* Path to the file */
    1739     int8_t            priority;    /* TR_PRI_HIGH, _NORMAL, or _LOW */
     1757    tr_priority_t     priority;    /* TR_PRI_HIGH, _NORMAL, or _LOW */
    17401758    int8_t            dnd;         /* "do not download" flag */
    17411759    int8_t            is_renamed;  /* true if we're using a different path from the one in the metainfo; ie, if the user has renamed it */
    17421760    tr_piece_index_t  firstPiece;  /* We need pieces [firstPiece... */
    tr_file; 
    17481766/** @brief a part of tr_info that represents a single piece of the torrent's content */
    17491767typedef struct tr_piece
    17501768{
    1751     time_t   timeChecked;              /* the last time we tested this piece */
    1752     uint8_t  hash[SHA_DIGEST_LENGTH];  /* pieces hash */
    1753     int8_t   priority;                 /* TR_PRI_HIGH, _NORMAL, or _LOW */
    1754     int8_t   dnd;                      /* "do not download" flag */
     1769    time_t        timeChecked;              /* the last time we tested this piece */
     1770    uint8_t       hash[SHA_DIGEST_LENGTH];  /* pieces hash */
     1771    tr_priority_t priority;                 /* TR_PRI_HIGH, _NORMAL, or _LOW */
     1772    int8_t        dnd;                      /* "do not download" flag */
     1773    int8_t        maxRequestsPerBlock;
    17551774}
    17561775tr_piece;
    17571776
    const tr_stat * tr_torrentStat (tr_torrent * torrent); 
    20282047    reduce the CPU load if you're calling tr_torrentStat () frequently. */
    20292048const tr_stat * tr_torrentStatCached (tr_torrent * torrent);
    20302049
     2050void tr_torrentFlushCache (tr_torrent * tor, void ** piecesBitmask,
     2051                           size_t * piecesLength);
     2052
    20312053/** @deprecated */
    20322054void tr_torrentSetAddedDate (tr_torrent * torrent,
    20332055                             time_t       addedDate);