Welcome to mirror list, hosted at ThFree Co, Russian Federation.

rarity-map.js « lib - github.com/webtorrent/webtorrent.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 2d7a2ceeb85b07deb7ef42db2aab3f579505fd0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
module.exports = RarityMap

/**
 * Mapping of torrent pieces to their respective availability in the swarm. Used by
 * the torrent manager for implementing the rarest piece first selection strategy.
 *
 * @param {Swarm}  swarm bittorrent-swarm to track availability
 * @param {number} numPieces number of pieces in the torrent
 */
function RarityMap (swarm, numPieces) {
  var self = this

  self.swarm = swarm
  self.numPieces = numPieces

  function initWire (wire) {
    wire.on('have', function (index) {
      self.pieces[index]++
    })
    wire.on('bitfield', self.recalculate.bind(self))
    wire.on('close', function () {
      for (var i = 0; i < self.numPieces; ++i) {
        self.pieces[i] -= wire.peerPieces.get(i)
      }
    })
  }

  self.swarm.wires.forEach(initWire)
  self.swarm.on('wire', function (wire) {
    self.recalculate()
    initWire(wire)
  })

  self.recalculate()
}

/**
 * Recalculates piece availability across all peers in the swarm.
 */
RarityMap.prototype.recalculate = function () {
  var self = this

  self.pieces = []
  for (var i = 0; i < self.numPieces; ++i) {
    self.pieces[i] = 0
  }

  self.swarm.wires.forEach(function (wire) {
    for (var i = 0; i < self.numPieces; ++i) {
      self.pieces[i] += wire.peerPieces.get(i)
    }
  })
}

/**
 * Get the index of the rarest piece. Optionally, pass a filter function to exclude
 * certain pieces (for instance, those that we already have).
 *
 * @param {function} pieceFilterFunc
 * @return {number} index of rarest piece, or -1
 */
RarityMap.prototype.getRarestPiece = function (pieceFilterFunc) {
  var self = this
  var candidates = []
  var min = Infinity
  pieceFilterFunc = pieceFilterFunc || function () { return true }

  for (var i = 0; i < self.numPieces; ++i) {
    if (!pieceFilterFunc(i)) continue

    var availability = self.pieces[i]
    if (availability === min) {
      candidates.push(i)
    } else if (availability < min) {
      candidates = [ i ]
      min = availability
    }
  }

  if (candidates.length > 0) {
    // if there are multiple pieces with the same availability, choose one randomly
    return candidates[Math.random() * candidates.length | 0]
  } else {
    return -1
  }
}