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

github.com/webtorrent/webtorrent.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFeross Aboukhadijeh <feross@feross.org>2014-09-21 05:41:24 +0400
committerFeross Aboukhadijeh <feross@feross.org>2014-09-21 05:41:24 +0400
commit93686505fbc90522c75b6c151ec7261aa76098de (patch)
tree5b474b920e79b7b39b6804fac5e6a641de6ae843 /lib/rarity-map.js
parent2e14192c311f64c20496a72af7ffce36495be92b (diff)
merge `bittorrent-client` into this module
When I started the WebTorrent project I thought there were going to need to be two separate client implementations (bittorrent-client and webtorrent-client) that would get tied together in a higher-level module. Fortunately, this was not necessary because of the awesome “browser” field support in browserify. By substituting just a few modules, we can make the same module (webtorrent) work in node AND the browser, with the same codebase! So, from now on, you can just `require(‘webtorrent’)` in node or the browser, and it will just work. You can also `npm install webtorrent` if you want to use bittorrent in a node app or script. Lastly, you can `npm install webtorrent -g` if you want to use webtorrent as a command line app (it installs a `webtorrent` command).
Diffstat (limited to 'lib/rarity-map.js')
-rw-r--r--lib/rarity-map.js86
1 files changed, 86 insertions, 0 deletions
diff --git a/lib/rarity-map.js b/lib/rarity-map.js
new file mode 100644
index 0000000..2d7a2ce
--- /dev/null
+++ b/lib/rarity-map.js
@@ -0,0 +1,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
+ }
+}