bes  Updated for version 3.17.0
BESInterface.cc
1 // BESInterface.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 "config.h"
34 
35 #include <cstdlib>
36 
37 #include <signal.h>
38 #if HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41 
42 #include <setjmp.h> // Used for the timeout processing
43 
44 #include <string>
45 #include <sstream>
46 #include <iostream>
47 
48 #include "BESInterface.h"
49 
50 #include "TheBESKeys.h"
51 #include "BESResponseHandler.h"
52 #include "BESAggFactory.h"
53 #include "BESAggregationServer.h"
54 #include "BESReporterList.h"
55 #include "BESContextManager.h"
56 
57 #include "BESExceptionManager.h"
58 
59 #include "BESDataNames.h"
60 
61 #include "BESDebug.h"
62 #include "BESStopWatch.h"
63 #include "BESTimeoutError.h"
64 #include "BESInternalError.h"
65 #include "BESInternalFatalError.h"
66 
67 #include "BESLog.h"
68 
69 using namespace std;
70 
71 list<p_bes_init> BESInterface::_init_list;
72 list<p_bes_end> BESInterface::_end_list;
73 
74 static jmp_buf timeout_jump;
75 static bool timeout_jump_valid = false;
76 
77 // Define this to use sigwait() is a child thread to detect that SIGALRM
78 // has been raised (i.e., that the timeout interval has elapsed). This
79 // does not currently work, but could be a way to get information about
80 // a timeout back to the BES's client if the BES itslef were structured
81 // differently. See my comment further down. jhrg 12/28/15
82 #undef USE_SIGWAIT
83 
84 // timeout period in seconds; 0 --> no timeout. This is a static value so
85 // that it can be accessed by the signal handler. jhrg 1/4/16
86 static volatile int timeout = 0;
87 
88 #define BES_TIMEOUT_KEY "BES.TimeOutInSeconds"
89 
90 static void catch_sig_alarm(int sig)
91 {
92  if (sig == SIGALRM) {
93  LOG("Child listener timeout after " << timeout << " seconds, exiting." << endl);
94 
95  // Causes setjmp() below to return 1; see the call to
96  // execute_data_request_plan() in execute_request() below.
97  // jhrg 12/29/15
98  if (timeout_jump_valid)
99  longjmp(timeout_jump, 1);
100  else {
101  // This is the old version of this code; it forces the BES child
102  // listener to exit without returning an error message to the
103  // OLFS/client. jhrg 12/29/15
104  signal(SIGTERM, SIG_DFL);
105  raise(SIGTERM);
106  }
107  }
108 }
109 
110 static void register_signal_handler()
111 {
112  struct sigaction act;
113  sigemptyset(&act.sa_mask);
114  sigaddset(&act.sa_mask, SIGALRM);
115  act.sa_flags = 0;
116 
117  // Note that we do not set SA_RESTART so an interrupted system call
118  // will return with an error and errno set to EINTR.
119 
120  act.sa_handler = catch_sig_alarm;
121  if (sigaction(SIGALRM, &act, 0))
122  throw BESInternalFatalError("Could not register a handler to catch alarm/timeout.", __FILE__, __LINE__);
123 }
124 
125 #if USE_SIGWAIT
126 
127 // If the BES is changed so that the plan build here is run in a child thread,
128 // then we can have a much more flexible signal catching scheme, including catching
129 // the alarm signal used for the timeout. It's not possible to throw from a child
130 // thread to a parent thread, but if the parent thread sees that SIGALRM is
131 // raised, then it can stop the child thread (which is running the 'plan') and
132 // return a suitable message to the front end. Similarly, the BES could also
133 // handle a number of other signals using this scheme. These signals (SIGPIPE, ...)
134 // are currently processed using while/for loop(s) in the bes/server code. It may
135 // be that these signals are caught only in the master listener, but I can't
136 // quite figure that out now... jhrg 12/28/15
137 //
138 // NB: It might be possible to edit this so that it writes info to the OLFS and
139 // then uses the 'raise SIGTERM' technique to exit. That way the OLFS will at least
140 // get a message about the timeout. I'm not sure how to close up the PPT part
141 // of the conversation, however. The idea would be that the current command's DHI
142 // would be passed in as an arg and then the stream accessed that way. The BESError
143 // would be written to the stream and the child process killed. jhrg 12/2/9/15
144 
145 #include <pthread.h>
146 
147 // An alternative to a function that catches the signal; use sigwait()
148 // in a child thread after marking the signal as blocked. When/if sigwait()
149 // returns, look at the signal number and if it is the alarm, sort out
150 // what to do (throw an exception, ...). NB: A signal handler cannot
151 // portably throw an exception, but this code can.
152 
153 static pthread_t alarm_thread;
154 
155 static void* alarm_wait(void * /* arg */)
156 {
157  BESDEBUG("bes", "Starting: " << __PRETTY_FUNCTION__ << endl);
158 
159  // block SIGALRM
160  sigset_t sigset;
161  sigemptyset(&sigset);
162  sigaddset(&sigset, SIGALRM);
163  sigprocmask(SIG_BLOCK, &sigset, NULL);
164 
165  // Might replace this with a while loop. Not sure about interactions
166  // with other signal processing code in the BES. jhrg 12/28/15
167  int sig;
168  int result = sigwait(&sigset, &sig);
169  if (result != 0) {
170  BESDEBUG("bes", "Fatal error establishing timeout: " << strerror(result) << endl);
171  throw BESInternalFatalError(string("Fatal error establishing timeout: ") + strerror(result), __FILE__, __LINE__);
172  }
173  else if (result == 0 && sig == SIGALRM) {
174  BESDEBUG("bes", "Timeout found in " << __PRETTY_FUNCTION__ << endl);
175  throw BESTimeoutError("Timeout", __FILE__, __LINE__);
176  }
177  else {
178  stringstream oss;
179  oss << "While waiting for a timeout, found signal '" << result << "' in " << __PRETTY_FUNCTION__ << ends;
180  BESDEBUG("bes", oss.str() << endl);
181  throw BESInternalFatalError(oss.str(), __FILE__, __LINE__);
182  }
183 }
184 
185 static void wait_for_timeout()
186 {
187  BESDEBUG("bes", "Entering: " << __PRETTY_FUNCTION__ << endl);
188 
189  pthread_attr_t thread_attr;
190 
191  if (pthread_attr_init(&thread_attr) != 0)
192  throw BESInternalFatalError("Failed to initialize pthread attributes.", __FILE__, __LINE__);
193  if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED /*PTHREAD_CREATE_JOINABLE*/) != 0)
194  throw BESInternalFatalError("Failed to complete pthread attribute initialization.", __FILE__, __LINE__);
195 
196  int status = pthread_create(&alarm_thread, &thread_attr, alarm_wait, NULL);
197  if (status != 0)
198  throw BESInternalFatalError("Failed to start the timeout wait thread.", __FILE__, __LINE__);
199 }
200 #endif
201 
202 BESInterface::BESInterface(ostream *output_stream) :
203  _strm(output_stream), _timeout_from_keys(0), _dhi(0), _transmitter(0)
204 {
205  if (!output_stream) {
206  throw BESInternalError("output stream must be set in order to output responses", __FILE__, __LINE__);
207  }
208 
209  // Grab the BES Key for the timeout. Note that the Hyrax server generally
210  // overrides this value using a 'context' that is set/sent by the OLFS.
211  // Also note that a value of zero means no timeout, but that the context
212  // with override that too. jhrg 1/4/16
213  bool found;
214  string timeout_key_value;
215  TheBESKeys::TheKeys()->get_value(BES_TIMEOUT_KEY, timeout_key_value, found);
216  if (found) {
217  istringstream iss(timeout_key_value);
218  iss >> _timeout_from_keys;
219  }
220 
221  // Install signal handler for alarm() here
222  register_signal_handler();
223 
224 #if USE_SIGWAIT
225  wait_for_timeout();
226 #endif
227 }
228 
229 BESInterface::~BESInterface()
230 {
231 }
232 
271 extern BESStopWatch *bes_timing::elapsedTimeToReadStart;
272 extern BESStopWatch *bes_timing::elapsedTimeToTransmitStart;
273 
274 int BESInterface::execute_request(const string &from)
275 {
276  BESDEBUG("bes", "Entering: " << __PRETTY_FUNCTION__ << endl);
277 
278  if (!_dhi) {
279  throw BESInternalError("DataHandlerInterface can not be null", __FILE__, __LINE__);
280  }
281 
282  BESStopWatch sw;
283  if (BESISDEBUG(TIMING_LOG)) {
284  sw.start("BESInterface::execute_request", _dhi->data[REQUEST_ID]);
285 
286  bes_timing::elapsedTimeToReadStart = new BESStopWatch();
287  bes_timing::elapsedTimeToReadStart->start("TIME_TO_READ_START", _dhi->data[REQUEST_ID]);
288 
289  bes_timing::elapsedTimeToTransmitStart = new BESStopWatch();
290  bes_timing::elapsedTimeToTransmitStart->start("TIME_TO_TRANSMIT_START", _dhi->data[REQUEST_ID]);
291  }
292 
293  if (!_dhi) {
294  throw BESInternalError("DataHandlerInterface can not be null", __FILE__, __LINE__);
295  }
296 
297  _dhi->set_output_stream(_strm);
298  _dhi->data[REQUEST_FROM] = from;
299 
300  pid_t thepid = getpid();
301  ostringstream ss;
302  ss << thepid;
303  _dhi->data[SERVER_PID] = ss.str();
304 
305  // This is never used except as an arg to finish. jhrg 12/23/15
306  //int status = 0;
307 
308  // We split up the calls for the reason that if we catch an
309  // exception during the initialization, building, execution, or response
310  // transmit of the request then we can transmit the exception/error
311  // information.
312  try {
313  initialize();
314 
315  *(BESLog::TheLog()) << _dhi->data[SERVER_PID] << " from " << _dhi->data[REQUEST_FROM] << " request received"
316  << endl;
317 
318  // This does not do anything here or in BESBasicInterface or BESXMLInterface.
319  // Remove it? jhrg 12/23/15
320  validate_data_request();
321 
322  build_data_request_plan();
323 
324  if (!_transmitter)
325  throw BESInternalError("Unable to transmit the response, no transmitter", __FILE__, __LINE__);
326 
327  // This method does two key things: Calls the request handler to make a
328  // 'response object' (the C++ object that will hold the response) and
329  // then calls the transmitter to actually send it or build and send it.
330  //
331  // The timeout is also set in execute_data_request_plan(). The alarm signal
332  // handler (above), run when the timeout expires, will call longjmp with a
333  // return value of 1.
334  if (setjmp(timeout_jump) == 0) {
335  timeout_jump_valid = true;
336  execute_data_request_plan();
337  // Once we exit the block where setjmp() was called, the jump_buf is not valid
338  timeout_jump_valid = false;
339  }
340  else {
341  ostringstream oss;
342  oss << "BES listener timeout after " << timeout << " seconds." << ends;
343  throw BESTimeoutError(oss.str(), __FILE__, __LINE__);
344  }
345 
346  _dhi->executed = true;
347  }
348  catch (BESError & ex) {
349  timeout_jump_valid = false;
350  return exception_manager(ex);
351  }
352  catch (bad_alloc &e) {
353  timeout_jump_valid = false;
354  BESInternalFatalError ex(string("BES out of memory: ") + e.what(), __FILE__, __LINE__);
355  return exception_manager(ex);
356  }
357  catch (exception &e) {
358  timeout_jump_valid = false;
359  BESInternalFatalError ex(string("C++ Exception: ") + e.what(), __FILE__, __LINE__);
360  return exception_manager(ex);
361  }
362  catch (...) {
363  timeout_jump_valid = false;
364  BESInternalError ex("An undefined exception has been thrown", __FILE__, __LINE__);
365  return exception_manager(ex);
366  }
367 
368  delete bes_timing::elapsedTimeToReadStart;
369  bes_timing::elapsedTimeToReadStart = 0;
370 
371  delete bes_timing::elapsedTimeToTransmitStart;
372  bes_timing::elapsedTimeToTransmitStart = 0;
373 
374  return finish(0 /* status */);;
375 }
376 
377 // I think this code was written when execute_request() called transmit_data()
378 // (and invoke_aggregation()). I think that the code up to the log_status()
379 // call is redundant. This means that so is the param 'status'. jhrg 12/23/15
380 int BESInterface::finish(int /*status*/)
381 {
382  BESDEBUG("bes", "Entering: " << __PRETTY_FUNCTION__ << " ***" << endl);
383 
384 #if 0
385  int status = 0;
386  try {
387  // if there was an error during initialization, validation,
388  // execution or transmit of the response then we need to transmit
389  // the error information. Once printed, delete the error
390  // information since we are done with it.
391  if (_dhi->error_info) {
392  transmit_data();
393  delete _dhi->error_info;
394  _dhi->error_info = 0;
395  }
396  }
397  catch (BESError &ex) {
398  status = exception_manager(ex);
399  }
400  catch (bad_alloc &) {
401  string serr = "BES out of memory";
402  BESInternalFatalError ex(serr, __FILE__, __LINE__);
403  status = exception_manager(ex);
404  }
405  catch (...) {
406  string serr = "An undefined exception has been thrown";
407  BESInternalError ex(serr, __FILE__, __LINE__);
408  status = exception_manager(ex);
409  }
410 #endif
411 
412  // If there is error information then the transmit of the error failed,
413  // print it to standard out. Once printed, delete the error
414  // information since we are done with it.
415  if (_dhi->error_info) {
416  _dhi->error_info->print(cout);
417  delete _dhi->error_info;
418  _dhi->error_info = 0;
419  }
420 
421  // if there is a problem with the rest of these steps then all we will
422  // do is log it to the BES log file and not handle the exception with
423  // the exception manager.
424  try {
425  log_status();
426  }
427  catch (BESError &ex) {
428  (*BESLog::TheLog()) << "Problem logging status: " << ex.get_message() << endl;
429  }
430  catch (...) {
431  (*BESLog::TheLog()) << "Unknown problem logging status" << endl;
432  }
433 
434  try {
435  report_request();
436  }
437  catch (BESError &ex) {
438  (*BESLog::TheLog()) << "Problem reporting request: " << ex.get_message() << endl;
439  }
440  catch (...) {
441  (*BESLog::TheLog()) << "Unknown problem reporting request" << endl;
442  }
443 
444  try {
445  end_request();
446  }
447  catch (BESError &ex) {
448  (*BESLog::TheLog()) << "Problem ending request: " << ex.get_message() << endl;
449  }
450  catch (...) {
451  (*BESLog::TheLog()) << "Unknown problem ending request" << endl;
452  }
453 
454  return 0/*status*/;
455 }
456 
457 int BESInterface::finish_with_error(int status)
458 {
459  if (!_dhi->error_info) {
460  // there wasn't an error ... so now what?
461  string serr = "Finish_with_error called with no error object";
462  BESInternalError ex(serr, __FILE__, __LINE__);
463  status = exception_manager(ex);
464  }
465 
466  return finish(status);
467 }
468 
469 void BESInterface::add_init_callback(p_bes_init init)
470 {
471  _init_list.push_back(init);
472 }
473 
480 {
481  BESStopWatch sw;
482  if (BESISDEBUG(TIMING_LOG)) sw.start("BESInterface::initialize", _dhi->data[REQUEST_ID]);
483 
484  BESDEBUG("bes", "Initializing request: " << _dhi->data[DATA_REQUEST] << " ... " << endl);
485  bool do_continue = true;
486  init_iter i = _init_list.begin();
487 
488  for (; i != _init_list.end() && do_continue == true; i++) {
489  p_bes_init p = *i;
490  do_continue = p(*_dhi);
491  }
492 
493  if (!do_continue) {
494  BESDEBUG("bes", "FAILED" << endl);
495  string se = "Initialization callback failed, exiting";
496  throw BESInternalError(se, __FILE__, __LINE__);
497  }
498  else {
499  BESDEBUG("bes", "OK" << endl);
500  }
501 }
502 
506 {
507 }
508 
526 {
527  BESStopWatch sw;
528  if (BESISDEBUG(TIMING_LOG))
529  sw.start("BESInterface::execute_data_request_plan(\"" + _dhi->data[DATA_REQUEST] + "\")",
530  _dhi->data[REQUEST_ID]);
531 
532  // Set timeout if the 'bes_timeout' context value was passed in with the
533  // command.
534  bool found = false;
535  string context = BESContextManager::TheManager()->get_context("bes_timeout", found);
536  if (found) {
537  timeout = strtol(context.c_str(), NULL, 10);
538  VERBOSE("Set request timeout to " << timeout << " seconds (from context)." << endl);
539  alarm(timeout);
540  }
541  else if (_timeout_from_keys != 0) {
542  timeout = _timeout_from_keys;
543  VERBOSE("Set request timeout to " << timeout << " seconds (from keys)." << endl);
544  alarm(timeout);
545  }
546 
547 
548  BESDEBUG("bes", "Executing request: " << _dhi->data[DATA_REQUEST] << " ... " << endl);
549  BESResponseHandler *rh = _dhi->response_handler;
550  if (rh) {
551  rh->execute(*_dhi);
552  }
553  else {
554  BESDEBUG("bes", "FAILED" << endl);
555  string se = "The response handler \"" + _dhi->action + "\" does not exist";
556  throw BESInternalError(se, __FILE__, __LINE__);
557  }
558  BESDEBUG("bes", "OK" << endl);
559 
560  // Now we need to do the post processing piece of executing the request
561  invoke_aggregation();
562 
563  // And finally, transmit the response of this request
564  transmit_data();
565 
566  // Only clear the timeout if it has been set.
567  if (timeout != 0) {
568  timeout = 0;
569  alarm(0);
570  }
571 }
572 
576 {
577  BESStopWatch sw;
578  if (BESISDEBUG(TIMING_LOG)) sw.start("BESInterface::invoke_aggregation", _dhi->data[REQUEST_ID]);
579 
580  if (_dhi->data[AGG_CMD] != "") {
581  BESDEBUG("bes", "aggregating with: " << _dhi->data[AGG_CMD] << " ... "<< endl);
582  BESAggregationServer *agg = BESAggFactory::TheFactory()->find_handler(_dhi->data[AGG_HANDLER]);
583  if (agg) {
584  agg->aggregate(*_dhi);
585  }
586  else {
587  BESDEBUG("bes", "FAILED" << endl);
588  string se = "The aggregation handler " + _dhi->data[AGG_HANDLER] + "does not exist";
589  throw BESInternalError(se, __FILE__, __LINE__);
590  }
591  BESDEBUG("bes", "OK" << endl);
592  }
593 }
594 
609 {
610  BESStopWatch sw;
611  if (BESISDEBUG(TIMING_LOG)) sw.start("BESInterface::transmit_data", _dhi->data[REQUEST_ID]);
612 
613  BESDEBUG("bes", "BESInterface::transmit_data() - Transmitting request: " << _dhi->data[DATA_REQUEST] << endl);
614 #if 0
615  if (_transmitter) {
616 #endif
617  if (_dhi->error_info) {
618  ostringstream strm;
619  _dhi->error_info->print(strm);
620  (*BESLog::TheLog()) << strm.str() << endl;
621  BESDEBUG("bes", " transmitting error info using transmitter ... " << endl << strm.str() << endl);
622 
623  _dhi->error_info->transmit(_transmitter, *_dhi);
624  }
625  else if (_dhi->response_handler) {
626  BESDEBUG("bes", " BESInterface::transmit_data() - Response handler " << _dhi->response_handler->get_name() << endl);
627 
628  _dhi->response_handler->transmit(_transmitter, *_dhi);
629  }
630 #if 0
631  }
632  else {
633 
634  if (_dhi->error_info) {
635  BESDEBUG("bes", "BESInterface::transmit_data() - Transmitting error info using cout ... " << endl);
636  _dhi->error_info->print(cout);
637  delete _dhi->error_info;
638  _dhi->error_info = 0;
639  }
640  else {
641  BESDEBUG("bes", "BESInterface::transmit_data() - Unable to transmit the response ... FAILED " << endl);
642  //string err = ;
643  throw BESInternalError("Unable to transmit the response, no transmitter", __FILE__, __LINE__);
644  }
645  }
646 #endif
647 
648  BESDEBUG("bes", "BESInterface::transmit_data() - OK" << endl);
649 }
650 
654 {
655 }
656 
669 {
670  BESDEBUG("bes", "Reporting on request: " << _dhi->data[DATA_REQUEST] << " ... " << endl);
671 
672  BESReporterList::TheList()->report(*_dhi);
673 
674  BESDEBUG("bes", "OK" << endl);
675 }
676 
677 void BESInterface::add_end_callback(p_bes_end end)
678 {
679  _end_list.push_back(end);
680 }
681 
688 {
689  BESDEBUG("bes", "Ending request: " << _dhi->data[DATA_REQUEST] << " ... " << endl);
690  end_iter i = _end_list.begin();
691  for (; i != _end_list.end(); i++) {
692  p_bes_end p = *i;
693  p(*_dhi);
694  }
695 
696  // now clean up any containers that were used in the request, release
697  // the resource
698  _dhi->first_container();
699  while (_dhi->container) {
700  BESDEBUG("bes", "Calling BESContainer::release()" << endl);
701  _dhi->container->release();
702  _dhi->next_container();
703  }
704 
705  BESDEBUG("bes", "OK" << endl);
706 }
707 
711 {
712  if (_dhi) _dhi->clean();
713 }
714 
728 {
729  return BESExceptionManager::TheEHM()->handle_exception(e, *_dhi);
730 }
731 
740 void BESInterface::dump(ostream & strm) const
741 {
742  strm << BESIndent::LMarg << "BESInterface::dump - (" << (void *) this << ")" << endl;
743  BESIndent::Indent();
744 
745  if (_init_list.size()) {
746  strm << BESIndent::LMarg << "termination functions:" << endl;
747  BESIndent::Indent();
748  init_iter i = _init_list.begin();
749  for (; i != _init_list.end(); i++) {
750  // TODO ISO C++ forbids casting between pointer-to-function and pointer-to-object
751  // ...also below
752  strm << BESIndent::LMarg << (void *) (*i) << endl;
753  }
754  BESIndent::UnIndent();
755  }
756  else {
757  strm << BESIndent::LMarg << "termination functions: none" << endl;
758  }
759 
760  if (_end_list.size()) {
761  strm << BESIndent::LMarg << "termination functions:" << endl;
762  BESIndent::Indent();
763  end_iter i = _end_list.begin();
764  for (; i != _end_list.end(); i++) {
765  strm << BESIndent::LMarg << (void *) (*i) << endl;
766  }
767  BESIndent::UnIndent();
768  }
769  else {
770  strm << BESIndent::LMarg << "termination functions: none" << endl;
771  }
772 
773  strm << BESIndent::LMarg << "data handler interface:" << endl;
774  BESIndent::Indent();
775  _dhi->dump(strm);
776  BESIndent::UnIndent();
777 
778  if (_transmitter) {
779  strm << BESIndent::LMarg << "transmitter:" << endl;
780  BESIndent::Indent();
781  _transmitter->dump(strm);
782  BESIndent::UnIndent();
783  }
784  else {
785  strm << BESIndent::LMarg << "transmitter: not set" << endl;
786  }
787  BESIndent::UnIndent();
788 }
error thrown if there is a user syntax error in the request or any other user error ...
exception thrown if an internal error is found and is fatal to the BES
exception thrown if inernal error encountered
virtual void initialize()
Initialize the BES object.
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:97
virtual void execute(BESDataHandlerInterface &dhi)=0
knows how to build a requested response object
STL namespace.
virtual int exception_manager(BESError &e)
Manage any exceptions thrown during the whole process.
virtual void aggregate(BESDataHandlerInterface &dhi)=0
aggregate the response object
virtual string get_context(const string &name, bool &found)
retrieve the value of the specified context from the BES
virtual bool start(string name)
Definition: BESStopWatch.cc:57
virtual void transmit_data()
Transmit the resulting response object.
handler object that knows how to create a specific response object
Abstract exception class for the BES with basic string message.
Definition: BESError.h:56
virtual void report_request()
Report the request and status of the request to BESReporterList::TheList()
virtual void validate_data_request()
Validate the incoming request information.
virtual void clean()
Clean up after the request.
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: BESKeys.cc:481
virtual void invoke_aggregation()
Aggregate the resulting response object.
virtual void end_request()
End the BES request.
virtual void dump(ostream &strm) const
dumps information about this object
virtual BESAggregationServer * find_handler(const string &handler_name)
returns the aggregation handler with the given name in the list
virtual void log_status()
Log the status of the request.
virtual int handle_exception(BESError &e, BESDataHandlerInterface &dhi)
Manage any exceptions thrown during the handling of a request.
Abstraction representing mechanism for aggregating data.
virtual void execute_data_request_plan()
Execute the data request plan.
static BESKeys * TheKeys()
Definition: TheBESKeys.cc:43