# HG changeset patch # User John "Elwin" Edwards # Date 1396376605 25200 # Node ID 245a2959f504f6a898c3de4dd7bf8a7d65be0fad # Parent b5a1430d0f71c7c12201d8794a12a5f23990dfd2 Begin support for watching dgamelaunch games. watcher.c is a subprocess which uses inotify to watch the inprogress directories. A C program is used because node's fs.watch() can't tell the difference between creation and deletion. diff -r b5a1430d0f71 -r 245a2959f504 rlgwebd.js --- a/rlgwebd.js Tue Apr 01 09:20:11 2014 -0700 +++ b/rlgwebd.js Tue Apr 01 11:23:25 2014 -0700 @@ -944,6 +944,38 @@ return null; } +function startProgressWatcher() { + var watchdirs = []; + for (var gname in games) { + watchdirs.push(path.join("/dgldir/inprogress", gname)); + } + var subproc = child_process.spawn("/bin/watcher", watchdirs); + subproc.stdout.setEncoding('utf8'); + subproc.stdout.on('data', function (chunk) { + var fname = chunk.slice(2, -1); + var filere = /.*\/([^\/]*)\/([^\/:]*):(node:)?(.*)/; + var matchresult = fname.match(filere); + if (!matchresult || matchresult[3]) + return; + gname = matchresult[1]; + pname = matchresult[2]; + if (chunk[0] == "E") { + tslog("DGL: %s is playing %s: %s", pname, gname, fname) + } + else if (chunk[0] == "C") { + tslog("DGL: %s started playing %s: %s", pname, gname, fname) + } + else if (chunk[0] == "D") { + tslog("DGL: %s finished playing %s: %s", pname, gname, fname) + } + else { + tslog("Watcher says: %s", chunk) + } + }); + subproc.stdout.resume(); + return subproc; +} + function serveStatic(req, res, fname) { var nname = path.normalize(fname); if (nname == "" || nname == "/") @@ -1374,6 +1406,7 @@ for (var sessid in sessions) { sessions[sessid].close(); } + progressWatcher.stdin.end("\n"); setTimeout(shutdown, 2000); } } @@ -1396,6 +1429,7 @@ var httpServer; // declare here so shutdown() can find it var wsServer; +var progressWatcher; /* This could be nonblocking, but nothing else can start yet anyway. */ if (fs.existsSync(ctlsocket)) { @@ -1433,6 +1467,7 @@ wsServer = new WebSocketServer({"httpServer": httpServer}); wsServer.on("request", wsHandler); tslog('WebSockets are online'); + progressWatcher = startProgressWatcher(); setInterval(pushStatus, 4000); }); diff -r b5a1430d0f71 -r 245a2959f504 watcher.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/watcher.c Tue Apr 01 11:23:25 2014 -0700 @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct watchdir { + int wd; + char *name; +}; + +char ibuf[sizeof(struct inotify_event) + NAME_MAX + 1]; + +int startwatch(int ifd, char *dir, struct watchdir *w) { + DIR *dstream; + struct dirent *ent; + + w->name = dir; + w->wd = inotify_add_watch(ifd, dir, IN_CREATE|IN_DELETE|IN_DELETE_SELF); + if (w->wd < 0) { + fprintf(stderr, "Could not watch %s\n", dir); + return 1; + } + dstream = opendir(dir); + if (dstream == NULL) { + fprintf(stderr, "%s is not a readable directory\n", dir); + inotify_rm_watch(ifd, w->wd); + w->wd = -1; + return 1; + } + ent = readdir(dstream); + while (ent != NULL) { + if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, "..")) + printf("E %s/%s\n", dir, ent->d_name); + ent = readdir(dstream); + } + closedir(dstream); + fflush(stdout); + return 0; +} + +int main(int argc, char *argv[]) { + int ifd, rsize, off, done, nwatchers, i; + char typecode; + struct inotify_event *iev; + fd_set rfds; + struct watchdir *watchers; + + done = 0; + nwatchers = argc - 1; + iev = (struct inotify_event *) ibuf; + ifd = inotify_init(); + if (nwatchers == 0) { + watchers = malloc(sizeof(struct watchdir)); + nwatchers = 1; + startwatch(ifd, ".", watchers); + } + else { + watchers = malloc(nwatchers * sizeof(struct watchdir)); + for (i = 0; i < nwatchers; i++) { + startwatch(ifd, argv[i+1], watchers + i); + } + } + + while (!done) { + FD_ZERO(&rfds); + FD_SET(0, &rfds); + FD_SET(ifd, &rfds); + select(ifd + 1, &rfds, NULL, NULL, NULL); + if (FD_ISSET(ifd, &rfds)) { + off = 0; + rsize = read(ifd, ibuf, sizeof(struct inotify_event) + NAME_MAX + 1); + while (off < rsize) { + iev = (struct inotify_event *) (ibuf + off); + if (iev->mask & IN_CREATE) + typecode = 'C'; + else if (iev->mask & IN_DELETE) + typecode = 'D'; + else + typecode = '?'; + for (i = 0; i < nwatchers; i++) { + if (watchers[i].wd == iev->wd) + printf("%c %s/%s\n", typecode, watchers[i].name, iev->name); + } + off += sizeof(struct inotify_event) + iev->len; + } + fflush(stdout); + } + if (FD_ISSET(0, &rfds)) { + read(0, &typecode, 1); + if (typecode == '\n') + done = 1; + } + + } + close(ifd); + return 0; +}