bes  Updated for version 3.17.1
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 // This function uses the static variables timeout_jump_valid and timeout_jump
91 // The code looks at the value of BES.TimeOutInSeconds and/or the timeout
92 // context sent in the current request and, if that is greater than zero,
93 // uses that as the maximum amount of time for the request. The system alarm
94 // is set and this function is registered as the handler. If timeout_jump_valid
95 // is true, then it will use longjmp() (yes, really...) to end the request. Look
96 // below in execute_request() for the call to setjump() to see how this works.
97 // See the SIGWAIT code that's commented out below for an alternative impl.
98 // jhrg 5/31/16
99 static void catch_sig_alarm(int sig)
100 {
101  if (sig == SIGALRM) {
102  LOG("Child listener timeout after " << timeout << " seconds, exiting." << endl);
103 
104  // Causes setjmp() below to return 1; see the call to
105  // execute_data_request_plan() in execute_request() below.
106  // jhrg 12/29/15
107  if (timeout_jump_valid)
108  longjmp(timeout_jump, 1);
109  else {
110  // This is the old version of this code; it forces the BES child
111  // listener to exit without returning an error message to the
112  // OLFS/client. jhrg 12/29/15
113  signal(SIGTERM, SIG_DFL);
114  raise(SIGTERM);
115  }
116  }
117 }
118 
119 static void register_signal_handler()
120 {
121  struct sigaction act;
122  sigemptyset(&act.sa_mask);
123  sigaddset(&act.sa_mask, SIGALRM);
124  act.sa_flags = 0;
125 
126  // Note that we do not set SA_RESTART so an interrupted system call
127  // will return with an error and errno set to EINTR.
128 
129  act.sa_handler = catch_sig_alarm;
130  if (sigaction(SIGALRM, &act, 0))
131  throw BESInternalFatalError("Could not register a handler to catch alarm/timeout.", __FILE__, __LINE__);
132 }
133 
134 #if USE_SIGWAIT
135 
136 // If the BES is changed so that the plan built here is run in a child thread,
137 // then we can have a much more flexible signal catching scheme, including catching
138 // the alarm signal used for the timeout. It's not possible to throw from a child
139 // thread to a parent thread, but if the parent thread sees that SIGALRM is
140 // raised, then it can stop the child thread (which is running the 'plan') and
141 // return a suitable message to the front end. Similarly, the BES could also
142 // handle a number of other signals using this scheme. These signals (SIGPIPE, ...)
143 // are currently processed using while/for loop(s) in the bes/server code. It may
144 // be that these signals are caught only in the master listener, but I can't
145 // quite figure that out now... jhrg 12/28/15
146 //
147 // NB: It might be possible to edit this so that it writes info to the OLFS and
148 // then uses the 'raise SIGTERM' technique to exit. That way the OLFS will at least
149 // get a message about the timeout. I'm not sure how to close up the PPT part
150 // of the conversation, however. The idea would be that the current command's DHI
151 // would be passed in as an arg and then the stream accessed that way. The BESError
152 // would be written to the stream and the child process killed. jhrg 12/2/9/15
153 
154 #include <pthread.h>
155 
156 // An alternative to a function that catches the signal; use sigwait()
157 // in a child thread after marking the signal as blocked. When/if sigwait()
158 // returns, look at the signal number and if it is the alarm, sort out
159 // what to do (throw an exception, ...). NB: A signal handler cannot
160 // portably throw an exception, but this code can.
161 
162 static pthread_t alarm_thread;
163 
164 static void* alarm_wait(void * /* arg */)
165 {
166  BESDEBUG("bes", "Starting: " << __PRETTY_FUNCTION__ << endl);
167 
168  // block SIGALRM
169  sigset_t sigset;
170  sigemptyset(&sigset);
171  sigaddset(&sigset, SIGALRM);
172  sigprocmask(SIG_BLOCK, &sigset, NULL);
173 
174  // Might replace this with a while loop. Not sure about interactions
175  // with other signal processing code in the BES. jhrg 12/28/15
176  int sig;
177  int result = sigwait(&sigset, &sig);
178  if (result != 0) {
179  BESDEBUG("bes", "Fatal error establishing timeout: " << strerror(result) << endl);
180  throw BESInternalFatalError(string("Fatal error establishing timeout: ") + strerror(result), __FILE__, __LINE__);
181  }
182  else if (result == 0 && sig == SIGALRM) {
183  BESDEBUG("bes", "Timeout found in " << __PRETTY_FUNCTION__ << endl);
184  throw BESTimeoutError("Timeout", __FILE__, __LINE__);
185  }
186  else {
187  stringstream oss;
188  oss << "While waiting for a timeout, found signal '" << result << "' in " << __PRETTY_FUNCTION__ << ends;
189  BESDEBUG("bes", oss.str() << endl);
190  throw BESInternalFatalError(oss.str(), __FILE__, __LINE__);
191  }
192 }
193 
194 static void wait_for_timeout()
195 {
196  BESDEBUG("bes", "Entering: " << __PRETTY_FUNCTION__ << endl);
197 
198  pthread_attr_t thread_attr;
199 
200  if (pthread_attr_init(&thread_attr) != 0)
201  throw BESInternalFatalError("Failed to initialize pthread attributes.", __FILE__, __LINE__);
202  if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED /*PTHREAD_CREATE_JOINABLE*/) != 0)
203  throw BESInternalFatalError("Failed to complete pthread attribute initialization.", __FILE__, __LINE__);
204 
205  int status = pthread_create(&alarm_thread, &thread_attr, alarm_wait, NULL);
206  if (status != 0)
207  throw BESInternalFatalError("Failed to start the timeout wait thread.", __FILE__, __LINE__);
208 }
209 #endif
210 
211 BESInterface::BESInterface(ostream *output_stream) :
212  _strm(output_stream), _timeout_from_keys(0), _dhi(0), _transmitter(0)
213 {
214  if (!output_stream) {
215  throw BESInternalError("output stream must be set in order to output responses", __FILE__, __LINE__);
216  }
217 
218  // Grab the BES Key for the timeout. Note that the Hyrax server generally
219  // overrides this value using a 'context' that is set/sent by the OLFS.
220  // Also note that a value of zero means no timeout, but that the context
221  // can override that too. jhrg 1/4/16
222  bool found;
223  string timeout_key_value;
224  TheBESKeys::TheKeys()->get_value(BES_TIMEOUT_KEY, timeout_key_value, found);
225  if (found) {
226  istringstream iss(timeout_key_value);
227  iss >> _timeout_from_keys;
228  }
229 
230  // Install signal handler for alarm() here
231  register_signal_handler();
232 
233 #if USE_SIGWAIT
234  wait_for_timeout();
235 #endif
236 }
237 
238 BESInterface::~BESInterface()
239 {
240 }
241 
280 extern BESStopWatch *bes_timing::elapsedTimeToReadStart;
281 extern BESStopWatch *bes_timing::elapsedTimeToTransmitStart;
282 
283 int BESInterface::execute_request(const string &from)
284 {
285  BESDEBUG("bes", "Entering: " << __PRETTY_FUNCTION__ << endl);
286 
287  if (!_dhi) {
288  throw BESInternalError("DataHandlerInterface can not be null", __FILE__, __LINE__);
289  }
290 
291  BESStopWatch sw;
292  if (BESISDEBUG(TIMING_LOG)) {
293  sw.start("BESInterface::execute_request", _dhi->data[REQUEST_ID]);
294 
295  bes_timing::elapsedTimeToReadStart = new BESStopWatch();
296  bes_timing::elapsedTimeToReadStart->start("TIME_TO_READ_START", _dhi->data[REQUEST_ID]);
297 
298  bes_timing::elapsedTimeToTransmitStart = new BESStopWatch();
299  bes_timing::elapsedTimeToTransmitStart->start("TIME_TO_TRANSMIT_START", _dhi->data[REQUEST_ID]);
300  }
301 
302  if (!_dhi) {
303  throw BESInternalError("DataHandlerInterface can not be null", __FILE__, __LINE__);
304  }
305 
306  _dhi->set_output_stream(_strm);
307  _dhi->data[REQUEST_FROM] = from;
308 
309  pid_t thepid = getpid();
310  ostringstream ss;
311  ss << thepid;
312  _dhi->data[SERVER_PID] = ss.str();
313 
314  // This is never used except as an arg to finish. jhrg 12/23/15
315  //int status = 0;
316 
317  // We split up the calls for the reason that if we catch an
318  // exception during the initialization, building, execution, or response
319  // transmit of the request then we can transmit the exception/error
320  // information.
321  try {
322  initialize();
323 
324  *(BESLog::TheLog()) << _dhi->data[SERVER_PID] << " from " << _dhi->data[REQUEST_FROM] << " request received"
325  << endl;
326 
327  // This does not do anything here or in BESBasicInterface or BESXMLInterface.
328  // Remove it? jhrg 12/23/15
329  validate_data_request();
330 
331  build_data_request_plan();
332 
333  if (!_transmitter)
334  throw BESInternalError("Unable to transmit the response, no transmitter", __FILE__, __LINE__);
335 
336  // This method does two key things: Calls the request handler to make a
337  // 'response object' (the C++ object that will hold the response) and
338  // then calls the transmitter to actually send it or build and send it.
339  //
340  // The timeout is also set in execute_data_request_plan(). The alarm signal
341  // handler (above), run when the timeout expires, will call longjmp with a
342  // return value of 1.
343  if (setjmp(timeout_jump) == 0) {
344  timeout_jump_valid = true;
345  execute_data_request_plan();
346  // Once we exit the block where setjmp() was called, the jump_buf is not valid
347  timeout_jump_valid = false;
348  }
349  else {
350  ostringstream oss;
351  oss << "BES listener timeout after " << timeout << " seconds." << ends;
352  throw BESTimeoutError(oss.str(), __FILE__, __LINE__);
353  }
354 
355  _dhi->executed = true;
356  }
357  catch (BESError & ex) {
358  timeout_jump_valid = false;
359  return exception_manager(ex);
360  }
361  catch (bad_alloc &e) {
362  timeout_jump_valid = false;
363  BESInternalFatalError ex(string("BES out of memory: ") + e.what(), __FILE__, __LINE__);
364  return exception_manager(ex);
365  }
366  catch (exception &e) {
367  timeout_jump_valid = false;
368  BESInternalFatalError ex(string("C++ Exception: ") + e.what(), __FILE__, __LINE__);
369  return exception_manager(ex);
370  }
371  catch (...) {
372  timeout_jump_valid = false;
373  BESInternalError ex("An undefined exception has been thrown", __FILE__, __LINE__);
374  return exception_manager(ex);
375  }
376 
377  delete bes_timing::elapsedTimeToReadStart;
378  bes_timing::elapsedTimeToReadStart = 0;
379 
380  delete bes_timing::elapsedTimeToTransmitStart;
381  bes_timing::elapsedTimeToTransmitStart = 0;
382 
383  return finish(0 /* status */);;
384 }
385 
386 // I think this code was written when execute_request() called transmit_data()
387 // (and invoke_aggregation()). I think that the code up to the log_status()
388 // call is redundant. This means that so is the param 'status'. jhrg 12/23/15
389 int BESInterface::finish(int /*status*/)
390 {
391  BESDEBUG("bes", "Entering: " << __PRETTY_FUNCTION__ << " ***" << endl);
392 
393 #if 0
394  int status = 0;
395  try {
396  // if there was an error during initialization, validation,
397  // execution or transmit of the response then we need to transmit
398  // the error information. Once printed, delete the error
399  // information since we are done with it.
400  if (_dhi->error_info) {
401  transmit_data();
402  delete _dhi->error_info;
403  _dhi->error_info = 0;
404  }
405  }
406  catch (BESError &ex) {
407  status = exception_manager(ex);
408  }
409  catch (bad_alloc &) {
410  string serr = "BES out of memory";
411  BESInternalFatalError ex(serr, __FILE__, __LINE__);
412  status = exception_manager(ex);
413  }
414  catch (...) {
415  string serr = "An undefined exception has been thrown";
416  BESInternalError ex(serr, __FILE__, __LINE__);
417  status = exception_manager(ex);
418  }
419 #endif
420 
421  // If there is error information then the transmit of the error failed,
422  // print it to standard out. Once printed, delete the error
423  // information since we are done with it.
424  if (_dhi->error_info) {
425  _dhi->error_info->print(cout);
426  delete _dhi->error_info;
427  _dhi->error_info = 0;
428  }
429 
430  // if there is a problem with the rest of these steps then all we will
431  // do is log it to the BES log file and not handle the exception with
432  // the exception manager.
433  try {
434  log_status();
435  }
436  catch (BESError &ex) {
437  (*BESLog::TheLog()) << "Problem logging status: " << ex.get_message() << endl;
438  }
439  catch (...) {
440  (*BESLog::TheLog()) << "Unknown problem logging status" << endl;
441  }
442 
443  try {
444  report_request();
445  }
446  catch (BESError &ex) {
447  (*BESLog::TheLog()) << "Problem reporting request: " << ex.get_message() << endl;
448  }
449  catch (...) {
450  (*BESLog::TheLog()) << "Unknown problem reporting request" << endl;
451  }
452 
453  try {
454  end_request();
455  }
456  catch (BESError &ex) {
457  (*BESLog::TheLog()) << "Problem ending request: " << ex.get_message() << endl;
458  }
459  catch (...) {
460  (*BESLog::TheLog()) << "Unknown problem ending request" << endl;
461  }
462 
463  return 0/*status*/;
464 }
465 
466 int BESInterface::finish_with_error(int status)
467 {
468  if (!_dhi->error_info) {
469  // there wasn't an error ... so now what?
470  string serr = "Finish_with_error called with no error object";
471  BESInternalError ex(serr, __FILE__, __LINE__);
472  status = exception_manager(ex);
473  }
474 
475  return finish(status);
476 }
477 
478 void BESInterface::add_init_callback(p_bes_init init)
479 {
480  _init_list.push_back(init);
481 }
482 
489 {
490  BESStopWatch sw;
491  if (BESISDEBUG(TIMING_LOG)) sw.start("BESInterface::initialize", _dhi->data[REQUEST_ID]);
492 
493  BESDEBUG("bes", "Initializing request: " << _dhi->data[DATA_REQUEST] << " ... " << endl);
494  bool do_continue = true;
495  init_iter i = _init_list.begin();
496 
497  for (; i != _init_list.end() && do_continue == true; i++) {
498  p_bes_init p = *i;
499  do_continue = p(*_dhi);
500  }
501 
502  if (!do_continue) {
503  BESDEBUG("bes", "FAILED" << endl);
504  string se = "Initialization callback failed, exiting";
505  throw BESInternalError(se, __FILE__, __LINE__);
506  }
507  else {
508  BESDEBUG("bes", "OK" << endl);
509  }
510 }
511 
515 {
516 }
517 
535 {
536  BESStopWatch sw;
537  if (BESISDEBUG(TIMING_LOG))
538  sw.start("BESInterface::execute_data_request_plan(\"" + _dhi->data[DATA_REQUEST] + "\")",
539  _dhi->data[REQUEST_ID]);
540 
541  // Set timeout if the 'bes_timeout' context value was passed in with the
542  // command.
543  bool found = false;
544  string context = BESContextManager::TheManager()->get_context("bes_timeout", found);
545  if (found) {
546  timeout = strtol(context.c_str(), NULL, 10);
547  VERBOSE("Set request timeout to " << timeout << " seconds (from context)." << endl);
548  alarm(timeout);
549  }
550  else if (_timeout_from_keys != 0) {
551  timeout = _timeout_from_keys;
552  VERBOSE("Set request timeout to " << timeout << " seconds (from keys)." << endl);
553  alarm(timeout);
554  }
555 
556 
557  BESDEBUG("bes", "Executing request: " << _dhi->data[DATA_REQUEST] << " ... " << endl);
558  BESResponseHandler *rh = _dhi->response_handler;
559  if (rh) {
560  rh->execute(*_dhi);
561  }
562  else {
563  BESDEBUG("bes", "FAILED" << endl);
564  string se = "The response handler \"" + _dhi->action + "\" does not exist";
565  throw BESInternalError(se, __FILE__, __LINE__);
566  }
567  BESDEBUG("bes", "OK" << endl);
568 
569  // Now we need to do the post processing piece of executing the request
570  invoke_aggregation();
571 
572  // And finally, transmit the response of this request
573  transmit_data();
574 
575  // Only clear the timeout if it has been set.
576  if (timeout != 0) {
577  timeout = 0;
578  alarm(0);
579  }
580 }
581 
585 {
586  BESStopWatch sw;
587  if (BESISDEBUG(TIMING_LOG)) sw.start("BESInterface::invoke_aggregation", _dhi->data[REQUEST_ID]);
588 
589  if (_dhi->data[AGG_CMD] != "") {
590  BESDEBUG("bes", "aggregating with: " << _dhi->data[AGG_CMD] << " ... "<< endl);
591  BESAggregationServer *agg = BESAggFactory::TheFactory()->find_handler(_dhi->data[AGG_HANDLER]);
592  if (agg) {
593  agg->aggregate(*_dhi);
594  }
595  else {
596  BESDEBUG("bes", "FAILED" << endl);
597  string se = "The aggregation handler " + _dhi->data[AGG_HANDLER] + "does not exist";
598  throw BESInternalError(se, __FILE__, __LINE__);
599  }
600  BESDEBUG("bes", "OK" << endl);
601  }
602 }
603 
618 {
619  BESStopWatch sw;
620  if (BESISDEBUG(TIMING_LOG)) sw.start("BESInterface::transmit_data", _dhi->data[REQUEST_ID]);
621 
622  BESDEBUG("bes", "BESInterface::transmit_data() - Transmitting request: " << _dhi->data[DATA_REQUEST] << endl);
623 #if 0
624  if (_transmitter) {
625 #endif
626  if (_dhi->error_info) {
627  ostringstream strm;
628  _dhi->error_info->print(strm);
629  (*BESLog::TheLog()) << strm.str() << endl;
630  BESDEBUG("bes", " transmitting error info using transmitter ... " << endl << strm.str() << endl);
631 
632  _dhi->error_info->transmit(_transmitter, *_dhi);
633  }
634  else if (_dhi->response_handler) {
635  BESDEBUG("bes", " BESInterface::transmit_data() - Response handler " << _dhi->response_handler->get_name() << endl);
636 
637  _dhi->response_handler->transmit(_transmitter, *_dhi);
638  }
639 #if 0
640  }
641  else {
642 
643  if (_dhi->error_info) {
644  BESDEBUG("bes", "BESInterface::transmit_data() - Transmitting error info using cout ... " << endl);
645  _dhi->error_info->print(cout);
646  delete _dhi->error_info;
647  _dhi->error_info = 0;
648  }
649  else {
650  BESDEBUG("bes", "BESInterface::transmit_data() - Unable to transmit the response ... FAILED " << endl);
651  //string err = ;
652  throw BESInternalError("Unable to transmit the response, no transmitter", __FILE__, __LINE__);
653  }
654  }
655 #endif
656 
657  BESDEBUG("bes", "BESInterface::transmit_data() - OK" << endl);
658 }
659 
663 {
664 }
665 
678 {
679  BESDEBUG("bes", "Reporting on request: " << _dhi->data[DATA_REQUEST] << " ... " << endl);
680 
681  BESReporterList::TheList()->report(*_dhi);
682 
683  BESDEBUG("bes", "OK" << endl);
684 }
685 
686 void BESInterface::add_end_callback(p_bes_end end)
687 {
688  _end_list.push_back(end);
689 }
690 
697 {
698  BESDEBUG("bes", "Ending request: " << _dhi->data[DATA_REQUEST] << " ... " << endl);
699  end_iter i = _end_list.begin();
700  for (; i != _end_list.end(); i++) {
701  p_bes_end p = *i;
702  p(*_dhi);
703  }
704 
705  // now clean up any containers that were used in the request, release
706  // the resource
707  _dhi->first_container();
708  while (_dhi->container) {
709  BESDEBUG("bes", "Calling BESContainer::release()" << endl);
710  _dhi->container->release();
711  _dhi->next_container();
712  }
713 
714  BESDEBUG("bes", "OK" << endl);
715 }
716 
720 {
721  if (_dhi) _dhi->clean();
722 }
723 
737 {
738  return BESExceptionManager::TheEHM()->handle_exception(e, *_dhi);
739 }
740 
749 void BESInterface::dump(ostream & strm) const
750 {
751  strm << BESIndent::LMarg << "BESInterface::dump - (" << (void *) this << ")" << endl;
752  BESIndent::Indent();
753 
754  if (_init_list.size()) {
755  strm << BESIndent::LMarg << "termination functions:" << endl;
756  BESIndent::Indent();
757  init_iter i = _init_list.begin();
758  for (; i != _init_list.end(); i++) {
759  // TODO ISO C++ forbids casting between pointer-to-function and pointer-to-object
760  // ...also below
761  strm << BESIndent::LMarg << (void *) (*i) << endl;
762  }
763  BESIndent::UnIndent();
764  }
765  else {
766  strm << BESIndent::LMarg << "termination functions: none" << endl;
767  }
768 
769  if (_end_list.size()) {
770  strm << BESIndent::LMarg << "termination functions:" << endl;
771  BESIndent::Indent();
772  end_iter i = _end_list.begin();
773  for (; i != _end_list.end(); i++) {
774  strm << BESIndent::LMarg << (void *) (*i) << endl;
775  }
776  BESIndent::UnIndent();
777  }
778  else {
779  strm << BESIndent::LMarg << "termination functions: none" << endl;
780  }
781 
782  strm << BESIndent::LMarg << "data handler interface:" << endl;
783  BESIndent::Indent();
784  _dhi->dump(strm);
785  BESIndent::UnIndent();
786 
787  if (_transmitter) {
788  strm << BESIndent::LMarg << "transmitter:" << endl;
789  BESIndent::Indent();
790  _transmitter->dump(strm);
791  BESIndent::UnIndent();
792  }
793  else {
794  strm << BESIndent::LMarg << "transmitter: not set" << endl;
795  }
796  BESIndent::UnIndent();
797 }
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