bes  Updated for version 3.20.6
ServerApp.cc
1 // ServerApp.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include <unistd.h>
34 #include <signal.h>
35 #include <sys/wait.h> // for wait
36 #include <sys/types.h>
37 
38 #include <iostream>
39 #include <fstream>
40 #include <sstream>
41 #include <cstring>
42 #include <cstdlib>
43 #include <cerrno>
44 
45 #include <libxml/xmlmemory.h>
46 
47 using std::cout;
48 using std::cerr;
49 using std::endl;
50 using std::ios;
51 using std::ostringstream;
52 using std::ofstream;
53 using std::ostream;
54 using std::string;
55 
56 #include "config.h"
57 
58 #include "ServerApp.h"
59 #include "ServerExitConditions.h"
60 #include "TheBESKeys.h"
61 #include "BESLog.h"
62 #include "SocketListener.h"
63 #include "TcpSocket.h"
64 #include "UnixSocket.h"
65 #include "BESServerHandler.h"
66 #include "BESError.h"
67 #include "PPTServer.h"
68 #include "BESMemoryManager.h"
69 #include "BESDebug.h"
70 #include "BESCatalogUtils.h"
71 #include "BESServerUtils.h"
72 
73 #include "BESDefaultModule.h"
74 #include "BESXMLDefaultCommands.h"
75 #include "BESDaemonConstants.h"
76 
77 static int session_id = 0;
78 
79 // These are set to 1 by their respective handlers and then processed in the
80 // signal processing loop.
81 static volatile sig_atomic_t sigchild = 0;
82 static volatile sig_atomic_t sigpipe = 0;
83 static volatile sig_atomic_t sigterm = 0;
84 static volatile sig_atomic_t sighup = 0;
85 
86 // Set in ServerApp::initialize().
87 // Added jhrg 9/22/15
88 static volatile int master_listener_pid = -1;
89 
90 static string bes_exit_message(int cpid, int stat)
91 {
92  ostringstream oss;
93  oss << "beslistener child pid: " << cpid;
94  if (WIFEXITED(stat)) { // exited via exit()?
95  oss << " exited with status: " << WEXITSTATUS(stat);
96  }
97  else if (WIFSIGNALED(stat)) { // exited via a signal?
98  oss << " exited with signal: " << WTERMSIG(stat);
99 #ifdef WCOREDUMP
100  if (WCOREDUMP(stat)) oss << " and a core dump!";
101 #endif
102  }
103  else {
104  oss << " exited, but I have no clue as to why";
105  }
106 
107  return oss.str();
108 }
109 
110 // These two functions duplicate code in daemon.cc
111 static void block_signals()
112 {
113  sigset_t set;
114  sigemptyset(&set);
115  sigaddset(&set, SIGCHLD);
116  sigaddset(&set, SIGHUP);
117  sigaddset(&set, SIGTERM);
118  sigaddset(&set, SIGPIPE);
119 
120  if (sigprocmask(SIG_BLOCK, &set, 0) < 0) {
121  throw BESInternalError(string("sigprocmask error: ") + strerror(errno) + " while trying to block signals.",
122  __FILE__, __LINE__);
123  }
124 }
125 
126 static void unblock_signals()
127 {
128  sigset_t set;
129  sigemptyset(&set);
130  sigaddset(&set, SIGCHLD);
131  sigaddset(&set, SIGHUP);
132  sigaddset(&set, SIGTERM);
133  sigaddset(&set, SIGPIPE);
134 
135  if (sigprocmask(SIG_UNBLOCK, &set, 0) < 0) {
136  throw BESInternalError(string("sigprocmask error: ") + strerror(errno) + " while trying to unblock signals.",
137  __FILE__, __LINE__);
138  }
139 }
140 
141 // I moved the signal handlers here so that signal processing would be simpler
142 // and no library calls would be made to functions that are not 'asynch safe'.
143 // This was the fix for ticket 2025 and friends (the zombie process problem).
144 // jhrg 3/3/14
145 
146 // This is needed so that the master bes listener will get the exit status of
147 // all of the child bes listeners (preventing them from becoming zombies).
148 static void CatchSigChild(int sig)
149 {
150  if (sig == SIGCHLD) {
151  sigchild = 1;
152  }
153 }
154 
155 // If the HUP signal is sent to the master beslistener, it should exit and
156 // return a value indicating to the besdaemon that it should be restarted.
157 // This also has the side-affect of re-reading the configuration file.
158 static void CatchSigHup(int sig)
159 {
160  if (sig == SIGHUP) {
161  sighup = 1;
162  }
163 }
164 
165 static void CatchSigPipe(int sig)
166 {
167  if (sig == SIGPIPE) {
168  // When a child listener catches SIGPIPE it is because of a
169  // failure on one of its I/O connections - file I/O or, more
170  // likely, network I/O. I have found that C++ ostream objects
171  // seem to 'hide' sigpipe so that a child listener will run
172  // for some time after the client has dropped the
173  // connection. Whether this is from buffering or some other
174  // problem, the situation happens when either the remote
175  // client to exits (e.g., curl) or when Tomcat is stopped
176  // using SIGTERM. So, even though the normal behavior for a
177  // Unix daemon is to look at error codes from write(), etc.,
178  // and exit based on those, this code exits whenever the child
179  // listener catches SIGPIPE. However, if this is the Master
180  // listener, allow the processing loop to handle this signal
181  // and do not exit. jhrg 9/22/15
182  if (getpid() != master_listener_pid) {
183  (*BESLog::TheLog()) << "Child listener (PID: " << getpid() << ") caught SIGPIPE (master listener PID: "
184  << master_listener_pid << "). Child listener Exiting." << endl;
185 
186  // cleanup code here; only the Master listener should run the code
187  // in ServerApp::terminate(); do nothing for cleanup for a child
188  // listener. jhrg 9/22/15
189 
190  // Note that exit() is not safe for use in a signal
191  // handler, so we fallback to the default behavior, which
192  // is to exit.
193  signal(sig, SIG_DFL);
194  raise(sig);
195  }
196  else {
197  LOG("Master listener (PID: " << getpid() << ") caught SIGPIPE." << endl);
198 
199  sigpipe = 1;
200  }
201  }
202 }
203 
204 // This is the default signal sent by 'kill'; when the master beslistener gets
205 // this signal it should stop. besdaemon should not try to start a new
206 // master beslistener.
207 static void CatchSigTerm(int sig)
208 {
209  if (sig == SIGTERM) {
210  sigterm = 1;
211  }
212 }
213 
222 static void register_signal_handlers()
223 {
224  struct sigaction act;
225  sigemptyset(&act.sa_mask);
226  sigaddset(&act.sa_mask, SIGCHLD);
227  sigaddset(&act.sa_mask, SIGPIPE);
228  sigaddset(&act.sa_mask, SIGTERM);
229  sigaddset(&act.sa_mask, SIGHUP);
230  act.sa_flags = 0;
231 #ifdef SA_RESTART
232  BESDEBUG("beslistener", "beslistener: setting restart for sigchld." << endl);
233  act.sa_flags |= SA_RESTART;
234 #endif
235 
236  BESDEBUG("beslistener", "beslistener: Registering signal handlers ... " << endl);
237 
238  act.sa_handler = CatchSigChild;
239  if (sigaction(SIGCHLD, &act, 0))
240  throw BESInternalFatalError("Could not register a handler to catch beslistener child process status.", __FILE__,
241  __LINE__);
242 
243  act.sa_handler = CatchSigPipe;
244  if (sigaction(SIGPIPE, &act, 0) < 0)
245  throw BESInternalFatalError("Could not register a handler to catch beslistener pipe signal.", __FILE__,
246  __LINE__);
247 
248  act.sa_handler = CatchSigTerm;
249  if (sigaction(SIGTERM, &act, 0) < 0)
250  throw BESInternalFatalError("Could not register a handler to catch beslistener terminate signal.", __FILE__,
251  __LINE__);
252 
253  act.sa_handler = CatchSigHup;
254  if (sigaction(SIGHUP, &act, 0) < 0)
255  throw BESInternalFatalError("Could not register a handler to catch beslistener hup signal.", __FILE__,
256  __LINE__);
257 
258  BESDEBUG("beslistener", "beslistener: OK" << endl);
259 }
260 
261 ServerApp::ServerApp() :
262  BESModuleApp(), _portVal(0), _gotPort(false), _IPVal(""), _gotIP(false), _unixSocket(""), _secure(false), _mypid(0), _ts(0), _us(0), _ps(0)
263 {
264  _mypid = getpid();
265 }
266 
267 ServerApp::~ServerApp()
268 {
269  delete TheBESKeys::TheKeys();
270 
271 #if 0
272  BESCatalogUtils::delete_all_catalogs();
273 #endif
274 
275 }
276 
277 int ServerApp::initialize(int argc, char **argv)
278 {
279  int c = 0;
280  bool needhelp = false;
281  string dashi;
282  string dashc;
283  string dashd = "";
284 
285  // If you change the getopt statement below, be sure to make the
286  // corresponding change in daemon.cc and besctl.in
287  while ((c = getopt(argc, argv, "hvsd:c:p:u:i:r:H:")) != -1) {
288  switch (c) {
289  case 'i':
290  dashi = optarg;
291  break;
292  case 'c':
293  dashc = optarg;
294  break;
295  case 'r':
296  break; // we can ignore the /var/run directory option here
297  case 'p':
298  _portVal = atoi(optarg);
299  _gotPort = true;
300  break;
301  case 'H':
302  _IPVal = optarg;
303  _gotIP = true;
304  break;
305  case 'u':
306  _unixSocket = optarg;
307  break;
308  case 'd':
309  dashd = optarg;
310  // BESDebug::SetUp(optarg);
311  break;
312  case 'v':
313  BESServerUtils::show_version(BESApp::TheApplication()->appName());
314  break;
315  case 's':
316  _secure = true;
317  break;
318  case 'h':
319  case '?':
320  default:
321  needhelp = true;
322  break;
323  }
324  }
325 
326  // before we can do any processing, log any messages, initialize any
327  // modules, do anything, we need to determine where the BES
328  // configuration file lives. From here we get the name of the log
329  // file, group and user id, and information that the modules will
330  // need to run properly.
331 
332  // If the -c option was passed, set the config file name in TheBESKeys
333  if (!dashc.empty()) {
334  TheBESKeys::ConfigFile = dashc;
335  }
336 
337  // If the -c option was not passed, but the -i option
338  // was passed, then use the -i option to construct
339  // the path to the config file
340  if (dashc.empty() && !dashi.empty()) {
341  if (dashi[dashi.length() - 1] != '/') {
342  dashi += '/';
343  }
344  string conf_file = dashi + "etc/bes/bes.conf";
345  TheBESKeys::ConfigFile = conf_file;
346  }
347 
348  if (!dashd.empty()) BESDebug::SetUp(dashd);
349 
350  // register the two debug context for the server and ppt. The
351  // Default Module will register the bes context.
352  BESDebug::Register("server");
353  BESDebug::Register("ppt");
354 
355  // Because we are now running as the user specified in the
356  // configuration file, we won't be able to listen on system ports.
357  // If this is a problem, we may need to move this code above setting
358  // the user and group ids.
359  bool found = false;
360  string port_key = "BES.ServerPort";
361  if (!_gotPort) {
362  string sPort;
363  try {
364  TheBESKeys::TheKeys()->get_value(port_key, sPort, found);
365  }
366  catch (BESError &e) {
367  string err = string("FAILED: ") + e.get_message();
368  cerr << err << endl;
369  LOG(err << endl);
370  exit(SERVER_EXIT_FATAL_CANNOT_START);
371  }
372  if (found) {
373  _portVal = atoi(sPort.c_str());
374  if (_portVal != 0) {
375  _gotPort = true;
376  }
377  }
378  }
379 
380  found = false;
381  string ip_key = "BES.ServerIP";
382  if (!_gotIP) {
383  try {
384  TheBESKeys::TheKeys()->get_value(ip_key, _IPVal, found);
385  }
386  catch (BESError &e) {
387  string err = string("FAILED: ") + e.get_message();
388  cerr << err << endl;
389  LOG(err << endl);
390  exit(SERVER_EXIT_FATAL_CANNOT_START);
391  }
392 
393  if (found) {
394  _gotIP = true;
395  }
396  }
397 
398  found = false;
399  string socket_key = "BES.ServerUnixSocket";
400  if (_unixSocket == "") {
401  try {
402  TheBESKeys::TheKeys()->get_value(socket_key, _unixSocket, found);
403  }
404  catch (BESError &e) {
405  string err = string("FAILED: ") + e.get_message();
406  cerr << err << endl;
407  LOG(err << endl);
408  exit(SERVER_EXIT_FATAL_CANNOT_START);
409  }
410  }
411 
412  if (!_gotPort && _unixSocket == "") {
413  string msg = "Must specify a tcp port or a unix socket or both\n";
414  msg += "Please specify on the command line with -p <port>";
415  msg += " and/or -u <unix_socket>\n";
416  msg += "Or specify in the bes configuration file with " + port_key + " and/or " + socket_key + "\n";
417  cout << endl << msg;
418  LOG(msg << endl);
419  BESServerUtils::show_usage(BESApp::TheApplication()->appName());
420  }
421 
422  found = false;
423  if (_secure == false) {
424  string key = "BES.ServerSecure";
425  string isSecure;
426  try {
427  TheBESKeys::TheKeys()->get_value(key, isSecure, found);
428  }
429  catch (BESError &e) {
430  string err = string("FAILED: ") + e.get_message();
431  cerr << err << endl;
432  LOG(err << endl);
433  exit(SERVER_EXIT_FATAL_CANNOT_START);
434  }
435  if (isSecure == "Yes" || isSecure == "YES" || isSecure == "yes") {
436  _secure = true;
437  }
438  }
439 
440  BESDEBUG("beslistener", "beslistener: initializing default module ... " << endl);
441  BESDefaultModule::initialize(argc, argv);
442  BESDEBUG("beslistener", "beslistener: done initializing default module" << endl);
443 
444  BESDEBUG("beslistener", "beslistener: initializing default commands ... " << endl);
446  BESDEBUG("beslistener", "beslistener: done initializing default commands" << endl);
447 
448  // This will load and initialize all of the modules
449  BESDEBUG("beslistener", "beslistener: initializing loaded modules ... " << endl);
450  int ret = BESModuleApp::initialize(argc, argv);
451  BESDEBUG("beslistener", "beslistener: done initializing loaded modules" << endl);
452 
453  BESDEBUG("beslistener", "beslistener: initialized settings:" << *this);
454 
455  if (needhelp) {
456  BESServerUtils::show_usage(BESApp::TheApplication()->appName());
457  }
458 
459  // This sets the process group to be ID of this process. All children
460  // will get this GID. Then use killpg() to send a signal to this process
461  // and all of the children.
462  session_id = setsid();
463  BESDEBUG("beslistener", "beslistener: The master beslistener session id (group id): " << session_id << endl);
464 
465  master_listener_pid = getpid();
466  BESDEBUG("beslistener", "beslistener: The master beslistener Process id: " << master_listener_pid << endl);
467 
468  return ret;
469 }
470 
472 {
473  try {
474  BESDEBUG("beslistener", "beslistener: initializing memory pool ... " << endl);
475  BESMemoryManager::initialize_memory_pool();
476  BESDEBUG("beslistener", "OK" << endl);
477 
478  SocketListener listener;
479  if (_portVal) {
480  if (!_IPVal.empty())
481  _ts = new TcpSocket(_IPVal, _portVal);
482  else
483  _ts = new TcpSocket(_portVal);
484 
485  listener.listen(_ts);
486 
487  BESDEBUG("beslistener", "beslistener: listening on port (" << _portVal << ")" << endl);
488 
489  // Write to stdout works because the besdaemon is listening on the
490  // other end of a pipe where the pipe fd[1] has been dup2'd to
491  // stdout. See daemon.cc:start_master_beslistener.
492  // NB BESLISTENER_PIPE_FD is 1 (stdout)
493  int status = BESLISTENER_RUNNING;
494  int res = write(BESLISTENER_PIPE_FD, &status, sizeof(status));
495 
496  if (res == -1) {
497  LOG("Master listener could not send status to daemon: " << strerror(errno) << endl);
498  ::exit(SERVER_EXIT_FATAL_CANNOT_START);
499  }
500  }
501 
502  if (!_unixSocket.empty()) {
503  _us = new UnixSocket(_unixSocket);
504  listener.listen(_us);
505  BESDEBUG("beslistener", "beslistener: listening on unix socket (" << _unixSocket << ")" << endl);
506  }
507 
508  BESServerHandler handler;
509 
510  _ps = new PPTServer(&handler, &listener, _secure);
511 
512  register_signal_handlers();
513 
514  // Loop forever, processing signals and running the code in PPTServer::initConnection().
515  // NB: The code in initConnection() used to loop forever, but I moved that out to here
516  // so the signal handlers could be in this class. The PPTServer::initConnection() method
517  // is also used by daemon.cc but this class (ServerApp; the beslistener) and the besdaemon
518  // need to do different things for the signals like HUP and TERM, so they cannot share
519  // the signal processing code. One fix for the problem described in ticket 2025 was to
520  // move the signal handlers into PPTServer. Changing how the 'forever' loops are organized
521  // and keeping the signal processing code here (and in daemon.cc) is another solution that
522  // preserves the correct behavior of the besdaemon, too. jhrg 3/5/14
523  while (true) {
524  block_signals();
525 
526  if (sigterm | sighup | sigchild | sigpipe) {
527  int stat;
528  pid_t cpid;
529  while ((cpid = wait4(0 /*any child in the process group*/, &stat, WNOHANG, 0/*no rusage*/)) > 0) {
530  _ps->decr_num_children();
531  if (sigpipe) {
532  LOG("Master listener caught SISPIPE from child: " << cpid << endl);
533  }
534 
535  BESDEBUG("ppt2",
536  bes_exit_message(cpid, stat) << "; num children: " << _ps->get_num_children() << endl);
537  }
538  }
539 
540  if (sighup) {
541  BESDEBUG("ppt2", "Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
542 
543  LOG("Master listener caught SIGHUP, exiting with SERVER_EXIT_RESTART" << endl);
544  ::exit(SERVER_EXIT_RESTART);
545  }
546 
547  if (sigterm) {
548  BESDEBUG("ppt2", "Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
549 
550  LOG("Master listener caught SIGTERM, exiting with SERVER_NORMAL_SHUTDOWN" << endl);
551  ::exit(SERVER_EXIT_NORMAL_SHUTDOWN);
552  }
553 
554  sigchild = 0; // Only reset this signal, all others cause an exit/restart
555  unblock_signals();
556 
557  // This is where the 'child listener' is started. This method will call
558  // BESServerHandler::handle(...) that will, in turn, fork. The child process
559  // becomes the 'child listener' that actually processes a request.
560  //
561  // This call blocks, using select(), until a client asks for another beslistener.
562  _ps->initConnection();
563  }
564 
565  _ps->closeConnection();
566  }
567  catch (BESError &se) {
568  BESDEBUG("beslistener", "beslistener: caught BESError (" << se.get_message() << ")" << endl);
569 
570  LOG(se.get_message() << endl);
571  int status = SERVER_EXIT_FATAL_CANNOT_START;
572  write(BESLISTENER_PIPE_FD, &status, sizeof(status));
573  close(BESLISTENER_PIPE_FD);
574  return 1;
575  }
576  catch (...) {
577  LOG("caught unknown exception initializing sockets" << endl);
578  int status = SERVER_EXIT_FATAL_CANNOT_START;
579  write(BESLISTENER_PIPE_FD, &status, sizeof(status));
580  close(BESLISTENER_PIPE_FD);
581  return 1;
582  }
583 
584  close(BESLISTENER_PIPE_FD);
585  return 0;
586 }
587 
589 {
590  pid_t apppid = getpid();
591  if (apppid == _mypid) {
592  // These are all safe to call in a signalhandler
593  if (_ps) {
594  _ps->closeConnection();
595  delete _ps;
596  }
597  if (_ts) {
598  _ts->close();
599  delete _ts;
600  }
601  if (_us) {
602  _us->close();
603  delete _us;
604  }
605 
606  // Do this in the reverse order that it was initialized. So
607  // terminate the loaded modules first, then the default
608  // commands, then the default module.
609 
610  // These are not safe to call in a signal handler
611  BESDEBUG("beslistener", "beslistener: terminating loaded modules ... " << endl);
613  BESDEBUG("beslistener", "beslistener: done terminating loaded modules" << endl);
614 
615  BESDEBUG("beslistener", "beslistener: terminating default commands ... " << endl);
617  BESDEBUG("beslistener", "beslistener: done terminating default commands ... " << endl);
618 
619  BESDEBUG("beslistener", "beslistener: terminating default module ... " << endl);
620  BESDefaultModule::terminate();
621  BESDEBUG("beslistener", "beslistener: done terminating default module ... " << endl);
622 
623  xmlCleanupParser();
624  }
625  return sig;
626 }
627 
634 void ServerApp::dump(ostream &strm) const
635 {
636  strm << BESIndent::LMarg << "ServerApp::dump - (" << (void *) this << ")" << endl;
637  BESIndent::Indent();
638  strm << BESIndent::LMarg << "got IP? " << _gotIP << endl;
639  strm << BESIndent::LMarg << "IP: " << _IPVal << endl;
640  strm << BESIndent::LMarg << "got port? " << _gotPort << endl;
641  strm << BESIndent::LMarg << "port: " << _portVal << endl;
642  strm << BESIndent::LMarg << "unix socket: " << _unixSocket << endl;
643  strm << BESIndent::LMarg << "is secure? " << _secure << endl;
644  strm << BESIndent::LMarg << "pid: " << _mypid << endl;
645  if (_ts) {
646  strm << BESIndent::LMarg << "tcp socket:" << endl;
647  BESIndent::Indent();
648  _ts->dump(strm);
649  BESIndent::UnIndent();
650  }
651  else {
652  strm << BESIndent::LMarg << "tcp socket: null" << endl;
653  }
654  if (_us) {
655  strm << BESIndent::LMarg << "unix socket:" << endl;
656  BESIndent::Indent();
657  _us->dump(strm);
658  BESIndent::UnIndent();
659  }
660  else {
661  strm << BESIndent::LMarg << "unix socket: null" << endl;
662  }
663  if (_ps) {
664  strm << BESIndent::LMarg << "ppt server:" << endl;
665  BESIndent::Indent();
666  _ps->dump(strm);
667  BESIndent::UnIndent();
668  }
669  else {
670  strm << BESIndent::LMarg << "ppt server: null" << endl;
671  }
672  BESModuleApp::dump(strm);
673  BESIndent::UnIndent();
674 }
675 
676 int main(int argc, char **argv)
677 {
678  try {
679  ServerApp app;
680  return app.main(argc, argv);
681  }
682  catch (BESError &e) {
683  cerr << "Caught unhandled exception: " << endl;
684  cerr << e.get_message() << endl;
685  return 1;
686  }
687  catch (...) {
688  cerr << "Caught unhandled, unknown exception" << endl;
689  return 1;
690  }
691  return 0;
692 }
693 
BESModuleApp::initialize
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
Definition: BESModuleApp.cc:69
ServerApp::run
virtual int run()
The body of the application, implementing the primary functionality of the BES application.
Definition: ServerApp.cc:471
TheBESKeys::ConfigFile
static std::string ConfigFile
Definition: TheBESKeys.h:149
PPTServer
Definition: PPTServer.h:42
BESModuleApp
Base application object for all BES applications.
Definition: BESModuleApp.h:56
BESInternalFatalError
exception thrown if an internal error is found and is fatal to the BES
Definition: BESInternalFatalError.h:43
ServerApp::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: ServerApp.cc:634
BESServerHandler
Definition: BESServerHandler.h:48
ServerApp::initialize
virtual int initialize(int argC, char **argV)
Load and initialize any BES modules.
Definition: ServerApp.cc:277
BESError::get_message
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
TcpSocket
Definition: TcpSocket.h:40
BESApp::main
virtual int main(int argC, char **argV)
main routine, the main entry point for any BES applications.
Definition: BESApp.cc:54
BESModuleApp::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESModuleApp.cc:242
BESModuleApp::terminate
virtual int terminate(int sig=0)
clean up after the application
Definition: BESModuleApp.cc:201
BESDebug::SetUp
static void SetUp(const std::string &values)
Sets up debugging for the bes.
Definition: BESDebug.cc:64
TheBESKeys::TheKeys
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:62
BESApp::TheApplication
static BESApp * TheApplication(void)
Returns the BESApp application object for this application.
Definition: BESApp.h:137
UnixSocket
Definition: UnixSocket.h:42
BESDebug::Register
static void Register(const std::string &flagName)
register the specified debug flag
Definition: BESDebug.h:138
BESXMLDefaultCommands::terminate
static int terminate(void)
Removes the default set of BES XML commands from the list of possible commands.
Definition: BESXMLDefaultCommands.cc:130
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
ServerApp
Definition: ServerApp.h:41
ServerApp::terminate
virtual int terminate(int sig=0)
clean up after the application
Definition: ServerApp.cc:588
TheBESKeys::get_value
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: TheBESKeys.cc:272
SocketListener
Definition: SocketListener.h:42
BESError
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
BESXMLDefaultCommands::initialize
static int initialize(int argc, char **argv)
Loads the default set of BES XML commands.
Definition: BESXMLDefaultCommands.cc:73