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>
90#if USE_LOCAL_TIMEOUT_SCHEME
92#include <libdap/SignalHandler.h>
93#include <libdap/EventHandler.h>
94#include <libdap/AlarmHandler.h>
98#include "TheBESKeys.h"
99#include "BESDapResponseBuilder.h"
100#include "BESContextManager.h"
101#include "BESDapFunctionResponseCache.h"
102#include "BESStoredDapResultCache.h"
105#include "BESResponseObject.h"
106#include "BESDDSResponse.h"
107#include "BESDataDDSResponse.h"
108#include "BESDMRResponse.h"
109#include "BESDataHandlerInterface.h"
110#include "BESInternalFatalError.h"
111#include "BESSyntaxUserError.h"
112#include "BESDataNames.h"
114#include "BESRequestHandler.h"
115#include "BESRequestHandlerList.h"
116#include "BESNotFoundError.h"
121#include "BESStopWatch.h"
122#include "DapFunctionUtils.h"
123#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(std::string _sr)
225 BESDEBUG(MODULE, prolog <<
"store_result: " << _sr << endl);
228std::string BESDapResponseBuilder::get_async_accepted()
const
233void BESDapResponseBuilder::set_async_accepted(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.length() && 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);
368throw_if_dap2_response_too_big(DDS *dds)
370 if (dds->too_big()) {
373 msg <<
"The Request for " << request_size / 1024 <<
" kilobytes is too large; ";
374 msg <<
"requests on this server are limited to "
375 + long_to_string(dds->get_response_limit() /1024) +
"KB.";
376 throw Error(msg.str());
379 msg <<
"The submitted DAP2 request will generate a " << dds->get_request_size_kb(
true);
380 msg <<
" kilobyte response, which is too large. ";
381 msg <<
"The maximum response size for this server is limited to " << dds->get_response_limit_kb();
382 msg <<
" kilobytes.";
388throw_if_dap4_response_too_big(DMR &dmr)
392 msg <<
"The submitted DAP4 request will generate a " << dmr.request_size_kb(
true);
393 msg <<
" kilobyte response, which is too large. ";
394 msg <<
"The maximum response size for this server is limited to " << dmr.response_limit_kb();
395 msg <<
" kilobytes.";
414void BESDapResponseBuilder::send_das(ostream &out, DAS &das,
bool with_mime_headers)
const
416 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
"2.0");
440void BESDapResponseBuilder::send_das(ostream &out, DDS **dds, ConstraintEvaluator &eval,
bool constrained,
441 bool with_mime_headers)
443#if USE_LOCAL_TIMEOUT_SCHEME
445 establish_timeout(out);
446 dds.set_timeout(d_timeout);
453 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
"2.0");
457 (*dds)->print_das(out);
469 ConstraintEvaluator func_eval;
473 if (responseCache && responseCache->can_be_cached(*dds, get_btp_func_ce())) {
477 func_eval.parse_constraint(get_btp_func_ce(), **dds);
478 fdds = func_eval.eval_function_clauses(**dds);
481 delete *dds; *dds = 0;
484 if (with_mime_headers)
485 set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
490 (*dds)->print_das(out);
493 eval.parse_constraint(
d_dap2ce, **dds);
495 if (with_mime_headers)
496 set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
501 (*dds)->print_das(out);
527 bool with_mime_headers)
530 if (with_mime_headers)
531 set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
542#if USE_LOCAL_TIMEOUT_SCHEME
544 establish_timeout(out);
545 dds.set_timeout(d_timeout);
555 ConstraintEvaluator func_eval;
560 if (responseCache && responseCache->can_be_cached(*dds, get_btp_func_ce())) {
564 func_eval.parse_constraint(get_btp_func_ce(), **dds);
565 fdds = func_eval.eval_function_clauses(**dds);
568 delete *dds; *dds = 0;
576 (*dds)->mark_all(
false);
588 promote_function_output_structures(*dds);
590 eval.parse_constraint(
d_dap2ce, **dds);
592 if (with_mime_headers)
593 set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
599 (*dds)->print_constrained(out);
602 eval.parse_constraint(
d_dap2ce, **dds);
604 if (with_mime_headers)
605 set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset),(*dds)->get_dap_version());
611 (*dds)->print_constrained(out);
617#ifdef DAP2_STORED_RESULTS
632bool BESDapResponseBuilder::store_dap2_result(ostream &out, DDS &dds, ConstraintEvaluator &eval)
634 if (get_store_result().empty())
return false;
636 string serviceUrl = get_store_result();
647 string *stylesheet_ref = 0, ss_ref_value;
649 if (found && !ss_ref_value.empty()) {
650 stylesheet_ref = &ss_ref_value;
654 if (resultCache == NULL) {
661 string msg =
"The Stored Result request cannot be serviced. ";
662 msg +=
"Unable to acquire StoredResultCache instance. ";
663 msg +=
"This is most likely because the StoredResultCache is not (correctly) configured.";
665 BESDEBUG(MODULE, prolog <<
"[WARNING] " << msg << endl);
667 d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
668 out << xmlWrtr.get_doc();
671 BESDEBUG(MODULE,prolog <<
"Sent AsyncRequestRejected" << endl);
673 else if (get_async_accepted().length() != 0) {
678 BESDEBUG(MODULE, prolog <<
"serviceUrl="<< serviceUrl << endl);
681 string storedResultId =
"";
682 storedResultId = resultCache->store_dap2_result(dds,
get_ce(),
this, &eval);
684 BESDEBUG(MODULE, prolog <<
"storedResultId='"<< storedResultId <<
"'" << endl);
687 BESDEBUG(MODULE, prolog <<
"targetURL='"<< targetURL <<
"'" << endl);
690 d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
691 out << xmlWrtr.get_doc();
694 BESDEBUG(MODULE, prolog <<
"Sent DAP4 AsyncAccepted response" << endl);
701 d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
702 out << xmlWrtr.get_doc();
705 BESDEBUG(MODULE, prolog <<
"Sent DAP4 AsyncRequired response" << endl);
719 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
725 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
727 (*dds)->print_constrained(out);
731 XDRStreamMarshaller m(out);
734 for (DDS::Vars_iter i = (*dds)->var_begin(); i != (*dds)->var_end(); i++) {
735 if ((*i)->send_p()) {
737 (*i)->serialize(eval, **dds, m, ce_eval);
738#ifdef CLEAR_LOCAL_DATA
739 (*i)->clear_local_data();
744 BESDEBUG(MODULE, prolog <<
"END" << endl);
747#ifdef DAP2_STORED_RESULTS
756void BESDapResponseBuilder::serialize_dap2_data_ddx(ostream &out, DDS **dds, ConstraintEvaluator &eval,
757 const string &boundary,
const string &start,
bool ce_eval)
759 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
762 libdap::set_mime_ddx_boundary(out, boundary, start, dods_ddx, x_plain);
768 uuid_unparse(uu, uuid.data());
770 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0) strncpy(domain,
"opendap.org", 255);
772 string cid = string(uuid.data()) +
"@" + string(domain.data());
776 (*dds)->print_xml_writer(out,
true, cid);
779 set_mime_data_boundary(out, boundary, cid, dods_data_ddx , x_plain);
781 XDRStreamMarshaller m(out);
783 conditional_timeout_cancel();
787 for (DDS::Vars_iter i = (*dds)->var_begin(); i != (*dds)->var_end(); i++) {
788 if ((*i)->send_p()) {
789 (*i)->serialize(eval, **dds, m, ce_eval);
790#ifdef CLEAR_LOCAL_DATA
791 (*i)->clear_local_data();
796 BESDEBUG(MODULE, prolog <<
"END" << endl);
817void BESDapResponseBuilder::remove_timeout()
const
819#if USE_LOCAL_TIMEOUT_SCHEME
841 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
852 set_async_accepted(dhi.
data[ASYNC]);
853 set_store_result(dhi.
data[STORE_RESULT]);
855 ConstraintEvaluator &eval = bdds->
get_ce();
866 ConstraintEvaluator func_eval;
868 if (responseCache && responseCache->can_be_cached(dds, get_btp_func_ce())) {
872 func_eval.parse_constraint(get_btp_func_ce(), *dds);
873 fdds = func_eval.eval_function_clauses(*dds);
880 dds->mark_all(
false);
882 promote_function_output_structures(dds);
885 eval.parse_constraint(
d_dap2ce, *dds);
886 BESDEBUG(MODULE, prolog <<
"END"<< endl);
912 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
914 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
919 if (!bdds)
throw BESInternalFatalError(
"Expected a BESDataDDSResponse instance", __FILE__, __LINE__);
921 DDS *dds = bdds->get_dds();
925 set_async_accepted(dhi.
data[ASYNC]);
926 set_store_result(dhi.
data[STORE_RESULT]);
931 if(bdds->get_ia_flag() ==
false) {
933 besRH->add_attributes(dhi);
936 ConstraintEvaluator &eval = bdds->get_ce();
944 if (!get_btp_func_ce().empty()) {
945 BESDEBUG(MODULE,prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
949 ConstraintEvaluator func_eval;
951 if (responseCache && responseCache->can_be_cached(dds, get_btp_func_ce())) {
955 func_eval.parse_constraint(get_btp_func_ce(), *dds);
956 fdds = func_eval.eval_function_clauses(*dds);
968 dds->mark_all(
false);
979 promote_function_output_structures(dds);
983 eval.parse_constraint(
get_ce(), *dds);
985 dds->tag_nested_sequences();
987 throw_if_dap2_response_too_big(dds);
991 for (DDS::Vars_iter i = dds->var_begin(), e = dds->var_end(); i != e; ++i) {
992 if ((*i)->send_p()) {
994 (*i)->intern_data(eval, *dds);
996 catch(std::exception &e) {
997 throw BESSyntaxUserError(
string(
"Caught a C++ standard exception while working on '") + (*i)->name() +
"' The error was: " + e.what(), __FILE__, __LINE__);
1002 BESDEBUG(MODULE, prolog <<
"END"<< endl);
1019void BESDapResponseBuilder::send_dap2_data(ostream &data_stream, DDS **dds, ConstraintEvaluator &eval,
1020 bool with_mime_headers)
1022 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
1024#if USE_LOCAL_TIMEOUT_SCHEME
1026 establish_timeout(data_stream);
1027 dds.set_timeout(d_timeout);
1036 if (!get_btp_func_ce().empty()) {
1037 BESDEBUG(MODULE,prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
1041 ConstraintEvaluator func_eval;
1043 if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1047 func_eval.parse_constraint(get_btp_func_ce(), **dds);
1048 fdds = func_eval.eval_function_clauses(**dds);
1051 delete *dds; *dds = 0;
1054 (*dds)->mark_all(
false);
1056 promote_function_output_structures(*dds);
1059 eval.parse_constraint(
get_ce(), **dds);
1061 (*dds)->tag_nested_sequences();
1063 throw_if_dap2_response_too_big(*dds);
1065 if (with_mime_headers)
1066 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1068#if STORE_DAP2_RESULT_FEATURE
1070 if (!store_dap2_result(data_stream, **dds, eval)) {
1079 BESDEBUG(MODULE, prolog <<
"Simple constraint" << endl);
1081 eval.parse_constraint(
get_ce(), **dds);
1083 (*dds)->tag_nested_sequences();
1085 throw_if_dap2_response_too_big(*dds);
1087 if (with_mime_headers)
1088 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1090#if STORE_DAP2_RESULT_FEATURE
1092 if (!store_dap2_result(data_stream, **dds, eval)) {
1100 dap_utils::log_request_and_memory_size(dds);
1105 struct rusage usage;
1107 usage_val = getrusage(RUSAGE_SELF, &usage);
1109 if (usage_val == 0){
1110 long mem_size = usage.ru_maxrss;
1111 INFO_LOG(prolog <<
"request size: "<< req_size <<
"KB -|- memory used by process: " << mem_size <<
"KB" << endl);
1114 INFO_LOG(prolog <<
"request size: "<< req_size <<
"KB" << endl );
1118 data_stream << flush;
1120 BESDEBUG(MODULE, prolog <<
"END"<< endl);
1125 bool with_mime_headers)
1127 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
1129 ostream & data_stream = dhi.get_output_stream();
1130#if USE_LOCAL_TIMEOUT_SCHEME
1132 establish_timeout(data_stream);
1133 dds.set_timeout(d_timeout);
1142 if (!get_btp_func_ce().empty()) {
1143 BESDEBUG(MODULE, prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
1153 if(!bdds->get_ia_flag()) {
1155 besRH->add_attributes(dhi);
1160 ConstraintEvaluator func_eval;
1161 DDS *fdds =
nullptr;
1162 if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1166 func_eval.parse_constraint(get_btp_func_ce(), **dds);
1167 fdds = func_eval.eval_function_clauses(**dds);
1174 (*dds)->mark_all(
false);
1176 promote_function_output_structures(*dds);
1179 eval.parse_constraint(
get_ce(), **dds);
1181 (*dds)->tag_nested_sequences();
1183 throw_if_dap2_response_too_big(*dds);
1185 if (with_mime_headers)
1186 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1188#if STORE_DAP2_RESULT_FEATURE
1190 if (!store_dap2_result(data_stream, **dds, eval)) {
1199 BESDEBUG(MODULE, prolog <<
"Simple constraint" << endl);
1201 eval.parse_constraint(
get_ce(), **dds);
1203 (*dds)->tag_nested_sequences();
1205 throw_if_dap2_response_too_big(*dds);
1207 if (with_mime_headers)
1208 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1210#if STORE_DAP2_RESULT_FEATURE
1212 if (!store_dap2_result(data_stream, **dds, eval)) {
1220 dap_utils::log_request_and_memory_size(dds);
1223 struct rusage usage;
1225 usage_val = getrusage(RUSAGE_SELF, &usage);
1227 if (usage_val == 0){
1228 long mem_size = usage.ru_maxrss;
1229 INFO_LOG(prolog <<
"request size: "<< req_size <<
"KB -|- memory used by process: " << mem_size <<
"KB" << endl );
1232 INFO_LOG(prolog <<
"request size: "<< req_size <<
"KB" << endl );
1236 data_stream << flush;
1238 BESDEBUG(MODULE, prolog <<
"END"<< endl);
1261 if (with_mime_headers)
1262 set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1264 (*dds)->print_xml_writer(out,
false ,
"");
1270#if USE_LOCAL_TIMEOUT_SCHEME
1272 establish_timeout(out);
1273 dds.set_timeout(d_timeout);
1285 ConstraintEvaluator func_eval;
1287 if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1291 func_eval.parse_constraint(get_btp_func_ce(), **dds);
1292 fdds = func_eval.eval_function_clauses(**dds);
1295 delete *dds; *dds = 0;
1298 (*dds)->mark_all(
false);
1300 promote_function_output_structures(*dds);
1302 eval.parse_constraint(
d_dap2ce, **dds);
1304 if (with_mime_headers)
1305 set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1311 (*dds)->print_xml_writer(out,
true,
"");
1314 eval.parse_constraint(
d_dap2ce, **dds);
1316 if (with_mime_headers)
1317 set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1324 (*dds)->print_xml_writer(out,
true,
"");
1330void BESDapResponseBuilder::send_dmr(ostream &out, DMR &dmr,
bool with_mime_headers)
1337 BESDEBUG(MODULE, prolog <<
"Parsing DAP4 constraint: '"<<
d_dap4ce <<
"'"<< endl);
1339 D4ConstraintEvaluator parser(&dmr);
1340 bool parse_ok = parser.parse(
d_dap4ce);
1343 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1351 dmr.root()->set_send_p(
true);
1354 if (with_mime_headers) set_mime_text(out, dap4_dmr, x_plain, last_modified_time(d_dataset), dmr.dap_version());
1360 BESDEBUG(MODULE, prolog <<
"dmr.request_xml_base(): '"<< dmr.request_xml_base() <<
"' (dmr: " << (
void *) &dmr <<
")" << endl);
1363 dmr.print_dap4(xml, !
d_dap4ce.empty() );
1364 out << xml.get_doc() << flush;
1367void BESDapResponseBuilder::send_dap4_data_using_ce(ostream &out, DMR &dmr,
bool with_mime_headers)
1370 BESDEBUG(MODULE ,
"BESDapResponseBuilder::send_dap4_data_using_ce() - expression constraint is not empty. " <<endl);
1371 D4ConstraintEvaluator parser(&dmr);
1372 bool parse_ok = parser.parse(
d_dap4ce);
1375 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1383 dmr.set_ce_empty(
true);
1384 dmr.root()->set_send_p(
true);
1387 dap_utils::log_request_and_memory_size(dmr);
1388 throw_if_dap4_response_too_big(dmr);
1392 for (
auto i = dmr.root()->var_begin(), e = dmr.root()->var_end(); i != e; ++i) {
1393 BESDEBUG(MODULE , prolog << (*i)->name() << endl);
1394 if ((*i)->send_p()) {
1395 BESDEBUG(MODULE , prolog <<
"Obtain data- " << (*i)->name() << endl);
1396 D4Attributes *d4_attrs = (*i)->attributes();
1397 BESDEBUG(MODULE , prolog <<
"Number of attributes " << d4_attrs << endl);
1398 for (
auto ii = d4_attrs->attribute_begin(), ee = d4_attrs->attribute_end(); ii != ee; ++ii) {
1399 BESDEBUG(MODULE ,prolog <<
"Attribute name is " << (*ii)->name() << endl);
1421 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
1423 BESDEBUG(MODULE , prolog <<
"Expression constraint is not empty. " <<endl);
1424 D4ConstraintEvaluator parser(&dmr);
1425 bool parse_ok = parser.parse(
d_dap4ce);
1428 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1436 dmr.set_ce_empty(
true);
1437 dmr.root()->set_send_p(
true);
1439 throw_if_dap4_response_too_big(dmr);
1442void BESDapResponseBuilder::send_dap4_data(ostream &out, DMR &dmr,
bool with_mime_headers)
1448 D4BaseTypeFactory d4_factory;
1449 DMR function_result(&d4_factory,
"function_results");
1453 if (!ServerFunctionsList::TheList()) {
1455 msg <<
"The function expression could not be evaluated because ";
1456 msg <<
"there are no server-side functions defined on this server.";
1460 D4FunctionEvaluator parser(&dmr, ServerFunctionsList::TheList());
1464 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1467 parser.eval(&function_result);
1471 send_dap4_data_using_ce(out, function_result, with_mime_headers);
1474 send_dap4_data_using_ce(out, dmr, with_mime_headers);
1484 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
1486 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
1488 if (with_mime_headers) set_mime_binary(out, dap4_data, x_plain, last_modified_time(d_dataset), dmr.dap_version());
1490 BESDEBUG(MODULE, prolog <<
"dmr.request_xml_base(): \"" << dmr.request_xml_base() <<
"\""<< endl);
1494 dmr.print_dap4(xml, !
d_dap4ce.empty());
1499 chunked_ostream cos(out, max((
unsigned int) CHUNK_SIZE, xml.get_doc_size() + 2));
1506 cos << xml.get_doc() << CRLF << flush;
1509 D4StreamMarshaller m(cos);
1510 dmr.root()->serialize(m, dmr, !
d_dap4ce.empty());
1511#ifdef CLEAR_LOCAL_DATA
1512 dmr.root()->clear_local_data();
1516 BESDEBUG(MODULE, prolog <<
"END" << endl);
1535 if (get_store_result().length() != 0) {
1536 string serviceUrl = get_store_result();
1543 string *stylesheet_ref = 0, ss_ref_value;
1545 if (found && !ss_ref_value.empty()) {
1546 stylesheet_ref = &ss_ref_value;
1550 if (resultCache == NULL) {
1557 string msg =
"The Stored Result request cannot be serviced. ";
1558 msg +=
"Unable to acquire StoredResultCache instance. ";
1559 msg +=
"This is most likely because the StoredResultCache is not (correctly) configured.";
1561 BESDEBUG(MODULE, prolog <<
"[WARNING] " << msg << endl);
1562 d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
1563 out << xmlWrtr.get_doc();
1565 BESDEBUG(MODULE, prolog <<
"Sent AsyncRequestRejected" << endl);
1570 if (get_async_accepted().length() != 0) {
1575 BESDEBUG(MODULE, prolog <<
"serviceUrl="<< serviceUrl << endl);
1577 string storedResultId =
"";
1580 BESDEBUG(MODULE,prolog <<
"storedResultId='"<< storedResultId <<
"'" << endl);
1583 BESDEBUG(MODULE, prolog <<
"targetURL='"<< targetURL <<
"'" << endl);
1585 d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
1586 out << xmlWrtr.get_doc();
1588 BESDEBUG(MODULE, prolog <<
"Sent AsyncAccepted" << endl);
1596 d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
1597 out << xmlWrtr.get_doc();
1599 BESDEBUG(MODULE, prolog <<
"Sent AsyncAccepted" << endl);
1630 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
1631 BESDEBUG(MODULE , prolog <<
"BEGIN" << endl);
1633 unique_ptr<DMR> dmr = setup_dap4_intern_data(obj, dhi);
1635 intern_dap4_data_grp(dmr->root());
1637 return dmr.release();
1648 unique_ptr<DMR> dmr(bdmr->get_dmr());
1651 bdmr->set_dmr(
nullptr);
1661 set_async_accepted(dhi.
data[ASYNC]);
1662 set_store_result(dhi.
data[STORE_RESULT]);
1665 D4BaseTypeFactory d4_factory;
1666 unique_ptr<DMR> function_result(
new DMR(&d4_factory,
"function_results"));
1670 if (!ServerFunctionsList::TheList()) {
1672 msg <<
"The function expression could not be evaluated because ";
1673 msg <<
"there are no server-side functions defined on this server.";
1677 D4FunctionEvaluator parser(dmr.get(), ServerFunctionsList::TheList());
1681 msg <<
"Failed to parse the provided DAP4 server-side function expression: " <<
d_dap4function;
1685 parser.eval(function_result.get());
1691 return function_result;
1694 BESDEBUG(MODULE , prolog <<
"Processing the constraint expression. " << endl);
1700void BESDapResponseBuilder::intern_dap4_data_grp(libdap::D4Group* grp) {
1701 for (D4Group::Vars_iter i = grp->var_begin(), e = grp->var_end(); i != e; ++i) {
1702 BESDEBUG(MODULE ,
"BESDapResponseBuilder::intern_dap4_data() - "<< (*i)->name() <<endl);
1703 if ((*i)->send_p()) {
1704 BESDEBUG(MODULE ,
"BESDapResponseBuilder::intern_dap4_data() Obtain data- "<< (*i)->name() <<endl);
1705 (*i)->intern_data();
1709 for (D4Group::groupsIter gi = grp->grp_begin(), ge = grp->grp_end(); gi != ge; ++gi) {
1710 BESDEBUG(MODULE ,
"BESDapResponseBuilder::intern_dap4_data() group- "<< (*gi)->name() <<endl);
1711 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.
libdap::ConstraintEvaluator & get_ce()
void set_dds(libdap::DDS *ddsIn)
Represents an OPeNDAP DMR DAP4 data 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 void set_dataset_name(const std::string _dataset)
Set the dataset pathname.
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 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 void set_dap4ce(std::string _ce)
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 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.
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 void set_dap4function(std::string _func)
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.
void set_dds(libdap::DDS *ddsIn)
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
static bool IsSet(const std::string &flagName)
see if the debug context flagName is set to true
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
virtual BESRequestHandler * find_handler(const std::string &handler_name)
find and return the specified request handler
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 bool start(std::string name)
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()