50 #include "BESInterface.h"
52 #include "TheBESKeys.h"
53 #include "BESResponseHandler.h"
54 #include "BESContextManager.h"
56 #include "BESDapError.h"
58 #include "BESTransmitterNames.h"
59 #include "BESDataNames.h"
60 #include "BESTransmitterNames.h"
61 #include "BESReturnManager.h"
62 #include "BESSyntaxUserError.h"
64 #include "BESInfoList.h"
65 #include "BESXMLInfo.h"
68 #include "BESStopWatch.h"
69 #include "BESTimeoutError.h"
70 #include "BESInternalError.h"
71 #include "BESInternalFatalError.h"
72 #include "ServerAdministrator.h"
77 #define EXCLUDE_FILE_INFO_FROM_LOG "BES.DoNotLogSourceFilenames"
82 static jmp_buf timeout_jump;
83 static bool timeout_jump_valid =
false;
97 volatile int bes_timeout = 0;
99 #define BES_TIMEOUT_KEY "BES.TimeOutInSeconds"
110 static void catch_sig_alarm(
int sig)
112 if (sig == SIGALRM) {
113 LOG(
"BES timeout after " << bes_timeout <<
" seconds." << endl);
118 if (timeout_jump_valid)
119 longjmp(timeout_jump, 1);
124 signal(SIGTERM, SIG_DFL);
130 static void register_signal_handler()
132 struct sigaction act;
133 sigemptyset(&act.sa_mask);
134 sigaddset(&act.sa_mask, SIGALRM);
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__);
145 static inline void downcase(
string &s)
147 for (
unsigned int i = 0; i < s.length(); i++)
148 s[i] = tolower(s[i]);
153 string error_name =
"";
159 bool only_log_to_verbose =
false;
162 case BES_INTERNAL_FATAL_ERROR:
163 error_name =
"BES Internal Fatal Error";
166 case BES_INTERNAL_ERROR:
167 error_name =
"BES Internal Error";
170 case BES_SYNTAX_USER_ERROR:
171 error_name =
"BES User Syntax Error";
175 case BES_FORBIDDEN_ERROR:
176 error_name =
"BES Forbidden Error";
179 case BES_NOT_FOUND_ERROR:
180 error_name =
"BES Not Found Error";
185 error_name =
"BES Error";
190 LOG(
"ERROR: " << error_name <<
": " << e.
get_message() << endl);
197 if (only_log_to_verbose) {
238 static pthread_t alarm_thread;
240 static void* alarm_wait(
void * )
242 BESDEBUG(
"bes",
"Starting: " << __PRETTY_FUNCTION__ << endl);
246 sigemptyset(&sigset);
247 sigaddset(&sigset, SIGALRM);
248 sigprocmask(SIG_BLOCK, &sigset, NULL);
253 int result = sigwait(&sigset, &sig);
255 BESDEBUG(
"bes",
"Fatal error establishing timeout: " << strerror(result) << endl);
256 throw BESInternalFatalError(
string(
"Fatal error establishing timeout: ") + strerror(result), __FILE__, __LINE__);
258 else if (result == 0 && sig == SIGALRM) {
259 BESDEBUG(
"bes",
"Timeout found in " << __PRETTY_FUNCTION__ << endl);
264 oss <<
"While waiting for a timeout, found signal '" << result <<
"' in " << __PRETTY_FUNCTION__ << ends;
265 BESDEBUG(
"bes", oss.str() << endl);
270 static void wait_for_timeout()
272 BESDEBUG(
"bes",
"Entering: " << __PRETTY_FUNCTION__ << endl);
274 pthread_attr_t thread_attr;
276 if (pthread_attr_init(&thread_attr) != 0)
278 if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED ) != 0)
279 throw BESInternalFatalError(
"Failed to complete pthread attribute initialization.", __FILE__, __LINE__);
281 int status = pthread_create(&alarm_thread, &thread_attr, alarm_wait, NULL);
287 BESInterface::BESInterface(ostream *output_stream) :
288 d_strm(output_stream), d_timeout_from_keys(0), d_dhi_ptr(0), d_transmitter(0)
291 throw BESInternalError(
"Output stream must be set in order to output responses", __FILE__, __LINE__);
299 string timeout_key_value;
302 istringstream iss(timeout_key_value);
303 iss >> d_timeout_from_keys;
307 register_signal_handler();
315 extern BESStopWatch *bes_timing::elapsedTimeToReadStart;
316 extern BESStopWatch *bes_timing::elapsedTimeToTransmitStart;
332 string context = BESContextManager::TheManager()->
get_context(
"errors", found);
334 if (found && context == XML_ERRORS)
337 dhi.
error_info = BESInfoList::TheList()->build_info();
342 dhi.
error_info = BESInfoList::TheList()->build_info();
347 string admin_email =
"";
350 admin_email = sd.get_email();
353 admin_email =
"support@opendap.org";
355 if (admin_email.empty()) {
356 admin_email =
"support@opendap.org";
377 string context = BESContextManager::TheManager()->
get_context(
"errors", found);
378 if (context ==
"dap2" || context ==
"dap") {
379 libdap::ErrorCode ec = unknown_error;
382 ec = de->get_error_code();
398 s <<
"libdap exception building response: error_code = " << de->get_error_code() <<
": "
449 BESDEBUG(
"bes",
"Entering: " << __PRETTY_FUNCTION__ << endl);
452 throw BESInternalError(
"DataHandlerInterface can not be null", __FILE__, __LINE__);
456 if (BESISDEBUG(TIMING_LOG)) {
462 bes_timing::elapsedTimeToReadStart =
new BESStopWatch();
463 bes_timing::elapsedTimeToReadStart->
start(
"TIME_TO_READ_START",
d_dhi_ptr->
data[REQUEST_ID]);
465 bes_timing::elapsedTimeToTransmitStart =
new BESStopWatch();
466 bes_timing::elapsedTimeToTransmitStart->
start(
"TIME_TO_TRANSMIT_START",
d_dhi_ptr->
data[REQUEST_ID]);
489 VERBOSE(
d_dhi_ptr->
data[REQUEST_FROM] <<
" request received" << endl);
494 d_transmitter = BESReturnManager::TheManager()->find_transmitter(BASIC_TRANSMITTER);
496 throw BESInternalError(
string(
"Unable to find transmitter '") + BASIC_TRANSMITTER +
"'", __FILE__, __LINE__);
498 build_data_request_plan();
507 if (setjmp(timeout_jump) == 0) {
508 timeout_jump_valid =
true;
512 string context = BESContextManager::TheManager()->
get_context(
"bes_timeout", 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);
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);
527 execute_data_request_plan();
530 if (bes_timeout != 0) {
536 timeout_jump_valid =
false;
540 oss <<
"BES listener timeout after " << bes_timeout <<
" seconds." << ends;
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__);
552 timeout_jump_valid =
false;
555 catch (bad_alloc &e) {
556 timeout_jump_valid =
false;
560 catch (exception &e) {
561 timeout_jump_valid =
false;
566 timeout_jump_valid =
false;
567 BESInternalError ex(
"An unidentified exception has been thrown", __FILE__, __LINE__);
596 LOG(
"Problem logging status or running end of request cleanup: " << ex.
get_message() << endl);
599 LOG(
"Unknown problem logging status or running end of request cleanup" << endl);
631 strm << BESIndent::LMarg <<
"BESInterface::dump - (" << (
void *)
this <<
")" << endl;
634 strm << BESIndent::LMarg <<
"data handler interface:" << endl;
637 BESIndent::UnIndent();
640 strm << BESIndent::LMarg <<
"transmitter:" << endl;
643 BESIndent::UnIndent();
646 strm << BESIndent::LMarg <<
"transmitter: not set" << endl;
649 BESIndent::UnIndent();