31#ifdef HAVE_UUID_UUID_H
33#elif defined(HAVE_UUID_H)
36#error "Could not find UUID library header"
57#define CLEAR_LOCAL_DATA
58#undef USE_LOCAL_TIMEOUT_SCHEME
60#include <libdap/DAS.h>
61#include <libdap/DDS.h>
62#include <libdap/Structure.h>
63#include <libdap/ConstraintEvaluator.h>
64#include <libdap/DDXParserSAX2.h>
65#include <libdap/Ancillary.h>
66#include <libdap/XDRStreamMarshaller.h>
67#include <libdap/XDRFileUnMarshaller.h>
69#include <libdap/DMR.h>
70#include <libdap/D4Group.h>
71#include <libdap/D4Attributes.h>
72#include <libdap/XMLWriter.h>
73#include <libdap/D4AsyncUtil.h>
74#include <libdap/D4StreamMarshaller.h>
75#include <libdap/chunked_ostream.h>
76#include <libdap/chunked_istream.h>
77#include <libdap/D4ConstraintEvaluator.h>
78#include <libdap/D4FunctionEvaluator.h>
79#include <libdap/D4BaseTypeFactory.h>
81#include <libdap/ServerFunctionsList.h>
83#include <libdap/mime_util.h>
84#include <libdap/escaping.h>
85#include <libdap/util.h>
89#if USE_LOCAL_TIMEOUT_SCHEME
91#include <libdap/SignalHandler.h>
92#include <libdap/EventHandler.h>
93#include <libdap/AlarmHandler.h>
97#include "TheBESKeys.h"
98#include "BESDapResponseBuilder.h"
99#include "BESContextManager.h"
100#include "BESDapFunctionResponseCache.h"
101#include "BESStoredDapResultCache.h"
104#include "BESResponseObject.h"
105#include "BESDDSResponse.h"
106#include "BESDataDDSResponse.h"
107#include "BESDMRResponse.h"
108#include "BESDataHandlerInterface.h"
109#include "BESInternalFatalError.h"
110#include "BESSyntaxUserError.h"
111#include "BESDataNames.h"
113#include "BESRequestHandler.h"
114#include "BESRequestHandlerList.h"
115#include "BESNotFoundError.h"
120#include "BESStopWatch.h"
121#include "DapFunctionUtils.h"
122#include "RequestServiceTimer.h"
128const string CRLF =
"\r\n";
129const string BES_KEY_TIMEOUT_CANCEL =
"BES.CancelTimeoutOnSend";
132#define prolog std::string("BESDapResponseBuilder::").append(__func__).append("() - ")
134BESDapResponseBuilder::~BESDapResponseBuilder()
136#if USE_LOCAL_TIMEOUT_SCHEME
140 delete dynamic_cast<AlarmHandler*
>(SignalHandler::instance()->remove_handler(SIGALRM));
217std::string BESDapResponseBuilder::get_store_result()
const
222void BESDapResponseBuilder::set_store_result(
const std::string &_sr)
225 BESDEBUG(MODULE, prolog <<
"store_result: " << _sr << endl);
228std::string BESDapResponseBuilder::get_async_accepted()
const
233void BESDapResponseBuilder::set_async_accepted(
const std::string &_aa)
236 BESDEBUG(MODULE, prolog <<
"set_async_accepted() - async_accepted: " << _aa << endl);
264 d_dataset = www2id(ds,
"%",
"%20");
281static string::size_type find_closing_paren(
const string &ce, string::size_type pos)
288 pos = ce.find_first_of(
"()", pos + 1);
289 if (pos == string::npos){
291 msg <<
"Expected to find a matching closing parenthesis in: " << ce;
313 BESDEBUG(MODULE, prolog <<
"source expression: " << expr << endl);
321 string btp_function_ce;
322 string::size_type pos = 0;
326 string::size_type first_paren = ce.find(
"(", pos);
327 string::size_type closing_paren = string::npos;
328 if (first_paren != string::npos) closing_paren = find_closing_paren(ce, first_paren);
330 while (first_paren != string::npos && closing_paren != string::npos) {
332 string name = ce.substr(pos, first_paren - pos);
336 if (eval.find_function(name, &f)) {
338 if (!btp_function_ce.empty()) btp_function_ce +=
",";
339 btp_function_ce += ce.substr(pos, closing_paren + 1 - pos);
340 ce.erase(pos, closing_paren + 1 - pos);
341 if (ce[pos] ==
',') ce.erase(pos, 1);
344 pos = closing_paren + 1;
346 if (pos < ce.size() && ce.at(pos) ==
',') ++pos;
349 first_paren = ce.find(
"(", pos);
350 closing_paren = ce.find(
")", pos);
356 BESDEBUG(MODULE, prolog <<
"Modified constraint: " <<
d_dap2ce << endl);
357 BESDEBUG(MODULE, prolog <<
"BTP Function part: " << btp_function_ce << endl);
358 BESDEBUG(MODULE, prolog <<
"END" << endl);
377void BESDapResponseBuilder::send_das(ostream &out, DAS &das,
bool with_mime_headers)
const
379 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
"2.0");
381 dap_utils::throw_for_dap4_typed_attrs(&das, __FILE__, __LINE__);
405void BESDapResponseBuilder::send_das(ostream &out, DDS **dds, ConstraintEvaluator &eval,
bool constrained,
406 bool with_mime_headers)
408#if USE_LOCAL_TIMEOUT_SCHEME
410 establish_timeout(out);
411 dds.set_timeout(d_timeout);
418 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
"2.0");
421 (*dds)->mark_all(
true);
422 dap_utils::throw_for_dap4_typed_vars_or_attrs(*dds, __FILE__, __LINE__);
424 (*dds)->print_das(out);
436 ConstraintEvaluator func_eval;
437 BESDapFunctionResponseCache *responseCache = BESDapFunctionResponseCache::get_instance();
440 if (responseCache && responseCache->can_be_cached(*dds, get_btp_func_ce())) {
444 func_eval.parse_constraint(get_btp_func_ce(), **dds);
445 fdds = func_eval.eval_function_clauses(**dds);
448 delete *dds; *dds = 0;
451 if (with_mime_headers)
452 set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
457 (*dds)->print_das(out);
460 eval.parse_constraint(
d_dap2ce, **dds);
462 dap_utils::throw_for_dap4_typed_vars_or_attrs(*dds, __FILE__, __LINE__);
464 if (with_mime_headers)
465 set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
470 (*dds)->print_das(out);
496 bool with_mime_headers)
499 if (with_mime_headers)
500 set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
506 dap_utils::throw_for_dap4_typed_vars_or_attrs(*dds, __FILE__, __LINE__);
513#if USE_LOCAL_TIMEOUT_SCHEME
515 establish_timeout(out);
516 dds.set_timeout(d_timeout);
526 BESDEBUG(MODULE,prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
527 ConstraintEvaluator func_eval;
532 if (responseCache && responseCache->can_be_cached(*dds, get_btp_func_ce())) {
536 func_eval.parse_constraint(get_btp_func_ce(), **dds);
537 fdds = func_eval.eval_function_clauses(**dds);
540 delete *dds; *dds =
nullptr;
548 (*dds)->mark_all(
false);
560 promote_function_output_structures(*dds);
562 eval.parse_constraint(
d_dap2ce, **dds);
564 if (with_mime_headers)
565 set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
571 (*dds)->print_constrained(out);
574 BESDEBUG(MODULE, prolog <<
"Simple constraint: " <<
d_dap2ce << endl);
575 eval.parse_constraint(
d_dap2ce, **dds);
576 dap_utils::throw_for_dap4_typed_vars_or_attrs(*dds, __FILE__, __LINE__);
578 if (with_mime_headers)
579 set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset),(*dds)->get_dap_version());
585 (*dds)->print_constrained(out);
591#ifdef DAP2_STORED_RESULTS
606bool BESDapResponseBuilder::store_dap2_result(ostream &out, DDS &dds, ConstraintEvaluator &eval)
608 if (get_store_result().empty())
return false;
610 string serviceUrl = get_store_result();
621 string *stylesheet_ref = 0, ss_ref_value;
623 if (found && !ss_ref_value.empty()) {
624 stylesheet_ref = &ss_ref_value;
628 if (resultCache == NULL) {
635 string msg =
"The Stored Result request cannot be serviced. ";
636 msg +=
"Unable to acquire StoredResultCache instance. ";
637 msg +=
"This is most likely because the StoredResultCache is not (correctly) configured.";
639 BESDEBUG(MODULE, prolog <<
"[WARNING] " << msg << endl);
641 d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
642 out << xmlWrtr.get_doc();
645 BESDEBUG(MODULE,prolog <<
"Sent AsyncRequestRejected" << endl);
647 else if (get_async_accepted().size() != 0) {
652 BESDEBUG(MODULE, prolog <<
"serviceUrl="<< serviceUrl << endl);
655 string storedResultId =
"";
656 storedResultId = resultCache->store_dap2_result(dds,
get_ce(),
this, &eval);
658 BESDEBUG(MODULE, prolog <<
"storedResultId='"<< storedResultId <<
"'" << endl);
661 BESDEBUG(MODULE, prolog <<
"targetURL='"<< targetURL <<
"'" << endl);
664 d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
665 out << xmlWrtr.get_doc();
668 BESDEBUG(MODULE, prolog <<
"Sent DAP4 AsyncAccepted response" << endl);
675 d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
676 out << xmlWrtr.get_doc();
679 BESDEBUG(MODULE, prolog <<
"Sent DAP4 AsyncRequired response" << endl);
692 BES_STOPWATCH_START(MODULE, prolog +
"Timer");
697 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
699 (*dds)->print_constrained(out);
703 XDRStreamMarshaller m(out);
706 for (
auto i = (*dds)->var_begin(); i != (*dds)->var_end(); i++) {
707 if ((*i)->send_p()) {
709 (*i)->serialize(eval, **dds, m, ce_eval);
710#ifdef CLEAR_LOCAL_DATA
711 (*i)->clear_local_data();
716 BESDEBUG(MODULE, prolog <<
"END" << endl);
719#ifdef DAP2_STORED_RESULTS
728void BESDapResponseBuilder::serialize_dap2_data_ddx(ostream &out, DDS **dds, ConstraintEvaluator &eval,
729 const string &boundary,
const string &start,
bool ce_eval)
731 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
734 libdap::set_mime_ddx_boundary(out, boundary, start, dods_ddx, x_plain);
740 uuid_unparse(uu, uuid.data());
742 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0) strncpy(domain,
"opendap.org", 255);
744 string cid = string(uuid.data()) +
"@" + string(domain.data());
748 (*dds)->print_xml_writer(out,
true, cid);
751 set_mime_data_boundary(out, boundary, cid, dods_data_ddx , x_plain);
753 XDRStreamMarshaller m(out);
755 conditional_timeout_cancel();
759 for (DDS::Vars_iter i = (*dds)->var_begin(); i != (*dds)->var_end(); i++) {
760 if ((*i)->send_p()) {
761 (*i)->serialize(eval, **dds, m, ce_eval);
762#ifdef CLEAR_LOCAL_DATA
763 (*i)->clear_local_data();
768 BESDEBUG(MODULE, prolog <<
"END" << endl);
789void BESDapResponseBuilder::remove_timeout()
const
791#if USE_LOCAL_TIMEOUT_SCHEME
813 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
820 DDS *dds = bdds->get_dds();
824 set_async_accepted(dhi.
data[ASYNC]);
825 set_store_result(dhi.
data[STORE_RESULT]);
827 ConstraintEvaluator &eval = bdds->get_ce();
838 ConstraintEvaluator func_eval;
840 if (responseCache && responseCache->can_be_cached(dds, get_btp_func_ce())) {
844 func_eval.parse_constraint(get_btp_func_ce(), *dds);
845 fdds = func_eval.eval_function_clauses(*dds);
852 dds->mark_all(
false);
854 promote_function_output_structures(dds);
857 eval.parse_constraint(
d_dap2ce, *dds);
858 BESDEBUG(MODULE, prolog <<
"END"<< endl);
883 BES_STOPWATCH_START(MODULE, prolog +
"Timer");
885 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
890 if (!bdds)
throw BESInternalFatalError(
"Expected a BESDataDDSResponse instance", __FILE__, __LINE__);
892 DDS *dds = bdds->get_dds();
896 set_async_accepted(dhi.
data[ASYNC]);
897 set_store_result(dhi.
data[STORE_RESULT]);
902 if(!bdds->get_ia_flag()) {
904 besRH->add_attributes(dhi);
907 ConstraintEvaluator &eval = bdds->get_ce();
915 if (!get_btp_func_ce().empty()) {
916 BESDEBUG(MODULE,prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
920 ConstraintEvaluator func_eval;
922 if (responseCache && responseCache->can_be_cached(dds, get_btp_func_ce())) {
926 func_eval.parse_constraint(get_btp_func_ce(), *dds);
927 fdds = func_eval.eval_function_clauses(*dds);
939 dds->mark_all(
false);
950 promote_function_output_structures(dds);
954 eval.parse_constraint(
get_ce(), *dds);
956 dds->tag_nested_sequences();
958 dap_utils::throw_if_too_big(*dds, __FILE__, __LINE__);
963 for (
auto i = dds->var_begin(), e = dds->var_end(); i != e; ++i) {
964 if ((*i)->send_p()) {
966 (*i)->intern_data(eval, *dds);
968 catch(std::exception &e) {
969 throw BESSyntaxUserError(
string(
"Caught a C++ standard exception while working on '") + (*i)->name() +
"' The error was: " + e.what(), __FILE__, __LINE__);
974 BESDEBUG(MODULE, prolog <<
"END"<< endl);
991void BESDapResponseBuilder::send_dap2_data(ostream &data_stream, DDS **dds, ConstraintEvaluator &eval,
992 bool with_mime_headers)
994 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
996#if USE_LOCAL_TIMEOUT_SCHEME
998 establish_timeout(data_stream);
999 dds.set_timeout(d_timeout);
1008 if (!get_btp_func_ce().empty()) {
1009 BESDEBUG(MODULE,prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
1013 ConstraintEvaluator func_eval;
1014 DDS *fdds =
nullptr;
1015 if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1019 func_eval.parse_constraint(get_btp_func_ce(), **dds);
1020 fdds = func_eval.eval_function_clauses(**dds);
1023 delete *dds; *dds =
nullptr;
1026 (*dds)->mark_all(
false);
1028 promote_function_output_structures(*dds);
1031 eval.parse_constraint(
get_ce(), **dds);
1033 (*dds)->tag_nested_sequences();
1035 dap_utils::throw_if_too_big(**dds, __FILE__, __LINE__);
1037 if (with_mime_headers)
1038 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1040#if STORE_DAP2_RESULT_FEATURE
1042 if (!store_dap2_result(data_stream, **dds, eval)) {
1051 BESDEBUG(MODULE, prolog <<
"Simple constraint" << endl);
1053 eval.parse_constraint(
get_ce(), **dds);
1054 (*dds)->tag_nested_sequences();
1056 dap_utils::throw_for_dap4_typed_vars_or_attrs(*dds, __FILE__, __LINE__);
1057 dap_utils::throw_if_too_big(**dds, __FILE__, __LINE__);
1059 if (with_mime_headers)
1060 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1062#if STORE_DAP2_RESULT_FEATURE
1064 if (!store_dap2_result(data_stream, **dds, eval)) {
1072 dap_utils::log_response_and_memory_size(prolog, dds);
1077 struct rusage usage;
1079 usage_val = getrusage(RUSAGE_SELF, &usage);
1081 if (usage_val == 0){
1082 long mem_size = usage.ru_maxrss;
1083 INFO_LOG(prolog <<
"request size: "<< req_size <<
"KB -|- memory used by process: " << mem_size <<
"KB" << endl);
1086 INFO_LOG(prolog <<
"request size: "<< req_size <<
"KB" << endl );
1090 data_stream << flush;
1092 BESDEBUG(MODULE, prolog <<
"END"<< endl);
1097 bool with_mime_headers)
1099 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
1101 ostream & data_stream = dhi.get_output_stream();
1102#if USE_LOCAL_TIMEOUT_SCHEME
1104 establish_timeout(data_stream);
1105 dds.set_timeout(d_timeout);
1114 if (!get_btp_func_ce().empty()) {
1115 BESDEBUG(MODULE, prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
1121 auto *bdds =
dynamic_cast<BESDataDDSResponse *
> (response);
1123 throw BESInternalError(
"cast error", __FILE__, __LINE__);
1125 if(!bdds->get_ia_flag()) {
1127 besRH->add_attributes(dhi);
1131 BESDapFunctionResponseCache *response_cache = BESDapFunctionResponseCache::get_instance();
1132 ConstraintEvaluator func_eval;
1133 DDS *fdds =
nullptr;
1134 if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1138 func_eval.parse_constraint(get_btp_func_ce(), **dds);
1139 fdds = func_eval.eval_function_clauses(**dds);
1146 (*dds)->mark_all(
false);
1148 promote_function_output_structures(*dds);
1151 eval.parse_constraint(
get_ce(), **dds);
1153 (*dds)->tag_nested_sequences();
1155 dap_utils::throw_if_too_big(**dds, __FILE__, __LINE__);
1157 if (with_mime_headers)
1158 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1160#if STORE_DAP2_RESULT_FEATURE
1162 if (!store_dap2_result(data_stream, **dds, eval)) {
1171 BESDEBUG(MODULE, prolog <<
"Simple constraint" << endl);
1173 eval.parse_constraint(
get_ce(), **dds);
1174 (*dds)->tag_nested_sequences();
1176 dap_utils::throw_for_dap4_typed_vars_or_attrs(*dds, __FILE__, __LINE__);
1177 dap_utils::throw_if_too_big(**dds, __FILE__, __LINE__);
1179 if (with_mime_headers)
1180 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1182#if STORE_DAP2_RESULT_FEATURE
1184 if (!store_dap2_result(data_stream, **dds, eval)) {
1192 dap_utils::log_response_and_memory_size(prolog,dds);
1195 struct rusage usage;
1197 usage_val = getrusage(RUSAGE_SELF, &usage);
1199 if (usage_val == 0){
1200 long mem_size = usage.ru_maxrss;
1201 INFO_LOG(prolog <<
"request size: "<< req_size <<
"KB -|- memory used by process: " << mem_size <<
"KB" << endl );
1204 INFO_LOG(prolog <<
"request size: "<< req_size <<
"KB" << endl );
1208 data_stream << flush;
1210 BESDEBUG(MODULE, prolog <<
"END"<< endl);
1233 if (with_mime_headers)
1234 set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1236 (*dds)->print_xml_writer(out,
false ,
"");
1242#if USE_LOCAL_TIMEOUT_SCHEME
1244 establish_timeout(out);
1245 dds.set_timeout(d_timeout);
1257 ConstraintEvaluator func_eval;
1258 DDS *fdds =
nullptr;
1259 if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1263 func_eval.parse_constraint(get_btp_func_ce(), **dds);
1264 fdds = func_eval.eval_function_clauses(**dds);
1267 delete *dds; *dds = 0;
1270 (*dds)->mark_all(
false);
1272 promote_function_output_structures(*dds);
1274 eval.parse_constraint(
d_dap2ce, **dds);
1276 if (with_mime_headers)
1277 set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1283 (*dds)->print_xml_writer(out,
true,
"");
1286 eval.parse_constraint(
d_dap2ce, **dds);
1288 if (with_mime_headers)
1289 set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1296 (*dds)->print_xml_writer(out,
true,
"");
1302void BESDapResponseBuilder::send_dmr(ostream &out, DMR &dmr,
bool with_mime_headers)
1309 BESDEBUG(MODULE, prolog <<
"Parsing DAP4 constraint: '"<<
d_dap4ce <<
"'"<< endl);
1311 D4ConstraintEvaluator parser(&dmr);
1312 bool parse_ok = parser.parse(
d_dap4ce);
1315 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1323 dmr.root()->set_send_p(
true);
1326 if (with_mime_headers) set_mime_text(out, dap4_dmr, x_plain, last_modified_time(d_dataset), dmr.dap_version());
1332 BESDEBUG(MODULE, prolog <<
"dmr.request_xml_base(): '"<< dmr.request_xml_base() <<
"' (dmr: " << (
void *) &dmr <<
")" << endl);
1334 if (dmr.get_utf8_xml_encoding()) {
1335 auto xml = XMLWriter(
" ",
"UTF-8");
1336 dmr.print_dap4(xml, !
d_dap4ce.empty() );
1337 out << xml.get_doc() << flush;
1341 dmr.print_dap4(xml, !
d_dap4ce.empty() );
1342 out << xml.get_doc() << flush;
1346void BESDapResponseBuilder::send_dap4_data_using_ce(ostream &out, DMR &dmr,
bool with_mime_headers)
1349 BESDEBUG(MODULE ,
"BESDapResponseBuilder::send_dap4_data_using_ce() - expression constraint is not empty. " <<endl);
1350 D4ConstraintEvaluator parser(&dmr);
1351 bool parse_ok = parser.parse(
d_dap4ce);
1354 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1355 throw BESSyntaxUserError(msg.str(),__FILE__,__LINE__);
1362 dmr.set_ce_empty(
true);
1363 dmr.root()->set_send_p(
true);
1366 dap_utils::log_response_and_memory_size(prolog, dmr);
1367 dap_utils::throw_if_too_big(dmr, __FILE__, __LINE__);
1371 for (
auto i = dmr.root()->var_begin(), e = dmr.root()->var_end(); i != e; ++i) {
1372 BESDEBUG(MODULE , prolog << (*i)->name() << endl);
1373 if ((*i)->send_p()) {
1374 BESDEBUG(MODULE , prolog <<
"Obtain data- " << (*i)->name() << endl);
1375 D4Attributes *d4_attrs = (*i)->attributes();
1376 BESDEBUG(MODULE , prolog <<
"Number of attributes " << d4_attrs << endl);
1377 for (
auto ii = d4_attrs->attribute_begin(), ee = d4_attrs->attribute_end(); ii != ee; ++ii) {
1378 BESDEBUG(MODULE ,prolog <<
"Attribute name is " << (*ii)->name() << endl);
1399 BES_STOPWATCH_START(MODULE, prolog +
"Timer");
1401 BESDEBUG(MODULE , prolog <<
"Expression constraint is not empty. " <<endl);
1402 D4ConstraintEvaluator parser(&dmr);
1403 bool parse_ok = parser.parse(
d_dap4ce);
1406 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1414 dmr.set_ce_empty(
true);
1415 dmr.root()->set_send_p(
true);
1417 dap_utils::throw_if_too_big(dmr, __FILE__, __LINE__);
1420void BESDapResponseBuilder::send_dap4_data(ostream &out, DMR &dmr,
bool with_mime_headers)
1426 D4BaseTypeFactory d4_factory;
1427 DMR function_result(&d4_factory,
"function_results");
1431 if (!ServerFunctionsList::TheList()) {
1433 msg <<
"The function expression could not be evaluated because ";
1434 msg <<
"there are no server-side functions defined on this server.";
1438 D4FunctionEvaluator parser(&dmr, ServerFunctionsList::TheList());
1442 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1443 throw BESSyntaxUserError(msg.str(),__FILE__,__LINE__);
1445 parser.eval(&function_result);
1449 send_dap4_data_using_ce(out, function_result, with_mime_headers);
1452 send_dap4_data_using_ce(out, dmr, with_mime_headers);
1461 BES_STOPWATCH_START(MODULE, prolog +
"Timer");
1462 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
1464 if (with_mime_headers) set_mime_binary(out, dap4_data, x_plain, last_modified_time(d_dataset), dmr.dap_version());
1466 BESDEBUG(MODULE, prolog <<
"dmr.request_xml_base(): \"" << dmr.request_xml_base() <<
"\""<< endl);
1470 if (dmr.get_utf8_xml_encoding())
1471 xml = XMLWriter(
" ",
"UTF-8");
1472 dmr.print_dap4(xml, !
d_dap4ce.empty());
1477 chunked_ostream cos(out, max((
unsigned int) CHUNK_SIZE, xml.get_doc_size() + 2));
1484 cos << xml.get_doc() << CRLF << flush;
1487 D4StreamMarshaller m(cos);
1488 dmr.root()->serialize(m, dmr, !
d_dap4ce.empty());
1489#ifdef CLEAR_LOCAL_DATA
1490 dmr.root()->clear_local_data();
1494 BESDEBUG(MODULE, prolog <<
"END" << endl);
1513 if (!get_store_result().empty()) {
1514 string serviceUrl = get_store_result();
1518 if (dmr.get_utf8_xml_encoding())
1519 xmlWrtr = XMLWriter(
" ",
"UTF-8");
1523 string *stylesheet_ref =
nullptr, ss_ref_value;
1525 if (found && !ss_ref_value.empty()) {
1526 stylesheet_ref = &ss_ref_value;
1530 if (resultCache ==
nullptr) {
1537 string msg =
"The Stored Result request cannot be serviced. ";
1538 msg +=
"Unable to acquire StoredResultCache instance. ";
1539 msg +=
"This is most likely because the StoredResultCache is not (correctly) configured.";
1541 BESDEBUG(MODULE, prolog <<
"[WARNING] " << msg << endl);
1542 d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
1543 out << xmlWrtr.get_doc();
1545 BESDEBUG(MODULE, prolog <<
"Sent AsyncRequestRejected" << endl);
1550 if (!get_async_accepted().empty()) {
1555 BESDEBUG(MODULE, prolog <<
"serviceUrl="<< serviceUrl << endl);
1557 string storedResultId;
1560 BESDEBUG(MODULE,prolog <<
"storedResultId='"<< storedResultId <<
"'" << endl);
1563 BESDEBUG(MODULE, prolog <<
"targetURL='"<< targetURL <<
"'" << endl);
1565 d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
1566 out << xmlWrtr.get_doc();
1568 BESDEBUG(MODULE, prolog <<
"Sent AsyncAccepted" << endl);
1576 d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
1577 out << xmlWrtr.get_doc();
1579 BESDEBUG(MODULE, prolog <<
"Sent AsyncAccepted" << endl);
1609 BES_STOPWATCH_START(MODULE, prolog +
"Timer");
1610 BESDEBUG(MODULE , prolog <<
"BEGIN" << endl);
1612 unique_ptr<DMR> dmr = setup_dap4_intern_data(obj, dhi);
1614 intern_dap4_data_grp(dmr->root());
1616 return dmr.release();
1622 BES_STOPWATCH_START(MODULE, prolog +
"Timer");
1623 BESDEBUG(MODULE , prolog <<
"BEGIN" << endl);
1625 unique_ptr<DMR> dmr = setup_dap4_intern_data(obj, dhi);
1627 return dmr.release();
1635 auto bdmr =
dynamic_cast<BESDMRResponse *
>(obj);
1636 if (!bdmr)
throw BESInternalFatalError(
"Expected a BESDMRResponse instance", __FILE__, __LINE__);
1638 unique_ptr<DMR> dmr(bdmr->get_dmr());
1641 bdmr->set_dmr(
nullptr);
1651 set_async_accepted(dhi.
data[ASYNC]);
1652 set_store_result(dhi.
data[STORE_RESULT]);
1655 D4BaseTypeFactory d4_factory;
1656 unique_ptr<DMR> function_result(
new DMR(&d4_factory,
"function_results"));
1660 if (!ServerFunctionsList::TheList()) {
1662 msg <<
"The function expression could not be evaluated because ";
1663 msg <<
"there are no server-side functions defined on this server.";
1664 throw BESSyntaxUserError(msg.str(),__FILE__,__LINE__);
1667 D4FunctionEvaluator parser(dmr.get(), ServerFunctionsList::TheList());
1671 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1672 throw BESSyntaxUserError(msg.str(),__FILE__,__LINE__);
1675 parser.eval(function_result.get());
1681 return function_result;
1684 BESDEBUG(MODULE , prolog <<
"Processing the constraint expression. " << endl);
1690void BESDapResponseBuilder::intern_dap4_data_grp(libdap::D4Group* grp) {
1691 for (
auto i = grp->var_begin(), e = grp->var_end(); i != e; ++i) {
1692 BESDEBUG(MODULE ,
"BESDapResponseBuilder::intern_dap4_data() - "<< (*i)->name() <<endl);
1693 if ((*i)->send_p()) {
1694 BESDEBUG(MODULE ,
"BESDapResponseBuilder::intern_dap4_data() Obtain data- "<< (*i)->name() <<endl);
1695 (*i)->intern_data();
1699 for (
auto gi = grp->grp_begin(), ge = grp->grp_end(); gi != ge; ++gi) {
1700 BESDEBUG(MODULE ,
"BESDapResponseBuilder::intern_dap4_data() group- "<< (*gi)->name() <<endl);
1701 intern_dap4_data_grp(*gi);
std::string get_container_type() const
retrieve the type of data this container holds, such as cedar or netcdf.
Holds a DDS object within the BES.
Cache the results from server functions.
virtual libdap::DDS * get_or_cache_dataset(libdap::DDS *dds, const std::string &constraint)
Return a DDS loaded with data that can be serialized back to a client.
virtual std::string get_dataset_name() const
Get the dataset name.
virtual libdap::DMR * intern_dap4_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
std::string d_dap4function
DAP4 Constraint expression.
virtual std::string get_dap4function() const
Get the DAP4 server side function expression.
virtual void set_dataset_name(const std::string &_dataset)
Set the dataset pathname.
virtual void split_ce(libdap::ConstraintEvaluator &eval, const std::string &expr="")
virtual std::string get_ce() const
Get the constraint expression.
std::string d_dap2ce
Name of the dataset/database.
virtual libdap::DDS * process_dap2_dds(BESResponseObject *obj, BESDataHandlerInterface &dhi)
Transmit data.
virtual void serialize_dap4_data(std::ostream &out, libdap::DMR &dmr, bool with_mime_headers=true)
virtual libdap::DDS * intern_dap2_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
virtual void send_dds(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool constrained=false, bool with_mime_headers=true)
Transmit a DDS.
virtual void set_dap4function(const std::string &_func)
virtual std::string get_dap4ce() const
Get the DAP4 constraint expression.
virtual void dap4_process_ce_for_intern_data(libdap::DMR &dmr)
Parse the DAP4 CE and throw if the request is too large.
virtual void set_dap4ce(const std::string &_ce)
std::string d_async_accepted
Version string for the library's default protocol version.
virtual void send_ddx(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
virtual void serialize_dap2_data_dds(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool ce_eval=true)
std::string d_store_result
virtual bool store_dap4_result(std::ostream &out, libdap::DMR &dmr)
virtual void set_ce(std::string _ce)
std::string d_btp_func_ce
DAP4 Server Side Function expression.
std::string d_dap4ce
DAP2 Constraint expression.
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
Structure storing information used by the BES to handle the request.
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
void first_container()
set the container pointer to the first container in the containers list
BESContainer * container
pointer to current container in this interface
exception thrown if an internal error is found and is fatal to the BES
Represents a specific data type request handler.
virtual BESResponseObject * get_response_object()
return the current response object
Abstract base class representing a specific set of information in response to a request to the BES.
virtual string store_dap4_result(libdap::DMR &dmr, const string &constraint, BESDapResponseBuilder *rb)
static BESStoredDapResultCache * get_instance()
error thrown if there is a user syntax error in the request or any other user error
static void conditional_timeout_cancel()
Checks if the timeout alarm should be canceled based on the value of the BES key BES....
static std::string assemblePath(const std::string &firstPart, const std::string &secondPart, bool leadingSlash=false, bool trailingSlash=false)
Assemble path fragments making sure that they are separated by a single '/' character.
static RequestServiceTimer * TheTimer()
Return a pointer to a singleton timer instance. If an instance does not exist it will create and init...
void throw_if_timeout_expired(const std::string &message, const std::string &file, const int line)
Checks the RequestServiceTimer to determine if the time spent servicing the request at this point has...
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.