00001
00002
00003
00004
00005
00006
00007
00008 var spawn = require( 'child_process' ).spawn;
00009 var emitter = require( 'events' ).EventEmitter;
00010 var fs = require( 'fs' );
00011 var os = require( 'os');
00012 var arc = new emitter( );
00013 var xml = require( 'xml2js' );
00014 var parser = new xml.Parser( {explicitArray: false});
00015 var xmlrpc = require( 'xmlrpc' );
00016
00017
00018 var Status = function ( partition ) {
00019 this.state = "Shutdown";
00020 this.runNumber = 1000;
00021 this.systemPID = null;
00022 this.systemRunning = false;
00023 this.systemOutputBuffer = "";
00024 this.systemErrorBuffer = "";
00025 this.commandPID = null;
00026 this.commandRunning = false;
00027 this.commandOutputBuffer = "";
00028 this.commandErrorBuffer = "";
00029 this.stopPending = false;
00030 this.WFPlotsUpdated = Date.now( );
00031 this.WFFileSize = 0;
00032 this.WFFileMtime = 0;
00033 this.partition = partition;
00034 this.config = "";
00035 this.okToStartOnMon = false;
00036
00037 };
00038
00039 var configuration = {};
00040 configuration.artdaqDir = "~/artdaq-demo-base";
00041 configuration.setupScript = "setupARTDAQDEMO";
00042 configuration.runValue = 0;
00043 configuration.xmlObj;
00044
00045 function readConfiguration( systemStatus ) {
00046 var fileName = __dirname + "/../../artdaq-configuration/server/" + systemStatus.config;
00047 console.log( "Going to read configuration " + fileName );
00048 if ( fs.existsSync( fileName ) ) {
00049 var res = true;
00050 var config = "" + fs.readFileSync( fileName );
00051 var xmlObj;
00052 parser.parseString( config, function(err,result) {xmlObj = result;});
00053 configuration.xmlObj = xmlObj;
00054 configuration.artdaqDir = xmlObj['artdaq-configuration'].artdaqDir;
00055 configuration.setupScript = xmlObj['artdaq-configuration'].setupScript;
00056 configuration.runValue = xmlObj['artdaq-configuration'].dataLogger.runValue;
00057
00058 return res;
00059 }
00060 console.log( "Configuration file not found!" );
00061 return false;
00062 }
00063
00064 arc.MasterInitFunction = function ( workerData ) {
00065 var output = {};
00066 output.p0 = new Status( 0 );
00067 output.p1 = new Status( 1 );
00068 output.p2 = new Status( 2 );
00069 output.p3 = new Status( 3 );
00070 output.p0evt = [];
00071 output.p1evt = [];
00072 output.p2evt = [];
00073 output.p3evt = [];
00074 output.p0onmon = false;
00075 output.p1onmon = false;
00076 output.p2onmon = false;
00077 output.p3onmon = false;
00078
00079 if ( !fs.existsSync( __dirname + "/../client/P0" ) ) {
00080 fs.mkdirSync( __dirname + "/../client/P0" );
00081 }
00082 if ( !fs.existsSync( __dirname + "/../client/P1" ) ) {
00083 fs.mkdirSync( __dirname + "/../client/P1" );
00084 }
00085 if ( !fs.existsSync( __dirname + "/../client/P2" ) ) {
00086 fs.mkdirSync( __dirname + "/../client/P2" );
00087 }
00088 if ( !fs.existsSync( __dirname + "/../client/P3" ) ) {
00089 fs.mkdirSync( __dirname + "/../client/P3" );
00090 }
00091
00092 fs.chmodSync( __dirname + "/runARTDAQ.sh",'777' );
00093 fs.chmodSync( __dirname + "/killArtdaq.sh",'777' );
00094 fs.chmodSync( __dirname + "/cleanupArtdaq.sh",'777' );
00095
00096 workerData["artdaq-runcontrol"] = output;
00097 };
00098
00099 function checkCommand( systemStatus ) {
00100 if ( systemStatus.commandPID !== null ) {
00101 try {
00102 process.kill( systemStatus.commandPID,0 );
00103 systemStatus.commandRunning = true;
00104 } catch ( err ) {
00105 systemStatus.commandRunning = false;
00106 systemStatus.commandPID = null;
00107 }
00108 } else {
00109 systemStatus.commandRunning = false;
00110 }
00111 }
00112
00113 function checkSystem( systemStatus ) {
00114 if ( systemStatus.systemPID !== null ) {
00115 try {
00116 process.kill( systemStatus.systemPID,0 );
00117 systemStatus.systemRunning = true;
00118 } catch ( err ) {
00119 systemStatus.systemRunning = false;
00120 systemStatus.systemPID = null;
00121 }
00122 } else {
00123 systemStatus.systemRunning = false;
00124 }
00125 }
00126
00127 function startCommand( args,systemStatus ) {
00128 if ( readConfiguration( systemStatus ) ) {
00129 var port = ( systemStatus.partition * 100 ) + 5600;
00130 var configName = configuration.artdaqDir + "/P" + systemStatus.partition + "Config.xml";
00131 fs.createReadStream(__dirname + "/../../artdaq-configuration/server/" + systemStatus.config).pipe(fs.createWriteStream(configName));
00132 var commandArray = [systemStatus.config,configName,port,"manageSystem.sh", "-C", configName].concat( args );
00133 systemStatus.commandErrorBuffer = "";
00134 systemStatus.commandOutputBuffer = "";
00135 var out = fs.openSync( __dirname + "/../client/P" + systemStatus.partition + "/comm.out.log",'w' );
00136 var err = fs.openSync( __dirname + "/../client/P" + systemStatus.partition + "/comm.err.log",'w' );
00137 console.log( "Spawning: " + __dirname + "/runARTDAQ.sh " + commandArray );
00138 var command = spawn( __dirname + "/runARTDAQ.sh",commandArray,{ detached: true, stdio: ['ignore',out,err] } );
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 systemStatus.commandPID = command.pid;
00149 command.unref( );
00150 systemStatus.commandRunning = true;
00151 checkCommand( systemStatus );
00152 } else {
00153 console.log( "CANNOT READ CONFIGURATION. COMMAND NOT STARTED!!!!" );
00154 }
00155 }
00156
00157 function startSystem( systemStatus ) {
00158 if ( readConfiguration( systemStatus ) ) {
00159 console.log( "Starting System, Partition " + systemStatus.partition );
00160 var port = ( systemStatus.partition * 100 ) + 5600;
00161
00162 var logRoot = configuration.xmlObj['artdaq-configuration'].logDir;
00163 var eventBuilderHostnames = configuration.xmlObj['artdaq-configuration'].eventBuilders.hostnames.hostname;
00164 var aggregatorHostname = configuration.xmlObj['artdaq-configuration'].dataLogger.hostname;
00165 var boardReaderHostnames = configuration.xmlObj['artdaq-configuration'].boardReaders.boardReader.hostname;
00166
00167 console.log("Making PMT Log Directories");
00168 spawn("/bin/mkdir", ["-p","-m","0777",logRoot + "/pmt"]);
00169 spawn("/bin/mkdir", ["-p","-m","0777",logRoot + "/masterControl"]);
00170 if(aggregatorHostname != "localhost" && aggregatorHostname != os.hostname()) {
00171 spawn("/usr/bin/ssh", [aggregatorHostname, "/bin/mkdir -p -m 0777 " + logRoot + "/aggregator"]);
00172 } else {
00173 spawn("/bin/mkdir", ["-p","-m","0777",logRoot + "/aggregator"]);
00174 }
00175 for(var hn in eventBuilderHostnames) {
00176 if(hn != "localhost" && hn != os.hostname()) {
00177 spawn("/usr/bin/ssh", [hn, "/bin/mkdir -p -m 0777 " + logRoot + "/eventbuilder"]);
00178 } else {
00179 spawn("/bin/mkdir", ["-p","-m","0777",logRoot + "/eventbuilder"]);
00180 }
00181 }
00182 for(var hn in boardReaderHostnames) {
00183 if(hn != "localhost" && hn != os.hostname()) {
00184 spawn("/usr/bin/ssh", [hn, "/bin/mkdir -p -m 0777 " + logRoot + "/boardreader"]);
00185 } else {
00186 spawn("/bin/mkdir", ["-p","-m","0777",logRoot + "/boardreader"]);
00187 }
00188 }
00189
00190 var configName = configuration.artdaqDir + "/P" + systemStatus.partition + "Config.xml";
00191 fs.createReadStream(__dirname + "/../../artdaq-configuration/server/" + systemStatus.config).pipe(fs.createWriteStream(configName));
00192 var displayNumber = process.env.DISPLAY;
00193
00194 var commandArray = [systemStatus.config, configName,port,"pmt.rb","-p", port, "-C",configName,"--logpath", logRoot, "--display", displayNumber];
00195
00196 var out = fs.openSync( __dirname + "/../client/P" + systemStatus.partition + "/out.log",'w' );
00197 var err = fs.openSync( __dirname + "/../client/P" + systemStatus.partition + "/err.log",'w' );
00198 systemStatus.systemErrorBuffer = "";
00199 systemStatus.systemOutputBuffer = "";
00200 console.log( "Spawning: " + __dirname + "/runARTDAQ.sh " + commandArray.join( ' ' ) );
00201 var system = spawn( __dirname + "/runARTDAQ.sh",commandArray,{ detached: true, stdio: ['ignore',out,err] } );
00202 systemStatus.systemPID = system.pid;
00203 system.unref( );
00204 systemStatus.systemRunning = true;
00205 console.log( "Command Spawned" );
00206
00207 systemStatus.state = "Started";
00208 } else {
00209 console.log( "CANNOT READ CONFIGURATION. COMMAND NOT STARTED!!!!" );
00210 }
00211 }
00212
00213 function initialize( systemStatus ) {
00214 if ( systemStatus.commandRunning ) {
00215 setTimeout( function () { initialize( systemStatus ); } );
00216 }
00217 else {
00218 var onmonDir = __dirname + "/../client/P" + systemStatus.partition + "/artdaqdemo_onmon.root";
00219 var args = ["-M", onmonDir, "init"];
00220 startCommand( args,systemStatus );
00221 systemStatus.state = "Initialized";
00222 }
00223 }
00224
00225 function startRun( systemStatus ) {
00226 if ( systemStatus.commandRunning ) {
00227 setTimeout( function () { startRun( systemStatus ); },500 );
00228 }
00229 else {
00230 var args = ["-N",systemStatus.runNumber,"start"];
00231 startCommand( args,systemStatus );
00232 systemStatus.state = "Running";
00233 if ( readConfiguration( systemStatus ) && configuration.runValue > 0 ) {
00234 systemStatus.stopPending = true;
00235 startCommand( ["stop"],systemStatus );
00236 }
00237 }
00238 }
00239
00240 function pauseRun( systemStatus ) {
00241 if ( systemStatus.commandRunning ) {
00242 setTimeout( function () { pauseRun( systemStatus ); },500 );
00243 }
00244 else {
00245 var args = ["pause"];
00246 startCommand( args,systemStatus );
00247 systemStatus.state = "Paused";
00248 }
00249 }
00250
00251 function resumeRun( systemStatus ) {
00252 if ( systemStatus.commandRunning ) {
00253 setTimeout( function () { resumeRun( systemStatus ); },500 );
00254 }
00255 else {
00256 var args = ["resume"];
00257 startCommand( args,systemStatus );
00258 systemStatus.state = "Running";
00259 }
00260 }
00261
00262 function endRun( systemStatus ) {
00263 if ( systemStatus.commandRunning ) {
00264 setTimeout( function () { endRun( systemStatus ); },500 );
00265 }
00266 else {
00267 var args = ["stop"];
00268 startCommand( args,systemStatus );
00269 systemStatus.state = "Initialized";
00270 }
00271 }
00272
00273 function killSystem( systemStatus ) {
00274 checkCommand( systemStatus );
00275 if ( !systemStatus.commandRunning ) {
00276 checkSystem( systemStatus );
00277 if ( systemStatus.systemRunning ) {
00278 console.log( "Killing System, PID: " + systemStatus.systemPID );
00279 spawn( __dirname + '/killArtdaq.sh',[systemStatus.systemPID] );
00280 setTimeout( function () { killSystem( systemStatus ); },1000 );
00281 }
00282 } else {
00283 console.log( "Command running, spinning..." );
00284 setTimeout( function () { killSystem( systemStatus ); },1000 );
00285 }
00286 }
00287
00288 function shutdownSystem( systemStatus ) {
00289 if ( systemStatus.commandRunning ) {
00290 setTimeout( function () { shutdownSystem( systemStatus ); },500 );
00291 }
00292 else {
00293 console.log( "Shutting down system, Partition " + systemStatus.partition );
00294 var args = ["shutdown"];
00295 startCommand( args,systemStatus );
00296 spawn( __dirname + '/cleanupArtdaq.sh',[__dirname,systemStatus.partition] );
00297 systemStatus.state = "Shutdown";
00298 }
00299
00300 setTimeout( function () { killSystem( systemStatus ); },4000 );
00301 }
00302
00303 function getStatus( systemStatuses,partition ) {
00304 var systemStatus = systemStatuses["p" + partition];
00305
00306 systemStatus.okToStartOnMon = systemStatuses["p" + partition + "onmon"];
00307 while(systemStatuses["p"+partition+"evt"].length > 120) {
00308 systemStatuses["p"+partition+"evt"].shift();
00309 }
00310
00311 checkCommand( systemStatus );
00312 checkSystem( systemStatus );
00313 if ( fs.existsSync( __dirname + "/../client/P" + systemStatus.partition + "/artdaqdemo_onmon.root" ) ) {
00314 var stats = fs.statSync( __dirname + "/../client/P" + systemStatus.partition + "/artdaqdemo_onmon.root" );
00315 var statSize = stats.size;
00316 if ( statSize !== systemStatus.WFFileSize ) {
00317 systemStatus.WFFileSize = statSize;
00318 systemStatus.WFPlotsUpdated = Date.now( );
00319 console.log( "Plots Updated at " + systemStatus.WFPlotsUpdated );
00320 }
00321 if ( stats.mtime - systemStatus.WFFileMtime ) {
00322 systemStatus.WFFileMtime = stats.mtime;
00323 systemStatus.WFPlotsUpdated = Date.now( );
00324 console.log( "Plots Updated at " + systemStatus.WFPlotsUpdated );
00325 }
00326 } else {
00327 systemStatus.WFPlotsUpdated = null;
00328 }
00329 if ( fs.existsSync( __dirname + "/../client/P" + systemStatus.partition + "/out.log" ) ) {
00330 systemStatus.systemOutputBuffer = "" + fs.readFileSync( __dirname + "/../client/P" + systemStatus.partition + "/out.log" );
00331 }
00332 if ( fs.existsSync( __dirname + "/../client/P" + systemStatus.partition + "/err.log" ) ) {
00333 systemStatus.systemErrorBuffer = "" + fs.readFileSync( __dirname + "/../client/P" + systemStatus.partition + "/err.log" );
00334 }
00335 if ( fs.existsSync( __dirname + "/../client/P" + systemStatus.partition + "/comm.out.log" ) ) {
00336 systemStatus.commandOutputBuffer = "" + fs.readFileSync( __dirname + "/../client/P" + systemStatus.partition + "/comm.out.log" );
00337 }
00338 if ( fs.existsSync( __dirname + "/../client/P" + systemStatus.partition + "/comm.err.log" ) ) {
00339 systemStatus.commandErrorBuffer = "" + fs.readFileSync( __dirname + "/../client/P" + systemStatus.partition + "/comm.err.log" );
00340 }
00341 if ( systemStatus.stopPending && !systemStatus.commandRunning ) {
00342 systemStatus.state = "Initialized";
00343 }
00344 systemStatuses["p"+partition] = systemStatus;
00345 arc.emit( 'message', {name:"artdaq-runcontrol",data:systemStatus, target:"p"+partition} );
00346
00347 arc.emit( 'end',JSON.stringify( systemStatus ) );
00348 }
00349
00350 arc.GET_P0 = function ( systemStatuses ) {
00351 getStatus( systemStatuses,0 );
00352 };
00353
00354 arc.GET_P1 = function ( systemStatuses ) {
00355 getStatus( systemStatuses,1 );
00356 };
00357
00358 arc.GET_P2 = function ( systemStatuses ) {
00359 getStatus( systemStatuses,2 );
00360 };
00361
00362 arc.GET_P3 = function ( systemStatuses ) {
00363 getStatus( systemStatuses,3 );
00364 };
00365
00366 arc.RO_GetEvent = function( POST, systemStatuses ){
00367
00368
00369 var events = systemStatuses["p"+POST.partition+"evt"];
00370 if(events[0]) {
00371
00372
00373 if(POST.event == 0 || POST.event < events[0].event) {
00374 var data = events[0];
00375
00376 data.lastEvent = events[events.length - 1].event;
00377 return JSON.stringify(data);
00378 } else {
00379 for(var event in events) {
00380
00381
00382 if(events[event].event == POST.event) {
00383
00384 var data = events[event];
00385 data.lastEvent = events[events.length - 1].event;
00386 return JSON.stringify(data);
00387 }
00388 }
00389 if(POST.event < events[events.length -1 ].event) {
00390 return "ENOEVT";
00391 }
00392 }
00393 }
00394
00395 return "";
00396 };
00397
00398 arc.RW_GetEvent = function( POST, systemStatuses) {
00399 return arc.RO_GetEvent(POST, systemStatuses);
00400 };
00401
00402 arc.RW_Start = function ( POST,systemStatuses ) {
00403 systemStatuses["p" + POST.partition + "evt"] = [];
00404 systemStatuses["p" + POST.partition].config = POST.config;
00405 if ( systemStatuses["p" + POST.partition].state === "Shutdown" ) {
00406 startSystem( systemStatuses["p" + POST.partition] );
00407 }
00408 getStatus( systemStatuses,POST.partition );
00409 };
00410
00411 arc.RW_Init = function ( POST,systemStatuses ) {
00412 systemStatuses["p" + POST.partition].config = POST.config;
00413 if ( systemStatuses["p" + POST.partition].state === "Started" ) {
00414 initialize( systemStatuses["p" + POST.partition] );
00415 }
00416 getStatus( systemStatuses,POST.partition );
00417 };
00418
00419 arc.RW_Run = function ( POST,systemStatuses ) {
00420 systemStatuses["p" + POST.partition].config = POST.config;
00421 systemStatuses["p" + POST.partition].runNumber = POST.runNumber;
00422 if ( systemStatuses["p" + POST.partition].state === "Initialized" ) {
00423 startRun( systemStatuses["p" + POST.partition] );
00424 }
00425 getStatus( systemStatuses,POST.partition );
00426 };
00427
00428 arc.RW_Pause = function ( POST,systemStatuses ) {
00429 systemStatuses["p" + POST.partition].config = POST.config;
00430 if ( systemStatuses["p" + POST.partition].state === "Running" ) {
00431 pauseRun( systemStatuses["p" + POST.partition] );
00432 }
00433 getStatus( systemStatuses,POST.partition );
00434 };
00435
00436 arc.RW_Resume = function ( POST,systemStatuses ) {
00437 systemStatuses["p" + POST.partition].config = POST.config;
00438 if ( systemStatuses["p" + POST.partition].state === "Paused" ) {
00439 resumeRun( systemStatuses["p" + POST.partition] );
00440 }
00441 getStatus( systemStatuses,POST.partition );
00442 };
00443
00444 arc.RW_End = function ( POST,systemStatuses ) {
00445 systemStatuses["p" + POST.partition + "onmon"] = false;
00446 systemStatuses["p" + POST.partition].config = POST.config;
00447 if ( systemStatuses["p" + POST.partition].state === "Running" || systemStatuses["p" + POST.partition].state === "Paused" ) {
00448 endRun( systemStatuses["p" + POST.partition] );
00449 }
00450 getStatus( systemStatuses,POST.partition );
00451 };
00452
00453 arc.RW_Shutdown = function ( POST,systemStatuses ) {
00454 systemStatuses["p" + POST.partition].config = POST.config;
00455 if ( systemStatuses["p" + POST.partition].state === "Started" || systemStatuses["p" + POST.partition].state === "Initialized" || systemStatuses["p" + POST.partition].state === "Paused" ) {
00456 shutdownSystem( systemStatuses["p" + POST.partition] );
00457 }
00458 getStatus( systemStatuses,POST.partition );
00459 };
00460
00461 module.exports = function ( module_holder ) {
00462 module_holder["artdaq-runcontrol"] = arc;
00463 };