changeset 160:ed837da65e5f

RLGWebD: Clean up code related to session timestamps. TermSessions now store the timestamp of the latest data. This removes the need to use fstat() to calculate idle times. The reaper() function is removed. It may be useful to find another way to remove old login keys.
author John "Elwin" Edwards
date Sat, 03 Jan 2015 17:39:15 -0500
parents a613380ffdc2
children a2a25b7631f1
files rlgwebd.js
diffstat 1 files changed, 14 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/rlgwebd.js	Sat Jan 03 15:23:04 2015 -0500
+++ b/rlgwebd.js	Sat Jan 03 17:39:15 2015 -0500
@@ -19,7 +19,6 @@
 var chrootDir = "/var/dgl/";
 var dropToUser = "rodney";
 var serveStaticRoot = "/var/www/"; // inside the chroot
-var playtimeout = 3600000; // Idle time before games are autosaved, in ms
 
 /* Data on the games available. */
 var games = {
@@ -122,7 +121,8 @@
   this.emit('open', true, this.game.uname, this.pname);
   gamemux.emit('begin', this.game.uname, this.pname);
   /* Set up the lockfile and ttyrec */
-  var ts = timestamp();
+  this.lasttime = new Date();
+  var ts = timestamp(this.lasttime);
   var progressdir = path.join("/dgldir/inprogress", this.game.uname);
   this.lock = path.join(progressdir, this.pname + ":node:" + ts + ".ttyrec");
   var lmsg = this.term.pid.toString() + '\n' + this.h + '\n' + this.w + '\n'; 
@@ -134,15 +134,14 @@
    * with a complete screen. */
   this.framebuf = new Buffer(1024);
   this.frameoff = 0;
-  logins[lkey].sessions.push(this.game.uname + "/" + this.pname);
   /* END setup */
   function ttyrec_chunk(datastr) {
-    var ts = new Date();
+    ss.lasttime = new Date();
     var buf = new Buffer(datastr);
     var chunk = new Buffer(buf.length + 12);
     /* TTYREC headers */
-    chunk.writeUInt32LE(Math.floor(ts.getTime() / 1000), 0);
-    chunk.writeUInt32LE(1000 * (ts.getTime() % 1000), 4);
+    chunk.writeUInt32LE(Math.floor(ss.lasttime.getTime() / 1000), 0);
+    chunk.writeUInt32LE(1000 * (ss.lasttime.getTime() % 1000), 4);
     chunk.writeUInt32LE(buf.length, 8);
     buf.copy(chunk, 12);
     ss.record.write(chunk);
@@ -373,8 +372,10 @@
 }
 
 /* A few utility functions */
-function timestamp() {
-  dd = new Date();
+function timestamp(dd) {
+  if (!(dd instanceof Date)) {
+    dd = new Date();
+  }
   sd = dd.toISOString();
   sd = sd.slice(0, sd.indexOf("."));
   return sd.replace("T", ".");
@@ -457,47 +458,6 @@
   return getMsg(msgObj.utf8Data);
 }
 
-/* FIXME sessid removal */
-function reaper() {
-  return; // TODO figure out if this function is useful
-  var now = new Date();
-  function reapcheck(session) {
-    fs.fstat(session.record.fd, function (err, stats) {
-      if (!err && now - stats.mtime > playtimeout) {
-        tslog("Reaping session %s", session.sessid);
-        /* Dissociate it with its login name. */
-        var sn = logins[session.key].sessions.indexOf(session.sessid);
-        if (sn >= 0) {
-          logins[session.key].sessions.splice(sn, 1);
-        }
-        /* Shut it down. */
-        session.close();
-      }
-    });
-  }
-  for (var sessid in sessions) {
-    reapcheck(sessions[sessid]);
-  }
-  for (var lkey in logins) {
-    if (logins[lkey].sessions.length > 0) {
-      /* Check for games that have terminated normally, and remove them. */
-      var expired = [];
-      var targarray = logins[lkey].sessions;
-      /* Let's not find out what happens if you modify an array
-       * you're iterating through. */
-      for (var i = 0; i < targarray.length; i++) {
-        if (!(targarray[i] in sessions))
-          expired.push(targarray[i]);
-      }
-      if (expired.length > 0) {
-        for (var j = 0; j < expired.length; j++) {
-          targarray.splice(targarray.indexOf(expired[j]), 1);
-        }
-      }
-    }
-  }
-}
-
 function login(req, res, formdata) {
   if (!allowlogin) {
     sendError(res, 6, null, false);
@@ -528,7 +488,7 @@
     var lkey = randkey(2);
     while (lkey in logins)
       lkey = randkey(2);
-    logins[lkey] = {"name": username, "ts": new Date(), "sessions": []};
+    logins[lkey] = {"name": username, "ts": new Date()};
     res.writeHead(200, {'Content-Type': 'application/json'});
     var reply = {"t": "l", "k": lkey, "u": username};
     res.write(JSON.stringify(reply));
@@ -579,7 +539,7 @@
       var lkey = randkey(2);
       while (lkey in logins)
         lkey = randkey(2);
-      logins[lkey] = {"name": uname, "ts": new Date(), "sessions": []};
+      logins[lkey] = {"name": uname, "ts": new Date()};
       var reply = {"t": "r", "k": lkey, "u": uname};
       res.writeHead(200, {'Content-Type': 'application/json'});
       res.write(JSON.stringify(reply));
@@ -732,54 +692,23 @@
   return;
 }
 
-/* TODO simplify by storing timestamps instead of callin stat() */
+/* Currently, this doesn't do anything blocking, but keep the callback */
 function getStatus(callback) {
   var now = new Date();
   var statusinfo = {"s": allowlogin, "g": []};
-  function idleset(n, idletime) {
-    if (n >= 0 && n < statusinfo.g.length) {
-      statusinfo.g[n].i = idletime;
-    }
-    for (var j = 0; j < statusinfo.g.length; j++) {
-      if (!("i" in statusinfo.g[j]))
-        return;
-    }
-    callback(statusinfo);
-  }
   for (var tag in sessions) {
     var gamedesc = {};
     gamedesc["tag"] = tag;
     gamedesc["p"] = sessions[tag].pname;
     gamedesc["g"] = sessions[tag].game.uname;
+    gamedesc["i"] = now - sessions[tag].lasttime;
     statusinfo["g"].push(gamedesc);
   }
   statusinfo["dgl"] = [];
   for (var tag in dglgames) {
     statusinfo["dgl"].push(tag);
   }
-  if (statusinfo.g.length == 0) {
-    callback(statusinfo);
-    return;
-  }
-  function makecallback(i) {
-    return function (err, stats) {
-      if (err)
-        idleset(i, null);
-      else
-        idleset(i, now - stats.mtime);
-    }
-  }
-  for (var i = 0; i < statusinfo.g.length; i++) {
-    /* fd sometimes isn't a number, presumably when the file isn't open yet. */
-    /* FIXME sessid -> tag */
-    var tag = statusinfo.g[i].tag;
-    if (tag in sessions && typeof(sessions[tag].record.fd) == 'number') {
-      fs.fstat(sessions[tag].record.fd, makecallback(i));
-    }
-    else {
-      idleset(i, null);
-    }
-  }
+  callback(statusinfo);
 }
 
 function statusmsg(req, res) {
@@ -1134,7 +1063,6 @@
   httpServer = http.createServer(webHandler);
   httpServer.listen(httpPort);
   tslog('rlgwebd running on port %d', httpPort); 
-  setInterval(reaper, playtimeout / 4);
   wsServer = new WebSocketServer({"httpServer": httpServer});
   wsServer.on("request", wsHandler);
   tslog('WebSockets are online');