48 #include "BESInterface.h" 50 #include "TheBESKeys.h" 51 #include "BESResponseHandler.h" 52 #include "BESAggFactory.h" 53 #include "BESAggregationServer.h" 54 #include "BESReporterList.h" 55 #include "BESContextManager.h" 57 #include "BESExceptionManager.h" 59 #include "BESTransmitterNames.h" 60 #include "BESDataNames.h" 61 #include "BESTransmitterNames.h" 62 #include "BESReturnManager.h" 63 #include "BESSyntaxUserError.h" 66 #include "BESStopWatch.h" 67 #include "BESTimeoutError.h" 68 #include "BESInternalError.h" 69 #include "BESInternalFatalError.h" 75 static jmp_buf timeout_jump;
76 static bool timeout_jump_valid =
false;
90 volatile int bes_timeout = 0;
92 #define BES_TIMEOUT_KEY "BES.TimeOutInSeconds" 103 static void catch_sig_alarm(
int sig)
105 if (sig == SIGALRM) {
106 LOG(
"BES timeout after " << bes_timeout <<
" seconds." << endl);
111 if (timeout_jump_valid)
112 longjmp(timeout_jump, 1);
117 signal(SIGTERM, SIG_DFL);
123 static void register_signal_handler()
125 struct sigaction act;
126 sigemptyset(&act.sa_mask);
127 sigaddset(&act.sa_mask, SIGALRM);
133 act.sa_handler = catch_sig_alarm;
134 if (sigaction(SIGALRM, &act, 0))
135 throw BESInternalFatalError(
"Could not register a handler to catch alarm/timeout.", __FILE__, __LINE__);
166 static pthread_t alarm_thread;
168 static void* alarm_wait(
void * )
170 BESDEBUG(
"bes",
"Starting: " << __PRETTY_FUNCTION__ << endl);
174 sigemptyset(&sigset);
175 sigaddset(&sigset, SIGALRM);
176 sigprocmask(SIG_BLOCK, &sigset, NULL);
181 int result = sigwait(&sigset, &sig);
183 BESDEBUG(
"bes",
"Fatal error establishing timeout: " << strerror(result) << endl);
184 throw BESInternalFatalError(
string(
"Fatal error establishing timeout: ") + strerror(result), __FILE__, __LINE__);
186 else if (result == 0 && sig == SIGALRM) {
187 BESDEBUG(
"bes",
"Timeout found in " << __PRETTY_FUNCTION__ << endl);
192 oss <<
"While waiting for a timeout, found signal '" << result <<
"' in " << __PRETTY_FUNCTION__ << ends;
193 BESDEBUG(
"bes", oss.str() << endl);
198 static void wait_for_timeout()
200 BESDEBUG(
"bes",
"Entering: " << __PRETTY_FUNCTION__ << endl);
202 pthread_attr_t thread_attr;
204 if (pthread_attr_init(&thread_attr) != 0)
206 if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED ) != 0)
207 throw BESInternalFatalError(
"Failed to complete pthread attribute initialization.", __FILE__, __LINE__);
209 int status = pthread_create(&alarm_thread, &thread_attr, alarm_wait, NULL);
215 BESInterface::BESInterface(ostream *output_stream) :
216 d_strm(output_stream), d_timeout_from_keys(0), d_dhi_ptr(0), d_transmitter(0)
219 throw BESInternalError(
"Output stream must be set in order to output responses", __FILE__, __LINE__);
227 string timeout_key_value;
230 istringstream iss(timeout_key_value);
231 iss >> d_timeout_from_keys;
235 register_signal_handler();
243 extern BESStopWatch *bes_timing::elapsedTimeToReadStart;
244 extern BESStopWatch *bes_timing::elapsedTimeToTransmitStart;
287 BESDEBUG(
"bes",
"Entering: " << __PRETTY_FUNCTION__ << endl);
290 throw BESInternalError(
"DataHandlerInterface can not be null", __FILE__, __LINE__);
294 if (BESISDEBUG(TIMING_LOG)) {
300 bes_timing::elapsedTimeToReadStart =
new BESStopWatch();
301 bes_timing::elapsedTimeToReadStart->
start(
"TIME_TO_READ_START",
d_dhi_ptr->
data[REQUEST_ID]);
303 bes_timing::elapsedTimeToTransmitStart =
new BESStopWatch();
304 bes_timing::elapsedTimeToTransmitStart->
start(
"TIME_TO_TRANSMIT_START",
d_dhi_ptr->
data[REQUEST_ID]);
327 VERBOSE(
d_dhi_ptr->
data[REQUEST_FROM] <<
" request received" << endl);
332 d_transmitter = BESReturnManager::TheManager()->find_transmitter(BASIC_TRANSMITTER);
334 throw BESInternalError(
string(
"Unable to find transmitter '") + BASIC_TRANSMITTER +
"'", __FILE__, __LINE__);
336 build_data_request_plan();
345 if (setjmp(timeout_jump) == 0) {
346 timeout_jump_valid =
true;
350 string context = BESContextManager::TheManager()->
get_context(
"bes_timeout", found);
352 bes_timeout = strtol(context.c_str(), NULL, 10);
353 VERBOSE(
d_dhi_ptr->
data[REQUEST_FROM] <<
"Set request timeout to " << bes_timeout <<
" seconds (from context)." << endl);
356 else if (d_timeout_from_keys != 0) {
357 bes_timeout = d_timeout_from_keys;
358 VERBOSE(
d_dhi_ptr->
data[REQUEST_FROM] <<
"Set request timeout to " << bes_timeout <<
" seconds (from keys)." << endl);
362 execute_data_request_plan();
365 if (bes_timeout != 0) {
371 timeout_jump_valid =
false;
375 oss <<
"BES listener timeout after " << bes_timeout <<
" seconds." << ends;
382 timeout_jump_valid =
false;
385 catch (bad_alloc &e) {
386 timeout_jump_valid =
false;
390 catch (exception &e) {
391 timeout_jump_valid =
false;
396 timeout_jump_valid =
false;
397 BESInternalError ex(
"An undefined exception has been thrown", __FILE__, __LINE__);
402 delete bes_timing::elapsedTimeToReadStart;
403 bes_timing::elapsedTimeToReadStart = 0;
405 delete bes_timing::elapsedTimeToTransmitStart;
406 bes_timing::elapsedTimeToTransmitStart = 0;
418 void BESInterface::finish()
441 LOG(
"Problem logging status or running end of request cleanup: " << ex.
get_message() << endl);
444 LOG(
"Unknown problem logging status or running end of request cleanup" << endl);
448 int BESInterface::finish_with_error(
int status)
452 BESInternalError ex(
"Finish_with_error called with no error object", __FILE__, __LINE__);
503 strm << BESIndent::LMarg <<
"BESInterface::dump - (" << (
void *)
this <<
")" << endl;
506 strm << BESIndent::LMarg <<
"data handler interface:" << endl;
509 BESIndent::UnIndent();
512 strm << BESIndent::LMarg <<
"transmitter:" << endl;
515 BESIndent::UnIndent();
518 strm << BESIndent::LMarg <<
"transmitter: not set" << endl;
521 BESIndent::UnIndent();
virtual void dump(ostream &strm) const
dumps information about this object
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
void next_container()
set the container pointer to the next * container in the list, null if at the end or no containers in...
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual std::string get_message()
get the error message for this exception
BESDataHandlerInterface * d_dhi_ptr
Allocated by the child class.
virtual int exception_manager(BESError &e)
Manage any exceptions thrown during the whole process.
BESTransmitter * d_transmitter
The Transmitter to use for the result.
virtual string get_context(const string &name, bool &found)
retrieve the value of the specified context from the BES
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
virtual bool start(string name)
Abstract exception class for the BES with basic string message.
static TheBESKeys * TheKeys()
void dump(ostream &strm) const
dumps information about this object
map< string, string > data
the map of string data that will be required for the current request.
virtual void end_request()
End the BES request.
void first_container()
set the container pointer to the first container in the containers list
BESInfo * error_info
error information object
virtual int handle_exception(BESError &e, BESDataHandlerInterface &dhi)
Manage any exceptions thrown during the handling of a request.
virtual int execute_request(const string &from)
The entry point for command execution; called by BESServerHandler::execute()
virtual void print(ostream &strm)
print the information from this informational object to the specified stream
BESContainer * container
pointer to current container in this interface