artdaq_node_server  v1_01_01b
udpdump_module.js
1 // udpdump_module.js
2 // Author: Eric Flumerfelt, FNAL RSI
3 //
4 // This module allows the user to run the UDPDump and JSONDispatcher ART modules over a saved datafile
5 //
6 
7 var emitter = require('events').EventEmitter;
8 var udpd = new emitter();
9 
10 var fs = require('fs');
11 var path = require('path');
12 var spawn = require('child_process').spawn;
13 var dgram = require('dgram');
14 
15 
16 function startJSONListener() {
17  var server = dgram.createSocket('udp4');
18 
19  console.log("Setting up JSON listener for UDPDump module");
20  server.on("error", function (err) {
21  console.log("udpdump listen server error:\n" + err.stack);
22  server.close();
23  });
24 
25  server.on("message", function (msg, rinfo) {
26  ;
27  var thisEvent = JSON.parse(msg);
28  console.log("Dispatcher received event:" + thisEvent.event);
29  udpd.emit("message", { name: "udpdump", target: "events", method: "push", data: thisEvent });
30  });
31 
32  server.on("listening", function () {
33  var address = server.address();
34  console.log("server listening " +
35  address.address + ":" + address.port);
36  });
37 
38  console.log("Binding Server to port " + 45555);
39  server.bind(45555);
40  return server;
41 }
42 
43 function readConfigurations(data) {
44  var confDir = __dirname + "/../../artdaq-configuration/server/";
45  var confFiles = fs.readdirSync(confDir);
46  //console.log(confFiles);
47  var dataFiles = [];
48 
49  for (var file in confFiles) {
50  if (confFiles[file].search(".xml") < 0) { continue; }
51  var fileName = confDir + confFiles[file];
52  var res = true;
53  var config = "" + fs.readFileSync(fileName);
54 
55  if (!fs.existsSync(data.artdaqDir)) {
56  var matches = config.match(/<artdaqDir>(.*?)<\/artdaqDir>/i);
57  if (matches.length > 1 && fs.existsSync(matches[1])) {
58  data.artdaqDir = matches[1];
59  udpd.emit("message", { name: "udpdump", target: "artdaqDir", data: data.artdaqDir });
60  }
61  }
62 
63  if (!fs.existsSync(data.artdaqDir + '/' + data.setupScript)) {
64  matches = config.match(/<setupScript>(.*?)<\/setupScript>/i);
65  if (matches.length > 1 && fs.existsSync(data.artdaqDir + '/' + matches[1])) {
66  data.setupScript = matches[1];
67  udpd.emit('message', { name: "udpdump", target: "setupScript", data: data.setupScript });
68  }
69  }
70 
71  matches = config.match(/<dataDir>(.*?)<\/dataDir>/i);
72  if (matches.length > 1) {
73  var dataDirFiles = fs.readdirSync(matches[1]);
74  for (var fileIdx in dataDirFiles) {
75  if (dataDirFiles[fileIdx].search(".root") > 0) {
76  dataFiles.push(matches[1] + '/' + dataDirFiles[fileIdx]);
77  }
78  }
79  }
80  }
81 
82  return dataFiles;
83 }
84 
85 udpd.MasterInitFunction = function (workerData) {
86  var data = {};
87  data.events = [];
88  data.out = "";
89  data.err = "";
90  data.artPID = null;
91  data.artRunning = false;
92  data.artdaqDir = "/opt/otsdaqpoc/artdaq";
93  data.setupScript = "setupARTDAQOTS";
94  data.logTime = new Date();
95  data.logTime.setTime(0);
96 
97  workerData["udpdump"] = data;
98  return null;
99 };
100 
101 udpd.WorkerInitFunction = function (workerData) {
102  startJSONListener();
103  return null;
104 }
105 
106 udpd.RW_Start = function (POST, data) {
107  var fileIndex = POST.fileIndex;
108  var fileNames = readConfigurations(data);
109  var fileName = fileNames[fileIndex];
110  data.events = [];
111  udpd.emit('message', { data: data.events, name: "udpdump", target: "events" });
112 
113  var commandArray = [data.artdaqDir, data.setupScript, fileName];
114 
115  var out = fs.openSync(__dirname + "/../client/UDPDump.out.log", 'w');
116  var err = fs.openSync(__dirname + "/../client/UDPDump.err.log", 'w');
117  var system = spawn(__dirname + "/runART.sh", commandArray, { detached: true, stdio: ['ignore', out, err] });
118  data.artPID = system.pid;
119  system.unref();
120  data.artRunning = true;
121  console.log("Command Spawned");
122  udpd.emit('message', { data: data.artPID, target: "artPID", name: "udpdump" });
123  udpd.emit('message', { data: data.artRunning, target: "artRunning", name: "udpdump" });
124  return { out: "", err: "", running: true };
125 }
126 
127 function checkArt(data) {
128  if (data.artPID !== null) {
129  try {
130  process.kill(data.artPID, 0);
131  data.artRunning = true;
132  } catch (err) {
133  data.artRunning = false;
134  data.artPID = null;
135  }
136  } else {
137  data.artRunning = false;
138  }
139  udpd.emit('message', { data: data.artRunning, name: "udpdump", target: "artRunning" });
140  udpd.emit('message', { data: data.artPID, name: "udpdump", target: "artPID" });
141 }
142 
143 udpd.RW_Kill = function (POST, data) {
144  checkArt(data);
145  if (data.artPID !== null) {
146  process.kill(data.artPID, 15);
147  setTimeout(function () { process.kill(data.artPID, 9); }, 1000);
148  }
149 }
150 
151 udpd.RO_GetEvent = function (POST, data) {
152  var events = data.events;
153  if (events[0]) {
154  console.log("First event in buffer: " + events[0].event + ", last event in buffer: " + events[events.length - 1].event + ", Requested event: " + POST.event + ", Event Count: " + events.length);
155 
156  if (POST.event == 0 || POST.event < events[0].event) {
157  var evtdata = events[0];
158  console.log("Sending client event " + events[0].event);
159  evtdata.lastEvent = events[events.length - 1].event;
160  return JSON.stringify(evtdata);
161  } else {
162  if (events.length > events[events.length - 1].event - events[0].event + 1) {
163  events.sort(function (a, b) { return a.event - b.event; });
164  }
165 
166  for (var event in events) {
167  if (events[event].event == POST.event) {
168  console.log("Sending client event " + events[event].event);
169  var evtdata = events[event];
170  evtdata.lastEvent = events[events.length - 1].event;
171  return JSON.stringify(evtdata);
172  }
173  }
174  if (POST.event < events[events.length - 1 ].event) {
175  console.log("Returning ENOEVT");
176  return "ENOEVT";
177  }
178  }
179  }
180 
181  return "";
182 }
183 
184 udpd.GET_FileNames = function (data) {
185  var filePaths = readConfigurations(data);
186  var fileNames = [];
187  console.log(filePaths);
188  for (var fpath in filePaths) {
189  var name = path.basename(filePaths[fpath]);
190  fileNames.push("<option value=\"" + name + "\">" + name + "</option>");
191  }
192  return fileNames;
193 }
194 
195 //udpd.RW_GetEvent = function(POST, data){ return udpd.RO_GetEvent(POST, data); }
196 
197 udpd.GET_Log = function (data) {
198  checkArt(data);
199 
200  if (new Date(data.logTime).getTime() + 800 < new Date().getTime()) {
201  data.logTime = new Date();
202  if (fs.existsSync(__dirname + "/../client/UDPDump.out.log")) {
203  data.out = "" + fs.readFileSync(__dirname + "/../client/UDPDump.out.log", { encoding: 'utf8' });
204  }
205  if (fs.existsSync(__dirname + "/../client/UDPDump.err.log")) {
206  data.err = "" + fs.readFileSync(__dirname + "/../client/UDPDump.err.log", { encoding: 'utf8' });
207  }
208  udpd.emit("message", { name: "udpdump", data: data.out, target: "out" });
209  udpd.emit("message", { name: "udpdump", data: data.err, target: "err" });
210  }
211  return { out: data.out, err: data.err, running: data.artRunning };
212 }
213 
214 module.exports = function (module_holder) {
215  module_holder["udpdump"] = udpd;
216 };