Commit 49002611 authored by Leon Hiemstra's avatar Leon Hiemstra

added SIGHUP signal to reload configfile, REGMAP

parent c4acd04a
......@@ -52,6 +52,9 @@ Common::Common(list<class Node*>& nodelist)
Common::~Common()
{
for(auto node : NODE) {
delete node;
}
}
Node * Common::select_node(const int nr)
......
......@@ -49,6 +49,7 @@ class TCPCSSocket {
TCPCSSocket(int descr = -1);
~TCPCSSocket();
void Shutdown() { shutdown(sock,SHUT_RDWR); }
void Close() { close(sock); }
size_t rx(unsigned char* buf, size_t size) throw(const char*);
size_t _rx(unsigned char* buf, size_t size) throw(const char*);
size_t tx(const unsigned char* data, size_t size) throw(const char*);
......
......@@ -24,8 +24,10 @@
#include "ua_server.h"
extern volatile bool ServerRunning;
extern Serverdat SD;
UA_Server *mUaServer;
Serverdat *SD;
string p_termout(TermOutput& termout)
{
......@@ -84,7 +86,7 @@ static UA_StatusCode UNB_MethodCallback(UA_Server *server,
cout <<"inputStr->data=" << inputStr->data <<endl;
try {
SD->unb->read(termout,std::string((char *)inputStr->data),0,-1); // TODO: make read/write
SD.unb->read(termout,std::string((char *)inputStr->data),0,-1); // TODO: make read/write
} catch(runtime_error& e) {
cerr << "UNB_MethodCallback: " << e.what() << endl;
termout.strout << e.what();
......@@ -137,28 +139,39 @@ static void add_UNB_Method(UA_Server *server, std::string regname)
1, &inputArgument, 1, &outputArgument, NULL, NULL);
}
int ua_server(Serverdat *sd) {
SD = sd;
// FIXME: test the SD.ready* lines first
int ua_server_init(void)
{
TermOutput termout;
std::vector<int> nodes = SD->unb->get_nodes(); // all nodes
UA_Server *mUaServer = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(mUaServer));
std::vector<int> nodes = SD.unb->get_nodes(); // all nodes
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "UA Server add nodes");
addVariable(mUaServer);
for(auto node : nodes) {
RegisterMap *regmap = SD->unb->get_RegisterMap(termout, node);
RegisterMap *regmap = SD.unb->get_RegisterMap(termout, node);
std::string prefix = SD->unb->string_node_id(node);
std::string prefix = SD.unb->string_node_id(node);
std::vector<std::string> regnames = regmap->getRegnames(prefix);
for(auto m : regnames) {
add_UNB_Method(mUaServer, m);
}
}
return 0;
}
int ua_server_delete(void)
{
//UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_USERLAND, "UA Server delete nodes");
return 0;
}
int ua_server(void)
{
mUaServer = UA_Server_new();
UA_ServerConfig_setDefault(UA_Server_getConfig(mUaServer));
ua_server_init();
UA_StatusCode retval = UA_Server_run(mUaServer, &ServerRunning);
......
......@@ -25,6 +25,8 @@
using namespace std;
int ua_server(Serverdat *sd);
int ua_server_init(void);
int ua_server_delete(void);
int ua_server(void);
#endif // UA_SERVER_H
......@@ -124,6 +124,7 @@ bool Periph_system::read_system_info(ostringstream& strs)
(data & 0x000F0000) >> 16); strs << str;
sprintf(str," Hardware version = %d\n", ((data & 0x00000300) >> 8)); strs << str;
return retval;
// FIXME: test if design_name is expected, otherwise reload REGMAP by calling function: raise(SIGHUP);
}
bool Periph_system::mread(std::ostringstream& strs, const std::string addr,
......
......@@ -49,6 +49,7 @@ namespace po = boost::program_options;
volatile bool ServerRunning = true;
int debug = 0;
const char* SDPUNB_VERSION= " (testing) " __DATE__ " " __TIME__;
Serverdat SD;
......@@ -64,15 +65,16 @@ string print_termout(TermOutput& termout)
return s;
}
void control_server(TCPSSocket *sock, Serverdat *sd, const int clientId, std::atomic<size_t> *nthreads)
void control_server(TCPSSocket *sock, const int clientId, std::atomic<size_t> *nthreads)
{
bool quit=false;
while(ServerRunning) {
try {
sd->controlSocket[clientId] = new TCPCSSocket(sock->listen());
SD.ready_client[clientId] = true;
SD.controlSocket[clientId] = new TCPCSSocket(sock->listen());
string banner = "output={ SDP to Uniboard Translator " + string(SDPUNB_VERSION)
+ ". (use 'help' for available commands) }\n";
sd->controlSocket[clientId]->tx((unsigned char *)banner.c_str(), strlen(banner.c_str()));
SD.controlSocket[clientId]->tx((unsigned char *)banner.c_str(), strlen(banner.c_str()));
CMD Cmd;
string line;
......@@ -85,9 +87,9 @@ void control_server(TCPSSocket *sock, Serverdat *sd, const int clientId, std::at
unsigned char tcpbuf[c_TCP_CONTROL_BUFFERSIZE];
while(!quit) {
string prompt = "sdpunb:" + cmdname + ":" + to_string(cmdstatus.status) + ":CMD>";
sd->controlSocket[clientId]->tx((unsigned char *)prompt.c_str(), strlen(prompt.c_str()));
SD.controlSocket[clientId]->tx((unsigned char *)prompt.c_str(), strlen(prompt.c_str()));
int len = sd->controlSocket[clientId]->rx(tcpbuf, c_TCP_CONTROL_BUFFERSIZE);
int len = SD.controlSocket[clientId]->rx(tcpbuf, c_TCP_CONTROL_BUFFERSIZE);
if(len < 1) {
quit = true;
} else {
......@@ -97,33 +99,98 @@ void control_server(TCPSSocket *sock, Serverdat *sd, const int clientId, std::at
if (pos != string::npos) tcpbuf[pos] = 0;
pos = sbuf.find("\r");
if (pos != string::npos) tcpbuf[pos] = 0;
cmdstatusnew = Cmd.command(string((char *)tcpbuf), termout, cmdname, sd);
while(!SD.ready_init) { cout << "init not ready\n"; usleep(100000); }
SD.ready_client[clientId] = false;
cmdstatusnew = Cmd.command(string((char *)tcpbuf), termout, cmdname, &SD);
SD.ready_client[clientId] = true;
if(cmdstatusnew.status != CMD_EMPTY) cmdstatus = cmdstatusnew;
string s = print_termout(termout);
sd->controlSocket[clientId]->tx((unsigned char *)s.c_str(), strlen(s.c_str()));
SD.controlSocket[clientId]->tx((unsigned char *)s.c_str(), strlen(s.c_str()));
termout.clear();
if(cmdstatus.status == CMD_REQUEST_QUIT) {
quit = true;
}
}
}
sd->controlSocket[clientId]->Shutdown();
delete sd->controlSocket[clientId];
SD.controlSocket[clientId]->Shutdown();
delete SD.controlSocket[clientId];
} catch(const char *str) {
delete sd->controlSocket[clientId];
delete SD.controlSocket[clientId];
}
}
(*nthreads)--;
}
// FIXME: find a way to 'disable interrupts'
void wait_for_clients_to_start_init(void)
{
for(uint c=0; c<c_MAX_CONTROL_SERVERS; c++) {
while(!SD.ready_client[c]) { cout << "client not ready\n"; usleep(100000); }
}
SD.ready_init = false;
}
void server_init(void)
{
ostringstream sstr;
list<class NODE_config> NC;
ifstream ifs;
cout << "Reading configfile: " << SD.configfile << endl;
ifs.open(SD.configfile.c_str());
if (!ifs.is_open()) {
syslog(LOG_ERR,"Error opening config file: %s (use --configfile=filename)\n",
SD.configfile.c_str());
throw runtime_error("Cannot open configfile: \""+SD.configfile+"\" (use --configfile=filename)");
} else {
if(!importdatfile(ifs, NC)) {
syslog(LOG_ERR,"Error reading config file: %s\n", SD.configfile.c_str());
throw runtime_error("Cannot read configfile: \""+SD.configfile+"\"");
}
}
cout << "Hint: follow the syslog: tail -f /var/log/localmessages" << endl;
wait_for_clients_to_start_init();
list<class Node*> nodelist;
for(auto nc : NC) {
uint gn = (uint)nc.gn;
uint uniboardnr = GLOBALNODE_to_UNB(gn);
uint n = GLOBALNODE_to_NODE(gn);
string type = GLOBALNODE_to_TYPE(gn);
Node *node = new Node(nc.ipaddr, uniboardnr, n, type, nc.firmware);
nodelist.push_back(node);
}
SD.unb = new UniboardMap(nodelist);
SD.ready_init = true;
}
void server_delete(void)
{
wait_for_clients_to_start_init();
delete SD.unb;
}
static void stopHandler(int signal)
{
cerr << "received ctrl-c" << endl;
cerr << "received ctrl-c: exit" << endl;
ServerRunning = false;
usleep(1000000);
usleep(2000000);
exit(0);
}
static void hupHandler(int signal)
{
cerr << "received HUP signal: reload" << endl;
server_delete();
ua_server_delete();
server_init();
ua_server_init();
}
int main (int argc, char* argv[])
{
// defaults:
......@@ -131,7 +198,7 @@ int main (int argc, char* argv[])
bool nodaemon = false;
int verbose = 1;
debug=0;
string configfile = "/etc/uniboard.conf";
SD.configfile = "/etc/uniboard.conf";
std::atomic<size_t> ncthreads(0);
std::thread *control_server_thread[c_MAX_CONTROL_SERVERS];
......@@ -146,7 +213,7 @@ int main (int argc, char* argv[])
"With this flag, the server runs NOT as daemon")
("debug", po::value(&debug), "Prints out debug info (default=0)")
("verbose", po::value(&verbose), "More messages and infos")
("configfile", po::value<string>(&configfile)->default_value(configfile),
("configfile", po::value<string>(&SD.configfile)->default_value(SD.configfile),
"Specify uniboard configuration file location")
;
......@@ -176,69 +243,40 @@ int main (int argc, char* argv[])
signal(SIGINT, stopHandler);
//signal(SIGTERM, stopHandler);
signal(SIGHUP, hupHandler);
try {
/* Open syslog connection */
openlog(basename(argv[0]), 0, LOG_LOCAL0);
syslog(LOG_INFO,"Starting server %s\n", SDPUNB_VERSION);
ostringstream sstr;
list<class NODE_config> NC;
ifstream ifs;
cout << "Reading configfile: " << configfile << endl;
ifs.open(configfile.c_str());
if (!ifs.is_open()) {
cerr << "Error opening config file: " << configfile << " (use --configfile=filename)" << endl;
syslog(LOG_ERR,"Error opening config file: %s (use --configfile=filename)\n",
configfile.c_str());
exit(EXIT_FAILURE);
} else {
if(!importdatfile(ifs, NC)) {
cerr << "Error reading config file: " << configfile << endl;
syslog(LOG_ERR,"Error reading config file: %s\n", configfile.c_str());
exit(EXIT_FAILURE);
}
}
cout << "Hint: follow the syslog: tail -f /var/log/localmessages" << endl;
list<class Node*> nodelist;
for(auto nc : NC) {
uint gn = (uint)nc.gn;
uint uniboardnr = GLOBALNODE_to_UNB(gn);
uint n = GLOBALNODE_to_NODE(gn);
string type = GLOBALNODE_to_TYPE(gn);
Node *node = new Node(nc.ipaddr, uniboardnr, n, type, nc.firmware);
nodelist.push_back(node);
}
if(!nodaemon) {
if(daemon(1, 0) < 0) cerr << "Error fork as daemon: " << strerror(errno) << endl;
}
Serverdat control_server_dat;
control_server_dat.unb = new UniboardMap(nodelist);
for(uint c=0; c<c_MAX_CONTROL_SERVERS; c++) {
control_server_dat.tcpport = control_tcpport;
control_server_dat.verbose[c] = verbose;
SD.tcpport = control_tcpport;
SD.verbose[c] = verbose;
SD.ready_client[c] = true;
}
server_init();
TCPSSocket sock(control_tcpport, "", c_MAX_CONTROL_SERVERS);
for(uint c=0; c<c_MAX_CONTROL_SERVERS; c++) {
control_server_thread[c] = new std::thread(control_server, &sock, &control_server_dat, c, &ncthreads);
control_server_thread[c] = new std::thread(control_server, &sock, c, &ncthreads);
++ncthreads;
}
ua_server(&control_server_dat);
ua_server();
for(uint c=0; c<c_MAX_CONTROL_SERVERS; c++) { control_server_thread[c]->join(); }
for(uint c=0; c<c_MAX_CONTROL_SERVERS; c++) { delete control_server_thread[c]; }
for(auto node : nodelist) { delete node; }
closelog(); // close syslog connection
delete control_server_dat.unb;
server_delete();
exit(EXIT_SUCCESS);
} catch(exception& e) {
......
......@@ -25,6 +25,7 @@ using namespace std;
#include <list>
#include <iostream>
#include <fstream>
#include <atomic>
#include "map.h"
#include "io/tcpsocket.h"
......@@ -40,6 +41,9 @@ public:
UniboardMap *unb;
struct timespec t0;
TCPCSSocket *controlSocket[c_MAX_CONTROL_SERVERS];
std::string configfile;
std::atomic<bool> ready_client[c_MAX_CONTROL_SERVERS];
std::atomic<bool> ready_init;
};
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment