inline servicing of files currently downloading is now working!
authorPaul J R <me@pjr.cc>
Sun, 20 Jan 2013 20:44:13 +0000 (07:44 +1100)
committerPaul J R <me@pjr.cc>
Sun, 20 Jan 2013 20:44:13 +0000 (07:44 +1100)
lib/cache.js

index 6b6327d..a649991 100644 (file)
@@ -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!