From b466a00727f8c53f3afcfa04b19277ba6fe5b32f Mon Sep 17 00:00:00 2001 From: Paul J R Date: Mon, 21 Jan 2013 07:44:13 +1100 Subject: [PATCH] inline servicing of files currently downloading is now working! --- lib/cache.js | 113 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 83 insertions(+), 30 deletions(-) diff --git a/lib/cache.js b/lib/cache.js index 6b6327d..a649991 100644 --- a/lib/cache.js +++ b/lib/cache.js @@ -31,6 +31,13 @@ function upstreamRequest(unify) { //unify.b.write("would send to '" + xpath + "'"); //unify.b.end(); + // not doing this properly yet... + if(typeof global.repoproxy.downloads[unify.fullFilePath] != undefined && global.repoproxy.downloads[unify.fullFilePath] == 1) { + console.log("request for file thats being downloaded already, doing inline request"); + inlineService(unify); + return; + } + console.log("sending off to '%s'", xpath); var headReq = url.parse(xpath); @@ -108,41 +115,87 @@ function getAndService(unify, xpath, filesize) { unify.b.writeHead(200, {'Content-Length' : filesize}); - if(typeof global.repoproxy.downloads[unify.fullFilePath] != "undefined" && global.repoproxy.downloads[unify.fullFilePath] == 1) { - - console.log("service inline"); - unify.b.write("trying to service inline"); - unify.b.end(); - } else { - global.repoproxy.downloads[unify.fullFilePath] = 1; - + global.repoproxy.downloads[unify.fullFilePath] = 1; - http.get(xpath, function(res) { + + http.get(xpath, function(res) { + + var file = fs.createWriteStream(unify.fullFilePath); - var file = fs.createWriteStream(unify.fullFilePath); - - //console.log("res: ", res); + //console.log("res: ", res); + + //res.setEncoding("utf8"); + + res.on("data", function(data) { + //console.log("chunk"); + file.write(data); + unify.b.write(data); + }); + + res.on("end", function() { + console.log("end..."); + unify.b.end(); + file.end(); + global.repoproxy.downloads[unify.fullFilePath] = 0; + }); + + res.on("error", function(err) { + console.log("res threw error... ", err); + }); + }); +} + +// this is nasty nasty thing that can go horribly wrong in some ways, but currently works... +function inlineService(unify) { + // this method is called when we need to service a file thats being downloaded by something else + var metafilename = unify.fullPathDirName + "/.meta."+ path.basename(unify.requestFor) +".filesize"; + var fsizef = fs.createReadStream(metafilename); + var fsize = ""; + fsizef.on("data", function(data) { + fsize += data; + }); + + fsizef.on("end", function() { + var sentSoFar = 0; + unify.b.writeHead(200, {"Content-Length" : fsize }); - //res.setEncoding("utf8"); + // now we go into the file reading loop. + console.log("start of inline services"); + // we loop every 0.5s and do our thing - res.on("data", function(data) { - //console.log("chunk"); - file.write(data); - unify.b.write(data); - }); + function sendPieces() { + // this is going to be so fun i want to play real life frogger in real life traffic... + fs.stat(unify.fullFilePath, function(err, stats) { + if(err == null) { + if(stats["size"] > sentSoFar) { + // open the file, send the data + var rs = fs.createReadStream(unify.fullFilePath, {start: sentSoFar, end: stats["size"]}); + + rs.on("data", function(thisdata) { + //console.log("inline chunk: ", thisdata.length); + unify.b.write(thisdata); + }); + + rs.on("end", function() { + sentSoFar = stats["size"]; + // every second, we start again + if(sentSoFar != fsize) { + setTimeout(sendPieces, 1000); + } else { + // we're done! + unify.b.end(); + } + }); + } + } else { + console.log("inline service - we're in a very bad place"); + } + }); + + } - res.on("end", function() { - console.log("end..."); - unify.b.end(); - file.end(); - global.repoproxy.downloads[unify.fullFilePath] = 0; - }); - - res.on("error", function(err) { - console.log("res threw error... ", err); - }); - }); - } + setTimeout(sendPieces, 100); + }); } // the service file routine .... PLEASE KILL ME! -- 1.7.0.4