npmtest-torrent-cloud (v0.0.1)

Code coverage report for node-npmtest-torrent-cloud/node_modules/torrent-cloud/lib/file.js

Statements: 2.82% (2 / 71)      Branches: 0% (0 / 22)      Functions: 0% (0 / 7)      Lines: 2.82% (2 / 71)      Ignored: none     

All files » node-npmtest-torrent-cloud/node_modules/torrent-cloud/lib/ » file.js
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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 1222               1                                                                                                                                                                                                                                  
var torrents = require("./torrents");
var stream = require("stream");
var through = require('./util/through');
 
//in effect, this controls the size of the download buffer,
//it gets cleared as the upload progresses (prevents buffering the entire download in memory)
var MIN_PIECE_SIZE = 50*1024*1024;//~50Mb
 
function File(f, index, torrent) {
	var file = this;
	file.$f = f;
	//TODO (@jpillora) make downloads actually fall at piece boundaries
	var pieceSize = torrent.$engine.torrent.pieceLength;
	file.$pieceSize = Math.ceil(MIN_PIECE_SIZE/pieceSize)*pieceSize;
	
	file.i = index;
	file.downloading = false;
	file.name = f.name;
	file.path = f.path;
	file.length = f.length;
};
 
File.prototype = {
	createReadStream: function() {
		var file = this;
 
		//already created
		if(file.$r)
			return file.$r;
 
		//start download
		file.downloadError = undefined;
		file.cancelled = undefined;
		file.downloading = true;
		file.downloadLength = 0;
		torrents.emit("update");
 
		var piece = 0;
		var piecing = false;
		var waiting = false;
		var r = file.$r = new stream.Readable();
 
		var read = r._read = function() {
 
			//completed early
			if(file.cancelled)
				return;
 
			//download one piece at a time
			if(piecing) {
				waiting = true;
				return;
			}
			piecing = true;
			waiting = false;
 
			var s = piece * file.$pieceSize;
			var e = Math.min(s + file.$pieceSize, file.length);
 
			//EOF completed successfully
			if(s >= file.length)
				return file.$complete();
 
			//pull the next piece
			var download = file.$d = file.$f.createReadStream({
				start: s,
				end: e - 1
			});
 
			//extract chunk, place in this file
			var monitor = through(function transform(b) {
				file.downloadLength += b.length;
				torrents.emit("update");
				r.push(b);
			}, function(flush) {
				//next piece
				piece++;
				piecing = false;
				if(waiting)
					read();
				flush();
			});
 
			download.pipe(monitor);
		};
 
		return r;
	},
	cancel: function() {
		var file = this;
		//not open
		if(!file.$r || file.cancelled)
			return null;
 
		//attempt to close current download
		if(file.$d)
			file.$d.destroy();
 
		//close!
		file.cancelled = true;
		file.$complete("cancelled");
		file.$r = null;
		return true;
	},
	$complete: function(err) {
		var file = this;
		if(!file.downloading)
			return;
		file.downloading = false;
		torrents.emit("update");
		if(!file.$r)
			return;
 
		if(err)
			file.$r.emit("error", err);
		else
			file.$r.push(null);//EOF
	}
};
 
module.exports = File;