31 #ifdef HAVE_UUID_UUID_H
32 #include <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
62 #include <Structure.h>
63 #include <ConstraintEvaluator.h>
64 #include <DDXParserSAX2.h>
65 #include <Ancillary.h>
66 #include <XDRStreamMarshaller.h>
67 #include <XDRFileUnMarshaller.h>
71 #include <D4Attributes.h>
72 #include <XMLWriter.h>
73 #include <D4AsyncUtil.h>
74 #include <D4StreamMarshaller.h>
75 #include <chunked_ostream.h>
76 #include <chunked_istream.h>
77 #include <D4ConstraintEvaluator.h>
78 #include <D4FunctionEvaluator.h>
79 #include <D4BaseTypeFactory.h>
81 #include <ServerFunctionsList.h>
83 #include <mime_util.h>
87 #if USE_LOCAL_TIMEOUT_SCHEME
89 #include <SignalHandler.h>
90 #include <EventHandler.h>
91 #include <AlarmHandler.h>
95 #include "TheBESKeys.h"
96 #include "BESDapResponseBuilder.h"
97 #include "BESContextManager.h"
98 #include "BESDapFunctionResponseCache.h"
99 #include "BESStoredDapResultCache.h"
102 #include "BESResponseObject.h"
103 #include "BESDDSResponse.h"
104 #include "BESDataDDSResponse.h"
105 #include "BESDMRResponse.h"
106 #include "BESDataHandlerInterface.h"
107 #include "BESInternalFatalError.h"
108 #include "BESSyntaxUserError.h"
109 #include "BESDataNames.h"
111 #include "BESRequestHandler.h"
112 #include "BESRequestHandlerList.h"
113 #include "BESNotFoundError.h"
116 #include "BESDebug.h"
118 #include "BESStopWatch.h"
119 #include "DapFunctionUtils.h"
124 const string CRLF =
"\r\n";
125 const string BES_KEY_TIMEOUT_CANCEL =
"BES.CancelTimeoutOnSend";
128 #define prolog std::string("BESDapResponseBuilder::").append(__func__).append("() - ")
137 string cancel_timeout_on_send =
"";
139 if (found && !cancel_timeout_on_send.empty()) {
141 downcase(cancel_timeout_on_send);
142 if (cancel_timeout_on_send ==
"yes" || cancel_timeout_on_send ==
"true")
143 d_cancel_timeout_on_send =
true;
147 BESDapResponseBuilder::~BESDapResponseBuilder()
149 #if USE_LOCAL_TIMEOUT_SCHEME
153 delete dynamic_cast<AlarmHandler*
>(SignalHandler::instance()->remove_handler(SIGALRM));
180 d_dap2ce = www2id(_ce,
"%",
"%20");
203 d_dap4ce = www2id(_ce,
"%",
"%20");
211 return d_dap4function;
227 d_dap4function = www2id(_func,
"%",
"%20");
230 std::string BESDapResponseBuilder::get_store_result()
const
232 return d_store_result;
235 void BESDapResponseBuilder::set_store_result(std::string _sr)
237 d_store_result = _sr;
238 BESDEBUG(MODULE, prolog <<
"store_result: " << _sr << endl);
241 std::string BESDapResponseBuilder::get_async_accepted()
const
243 return d_async_accepted;
246 void BESDapResponseBuilder::set_async_accepted(std::string _aa)
248 d_async_accepted = _aa;
249 BESDEBUG(MODULE, prolog <<
"set_async_accepted() - async_accepted: " << _aa << endl);
277 d_dataset = www2id(ds,
"%",
"%20");
305 #if USE_LOCAL_TIMEOUT_SCHEME
320 #if USE_LOCAL_TIMEOUT_SCHEME
343 if (d_cancel_timeout_on_send)
357 #if USE_LOCAL_TIMEOUT_SCHEME
359 SignalHandler *sh = SignalHandler::instance();
360 EventHandler *old_eh = sh->register_handler(SIGALRM,
new AlarmHandler());
374 #if USE_LOCAL_TIMEOUT_SCHEME
377 SignalHandler *sh = SignalHandler::instance();
378 EventHandler *old_eh = sh->register_handler(SIGALRM,
new AlarmHandler());
400 static string::size_type find_closing_paren(
const string &ce, string::size_type pos)
407 pos = ce.find_first_of(
"()", pos + 1);
408 if (pos == string::npos)
409 throw Error(malformed_expr,
"Expected to find a matching closing parenthesis in " + ce);
429 BESDEBUG(MODULE, prolog <<
"source expression: " << expr << endl);
437 string btp_function_ce =
"";
438 string::size_type pos = 0;
442 string::size_type first_paren = ce.find(
"(", pos);
443 string::size_type closing_paren = string::npos;
444 if (first_paren != string::npos) closing_paren = find_closing_paren(ce, first_paren);
446 while (first_paren != string::npos && closing_paren != string::npos) {
448 string name = ce.substr(pos, first_paren - pos);
452 if (eval.find_function(name, &f)) {
454 if (!btp_function_ce.empty()) btp_function_ce +=
",";
455 btp_function_ce += ce.substr(pos, closing_paren + 1 - pos);
456 ce.erase(pos, closing_paren + 1 - pos);
457 if (ce[pos] ==
',') ce.erase(pos, 1);
460 pos = closing_paren + 1;
462 if (pos < ce.length() && ce.at(pos) ==
',') ++pos;
465 first_paren = ce.find(
"(", pos);
466 closing_paren = ce.find(
")", pos);
470 d_btp_func_ce = btp_function_ce;
472 BESDEBUG(MODULE, prolog <<
"Modified constraint: " << d_dap2ce << endl);
473 BESDEBUG(MODULE, prolog <<
"BTP Function part: " << btp_function_ce << endl);
474 BESDEBUG(MODULE, prolog <<
"END" << endl);
484 throw_if_dap2_response_too_big(DDS *dds)
486 if (dds->get_response_limit() != 0 && ((dds->get_request_size(
true)) > dds->get_response_limit())) {
487 string msg =
"The Request for " + long_to_string(dds->get_request_size(
true) / 1024)
488 +
"KB is too large; requests on this server are limited to "
489 + long_to_string(dds->get_response_limit() /1024) +
"KB.";
508 void BESDapResponseBuilder::send_das(ostream &out, DAS &das,
bool with_mime_headers)
const
510 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
"2.0");
534 void BESDapResponseBuilder::send_das(ostream &out, DDS **dds, ConstraintEvaluator &eval,
bool constrained,
535 bool with_mime_headers)
537 #if USE_LOCAL_TIMEOUT_SCHEME
539 establish_timeout(out);
540 dds.set_timeout(d_timeout);
543 if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset),
"2.0");
545 conditional_timeout_cancel();
547 (*dds)->print_das(out);
558 if (!d_btp_func_ce.empty()) {
559 ConstraintEvaluator func_eval;
563 if (responseCache && responseCache->can_be_cached(*dds, get_btp_func_ce())) {
567 func_eval.parse_constraint(get_btp_func_ce(), **dds);
568 fdds = func_eval.eval_function_clauses(**dds);
571 delete *dds; *dds = 0;
574 if (with_mime_headers)
575 set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
577 conditional_timeout_cancel();
579 (*dds)->print_das(out);
582 eval.parse_constraint(d_dap2ce, **dds);
584 if (with_mime_headers)
585 set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
587 conditional_timeout_cancel();
589 (*dds)->print_das(out);
615 bool with_mime_headers)
618 if (with_mime_headers)
619 set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
621 conditional_timeout_cancel();
628 #if USE_LOCAL_TIMEOUT_SCHEME
630 establish_timeout(out);
631 dds.set_timeout(d_timeout);
640 if (!d_btp_func_ce.empty()) {
641 ConstraintEvaluator func_eval;
646 if (responseCache && responseCache->can_be_cached(*dds, get_btp_func_ce())) {
650 func_eval.parse_constraint(get_btp_func_ce(), **dds);
651 fdds = func_eval.eval_function_clauses(**dds);
654 delete *dds; *dds = 0;
662 (*dds)->mark_all(
false);
674 promote_function_output_structures(*dds);
676 eval.parse_constraint(d_dap2ce, **dds);
678 if (with_mime_headers)
679 set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
682 conditional_timeout_cancel();
684 (*dds)->print_constrained(out);
687 eval.parse_constraint(d_dap2ce, **dds);
689 if (with_mime_headers)
690 set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset),(*dds)->get_dap_version());
692 conditional_timeout_cancel();
694 (*dds)->print_constrained(out);
700 #ifdef DAP2_STORED_RESULTS
715 bool BESDapResponseBuilder::store_dap2_result(ostream &out, DDS &dds, ConstraintEvaluator &eval)
717 if (get_store_result().empty())
return false;
719 string serviceUrl = get_store_result();
730 string *stylesheet_ref = 0, ss_ref_value;
732 if (found && ss_ref_value.length() > 0) {
733 stylesheet_ref = &ss_ref_value;
737 if (resultCache == NULL) {
744 string msg =
"The Stored Result request cannot be serviced. ";
745 msg +=
"Unable to acquire StoredResultCache instance. ";
746 msg +=
"This is most likely because the StoredResultCache is not (correctly) configured.";
748 BESDEBUG(MODULE, prolog <<
"[WARNING] " << msg << endl);
750 d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
751 out << xmlWrtr.get_doc();
754 BESDEBUG(MODULE,prolog <<
"Sent AsyncRequestRejected" << endl);
756 else if (get_async_accepted().length() != 0) {
761 BESDEBUG(MODULE, prolog <<
"serviceUrl="<< serviceUrl << endl);
764 string storedResultId =
"";
765 storedResultId = resultCache->store_dap2_result(dds, get_ce(),
this, &eval);
767 BESDEBUG(MODULE, prolog <<
"storedResultId='"<< storedResultId <<
"'" << endl);
770 BESDEBUG(MODULE, prolog <<
"targetURL='"<< targetURL <<
"'" << endl);
773 d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
774 out << xmlWrtr.get_doc();
777 BESDEBUG(MODULE, prolog <<
"Sent DAP4 AsyncAccepted response" << endl);
784 d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
785 out << xmlWrtr.get_doc();
788 BESDEBUG(MODULE, prolog <<
"Sent DAP4 AsyncRequired response" << endl);
802 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
804 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
806 (*dds)->print_constrained(out);
810 XDRStreamMarshaller m(out);
814 conditional_timeout_cancel();
817 for (DDS::Vars_iter i = (*dds)->var_begin(); i != (*dds)->var_end(); i++) {
818 if ((*i)->send_p()) {
819 (*i)->serialize(eval, **dds, m, ce_eval);
820 #ifdef CLEAR_LOCAL_DATA
821 (*i)->clear_local_data();
826 BESDEBUG(MODULE, prolog <<
"END" << endl);
829 #ifdef DAP2_STORED_RESULTS
838 void BESDapResponseBuilder::serialize_dap2_data_ddx(ostream &out, DDS **dds, ConstraintEvaluator &eval,
839 const string &boundary,
const string &start,
bool ce_eval)
841 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
844 libdap::set_mime_ddx_boundary(out, boundary, start, dods_ddx, x_plain);
850 uuid_unparse(uu, &uuid[0]);
852 if (getdomainname(domain, 255) != 0 || strlen(domain) == 0) strncpy(domain,
"opendap.org", 255);
854 string cid = string(&uuid[0]) +
"@" + string(&domain[0]);
858 (*dds)->print_xml_writer(out,
true, cid);
861 set_mime_data_boundary(out, boundary, cid, dods_data_ddx , x_plain);
863 XDRStreamMarshaller m(out);
865 conditional_timeout_cancel();
869 for (DDS::Vars_iter i = (*dds)->var_begin(); i != (*dds)->var_end(); i++) {
870 if ((*i)->send_p()) {
871 (*i)->serialize(eval, **dds, m, ce_eval);
872 #ifdef CLEAR_LOCAL_DATA
873 (*i)->clear_local_data();
878 BESDEBUG(MODULE, prolog <<
"END" << endl);
900 #if USE_LOCAL_TIMEOUT_SCHEME
921 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
930 set_dataset_name(dds->filename());
931 set_ce(dhi.
data[POST_CONSTRAINT]);
932 set_async_accepted(dhi.
data[ASYNC]);
933 set_store_result(dhi.
data[STORE_RESULT]);
935 ConstraintEvaluator &eval = bdds->
get_ce();
943 if (!d_btp_func_ce.empty()) {
946 ConstraintEvaluator func_eval;
948 if (responseCache && responseCache->can_be_cached(dds, get_btp_func_ce())) {
952 func_eval.parse_constraint(get_btp_func_ce(), *dds);
953 fdds = func_eval.eval_function_clauses(*dds);
960 dds->mark_all(
false);
962 promote_function_output_structures(dds);
965 eval.parse_constraint(d_dap2ce, *dds);
966 BESDEBUG(MODULE, prolog <<
"END"<< endl);
992 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
994 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
999 if (!bdds)
throw BESInternalFatalError(
"Expected a BESDataDDSResponse instance", __FILE__, __LINE__);
1001 DDS *dds = bdds->get_dds();
1003 set_dataset_name(dds->filename());
1004 set_ce(dhi.
data[POST_CONSTRAINT]);
1005 set_async_accepted(dhi.
data[ASYNC]);
1006 set_store_result(dhi.
data[STORE_RESULT]);
1011 if(bdds->get_ia_flag() ==
false) {
1013 besRH->add_attributes(dhi);
1016 ConstraintEvaluator &eval = bdds->get_ce();
1024 if (!get_btp_func_ce().empty()) {
1025 BESDEBUG(MODULE,prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
1029 ConstraintEvaluator func_eval;
1031 if (responseCache && responseCache->can_be_cached(dds, get_btp_func_ce())) {
1035 func_eval.parse_constraint(get_btp_func_ce(), *dds);
1036 fdds = func_eval.eval_function_clauses(*dds);
1048 dds->mark_all(
false);
1059 promote_function_output_structures(dds);
1063 eval.parse_constraint(get_ce(), *dds);
1065 dds->tag_nested_sequences();
1067 throw_if_dap2_response_too_big(dds);
1071 for (DDS::Vars_iter i = dds->var_begin(), e = dds->var_end(); i != e; ++i) {
1072 if ((*i)->send_p()) {
1074 (*i)->intern_data(eval, *dds);
1076 catch(std::exception &e) {
1077 throw BESSyntaxUserError(
string(
"Caught a C++ standard exception while working on '") + (*i)->name() +
"' The error was: " + e.what(), __FILE__, __LINE__);
1082 BESDEBUG(MODULE, prolog <<
"END"<< endl);
1100 void BESDapResponseBuilder::send_dap2_data(ostream &data_stream, DDS **dds, ConstraintEvaluator &eval,
1101 bool with_mime_headers)
1103 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
1105 #if USE_LOCAL_TIMEOUT_SCHEME
1107 establish_timeout(data_stream);
1108 dds.set_timeout(d_timeout);
1117 if (!get_btp_func_ce().empty()) {
1118 BESDEBUG(MODULE,prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
1122 ConstraintEvaluator func_eval;
1124 if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1128 func_eval.parse_constraint(get_btp_func_ce(), **dds);
1129 fdds = func_eval.eval_function_clauses(**dds);
1132 delete *dds; *dds = 0;
1135 (*dds)->mark_all(
false);
1137 promote_function_output_structures(*dds);
1140 eval.parse_constraint(get_ce(), **dds);
1142 (*dds)->tag_nested_sequences();
1144 throw_if_dap2_response_too_big(*dds);
1146 if (with_mime_headers)
1147 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1149 #if STORE_DAP2_RESULT_FEATURE
1151 if (!store_dap2_result(data_stream, **dds, eval)) {
1152 serialize_dap2_data_dds(data_stream, dds, eval,
true );
1155 serialize_dap2_data_dds(data_stream, dds, eval,
true );
1160 BESDEBUG(MODULE, prolog <<
"Simple constraint" << endl);
1162 eval.parse_constraint(get_ce(), **dds);
1164 (*dds)->tag_nested_sequences();
1166 throw_if_dap2_response_too_big(*dds);
1168 if (with_mime_headers)
1169 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1171 #if STORE_DAP2_RESULT_FEATURE
1173 if (!store_dap2_result(data_stream, **dds, eval)) {
1174 serialize_dap2_data_dds(data_stream, dds, eval);
1177 serialize_dap2_data_dds(data_stream, dds, eval);
1181 data_stream << flush;
1183 BESDEBUG(MODULE, prolog <<
"END"<< endl);
1187 void BESDapResponseBuilder::send_dap2_data(
BESDataHandlerInterface &dhi, DDS **dds, ConstraintEvaluator &eval,
1188 bool with_mime_headers)
1190 BESDEBUG(MODULE, prolog <<
"BEGIN"<< endl);
1192 ostream & data_stream = dhi.get_output_stream();
1193 #if USE_LOCAL_TIMEOUT_SCHEME
1195 establish_timeout(data_stream);
1196 dds.set_timeout(d_timeout);
1205 if (!get_btp_func_ce().empty()) {
1206 BESDEBUG(MODULE, prolog <<
"Found function(s) in CE: " << get_btp_func_ce() << endl);
1216 if(bdds->get_ia_flag() ==
false) {
1218 besRH->add_attributes(dhi);
1223 ConstraintEvaluator func_eval;
1225 if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1229 func_eval.parse_constraint(get_btp_func_ce(), **dds);
1230 fdds = func_eval.eval_function_clauses(**dds);
1233 delete *dds; *dds = 0;
1236 (*dds)->mark_all(
false);
1238 promote_function_output_structures(*dds);
1241 eval.parse_constraint(get_ce(), **dds);
1243 (*dds)->tag_nested_sequences();
1245 throw_if_dap2_response_too_big(*dds);
1247 if (with_mime_headers)
1248 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1250 #if STORE_DAP2_RESULT_FEATURE
1252 if (!store_dap2_result(data_stream, **dds, eval)) {
1253 serialize_dap2_data_dds(data_stream, dds, eval,
true );
1256 serialize_dap2_data_dds(data_stream, dds, eval,
true );
1261 BESDEBUG(MODULE, prolog <<
"Simple constraint" << endl);
1263 eval.parse_constraint(get_ce(), **dds);
1265 (*dds)->tag_nested_sequences();
1267 throw_if_dap2_response_too_big(*dds);
1269 if (with_mime_headers)
1270 set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1272 #if STORE_DAP2_RESULT_FEATURE
1274 if (!store_dap2_result(data_stream, **dds, eval)) {
1275 serialize_dap2_data_dds(data_stream, dds, eval);
1278 serialize_dap2_data_dds(data_stream, dds, eval);
1282 data_stream << flush;
1284 BESDEBUG(MODULE, prolog <<
"END"<< endl);
1302 if (d_dap2ce.empty()) {
1303 if (with_mime_headers)
1304 set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1306 (*dds)->print_xml_writer(out,
false ,
"");
1312 #if USE_LOCAL_TIMEOUT_SCHEME
1314 establish_timeout(out);
1315 dds.set_timeout(d_timeout);
1324 if (!d_btp_func_ce.empty()) {
1327 ConstraintEvaluator func_eval;
1329 if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1333 func_eval.parse_constraint(get_btp_func_ce(), **dds);
1334 fdds = func_eval.eval_function_clauses(**dds);
1337 delete *dds; *dds = 0;
1340 (*dds)->mark_all(
false);
1342 promote_function_output_structures(*dds);
1344 eval.parse_constraint(d_dap2ce, **dds);
1346 if (with_mime_headers)
1347 set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1349 conditional_timeout_cancel();
1351 (*dds)->print_xml_writer(out,
true,
"");
1354 eval.parse_constraint(d_dap2ce, **dds);
1356 if (with_mime_headers)
1357 set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1359 conditional_timeout_cancel();
1363 (*dds)->print_xml_writer(out,
true,
"");
1369 void BESDapResponseBuilder::send_dmr(ostream &out, DMR &dmr,
bool with_mime_headers)
1374 if (!d_dap4ce.empty()) {
1376 BESDEBUG(MODULE, prolog <<
"Parsing DAP4 constraint: '"<< d_dap4ce <<
"'"<< endl);
1378 D4ConstraintEvaluator parser(&dmr);
1379 bool parse_ok = parser.parse(d_dap4ce);
1380 if (!parse_ok)
throw Error(malformed_expr,
"Constraint Expression (" + d_dap4ce +
") failed to parse.");
1386 dmr.root()->set_send_p(
true);
1389 if (with_mime_headers) set_mime_text(out, dap4_dmr, x_plain, last_modified_time(d_dataset), dmr.dap_version());
1391 conditional_timeout_cancel();
1393 BESDEBUG(MODULE, prolog <<
"dmr.request_xml_base(): '"<< dmr.request_xml_base() <<
"' (dmr: " << (
void *) &dmr <<
")" << endl);
1396 dmr.print_dap4(xml, !d_dap4ce.empty() );
1397 out << xml.get_doc() << flush;
1400 void BESDapResponseBuilder::send_dap4_data_using_ce(ostream &out, DMR &dmr,
bool with_mime_headers)
1402 if (!d_dap4ce.empty()) {
1403 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap4_data_using_ce() - expression constraint is not empty. " <<endl);
1404 D4ConstraintEvaluator parser(&dmr);
1405 bool parse_ok = parser.parse(d_dap4ce);
1406 if (!parse_ok)
throw Error(malformed_expr,
"Constraint Expression (" + d_dap4ce +
") failed to parse.");
1412 dmr.root()->set_send_p(
true);
1415 if (dmr.response_limit() != 0 && (dmr.request_size(
true) > dmr.response_limit())) {
1416 string msg =
"The Request for " + long_to_string(dmr.request_size(
true))
1417 +
"KB is too large; requests for this server are limited to " + long_to_string(dmr.response_limit())
1424 for (D4Group::Vars_iter i = dmr.root()->var_begin(), e = dmr.root()->var_end(); i != e; ++i) {
1425 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap4_data_ce() - "<< (*i)->name() <<endl);
1426 if ((*i)->send_p()) {
1427 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap4_data() Obtain data- "<< (*i)->name() <<endl);
1428 D4Attributes*d4_attrs = (*i)->attributes();
1429 BESDEBUG(
"dap",
"BESDapResponseBuilder::send_dap4_data() number of attributes "<< d4_attrs <<endl);
1430 for (D4Attributes::D4AttributesIter ii = d4_attrs->attribute_begin(), ee = d4_attrs->attribute_end(); ii != ee; ++ii) {
1431 string name = (*ii)->name();
1432 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() attribute name is "<<name <<endl);
1441 if (!store_dap4_result(out, dmr)) {
1442 serialize_dap4_data(out, dmr, with_mime_headers);
1446 void BESDapResponseBuilder::intern_dap4_data_using_ce(DMR &dmr)
1449 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
1450 if (!d_dap4ce.empty()) {
1451 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data_using_ce() - expression constraint is not empty. " <<endl);
1452 D4ConstraintEvaluator parser(&dmr);
1453 bool parse_ok = parser.parse(d_dap4ce);
1454 if (!parse_ok)
throw Error(malformed_expr,
"Constraint Expression (" + d_dap4ce +
") failed to parse.");
1460 dmr.root()->set_send_p(
true);
1463 if (dmr.response_limit() != 0 && (dmr.request_size(
true) > dmr.response_limit())) {
1464 string msg =
"The Request for " + long_to_string(dmr.request_size(
true))
1465 +
"KB is too large; requests for this server are limited to " + long_to_string(dmr.response_limit())
1472 void BESDapResponseBuilder::send_dap4_data(ostream &out, DMR &dmr,
bool with_mime_headers)
1477 if (!d_dap4function.empty()) {
1478 D4BaseTypeFactory d4_factory;
1479 DMR function_result(&d4_factory,
"function_results");
1483 if (!ServerFunctionsList::TheList())
1485 "The function expression could not be evaluated because there are no server functions defined on this server");
1487 D4FunctionEvaluator parser(&dmr, ServerFunctionsList::TheList());
1488 bool parse_ok = parser.parse(d_dap4function);
1489 if (!parse_ok)
throw Error(
"Function Expression (" + d_dap4function +
") failed to parse.");
1491 parser.eval(&function_result);
1495 send_dap4_data_using_ce(out, function_result, with_mime_headers);
1498 send_dap4_data_using_ce(out, dmr, with_mime_headers);
1508 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
1510 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
1512 if (with_mime_headers) set_mime_binary(out, dap4_data, x_plain, last_modified_time(d_dataset), dmr.dap_version());
1514 BESDEBUG(MODULE, prolog <<
"dmr.request_xml_base(): \"" << dmr.request_xml_base() <<
"\""<< endl);
1518 dmr.print_dap4(xml, !d_dap4ce.empty());
1523 chunked_ostream cos(out, max((
unsigned int) CHUNK_SIZE, xml.get_doc_size() + 2));
1525 conditional_timeout_cancel();
1528 cos << xml.get_doc() << CRLF << flush;
1531 D4StreamMarshaller m(cos);
1532 dmr.root()->serialize(m, dmr, !d_dap4ce.empty());
1533 #ifdef CLEAR_LOCAL_DATA
1534 dmr.root()->clear_local_data();
1538 BESDEBUG(MODULE, prolog <<
"END" << endl);
1557 if (get_store_result().length() != 0) {
1558 string serviceUrl = get_store_result();
1565 string *stylesheet_ref = 0, ss_ref_value;
1567 if (found && ss_ref_value.length() > 0) {
1568 stylesheet_ref = &ss_ref_value;
1572 if (resultCache == NULL) {
1579 string msg =
"The Stored Result request cannot be serviced. ";
1580 msg +=
"Unable to acquire StoredResultCache instance. ";
1581 msg +=
"This is most likely because the StoredResultCache is not (correctly) configured.";
1583 BESDEBUG(MODULE, prolog <<
"[WARNING] " << msg << endl);
1584 d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
1585 out << xmlWrtr.get_doc();
1587 BESDEBUG(MODULE, prolog <<
"Sent AsyncRequestRejected" << endl);
1592 if (get_async_accepted().length() != 0) {
1597 BESDEBUG(MODULE, prolog <<
"serviceUrl="<< serviceUrl << endl);
1599 string storedResultId =
"";
1602 BESDEBUG(MODULE,prolog <<
"storedResultId='"<< storedResultId <<
"'" << endl);
1605 BESDEBUG(MODULE, prolog <<
"targetURL='"<< targetURL <<
"'" << endl);
1607 d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
1608 out << xmlWrtr.get_doc();
1610 BESDEBUG(MODULE, prolog <<
"Sent AsyncAccepted" << endl);
1618 d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
1619 out << xmlWrtr.get_doc();
1621 BESDEBUG(MODULE, prolog <<
"Sent AsyncAccepted" << endl);
1654 if (
BESDebug::IsSet(TIMING_LOG_KEY) || BESLog::TheLog()->is_verbose()) sw.
start(prolog +
"Timer",
"");
1655 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() - BEGIN"<< endl);
1661 if (!bdds)
throw BESInternalFatalError(
"Expected a BESDataDDSResponse instance", __FILE__, __LINE__);
1663 DDS *dds = bdds->get_dds();
1665 set_dataset_name(dds->filename());
1666 set_ce(dhi.
data[POST_CONSTRAINT]);
1667 set_async_accepted(dhi.
data[ASYNC]);
1668 set_store_result(dhi.
data[STORE_RESULT]);
1671 ConstraintEvaluator &eval = bdds->get_ce();
1676 DMR *dmr = bdmr->get_dmr();
1678 D4Group* root_grp=NULL;
1679 BESDEBUG(
"dap",
"BESDapResponseBuilder::dmr filename - END"<< dmr->filename() <<endl);
1682 set_dataset_name(dmr->filename());
1683 set_dap4ce(dhi.
data[DAP4_CONSTRAINT]);
1684 set_dap4function(dhi.
data[DAP4_FUNCTION]);
1685 set_async_accepted(dhi.
data[ASYNC]);
1686 set_store_result(dhi.
data[STORE_RESULT]);
1692 if (!d_dap4function.empty()) {
1693 D4BaseTypeFactory d4_factory;
1694 DMR function_result(&d4_factory,
"function_results");
1698 if (!ServerFunctionsList::TheList())
1700 "The function expression could not be evaluated because there are no server functions defined on this server");
1702 D4FunctionEvaluator parser(dmr, ServerFunctionsList::TheList());
1703 bool parse_ok = parser.parse(d_dap4function);
1704 if (!parse_ok)
throw Error(
"Function Expression (" + d_dap4function +
") failed to parse.");
1706 parser.eval(&function_result);
1710 intern_dap4_data_using_ce(function_result);
1711 root_grp = function_result.root();
1714 BESDEBUG(
"dap",
"BESDapResponseBuilder:: going to the expression constraint. " <<endl);
1715 intern_dap4_data_using_ce(*dmr);
1716 root_grp = dmr->root();
1724 for (D4Group::Vars_iter i = root_grp->var_begin(), e = root_grp->var_end(); i != e; ++i) {
1725 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() - "<< (*i)->name() <<endl);
1726 if ((*i)->send_p()) {
1727 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() Obtain data- "<< (*i)->name() <<endl);
1729 D4Attributes*d4_attrs = (*i)->attributes();
1730 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() number of attributes "<< d4_attrs <<endl);
1731 for (D4Attributes::D4AttributesIter ii = d4_attrs->attribute_begin(), ee = d4_attrs->attribute_end(); ii != ee; ++ii) {
1732 string name = (*ii)->name();
1733 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() attribute name is "<<name <<endl);
1736 (*i)->intern_data();
1740 for (D4Group::groupsIter gi = root_grp->grp_begin(), ge = root_grp->grp_end(); gi != ge; ++gi) {
1741 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() root group- "<< (*gi)->name() <<endl);
1742 intern_dap4_data_grp(*gi);
1744 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() - END"<< endl);
1749 void BESDapResponseBuilder::intern_dap4_data_grp(libdap::D4Group* grp) {
1750 for (D4Group::Vars_iter i = grp->var_begin(), e = grp->var_end(); i != e; ++i) {
1751 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() - "<< (*i)->name() <<endl);
1752 if ((*i)->send_p()) {
1753 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() Obtain data- "<< (*i)->name() <<endl);
1755 D4Attributes*d4_attrs = (*i)->attributes();
1756 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() number of attributes "<< d4_attrs <<endl);
1757 for (D4Attributes::D4AttributesIter ii = d4_attrs->attribute_begin(), ee = d4_attrs->attribute_end(); ii != ee; ++ii) {
1758 string name = (*ii)->name();
1759 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() attribute name is "<<name <<endl);
1762 (*i)->intern_data();
1766 for (D4Group::groupsIter gi = grp->grp_begin(), ge = grp->grp_end(); gi != ge; ++gi) {
1767 BESDEBUG(
"dap",
"BESDapResponseBuilder::intern_dap4_data() group- "<< (*gi)->name() <<endl);
1768 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.
void set_dds(libdap::DDS *ddsIn)
libdap::ConstraintEvaluator & get_ce()
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)
void register_timeout() const
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.
virtual void set_dap4ce(std::string _ce)
virtual void remove_timeout() const
Transmit data.
virtual libdap::DDS * process_dap2_dds(BESResponseObject *obj, BESDataHandlerInterface &dhi)
Process a DDS (i.e., apply a constraint) for a non-DAP transmitter.
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 establish_timeout(std::ostream &stream) const
virtual bool store_dap4_result(ostream &out, libdap::DMR &dmr)
void conditional_timeout_cancel()
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)
virtual void set_dap4function(std::string _func)
void set_timeout(int timeout=0)
virtual void set_ce(std::string _ce)
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 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.
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()