Files
growcontrold/src/main.cpp
T
hg c2c25dd30e Added restart as recovery when connection to devices is lost.
Added a heardbeat-file into which a timestamp is written every second.
2014-06-30 22:07:03 +02:00

208 lines
5.4 KiB
C++

/*
* main.cpp
*
* Created on: 10.06.2014
* Author: matzman
*/
#include <TfCPPsimple.h>
#include "GrowControl.h"
#include "GCException.h"
#include "IPCManager.h"
#include "third-party/daemon.h"
#include "third-party/pidfile.h"
#include <log4cpp/Category.hh>
#include <unistd.h>
#include <iostream>
#include <sstream>
#include <string>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <signal.h>
using namespace tfcppsimple;
using namespace growcontrol;
static log4cpp::Category& logger = log4cpp::Category::getInstance("growcontrol");
std::string pidFile = "/var/run/growcontrold.pid";
std::string socketPath = "/opt/growcontrol/growcontrold.socket";
std::string log4cppConfig = "log4cpp.config";
std::string host = "localhost";
std::string workDir = "/opt/growcontrol";
std::string heartBeatFile = "/opt/growcontrol/growcontrold.heartbeat";
uint16_t port = 4223;
bool daemonMode = false;
int pid_fd = 0;
GrowControl controller;
IPCManager ipcManager;
bool termSignalCaught = false;
void signalHandler(int signum) {
signal (signum, signalHandler);
switch (signum) {
case SIGHUP:
case SIGINT:
case SIGTERM:
logger << log4cpp::Priority::WARN << "Caught term signal, exiting ...";
termSignalCaught = true;
controller.shutdownController();
break;
default:
break;
}
}
void printUsage(std::ostream& stream, std::string name) {
stream << "Usage: " << name << " [-d] [-pid pid-file] [-s socket-path] [-l log4cpp-config] [-h host] [-p port] [-w work-dir]" << std::endl
<< "\t-d ... daemon mode" << std::endl
<< "\t-pid ... pid-file" << std::endl
<< "\t-s ... path of ipc socket" << std::endl
<< "\t-l ... path to log4cpp config file" << std::endl
<< "\t-h ... brickd address" << std::endl
<< "\t-p ... brickd port" << std::endl
<< "\t-hb ... heartbeat file" << std::endl
<< "\t-w ... working directory" << std::endl;
}
int main(int argc, char **argv) {
for (int t = 1; t < argc; t++) {
if (strcmp(argv[t], "-d") == 0) {
daemonMode = true;
} else if (strcmp(argv[t], "--help") == 0) {
printUsage(std::cerr, argv[0]);
exit(0);
} else if (strcmp(argv[t], "-pid") == 0) {
if (t+1 < argc && argv[t+1][0] != '-') {
t++;
pidFile = argv[t];
} else {
std::cerr << "Option -pid is missing an argument." << std::endl << std::endl;
printUsage(std::cerr, argv[0]);
exit(1);
}
} else if (strcmp(argv[t], "-s") == 0) {
if (t+1 < argc && argv[t+1][0] != '-') {
t++;
socketPath = argv[t];
} else {
std::cerr << "Option -s is missing an argument." << std::endl << std::endl;
printUsage(std::cerr, argv[0]);
exit(1);
}
} else if (strcmp(argv[t], "-l") == 0) {
if (t+1 < argc && argv[t+1][0] != '-') {
t++;
log4cppConfig = argv[t];
} else {
std::cerr << "Option -l is missing an argument." << std::endl << std::endl;
printUsage(std::cerr, argv[0]);
exit(1);
}
} else if (strcmp(argv[t], "-w") == 0) {
if (t+1 < argc && argv[t+1][0] != '-') {
t++;
workDir = argv[t];
} else {
std::cerr << "Option -w is missing an argument." << std::endl << std::endl;
printUsage(std::cerr, argv[0]);
exit(1);
}
} else if (strcmp(argv[t], "-h") == 0) {
if (t+1 < argc && argv[t+1][0] != '-') {
t++;
host = argv[t];
} else {
std::cerr << "Option -h is missing an argument." << std::endl << std::endl;
printUsage(std::cerr, argv[0]);
exit(1);
}
} else if (strcmp(argv[t], "-hb") == 0) {
if (t+1 < argc && argv[t+1][0] != '-') {
t++;
heartBeatFile = argv[t];
} else {
std::cerr << "Option -hb is missing an argument." << std::endl << std::endl;
printUsage(std::cerr, argv[0]);
exit(1);
}
} else if (strcmp(argv[t], "-p") == 0) {
if (t+1 < argc && argv[t+1][0] != '-') {
t++;
port = std::atoi(argv[t]);
if (port == 0) {
std::cerr << "Option -p has invalid argument \"" << argv[t] << "\"." << std::endl << std::endl;
printUsage(std::cerr, argv[0]);
exit(1);
}
} else {
std::cerr << "Option -p is missing an argument." << std::endl << std::endl;
printUsage(std::cerr, argv[0]);
exit(1);
}
} else {
std::cerr << "Unknown argument \"" << argv[t] << "\"." << std::endl << std::endl;
printUsage(std::cerr, argv[0]);
exit(1);
}
}
TfUtils::configureLog4CPP(log4cppConfig);
logger << log4cpp::Priority::INFO << "Daemon Mode: " << daemonMode;
logger << log4cpp::Priority::INFO << "Pid-File: " << pidFile;
logger << log4cpp::Priority::INFO << "socket-path: " << socketPath;
logger << log4cpp::Priority::INFO << "log4cpp-config: " << log4cppConfig;
logger << log4cpp::Priority::INFO << "Brickd-Address: " << host << ":" << port;
if (daemonMode) {
pid_fd = daemon_start(pidFile.c_str());
} else {
pid_fd = pidfile_acquire(pidFile.c_str(), getpid());
}
if (pid_fd >= 0) {
signal(SIGTERM, signalHandler);
signal(SIGINT, signalHandler);
signal(SIGHUP, signalHandler);
controller.connect(workDir, host, port);
if (!termSignalCaught) {
sleep(2);
try {
ipcManager.init(controller, socketPath);
} catch (GCException &e) {
}
controller.mainLoop(heartBeatFile);
logger << log4cpp::Priority::WARN << "Shutting down ipc ...";
ipcManager.shutdown();
}
} else {
logger << log4cpp::Priority::WARN << "Problems while forking/writing pid-file.";
}
logger << log4cpp::Priority::WARN << "Shutting down ...";
if (pid_fd >= 0) {
pidfile_release(pidFile.c_str(), pid_fd);
}
}