47#include "BESInterface.h"
49#include "TheBESKeys.h"
50#include "BESContextManager.h"
52#include "BESTransmitterNames.h"
53#include "BESDataNames.h"
54#include "BESReturnManager.h"
56#include "BESInfoList.h"
57#include "BESXMLInfo.h"
61#include "BESStopWatch.h"
62#include "BESInternalError.h"
63#include "BESInternalFatalError.h"
64#include "ServerAdministrator.h"
65#include "RequestServiceTimer.h"
70#define EXCLUDE_FILE_INFO_FROM_LOG "BES.DoNotLogSourceFilenames"
71#define prolog std::string("BESInterface::").append(__func__).append("() - ")
88volatile int bes_timeout = 0;
91#define BES_TIMEOUT_KEY "BES.TimeOutInSeconds"
93static inline void downcase(
string &s)
95 transform(s.begin(), s.end(), s.begin(), [](
int c) { return std::toupper(c); });
102std::string memory_info()
107 mem_info =
"Current memory usage is: " + std::to_string(mem_size) +
" KB.";
110 mem_info =
"Current memory usage is unknown.";
117static void log_error(
const BESError &e)
122 ERROR_LOG(
"ERROR! " + e.error_name() +
": " +
BESUtil::remove_crlf(err_msg) +
" " + memory_info());
127 + memory_info() +
"\n");
158static pthread_t alarm_thread;
160static void* alarm_wait(
void * )
162 BESDEBUG(
"bes",
"Starting: " << __PRETTY_FUNCTION__ << endl);
166 sigemptyset(&sigset);
167 sigaddset(&sigset, SIGALRM);
168 sigprocmask(SIG_BLOCK, &sigset, NULL);
173 int result = sigwait(&sigset, &sig);
175 BESDEBUG(
"bes",
"Fatal error establishing timeout: " << strerror(result) << endl);
176 throw BESInternalFatalError(
string(
"Fatal error establishing timeout: ") + strerror(result), __FILE__, __LINE__);
178 else if (result == 0 && sig == SIGALRM) {
179 BESDEBUG(
"bes",
"Timeout found in " << __PRETTY_FUNCTION__ << endl);
184 oss <<
"While waiting for a timeout, found signal '" << result <<
"' in " << __PRETTY_FUNCTION__ << ends;
185 BESDEBUG(
"bes", oss.str() << endl);
190static void wait_for_timeout()
192 BESDEBUG(
"bes",
"Entering: " << __PRETTY_FUNCTION__ << endl);
194 pthread_attr_t thread_attr;
196 if (pthread_attr_init(&thread_attr) != 0)
198 if (pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED ) != 0)
199 throw BESInternalFatalError(
"Failed to complete pthread attribute initialization.", __FILE__, __LINE__);
201 int status = pthread_create(&alarm_thread, &thread_attr, alarm_wait, NULL);
207BESInterface::BESInterface(ostream *output_stream) :
208 d_strm(output_stream)
211 throw BESInternalError(
"Output stream must be set in order to output responses", __FILE__, __LINE__);
223 string timeout_key_value;
226 istringstream iss(timeout_key_value);
227 iss >> d_timeout_from_keys;
245 string context = BESContextManager::TheManager()->get_context(
"errors", found);
247 if (found && context == XML_ERRORS)
250 dhi.
error_info = BESInfoList::TheList()->build_info();
257 admin_email = sd.get_email();
260 admin_email =
"support@opendap.org";
262 if (admin_email.empty()) {
263 admin_email =
"support@opendap.org";
284 string context = BESContextManager::TheManager()->get_context(
"bes_timeout", found);
286 d_bes_timeout = strtol(context.c_str(), NULL, 10);
287 VERBOSE(
d_dhi_ptr->data[REQUEST_FROM] +
"Set request timeout to " + std::to_string(d_bes_timeout)
288 +
" seconds (from context).");
300 VERBOSE(
d_dhi_ptr->data[REQUEST_FROM] +
"Set request timeout to " + std::to_string(d_bes_timeout)
301 +
" seconds (from keys).");
356 BESDEBUG(
"bes",
"Entering: " << __PRETTY_FUNCTION__ << endl);
359 throw BESInternalError(
"DataHandlerInterface can not be null", __FILE__, __LINE__);
378 d_dhi_ptr->data[SERVER_PID] = to_string(getpid());
387 VERBOSE(
d_dhi_ptr->data[REQUEST_FROM] +
" request received");
392 d_transmitter = BESReturnManager::TheManager()->find_transmitter(BASIC_TRANSMITTER);
394 throw BESInternalError(
string(
"Unable to find transmitter '") + BASIC_TRANSMITTER +
"'", __FILE__, __LINE__);
396 build_data_request_plan();
414 execute_data_request_plan();
422 BESDEBUG(
"bes",
string(__PRETTY_FUNCTION__) +
" - Caught BESError. msg: " << e.
get_message() << endl );
425 catch (
const bad_alloc &e) {
427 msg << __PRETTY_FUNCTION__ <<
" - BES out of memory. msg: " << e.
what() << endl;
428 BESDEBUG(
"bes", msg.str() << endl );
432 catch (
const exception &e) {
434 msg << __PRETTY_FUNCTION__ <<
" - Caught C++ Exception. msg: " << e.
what() << endl;
435 BESDEBUG(
"bes", msg.str() << endl );
440 string msg = string(__PRETTY_FUNCTION__) +
" - An unidentified exception has been thrown.";
441 BESDEBUG(
"bes", msg << endl );
471 ERROR_LOG(
"Problem logging status or running end of request cleanup: " + ex.
get_message());
474 ERROR_LOG(
"Unknown problem logging status or running end of request cleanup");
506 strm << BESIndent::LMarg <<
"BESInterface::dump - (" << (
void *)
this <<
")" << endl;
509 strm << BESIndent::LMarg <<
"data handler interface:" << endl;
512 BESIndent::UnIndent();
515 strm << BESIndent::LMarg <<
"transmitter:" << endl;
518 BESIndent::UnIndent();
521 strm << BESIndent::LMarg <<
"transmitter: not set" << endl;
524 BESIndent::UnIndent();
Structure storing information used by the BES to handle the request.
BESInfo * error_info
error information object
Base exception class for the BES with basic string message.
unsigned int get_line() const
get the line number where the exception was thrown
unsigned int get_bes_error_type() const
Return the return code for this error class.
const char * what() const noexcept override
Return a brief message about the exception.
std::string get_file() const
get the file name where the exception was thrown
std::string get_message() const
get the error message for this exception
virtual void begin_response(const std::string &response_name, BESDataHandlerInterface &dhi)
begin the informational response
virtual void add_exception(const BESError &e, const std::string &admin)
add exception information to this informational object
static int handleException(const BESError &e, BESDataHandlerInterface &dhi)
Make a BESXMLInfo object to hold the error information.
virtual int finish(int status)
virtual int execute_request(const std::string &from)
The entry point for command execution; called by BESServerHandler::execute()
virtual void end_request()
End the BES request.
BESDataHandlerInterface * d_dhi_ptr
Allocated by the child class.
BESTransmitter * d_transmitter
The Transmitter to use for the result.
void clear_bes_timeout()
Clear the bes timeout.
void dump(std::ostream &strm) const override
dumps information about this object
void set_bes_timeout()
Set the int 'd_bes_timeout' Use either the value of a 'bes_timeout' context or the value set in the B...
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
error thrown if there is a user syntax error in the request or any other user error
static long get_current_memory_usage() noexcept
Get the Resident Set Size in KB.
static std::string & remove_crlf(std::string &str)
"Sanitizes" the string by replacing any 0x0A (new line) or 0x0D (carriage return) characters with 0x2...
represents an xml formatted response object
static RequestServiceTimer * TheTimer()
Return a pointer to a singleton timer instance. If an instance does not exist it will create and init...
void start(std::chrono::milliseconds timeout_ms)
Set/Reset the timer start_time to now().
void disable_timeout()
Set the time_out is disabled.
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
Access to the singleton.
static int read_int_key(const std::string &key, int default_value)
Read an integer-valued key from the bes.conf file.
static bool read_bool_key(const std::string &key, bool default_value)
Read a boolean-valued key from the bes.conf file.
A ServerAdministrator object from the TheBESKeys associated with the string SERVER_ADMIN_KEY.