webapi-eca/js/server.js
2013-11-19 13:51:30 +01:00

152 lines
4.6 KiB
JavaScript

/*
* Rules Server
* ============
* This is the main module that is used to run the whole server:
*
* node server [log_type http_port]
*
* Valid `log_type`'s are:
*
* - `0`: standard I/O output (default)
* - `1`: log file (server.log)
* - `2`: silent
*
* `http_port` can be set to use another port, than defined in the
* [config](config.html) file, to listen to, e.g. used by the test suite.
*/
'use strict';
var path = require('path'),
log = require('./logging'),
semaphore = 0,
args = {},
procCmds = {},
adminCmds, http_listener, mm, db, engine;
/*
* Error handling of the express port listener requires special attention,
* thus we have to catch the process error, which is issued if
* the port is already in use.
*/
process.on('uncaughtException', function(err) {
switch(err.errno) {
case 'EADDRINUSE':
err.addInfo = 'http_port already in use, shutting down!';
log.error('RS', err);
shutDown();
break;
default: log.error(err);
}
});
/**
* ### Initialize the Server
* This function is invoked right after the module is loaded and starts the server.
*/
function init() {
log.print('RS', 'STARTING SERVER');
// Check whether the config file is ready, which is required to start the server.
if(!require('./config').isReady()) {
log.error('RS', 'Config file not ready!');
return;
}
// Fetch the `log_type` argument and post a log about which log type is used.
if(process.argv.length > 2) {
args.logType = parseInt(process.argv[2]) || 0;
if(args.logType === 0) log.print('RS', 'Log type set to standard I/O output');
else if(args.logType === 1) log.print('RS', 'Log type set to file output');
else if(args.logType === 2) log.print('RS', 'Log type set to silent');
else log.print('RS', 'Unknown log type, using standard I/O');
log(args);
} else log.print('RS', 'No log method passed, using standard I/O');
// Fetch the `http_port` argument
if(process.argv.length > 3) args.http_port = parseInt(process.argv[3]);
else log.print('RS', 'No HTTP port passed, using standard port from config file');
// Initialize all required modules with the args object.
db = require('./db_interface')(args);
db.isConnected(function(err, result) {
if(!err) continueInit();
});
}
function continueInit() {
log.print('RS', 'Initialzing engine');
engine = require('./engine')(args);
log.print('RS', 'Initialzing http listener');
http_listener = require('./http_listener')(args);
log.print('RS', 'Initialzing module manager');
mm = require('./module_manager')(args);
log.print('RS', 'Initialzing DB');
// Load the admin commands that are issued via HTTP requests.
adminCmds = {
'loadrules': mm.loadRulesFromFS,
'loadaction': mm.loadActionModuleFromFS,
'loadactions': mm.loadActionModulesFromFS,
'loadevent': mm.loadEventModuleFromFS,
'loadevents': mm.loadEventModulesFromFS,
'loadusers': http_listener.loadUsers,
'shutdown': shutDown
};
// Distribute handlers between modules to link the application.
log.print('RS', 'Passing handlers to engine');
engine.addDBLinkAndLoadActionsAndRules(db);
log.print('RS', 'Passing handlers to http listener');
http_listener.addHandlers(db, handleAdminCommands, engine.pushEvent);
log.print('RS', 'Passing handlers to module manager');
mm.addHandlers(db, engine.loadActionModule, engine.addRule);
}
/**
* admin commands handler receives all command arguments and an answerHandler
* object that eases response handling to the HTTP request issuer.
*/
function handleAdminCommands(args, answHandler) {
if(args && args.cmd) {
var func = adminCmds[args.cmd];
if(typeof func == 'function') func(args, answHandler);
} else log.print('RS', 'No command in request');
setTimeout(function(ah) {
answHandler = ah;
return function() {
if(!answHandler.isAnswered()) answHandler.answerError('Not handeled...');
};
}, 2000);
}
/**
* Shuts down the server.
* @param {Object} args
* @param {Object} answHandler
*/
function shutDown(args, answHandler) {
if(answHandler) answHandler.answerSuccess('Goodbye!');
log.print('RS', 'Received shut down command!');
if(engine) engine.shutDown();
if(http_listener) http_listener.shutDown();
}
/*
* ### Process Commands
*
* When the server is run as a child process, this function handles messages
* from the parent process (e.g. the testing suite)
*/
process.on('message', function(cmd) {
if(typeof procCmds[cmd] === 'function') procCmds[cmd]();
else console.error('err with command');
});
/**
* The die command redirects to the shutDown function.
*/
procCmds.die = shutDown;
/*
* *Start initialization*
*/
init();