bes  Updated for version 3.20.6
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 <Error.h>
49 
50 #include "BESInterface.h"
51 
52 #include "TheBESKeys.h"
53 #include "BESResponseHandler.h"
54 #include "BESContextManager.h"
55 
56 #include "BESDapError.h"
57 
58 #include "BESTransmitterNames.h"
59 #include "BESDataNames.h"
60 #include "BESTransmitterNames.h"
61 #include "BESReturnManager.h"
62 #include "BESSyntaxUserError.h"
63 
64 #include "BESInfoList.h"
65 #include "BESXMLInfo.h"
66 
67 #include "BESDebug.h"
68 #include "BESStopWatch.h"
69 #include "BESTimeoutError.h"
70 #include "BESInternalError.h"
71 #include "BESInternalFatalError.h"
72 #include "ServerAdministrator.h"
73 
74 #include "BESLog.h"
75 
76 // If not defined, this is false (source code file names are logged). jhrg 10/4/18
77 #define EXCLUDE_FILE_INFO_FROM_LOG "BES.DoNotLogSourceFilenames"
78 
79 using namespace std;
80 using std::endl;
81 
82 static jmp_buf timeout_jump;
83 static bool timeout_jump_valid = false;
84 
85 // Define this to use sigwait() in a child thread to detect that SIGALRM
86 // has been raised (i.e., that the timeout interval has elapsed). This
87 // does not currently work, but could be a way to get information about
88 // a timeout back to the BES's client if the BES itslef were structured
89 // differently. See my comment further down. jhrg 12/28/15
90 #undef USE_SIGWAIT
91 
92 // timeout period in seconds; 0 --> no timeout. This is a static value so
93 // that it can be accessed by the signal handler. jhrg 1/4/16
94 // I've made this globally visible so that other code that might want to
95 // alter the time out value can do so and this variable can be kept consistent.
96 // See BESStreamResponseHandler::execute() for an example. jhrg 1/24/17
97 volatile int bes_timeout = 0;
98 
99 #define BES_TIMEOUT_KEY "BES.TimeOutInSeconds"
100 
101 // This function uses the static variables timeout_jump_valid and timeout_jump
102 // The code looks at the value of BES.TimeOutInSeconds and/or the timeout
103 // context sent in the current request and, if that is greater than zero,
104 // uses that as the maximum amount of time for the request. The system alarm
105 // is set and this function is registered as the handler. If timeout_jump_valid
106 // is true, then it will use longjmp() (yes, really...) to end the request. Look
107 // below in execute_request() for the call to setjump() to see how this works.
108 // See the SIGWAIT code that's commented out below for an alternative impl.
109 // jhrg 5/31/16
110 static void catch_sig_alarm(int sig)
111 {
112  if (sig == SIGALRM) {
113  LOG("BES timeout after " << bes_timeout << " seconds." << endl);
114 
115  // Causes setjmp() below to return 1; see the call to
116  // execute_data_request_plan() in execute_request() below.
117  // jhrg 12/29/15
118  if (timeout_jump_valid)
119  longjmp(timeout_jump, 1);
120  else {
121  // This is the old version of this code; it forces the BES child
122  // listener to exit without returning an error message to the
123  // OLFS/client. jhrg 12/29/15
124  signal(SIGTERM, SIG_DFL);
125  raise(SIGTERM);
126  }
127  }
128 }
129 
130 static void register_signal_handler()
131 {
132  struct sigaction act;
133  sigemptyset(&act.sa_mask);
134  sigaddset(&act.sa_mask, SIGALRM);
135  act.sa_flags = 0;
136 
137  // Note that we do not set SA_RESTART so an interrupted system call
138  // will return with an error and errno set to EINTR.
139 
140  act.sa_handler = catch_sig_alarm;
141  if (sigaction(SIGALRM, &act, 0))
142  throw BESInternalFatalError("Could not register a handler to catch alarm/timeout.", __FILE__, __LINE__);
143 }
144 
145 static inline void downcase(string &s)
146 {
147  for (unsigned int i = 0; i < s.length(); i++)
148  s[i] = tolower(s[i]);
149 }
150 
151 static void log_error(BESError &e)
152 {
153  string error_name = "";
154 #if 0
155  // TODO This should be configurable; I'm changing the values below to always log all errors.
156  // I'm also confused about the actual intention. jhrg 11/14/17
157  //
158  // Simplified. jhrg 10/03/18
159  bool only_log_to_verbose = false;
160 #endif
161  switch (e.get_bes_error_type()) {
162  case BES_INTERNAL_FATAL_ERROR:
163  error_name = "BES Internal Fatal Error";
164  break;
165 
166  case BES_INTERNAL_ERROR:
167  error_name = "BES Internal Error";
168  break;
169 
170  case BES_SYNTAX_USER_ERROR:
171  error_name = "BES User Syntax Error";
172  // only_log_to_verbose = false; // TODO Was 'true.' jhrg 11/14/17
173  break;
174 
175  case BES_FORBIDDEN_ERROR:
176  error_name = "BES Forbidden Error";
177  break;
178 
179  case BES_NOT_FOUND_ERROR:
180  error_name = "BES Not Found Error";
181  // only_log_to_verbose = false; // TODO was 'true.' jhrg 11/14/17
182  break;
183 
184  default:
185  error_name = "BES Error";
186  break;
187  }
188 
189  if (TheBESKeys::TheKeys()->read_bool_key(EXCLUDE_FILE_INFO_FROM_LOG, false)) {
190  LOG("ERROR: " << error_name << ": " << e.get_message() << endl);
191  }
192  else {
193  LOG("ERROR: " << error_name << ": " << e.get_message() << " (" << e.get_file() << ":" << e.get_line() << ")" << endl);
194  }
195 
196 #if 0
197  if (only_log_to_verbose) {
198  VERBOSE("ERROR: " << error_name << ", error code: " << e.get_bes_error_type() << ", file: " << e.get_file() << ":"
199  << e.get_line() << ", message: " << e.get_message() << endl);
200 
201  }
202  else {
203  LOG("ERROR: " << error_name << ": " << e.get_message() << " (BES error code: " << e.get_bes_error_type() << ")." << endl);
204  VERBOSE(" at: " << e.get_file() << ":" << e.get_line() << endl);
205  }
206 #endif
207 
208 }
209 
210 #if USE_SIGWAIT
211 
212 // If the BES is changed so that the plan built here is run in a child thread,
213 // then we can have a much more flexible signal catching scheme, including catching
214 // the alarm signal used for the timeout. It's not possible to throw from a child
215 // thread to a parent thread, but if the parent thread sees that SIGALRM is
216 // raised, then it can stop the child thread (which is running the 'plan') and
217 // return a suitable message to the front end. Similarly, the BES could also
218 // handle a number of other signals using this scheme. These signals (SIGPIPE, ...)
219 // are currently processed using while/for loop(s) in the bes/server code. It may
220 // be that these signals are caught only in the master listener, but I can't
221 // quite figure that out now... jhrg 12/28/15
222 //
223 // NB: It might be possible to edit this so that it writes info to the OLFS and
224 // then uses the 'raise SIGTERM' technique to exit. That way the OLFS will at least
225 // get a message about the timeout. I'm not sure how to close up the PPT part
226 // of the conversation, however. The idea would be that the current command's DHI
227 // would be passed in as an arg and then the stream accessed that way. The BESError
228 // would be written to the stream and the child process killed. jhrg 12/2/9/15
229 
230 #include <pthread.h>
231 
232 // An alternative to a function that catches the signal; use sigwait()
233 // in a child thread after marking the signal as blocked. When/if sigwait()
234 // returns, look at the signal number and if it is the alarm, sort out
235 // what to do (throw an exception, ...). NB: A signal handler cannot
236 // portably throw an exception, but this code can.
237 
238 static pthread_t alarm_thread;
239 
240 static void* alarm_wait(void * /* arg */)
241 {
242  BESDEBUG("bes", "Starting: " << __PRETTY_FUNCTION__ << endl);
243 
244  // block SIGALRM
245  sigset_t sigset;
246  sigemptyset(&sigset);
247  sigaddset(&sigset, SIGALRM);
248  sigprocmask(SIG_BLOCK, &sigset, NULL);
249 
250  // Might replace this with a while loop. Not sure about interactions
251  // with other signal processing code in the BES. jhrg 12/28/15
252  int sig;
253  int result = sigwait(&sigset, &sig);
254  if (result != 0) {
255  BESDEBUG("bes", "Fatal error establishing timeout: " << strerror(result) << endl);
256  throw BESInternalFatalError(string("Fatal error establishing timeout: ") + strerror(result), __FILE__, __LINE__);
257  }
258  else if (result == 0 && sig == SIGALRM) {
259  BESDEBUG("bes", "Timeout found in " << __PRETTY_FUNCTION__ << endl);
260  throw BESTimeoutError("Timeout", __FILE__, __LINE__);
261  }
262  else {
263  stringstream oss;
264  oss << "While waiting for a timeout, found signal '" << result << "' in " << __PRETTY_FUNCTION__ << ends;
265  BESDEBUG("bes", oss.str() << endl);
266  throw BESInternalFatalError(oss.str(), __FILE__, __LINE__);
267  }
268 }
269 
270 static void wait_for_timeout()
271 {
272  BESDEBUG("bes", "Entering: " << __PRETTY_FUNCTION__ << endl);
273 
274  pthread_attr_t thread_attr;
275 
276  if (pthread_attr_init(&thread_attr) != 0)
277  throw BESInternalFatalError("Failed to initialize pthread attributes.", __FILE__, __LINE__);
278  if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED /*PTHREAD_CREATE_JOINABLE*/) != 0)
279  throw BESInternalFatalError("Failed to complete pthread attribute initialization.", __FILE__, __LINE__);
280 
281  int status = pthread_create(&alarm_thread, &thread_attr, alarm_wait, NULL);
282  if (status != 0)
283  throw BESInternalFatalError("Failed to start the timeout wait thread.", __FILE__, __LINE__);
284 }
285 #endif
286 
287 BESInterface::BESInterface(ostream *output_stream) :
288  d_strm(output_stream), d_timeout_from_keys(0), d_dhi_ptr(0), d_transmitter(0)
289 {
290  if (!d_strm) {
291  throw BESInternalError("Output stream must be set in order to output responses", __FILE__, __LINE__);
292  }
293 
294  // Grab the BES Key for the timeout. Note that the Hyrax server generally
295  // overrides this value using a 'context' that is set/sent by the OLFS.
296  // Also note that a value of zero means no timeout, but that the context
297  // can override that too. jhrg 1/4/16
298  bool found;
299  string timeout_key_value;
300  TheBESKeys::TheKeys()->get_value(BES_TIMEOUT_KEY, timeout_key_value, found);
301  if (found) {
302  istringstream iss(timeout_key_value);
303  iss >> d_timeout_from_keys;
304  }
305 
306  // Install signal handler for alarm() here
307  register_signal_handler();
308 
309 #if USE_SIGWAIT
310  wait_for_timeout();
311 #endif
312 }
313 
314 #if 0
315 extern BESStopWatch *bes_timing::elapsedTimeToReadStart;
316 extern BESStopWatch *bes_timing::elapsedTimeToTransmitStart;
317 #endif
318 
330 {
331  bool found = false;
332  string context = BESContextManager::TheManager()->get_context("errors", found);
333  downcase(context);
334  if (found && context == XML_ERRORS)
335  dhi.error_info = new BESXMLInfo();
336  else
337  dhi.error_info = BESInfoList::TheList()->build_info();
338 
339 #if 0
340  dhi.error_info = new BESXMLInfo();
341 // #else
342  dhi.error_info = BESInfoList::TheList()->build_info();
343 #endif
344 
345  log_error(e);
346 
347  string admin_email = "";
348  try {
350  admin_email = sd.get_email();
351  }
352  catch (...) {
353  admin_email = "support@opendap.org";
354  }
355  if (admin_email.empty()) {
356  admin_email = "support@opendap.org";
357  }
358 
359  dhi.error_info->begin_response(dhi.action_name.empty() ? "BES" : dhi.action_name, dhi);
360 
361  dhi.error_info->add_exception(e, admin_email);
362 
363  dhi.error_info->end_response();
364 
365  return e.get_bes_error_type();
366 }
367 
368 
369 #if 0
371 {
372  // If we are handling errors in a dap2 context, then create a
373  // DapErrorInfo object to transmit/print the error as a dap2
374  // response.
375  bool found = false;
376  // I changed 'dap_format' to 'errors' in the following line. jhrg 10/6/08
377  string context = BESContextManager::TheManager()->get_context("errors", found);
378  if (context == "dap2" || context == "dap") {
379  libdap::ErrorCode ec = unknown_error;
380  BESDapError *de = dynamic_cast<BESDapError*>(&e);
381  if (de) {
382  ec = de->get_error_code();
383  }
385  dhi.error_info = new BESDapErrorInfo(ec, e.get_message());
386 
387  return e.get_bes_error_type();
388  }
389  else {
390  // If we are not in a dap2 context and the exception is a dap
391  // handler exception, then convert the error message to include the
392  // error code. If it is or is not a dap exception, we simply return
393  // that the exception was not handled.
394  BESError *e_p = &e;
395  BESDapError *de = dynamic_cast<BESDapError*>(e_p);
396  if (de) {
397  ostringstream s;
398  s << "libdap exception building response: error_code = " << de->get_error_code() << ": "
399  << de->get_message();
400  e.set_message(s.str());
402  }
403  }
404  return 0;
405 }
406 #endif
407 
408 
447 int BESInterface::execute_request(const string &from)
448 {
449  BESDEBUG("bes", "Entering: " << __PRETTY_FUNCTION__ << endl);
450 
451  if (!d_dhi_ptr) {
452  throw BESInternalError("DataHandlerInterface can not be null", __FILE__, __LINE__);
453  }
454 
455  BESStopWatch sw;
456  if (BESISDEBUG(TIMING_LOG)) {
457  // It would be great to have more info to put here, but that is buried in
458  // BESXMLInterface::build_data_request_plan() where the XML document is
459  // parsed. jhrg 11/9/17
460  sw.start("BESInterface::execute_request", d_dhi_ptr->data[REQUEST_ID]);
461 #if 0
462  bes_timing::elapsedTimeToReadStart = new BESStopWatch();
463  bes_timing::elapsedTimeToReadStart->start("TIME_TO_READ_START", d_dhi_ptr->data[REQUEST_ID]);
464 
465  bes_timing::elapsedTimeToTransmitStart = new BESStopWatch();
466  bes_timing::elapsedTimeToTransmitStart->start("TIME_TO_TRANSMIT_START", d_dhi_ptr->data[REQUEST_ID]);
467 #endif
468  }
469 
470  // TODO These never change for the life of a BES, so maybe they can move out of
471  // code that runs for every request? jhrg 11/8/17
472  d_dhi_ptr->set_output_stream(d_strm);
473  d_dhi_ptr->data[REQUEST_FROM] = from;
474 
475  // TODO If this is only used for logging, it is not needed since the log has a copy
476  // of the BES PID. jhrg 11/13/17
477  ostringstream ss;
478  ss << getpid();
479  d_dhi_ptr->data[SERVER_PID] = ss.str();
480 
481  // We split up the calls for the reason that if we catch an
482  // exception during the initialization, building, execution, or response
483  // transmit of the request then we can transmit the exception/error
484  // information.
485  //
486  // TODO status is not used. jhrg 11/9/17
487  int status = 0; // save the return status from exception_manager() and return that.
488  try {
489  VERBOSE(d_dhi_ptr->data[REQUEST_FROM] << " request received" << endl);
490 
491  // Initialize the transmitter for this interface instance to the BASIC
492  // TRANSMITTER. This ensures that a simple response, such as an error,
493  // can be sent back to the OLFS should that be needed.
494  d_transmitter = BESReturnManager::TheManager()->find_transmitter(BASIC_TRANSMITTER);
495  if (!d_transmitter)
496  throw BESInternalError(string("Unable to find transmitter '") + BASIC_TRANSMITTER + "'", __FILE__, __LINE__);
497 
498  build_data_request_plan();
499 
500  // This method does two key things: Calls the request handler to make a
501  // 'response object' (the C++ object that will hold the response) and
502  // then calls the transmitter to actually send it or build and send it.
503  //
504  // The timeout is also set in execute_data_request_plan(). The alarm signal
505  // handler (above), run when the timeout expires, will call longjmp with a
506  // return value of 1.
507  if (setjmp(timeout_jump) == 0) {
508  timeout_jump_valid = true;
509 
510  // Set timeout? Use either the value from the keys or a context
511  bool found = false;
512  string context = BESContextManager::TheManager()->get_context("bes_timeout", found);
513  if (found) {
514  bes_timeout = strtol(context.c_str(), NULL, 10);
515  VERBOSE(d_dhi_ptr->data[REQUEST_FROM] << "Set request timeout to " << bes_timeout << " seconds (from context)." << endl);
516  alarm(bes_timeout);
517  }
518  else if (d_timeout_from_keys != 0) {
519  bes_timeout = d_timeout_from_keys;
520  VERBOSE(d_dhi_ptr->data[REQUEST_FROM] << "Set request timeout to " << bes_timeout << " seconds (from keys)." << endl);
521  alarm(bes_timeout);
522  }
523 
524  // HK-474. The exception caused by the errant config file in the ticket is
525  // thrown from inside SaxParserWrapper::rethrowException(). It will be caught
526  // below. jhrg 11/12//19
527  execute_data_request_plan();
528 
529  // Only clear the timeout if it has been set.
530  if (bes_timeout != 0) {
531  bes_timeout = 0;
532  alarm(0);
533  }
534 
535  // Once we exit the block where setjmp() was called, the jump_buf is not valid
536  timeout_jump_valid = false;
537  }
538  else {
539  ostringstream oss;
540  oss << "BES listener timeout after " << bes_timeout << " seconds." << ends;
541  throw BESTimeoutError(oss.str(), __FILE__, __LINE__);
542  }
543 
544  d_dhi_ptr->executed = true;
545  }
546  catch (libdap::Error &e) {
547  timeout_jump_valid = false;
548  BESInternalFatalError ex(string("BES caught a libdap exception: ") + e.get_error_message(), __FILE__, __LINE__);
549  status = handleException(ex, *d_dhi_ptr);
550  }
551  catch (BESError &e) {
552  timeout_jump_valid = false;
553  status = handleException(e, *d_dhi_ptr);
554  }
555  catch (bad_alloc &e) {
556  timeout_jump_valid = false;
557  BESInternalFatalError ex(string("BES out of memory: ") + e.what(), __FILE__, __LINE__);
558  status = handleException(ex, *d_dhi_ptr);
559  }
560  catch (exception &e) {
561  timeout_jump_valid = false;
562  BESInternalFatalError ex(string("C++ Exception: ") + e.what(), __FILE__, __LINE__);
563  status = handleException(ex, *d_dhi_ptr);
564  }
565  catch (...) {
566  timeout_jump_valid = false;
567  BESInternalError ex("An unidentified exception has been thrown", __FILE__, __LINE__);
568  status = handleException(ex, *d_dhi_ptr);
569  }
570 
571  return status;
572 }
573 
580 int BESInterface::finish(int status)
581 {
582  if (d_dhi_ptr->error_info) {
583  d_dhi_ptr->error_info->print(*d_strm /*cout*/);
584  delete d_dhi_ptr->error_info;
585  d_dhi_ptr->error_info = 0;
586  }
587 
588  // if there is a problem with the rest of these steps then all we will
589  // do is log it to the BES log file and not handle the exception with
590  // the exception manager.
591  try {
592  log_status();
593  end_request();
594  }
595  catch (BESError &ex) {
596  LOG("Problem logging status or running end of request cleanup: " << ex.get_message() << endl);
597  }
598  catch (...) {
599  LOG("Unknown problem logging status or running end of request cleanup" << endl);
600  }
601 
602  return status;
603 }
604 
611 {
612  // now clean up any containers that were used in the request, release
613  // the resource
615  while (d_dhi_ptr->container) {
616  d_dhi_ptr->container->release();
618  }
619 }
620 
629 void BESInterface::dump(ostream & strm) const
630 {
631  strm << BESIndent::LMarg << "BESInterface::dump - (" << (void *) this << ")" << endl;
632  BESIndent::Indent();
633 
634  strm << BESIndent::LMarg << "data handler interface:" << endl;
635  BESIndent::Indent();
636  d_dhi_ptr->dump(strm);
637  BESIndent::UnIndent();
638 
639  if (d_transmitter) {
640  strm << BESIndent::LMarg << "transmitter:" << endl;
641  BESIndent::Indent();
642  d_transmitter->dump(strm);
643  BESIndent::UnIndent();
644  }
645  else {
646  strm << BESIndent::LMarg << "transmitter: not set" << endl;
647  }
648 
649  BESIndent::UnIndent();
650 }
BESDataHandlerInterface::container
BESContainer * container
pointer to current container in this interface
Definition: BESDataHandlerInterface.h:75
BESDapErrorInfo
silent informational response object
Definition: BESDapErrorInfo.h:50
BESError::get_bes_error_type
virtual int get_bes_error_type()
Return the return code for this error class.
Definition: BESError.h:143
BESError::get_line
virtual int get_line()
get the line number where the exception was thrown
Definition: BESError.h:115
BESStopWatch::start
virtual bool start(std::string name)
Definition: BESStopWatch.cc:58
BESInternalFatalError
exception thrown if an internal error is found and is fatal to the BES
Definition: BESInternalFatalError.h:43
BESTransmitter::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESTransmitter.cc:132
BESDataHandlerInterface::next_container
void next_container()
set the container pointer to the next * container in the list, null if at the end or no containers in...
Definition: BESDataHandlerInterface.h:146
BESInterface::end_request
virtual void end_request()
End the BES request.
Definition: BESInterface.cc:610
BESXMLInfo
represents an xml formatted response object
Definition: BESXMLInfo.h:48
BESInfo::print
virtual void print(std::ostream &strm)
print the information from this informational object to the specified stream
Definition: BESInfo.cc:261
BESError::get_message
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
BESError::get_file
virtual std::string get_file()
get the file name where the exception was thrown
Definition: BESError.h:107
BESInterface::finish
virtual int finish(int status)
Definition: BESInterface.cc:580
TheBESKeys::TheKeys
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:62
BESInfo::add_exception
virtual void add_exception(BESError &e, const std::string &admin)
add exception information to this informational object
Definition: BESInfo.cc:234
BESDataHandlerInterface::data
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
Definition: BESDataHandlerInterface.h:90
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
BESStopWatch
Definition: BESStopWatch.h:55
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
BESDataHandlerInterface::dump
void dump(std::ostream &strm) const
dumps information about this object
Definition: BESDataHandlerInterface.cc:167
BESInterface::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESInterface.cc:629
BESInterface::d_transmitter
BESTransmitter * d_transmitter
The Transmitter to use for the result.
Definition: BESInterface.h:125
BESInterface::handleException
static int handleException(BESError &e, BESDataHandlerInterface &dhi)
Make a BESXMLInfo object to hold the error information.
Definition: BESInterface.cc:329
BESDataHandlerInterface::first_container
void first_container()
set the container pointer to the first container in the containers list
Definition: BESDataHandlerInterface.h:135
BESInterface::d_dhi_ptr
BESDataHandlerInterface * d_dhi_ptr
Allocated by the child class.
Definition: BESInterface.h:124
BESContextManager::get_context
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
Definition: BESContextManager.cc:77
BESInfo::begin_response
virtual void begin_response(const std::string &response_name, BESDataHandlerInterface &dhi)
begin the informational response
Definition: BESInfo.cc:124
BESDapError
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:59
BESDataHandlerInterface
Structure storing information used by the BES to handle the request.
Definition: BESDataHandlerInterface.h:56
BESError
Abstract exception class for the BES with basic string message.
Definition: BESError.h:58
bes::ServerAdministrator
A ServerAdministrator object from the TheBESKeys associated with the string SERVER_ADMIN_KEY.
Definition: ServerAdministrator.h:41
BESDataHandlerInterface::error_info
BESInfo * error_info
error information object
Definition: BESDataHandlerInterface.h:94
BESInterface::execute_request
virtual int execute_request(const std::string &from)
The entry point for command execution; called by BESServerHandler::execute()
Definition: BESInterface.cc:447
BESTimeoutError
error thrown if there is a user syntax error in the request or any other user error
Definition: BESTimeoutError.h:41
BESDapError::convert_error_code
int convert_error_code(int error_code, int current_error_type)
converts the libdap error code to the bes error type
Definition: BESDapError.cc:84
BESError::set_bes_error_type
virtual void set_bes_error_type(int type)
Set the return code for this particular error class.
Definition: BESError.h:132
BESError::set_message
virtual void set_message(const std::string &msg)
set the error message for this exception
Definition: BESError.h:91