bes  Updated for version 3.20.6
BESDapResponseBuilder.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2011 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #include "config.h"
26 
27 #include <signal.h>
28 #include <unistd.h>
29 #include <sys/stat.h>
30 
31 #ifdef HAVE_UUID_UUID_H
32 #include <uuid/uuid.h> // used to build CID header value for data ddx
33 #elif defined(HAVE_UUID_H)
34 #include <uuid.h>
35 #else
36 #error "Could not find UUID library header"
37 #endif
38 
39 
40 #ifndef WIN32
41 #include <sys/wait.h>
42 #else
43 #include <io.h>
44 #include <fcntl.h>
45 #include <process.h>
46 #endif
47 
48 #include <iostream>
49 #include <string>
50 #include <sstream>
51 #include <fstream>
52 
53 #include <cstring>
54 #include <ctime>
55 
56 //#define DODS_DEBUG
57 #define CLEAR_LOCAL_DATA
58 #undef USE_LOCAL_TIMEOUT_SCHEME
59 
60 #include <DAS.h>
61 #include <DDS.h>
62 #include <Structure.h>
63 #include <ConstraintEvaluator.h>
64 #include <DDXParserSAX2.h>
65 #include <Ancillary.h>
66 #include <XDRStreamMarshaller.h>
67 #include <XDRFileUnMarshaller.h>
68 
69 #include <DMR.h>
70 #include <D4Group.h>
71 #include <XMLWriter.h>
72 #include <D4AsyncUtil.h>
73 #include <D4StreamMarshaller.h>
74 #include <chunked_ostream.h>
75 #include <chunked_istream.h>
76 #include <D4ConstraintEvaluator.h>
77 #include <D4FunctionEvaluator.h>
78 #include <D4BaseTypeFactory.h>
79 
80 #include <ServerFunctionsList.h>
81 
82 #include <mime_util.h> // for last_modified_time() and rfc_822_date()
83 #include <escaping.h>
84 #include <util.h>
85 #if USE_LOCAL_TIMEOUT_SCHEME
86 #ifndef WIN32
87 #include <SignalHandler.h>
88 #include <EventHandler.h>
89 #include <AlarmHandler.h>
90 #endif
91 #endif
92 
93 #include "TheBESKeys.h"
94 #include "BESDapResponseBuilder.h"
95 #include "BESContextManager.h"
96 #include "BESDapFunctionResponseCache.h"
97 #include "BESStoredDapResultCache.h"
98 
99 #include "BESResponseObject.h"
100 #include "BESDDSResponse.h"
101 #include "BESDataDDSResponse.h"
102 #include "BESDataHandlerInterface.h"
103 #include "BESInternalFatalError.h"
104 #include "BESDataNames.h"
105 
106 #include "BESRequestHandler.h"
107 #include "BESRequestHandlerList.h"
108 #include "BESNotFoundError.h"
109 
110 #include "BESUtil.h"
111 #include "BESDebug.h"
112 #include "BESStopWatch.h"
113 #include "DapFunctionUtils.h"
114 
115 using namespace std;
116 using namespace libdap;
117 
118 const string CRLF = "\r\n"; // Change here, expr-test.cc
119 const string BES_KEY_TIMEOUT_CANCEL = "BES.CancelTimeoutOnSend";
120 
126 {
127  bool found = false;
128  string cancel_timeout_on_send = "";
129  TheBESKeys::TheKeys()->get_value(BES_KEY_TIMEOUT_CANCEL, cancel_timeout_on_send, found);
130  if (found && !cancel_timeout_on_send.empty()) {
131  // The default value is false.
132  downcase(cancel_timeout_on_send);
133  if (cancel_timeout_on_send == "yes" || cancel_timeout_on_send == "true")
134  d_cancel_timeout_on_send = true;
135  }
136 }
137 
138 BESDapResponseBuilder::~BESDapResponseBuilder()
139 {
140 #if USE_LOCAL_TIMEOUT_SCHEME
141  // If an alarm was registered, delete it. The register code in SignalHandler
142  // always deletes the old alarm handler object, so only the one returned by
143  // remove_handler needs to be deleted at this point.
144  delete dynamic_cast<AlarmHandler*>(SignalHandler::instance()->remove_handler(SIGALRM));
145 #endif
146 }
147 
155 {
156  return d_dap2ce;
157 }
158 
170 {
171  d_dap2ce = www2id(_ce, "%", "%20");
172 }
173 
178 {
179  return d_dap4ce;
180 }
181 
193 {
194  d_dap4ce = www2id(_ce, "%", "%20");
195 }
196 
201 {
202  return d_dap4function;
203 }
204 
217 {
218  d_dap4function = www2id(_func, "%", "%20");
219 }
220 
221 std::string BESDapResponseBuilder::get_store_result() const
222 {
223  return d_store_result;
224 }
225 
226 void BESDapResponseBuilder::set_store_result(std::string _sr)
227 {
228  d_store_result = _sr;
229  BESDEBUG("dap", "BESDapResponseBuilder::set_store_result() - store_result: " << _sr << endl);
230 }
231 
232 std::string BESDapResponseBuilder::get_async_accepted() const
233 {
234  return d_async_accepted;
235 }
236 
237 void BESDapResponseBuilder::set_async_accepted(std::string _aa)
238 {
239  d_async_accepted = _aa;
240  BESDEBUG("dap", "BESDapResponseBuilder::set_async_accepted() - async_accepted: " << _aa << endl);
241 }
242 
252 {
253  return d_dataset;
254 }
255 
267 {
268  d_dataset = www2id(ds, "%", "%20");
269 }
270 
277 {
278  d_timeout = t;
279 }
280 
283 {
284  return d_timeout;
285 }
286 
293 void
295 {
296 #if USE_LOCAL_TIMEOUT_SCHEME
297 #ifndef WIN32
298  alarm(d_timeout);
299 #endif
300 #endif
301 }
302 
308 void
310 {
311 #if USE_LOCAL_TIMEOUT_SCHEME
312 #ifndef WIN32
313  alarm(0);
314 #endif
315 #endif
316 }
317 
333 {
334  if (d_cancel_timeout_on_send)
335  alarm(0);
336 }
337 
347 {
348 #if USE_LOCAL_TIMEOUT_SCHEME
349 #ifndef WIN32
350  SignalHandler *sh = SignalHandler::instance();
351  EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler());
352  delete old_eh;
353 #endif
354 #endif
355 }
356 
357 
364 {
365 #if USE_LOCAL_TIMEOUT_SCHEME
366 #ifndef WIN32
367  if (d_timeout > 0) {
368  SignalHandler *sh = SignalHandler::instance();
369  EventHandler *old_eh = sh->register_handler(SIGALRM, new AlarmHandler());
370  delete old_eh;
371  alarm(d_timeout);
372  }
373 #endif
374 #endif
375 }
376 
391 static string::size_type find_closing_paren(const string &ce, string::size_type pos)
392 {
393  // Iterate over the string finding all ( or ) characters until the matching ) is found.
394  // For each ( found, increment count. When a ) is found and count is zero, it is the
395  // matching closing paren, otherwise, decrement count and keep looking.
396  int count = 1;
397  do {
398  pos = ce.find_first_of("()", pos + 1);
399  if (pos == string::npos)
400  throw Error(malformed_expr, "Expected to find a matching closing parenthesis in " + ce);
401 
402  if (ce[pos] == '(')
403  ++count;
404  else
405  --count; // must be ')'
406 
407  } while (count > 0);
408 
409  return pos;
410 }
411 
418 void BESDapResponseBuilder::split_ce(ConstraintEvaluator &eval, const string &expr)
419 {
420  BESDEBUG("dap", "BESDapResponseBuilder::split_ce() - source expression: " << expr << endl);
421 
422  string ce;
423  if (!expr.empty())
424  ce = expr;
425  else
426  ce = d_dap2ce;
427 
428  string btp_function_ce = "";
429  string::size_type pos = 0;
430 
431  // This hack assumes that the functions are listed first. Look for the first
432  // open paren and the last closing paren to accommodate nested function calls
433  string::size_type first_paren = ce.find("(", pos);
434  string::size_type closing_paren = string::npos;
435  if (first_paren != string::npos) closing_paren = find_closing_paren(ce, first_paren); //ce.find(")", pos);
436 
437  while (first_paren != string::npos && closing_paren != string::npos) {
438  // Maybe a BTP function; get the name of the potential function
439  string name = ce.substr(pos, first_paren - pos);
440 
441  // is this a BTP function
442  btp_func f;
443  if (eval.find_function(name, &f)) {
444  // Found a BTP function
445  if (!btp_function_ce.empty()) btp_function_ce += ",";
446  btp_function_ce += ce.substr(pos, closing_paren + 1 - pos);
447  ce.erase(pos, closing_paren + 1 - pos);
448  if (ce[pos] == ',') ce.erase(pos, 1);
449  }
450  else {
451  pos = closing_paren + 1;
452  // exception?
453  if (pos < ce.length() && ce.at(pos) == ',') ++pos;
454  }
455 
456  first_paren = ce.find("(", pos);
457  closing_paren = ce.find(")", pos);
458  }
459 
460  d_dap2ce = ce;
461  d_btp_func_ce = btp_function_ce;
462 
463  BESDEBUG("dap", "BESDapResponseBuilder::split_ce() - Modified constraint: " << d_dap2ce << endl);
464  BESDEBUG("dap", "BESDapResponseBuilder::split_ce() - BTP Function part: " << btp_function_ce << endl);
465  BESDEBUG("dap", "BESDapResponseBuilder::split_ce() - END" << endl);
466 }
467 
474 static void
475 throw_if_dap2_response_too_big(DDS *dds)
476 {
477  if (dds->get_response_limit() != 0 && ((dds->get_request_size(true)) > dds->get_response_limit())) {
478  string msg = "The Request for " + long_to_string(dds->get_request_size(true) / 1024)
479  + "KB is too large; requests on this server are limited to "
480  + long_to_string(dds->get_response_limit() /1024) + "KB.";
481  throw Error(msg);
482  }
483 }
484 
499 void BESDapResponseBuilder::send_das(ostream &out, DAS &das, bool with_mime_headers) const
500 {
501  if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), "2.0");
502 
503  das.print(out);
504 
505  out << flush;
506 }
507 
525 void BESDapResponseBuilder::send_das(ostream &out, DDS **dds, ConstraintEvaluator &eval, bool constrained,
526  bool with_mime_headers)
527 {
528 #if USE_LOCAL_TIMEOUT_SCHEME
529  // Set up the alarm.
530  establish_timeout(out);
531  dds.set_timeout(d_timeout);
532 #endif
533  if (!constrained) {
534  if (with_mime_headers) set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), "2.0");
535 
536  conditional_timeout_cancel();
537 
538  (*dds)->print_das(out);
539  out << flush;
540 
541  return;
542  }
543 
544  split_ce(eval);
545 
546  // If there are functions, parse them and eval.
547  // Use that DDS and parse the non-function ce
548  // Serialize using the second ce and the second dds
549  if (!d_btp_func_ce.empty()) {
550  ConstraintEvaluator func_eval;
551  BESDapFunctionResponseCache *responseCache = BESDapFunctionResponseCache::get_instance();
552 
553  DDS *fdds = 0; // nulll_ptr
554  if (responseCache && responseCache->can_be_cached(*dds, get_btp_func_ce())) {
555  fdds = responseCache->get_or_cache_dataset(*dds, get_btp_func_ce());
556  }
557  else {
558  func_eval.parse_constraint(get_btp_func_ce(), **dds);
559  fdds = func_eval.eval_function_clauses(**dds);
560  }
561 
562  delete *dds; *dds = 0;
563  *dds = fdds;
564 
565  if (with_mime_headers)
566  set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
567 
568  conditional_timeout_cancel();
569 
570  (*dds)->print_das(out);
571  }
572  else {
573  eval.parse_constraint(d_dap2ce, **dds); // Throws Error if the ce doesn't parse.
574 
575  if (with_mime_headers)
576  set_mime_text(out, dods_das, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
577 
578  conditional_timeout_cancel();
579 
580  (*dds)->print_das(out);
581  }
582 
583  out << flush;
584 }
585 
586 
605 void BESDapResponseBuilder::send_dds(ostream &out, DDS **dds, ConstraintEvaluator &eval, bool constrained,
606  bool with_mime_headers)
607 {
608  if (!constrained) {
609  if (with_mime_headers)
610  set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
611 
612  conditional_timeout_cancel();
613 
614  (*dds)->print(out);
615  out << flush;
616  return;
617  }
618 
619 #if USE_LOCAL_TIMEOUT_SCHEME
620  // Set up the alarm.
621  establish_timeout(out);
622  dds.set_timeout(d_timeout);
623 #endif
624 
625  // Split constraint into two halves
626  split_ce(eval);
627 
628  // If there are functions, parse them and eval.
629  // Use that DDS and parse the non-function ce
630  // Serialize using the second ce and the second dds
631  if (!d_btp_func_ce.empty()) {
632  ConstraintEvaluator func_eval;
633 
634  BESDapFunctionResponseCache *responseCache = BESDapFunctionResponseCache::get_instance();
635 
636  DDS *fdds = 0; // nulll_ptr
637  if (responseCache && responseCache->can_be_cached(*dds, get_btp_func_ce())) {
638  fdds = responseCache->get_or_cache_dataset(*dds, get_btp_func_ce());
639  }
640  else {
641  func_eval.parse_constraint(get_btp_func_ce(), **dds);
642  fdds = func_eval.eval_function_clauses(**dds);
643  }
644 
645  delete *dds; *dds = 0;
646  *dds = fdds;
647 
648  // Server functions might mark variables to use their read()
649  // methods. Clear that so the CE in d_dap2ce will control what is
650  // sent. If that is empty (there was only a function call) all
651  // of the variables in the intermediate DDS (i.e., the function
652  // result) will be sent.
653  (*dds)->mark_all(false);
654 
655  // This next step utilizes a well known static method (so really it's a function;),
656  // promote_function_output_structures() to look for
657  // one or more top level Structures whose name indicates (by way of ending with
658  // "_uwrap") that their contents should be promoted (aka moved) to the top level.
659  // This is in support of a hack around the current API where server side functions
660  // may only return a single DAP object and not a collection of objects. The name suffix
661  // "_unwrap" is used as a signal from the function to the the various response
662  // builders and transmitters that the representation needs to be altered before
663  // transmission, and that in fact is what happens in our friend
664  // promote_function_output_structures()
665  promote_function_output_structures(*dds);
666 
667  eval.parse_constraint(d_dap2ce, **dds);
668 
669  if (with_mime_headers)
670  set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
671 
672 
673  conditional_timeout_cancel();
674 
675  (*dds)->print_constrained(out);
676  }
677  else {
678  eval.parse_constraint(d_dap2ce, **dds); // Throws Error if the ce doesn't parse.
679 
680  if (with_mime_headers)
681  set_mime_text(out, dods_dds, x_plain, last_modified_time(d_dataset),(*dds)->get_dap_version());
682 
683  conditional_timeout_cancel();
684 
685  (*dds)->print_constrained(out);
686  }
687 
688  out << flush;
689 }
690 
691 #ifdef DAP2_STORED_RESULTS
692 
706 bool BESDapResponseBuilder::store_dap2_result(ostream &out, DDS &dds, ConstraintEvaluator &eval)
707 {
708  if (get_store_result().empty()) return false;
709 
710  string serviceUrl = get_store_result();
711 
712  XMLWriter xmlWrtr;
713  D4AsyncUtil d4au;
714 
715  // FIXME Keys should be read in initialize(). Also, I think the D4AsyncUtil should
716  // be removed from libdap - it is much more about how the BES processes these kinds
717  // of operations. Change this when working on the response caching for ODSIP. But...
718  // do we really need to put the style sheet in the bes.conf file? Should it be baked
719  // into the code (because we don't want people to change it)?
720  bool found;
721  string *stylesheet_ref = 0, ss_ref_value;
722  TheBESKeys::TheKeys()->get_value(D4AsyncUtil::STYLESHEET_REFERENCE_KEY, ss_ref_value, found);
723  if (found && ss_ref_value.length() > 0) {
724  stylesheet_ref = &ss_ref_value;
725  }
726 
728  if (resultCache == NULL) {
729 
735  string msg = "The Stored Result request cannot be serviced. ";
736  msg += "Unable to acquire StoredResultCache instance. ";
737  msg += "This is most likely because the StoredResultCache is not (correctly) configured.";
738 
739  BESDEBUG("dap", "[WARNING] " << msg << endl);
740 
741  d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
742  out << xmlWrtr.get_doc();
743  out << flush;
744 
745  BESDEBUG("dap", "BESDapResponseBuilder::store_dap2_result() - Sent AsyncRequestRejected" << endl);
746  }
747  else if (get_async_accepted().length() != 0) {
748 
752  BESDEBUG("dap", "BESDapResponseBuilder::store_dap2_result() - serviceUrl="<< serviceUrl << endl);
753 
755  string storedResultId = "";
756  storedResultId = resultCache->store_dap2_result(dds, get_ce(), this, &eval);
757 
758  BESDEBUG("dap",
759  "BESDapResponseBuilder::store_dap2_result() - storedResultId='"<< storedResultId << "'" << endl);
760 
761  string targetURL = BESUtil::assemblePath(serviceUrl, storedResultId);
762  BESDEBUG("dap", "BESDapResponseBuilder::store_dap2_result() - targetURL='"<< targetURL << "'" << endl);
763 
764  XMLWriter xmlWrtr;
765  d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
766  out << xmlWrtr.get_doc();
767  out << flush;
768 
769  BESDEBUG("dap", "BESDapResponseBuilder::store_dap2_result() - sent DAP4 AsyncAccepted response" << endl);
770  }
771  else {
776  d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
777  out << xmlWrtr.get_doc();
778  out << flush;
779 
780  BESDEBUG("dap", "BESDapResponseBuilder::store_dap2_result() - sent DAP4 AsyncRequired response" << endl);
781  }
782 
783  return true;
784 
785 }
786 #endif
787 
791 void BESDapResponseBuilder::serialize_dap2_data_dds(ostream &out, DDS **dds, ConstraintEvaluator &eval, bool ce_eval)
792 {
793  BESStopWatch sw;
794  if (BESISDEBUG(TIMING_LOG)) sw.start("BESDapResponseBuilder::serialize_dap2_data_dds", "");
795 
796  BESDEBUG("dap", "BESDapResponseBuilder::serialize_dap2_data_dds() - BEGIN" << endl);
797 
798  (*dds)->print_constrained(out);
799  out << "Data:\n";
800  out << flush;
801 
802  XDRStreamMarshaller m(out);
803 
804  // This only has an effect when the timeout in BESInterface::execute_request()
805  // is set. Otherwise it does nothing.
806  conditional_timeout_cancel();
807 
808  // Send all variables in the current projection (send_p())
809  for (DDS::Vars_iter i = (*dds)->var_begin(); i != (*dds)->var_end(); i++) {
810  if ((*i)->send_p()) {
811  (*i)->serialize(eval, **dds, m, ce_eval);
812 #ifdef CLEAR_LOCAL_DATA
813  (*i)->clear_local_data();
814 #endif
815  }
816  }
817 
818  BESDEBUG("dap", "BESDapResponseBuilder::serialize_dap2_data_dds() - END" << endl);
819 }
820 
821 #ifdef DAP2_STORED_RESULTS
822 
830 void BESDapResponseBuilder::serialize_dap2_data_ddx(ostream &out, DDS **dds, ConstraintEvaluator &eval,
831  const string &boundary, const string &start, bool ce_eval)
832 {
833  BESDEBUG("dap", __PRETTY_FUNCTION__ << " BEGIN" << endl);
834 
835  // Write the MPM headers for the DDX (text/xml) part of the response
836  libdap::set_mime_ddx_boundary(out, boundary, start, dods_ddx, x_plain);
837 
838  // Make cid
839  uuid_t uu;
840  uuid_generate(uu);
841  char uuid[37];
842  uuid_unparse(uu, &uuid[0]);
843  char domain[256];
844  if (getdomainname(domain, 255) != 0 || strlen(domain) == 0) strncpy(domain, "opendap.org", 255);
845 
846  string cid = string(&uuid[0]) + "@" + string(&domain[0]);
847 
848  // Send constrained DDX with a data blob reference.
849  // Note: CID passed but ignored jhrg 10/20/15
850  (*dds)->print_xml_writer(out, true, cid);
851 
852  // write the data part mime headers here
853  set_mime_data_boundary(out, boundary, cid, dods_data_ddx /* old value dap4_data*/, x_plain);
854 
855  XDRStreamMarshaller m(out);
856 
857  conditional_timeout_cancel();
858 
859 
860  // Send all variables in the current projection (send_p()).
861  for (DDS::Vars_iter i = (*dds)->var_begin(); i != (*dds)->var_end(); i++) {
862  if ((*i)->send_p()) {
863  (*i)->serialize(eval, **dds, m, ce_eval);
864 #ifdef CLEAR_LOCAL_DATA
865  (*i)->clear_local_data();
866 #endif
867  }
868  }
869 
870  BESDEBUG("dap", __PRETTY_FUNCTION__ << " END" << endl);
871 }
872 #endif
873 
891 {
892 #if USE_LOCAL_TIMEOUT_SCHEME
893  alarm(0);
894 #endif
895 }
896 
910 libdap::DDS *
912 {
913  BESDEBUG("dap", "BESDapResponseBuilder::process_dap2_dds() - BEGIN"<< endl);
914 
915  dhi.first_container();
916 
917  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *>(obj);
918  if (!bdds) throw BESInternalFatalError("Expected a BESDDSResponse instance", __FILE__, __LINE__);
919 
920  DDS *dds = bdds->get_dds();
921 
922  set_dataset_name(dds->filename());
923  set_ce(dhi.data[POST_CONSTRAINT]);
924  set_async_accepted(dhi.data[ASYNC]);
925  set_store_result(dhi.data[STORE_RESULT]);
926 
927  ConstraintEvaluator &eval = bdds->get_ce();
928 
929  // Split constraint into two halves
930  split_ce(eval);
931 
932  // If there are functions, parse them and eval.
933  // Use that DDS and parse the non-function ce
934  // Serialize using the second ce and the second dds
935  if (!d_btp_func_ce.empty()) {
936  BESDapFunctionResponseCache *responseCache = BESDapFunctionResponseCache::get_instance();
937 
938  ConstraintEvaluator func_eval;
939  DDS *fdds = 0; // nulll_ptr
940  if (responseCache && responseCache->can_be_cached(dds, get_btp_func_ce())) {
941  fdds = responseCache->get_or_cache_dataset(dds, get_btp_func_ce());
942  }
943  else {
944  func_eval.parse_constraint(get_btp_func_ce(), *dds);
945  fdds = func_eval.eval_function_clauses(*dds);
946  }
947 
948  delete dds; // Delete so that we can ...
949  bdds->set_dds(fdds); // Transfer management responsibility
950  dds = fdds;
951 
952  dds->mark_all(false);
953 
954  promote_function_output_structures(dds);
955  }
956 
957  eval.parse_constraint(d_dap2ce, *dds); // Throws Error if the ce doesn't parse.
958 
959  return dds;
960 }
961 
979 libdap::DDS *
981 {
982  BESDEBUG("dap", "BESDapResponseBuilder::intern_dap2_data() - BEGIN"<< endl);
983 
984  dhi.first_container();
985 
986  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(obj);
987  if (!bdds) throw BESInternalFatalError("Expected a BESDataDDSResponse instance", __FILE__, __LINE__);
988 
989  DDS *dds = bdds->get_dds();
990 
991  set_dataset_name(dds->filename());
992  set_ce(dhi.data[POST_CONSTRAINT]);
993  set_async_accepted(dhi.data[ASYNC]);
994  set_store_result(dhi.data[STORE_RESULT]);
995 
996 
997  // This function is used by all fileout modules and they need to include the attributes in data access.
998  // So obtain the attributes if necessary. KY 2019-10-30
999  if(bdds->get_ia_flag() == false) {
1000  BESRequestHandler *besRH = BESRequestHandlerList::TheList()->find_handler(dhi.container->get_container_type());
1001  besRH->add_attributes(dhi);
1002  }
1003 
1004  ConstraintEvaluator &eval = bdds->get_ce();
1005 
1006  // Split constraint into two halves; stores the function and non-function parts in this instance.
1007  split_ce(eval);
1008 
1009  // If there are functions, parse them and eval.
1010  // Use that DDS and parse the non-function ce
1011  // Serialize using the second ce and the second dds
1012  if (!get_btp_func_ce().empty()) {
1013  BESDEBUG("dap",
1014  "BESDapResponseBuilder::intern_dap2_data() - Found function(s) in CE: " << get_btp_func_ce() << endl);
1015 
1016  BESDapFunctionResponseCache *responseCache = BESDapFunctionResponseCache::get_instance();
1017 
1018  ConstraintEvaluator func_eval;
1019  DDS *fdds = 0; // nulll_ptr
1020  if (responseCache && responseCache->can_be_cached(dds, get_btp_func_ce())) {
1021  fdds = responseCache->get_or_cache_dataset(dds, get_btp_func_ce());
1022  }
1023  else {
1024  func_eval.parse_constraint(get_btp_func_ce(), *dds);
1025  fdds = func_eval.eval_function_clauses(*dds);
1026  }
1027 
1028  delete dds; // Delete so that we can ...
1029  bdds->set_dds(fdds); // Transfer management responsibility
1030  dds = fdds;
1031 
1032  // Server functions might mark (i.e. setting send_p) so variables will use their read()
1033  // methods. Clear that so the CE in d_dap2ce will control what is
1034  // sent. If that is empty (there was only a function call) all
1035  // of the variables in the intermediate DDS (i.e., the function
1036  // result) will be sent.
1037  dds->mark_all(false);
1038 
1039  // Look for one or more top level Structures whose name indicates (by way of ending with
1040  // "_uwrap") that their contents should be moved to the top level.
1041  //
1042  // This is in support of a hack around the current API where server side functions
1043  // may only return a single DAP object and not a collection of objects. The name suffix
1044  // "_unwrap" is used as a signal from the function to the the various response
1045  // builders and transmitters that the representation needs to be altered before
1046  // transmission, and that in fact is what happens in our friend
1047  // promote_function_output_structures()
1048  promote_function_output_structures(dds);
1049  }
1050 
1051  // evaluate the rest of the CE - the part that follows the function calls.
1052  eval.parse_constraint(get_ce(), *dds);
1053 
1054  dds->tag_nested_sequences(); // Tag Sequences as Parent or Leaf node.
1055 
1056  throw_if_dap2_response_too_big(dds);
1057 
1058  // Iterate through the variables in the DataDDS and read
1059  // in the data if the variable has the send flag set.
1060  for (DDS::Vars_iter i = dds->var_begin(), e = dds->var_end(); i != e; ++i) {
1061  if ((*i)->send_p()) {
1062  (*i)->intern_data(eval, *dds);
1063  }
1064  }
1065 
1066  BESDEBUG("dap", "BESDapResponseBuilder::intern_dap2_data() - END"<< endl);
1067 
1068  return dds;
1069 }
1070 
1071 
1084 void BESDapResponseBuilder::send_dap2_data(ostream &data_stream, DDS **dds, ConstraintEvaluator &eval,
1085  bool with_mime_headers)
1086 {
1087  BESDEBUG("dap", "BESDapResponseBuilder::send_dap2_data() - BEGIN"<< endl);
1088 
1089 #if USE_LOCAL_TIMEOUT_SCHEME
1090  // Set up the alarm.
1091  establish_timeout(data_stream);
1092  dds.set_timeout(d_timeout);
1093 #endif
1094 
1095  // Split constraint into two halves
1096  split_ce(eval);
1097 
1098  // If there are functions, parse them and eval.
1099  // Use that DDS and parse the non-function ce
1100  // Serialize using the second ce and the second dds
1101  if (!get_btp_func_ce().empty()) {
1102  BESDEBUG("dap",
1103  "BESDapResponseBuilder::send_dap2_data() - Found function(s) in CE: " << get_btp_func_ce() << endl);
1104 
1105  BESDapFunctionResponseCache *response_cache = BESDapFunctionResponseCache::get_instance();
1106 
1107  ConstraintEvaluator func_eval;
1108  DDS *fdds = 0; // nulll_ptr
1109  if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1110  fdds = response_cache->get_or_cache_dataset(*dds, get_btp_func_ce());
1111  }
1112  else {
1113  func_eval.parse_constraint(get_btp_func_ce(), **dds);
1114  fdds = func_eval.eval_function_clauses(**dds);
1115  }
1116 
1117  delete *dds; *dds = 0;
1118  *dds = fdds;
1119 
1120  (*dds)->mark_all(false);
1121 
1122  promote_function_output_structures(*dds);
1123 
1124  // evaluate the rest of the CE - the part that follows the function calls.
1125  eval.parse_constraint(get_ce(), **dds);
1126 
1127  (*dds)->tag_nested_sequences(); // Tag Sequences as Parent or Leaf node.
1128 
1129  throw_if_dap2_response_too_big(*dds);
1130 
1131  if (with_mime_headers)
1132  set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1133 
1134 #if STORE_DAP2_RESULT_FEATURE
1135  // This means: if we are not supposed to store the result, then serialize it.
1136  if (!store_dap2_result(data_stream, **dds, eval)) {
1137  serialize_dap2_data_dds(data_stream, dds, eval, true /* was 'false'. jhrg 3/10/15 */);
1138  }
1139 #else
1140  serialize_dap2_data_dds(data_stream, dds, eval, true /* was 'false'. jhrg 3/10/15 */);
1141 #endif
1142 
1143  }
1144  else {
1145  BESDEBUG("dap", "BESDapResponseBuilder::send_dap2_data() - Simple constraint" << endl);
1146 
1147  eval.parse_constraint(get_ce(), **dds); // Throws Error if the ce doesn't parse.
1148 
1149  (*dds)->tag_nested_sequences(); // Tag Sequences as Parent or Leaf node.
1150 
1151  throw_if_dap2_response_too_big(*dds);
1152 
1153  if (with_mime_headers)
1154  set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1155 
1156 #if STORE_DAP2_RESULT_FEATURE
1157  // This means: if we are not supposed to store the result, then serialize it.
1158  if (!store_dap2_result(data_stream, **dds, eval)) {
1159  serialize_dap2_data_dds(data_stream, dds, eval);
1160  }
1161 #else
1162  serialize_dap2_data_dds(data_stream, dds, eval);
1163 #endif
1164  }
1165 
1166  data_stream << flush;
1167 
1168  BESDEBUG("dap", "BESDapResponseBuilder::send_dap2_data() - END"<< endl);
1169 
1170 }
1171 
1172 void BESDapResponseBuilder::send_dap2_data(BESDataHandlerInterface &dhi, DDS **dds, ConstraintEvaluator &eval,
1173  bool with_mime_headers)
1174 {
1175  BESDEBUG("dap", "BESDapResponseBuilder::send_dap2_data() - BEGIN"<< endl);
1176 
1177  ostream & data_stream = dhi.get_output_stream();
1178 #if USE_LOCAL_TIMEOUT_SCHEME
1179  // Set up the alarm.
1180  establish_timeout(data_stream);
1181  dds.set_timeout(d_timeout);
1182 #endif
1183 
1184  // Split constraint into two halves
1185  split_ce(eval);
1186 
1187  // If there are functions, parse them and eval.
1188  // Use that DDS and parse the non-function ce
1189  // Serialize using the second ce and the second dds
1190  if (!get_btp_func_ce().empty()) {
1191  BESDEBUG("dap",
1192  "BESDapResponseBuilder::send_dap2_data() - Found function(s) in CE: " << get_btp_func_ce() << endl);
1193 
1194  // Server-side functions need to include the attributes in data access.
1195  // So obtain the attributes if necessary. KY 2019-10-30
1196  {
1197  BESResponseObject *response = dhi.response_handler->get_response_object();
1198  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *> (response);
1199  if (!bdds)
1200  throw BESInternalError("cast error", __FILE__, __LINE__);
1201 
1202  if(bdds->get_ia_flag() == false) {
1203  BESRequestHandler *besRH = BESRequestHandlerList::TheList()->find_handler(dhi.container->get_container_type());
1204  besRH->add_attributes(dhi);
1205  }
1206  }
1207 
1208  BESDapFunctionResponseCache *response_cache = BESDapFunctionResponseCache::get_instance();
1209  ConstraintEvaluator func_eval;
1210  DDS *fdds = 0; // nulll_ptr
1211  if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1212  fdds = response_cache->get_or_cache_dataset(*dds, get_btp_func_ce());
1213  }
1214  else {
1215  func_eval.parse_constraint(get_btp_func_ce(), **dds);
1216  fdds = func_eval.eval_function_clauses(**dds);
1217  }
1218 
1219  delete *dds; *dds = 0;
1220  *dds = fdds;
1221 
1222  (*dds)->mark_all(false);
1223 
1224  promote_function_output_structures(*dds);
1225 
1226  // evaluate the rest of the CE - the part that follows the function calls.
1227  eval.parse_constraint(get_ce(), **dds);
1228 
1229  (*dds)->tag_nested_sequences(); // Tag Sequences as Parent or Leaf node.
1230 
1231  throw_if_dap2_response_too_big(*dds);
1232 
1233  if (with_mime_headers)
1234  set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1235 
1236 #if STORE_DAP2_RESULT_FEATURE
1237  // This means: if we are not supposed to store the result, then serialize it.
1238  if (!store_dap2_result(data_stream, **dds, eval)) {
1239  serialize_dap2_data_dds(data_stream, dds, eval, true /* was 'false'. jhrg 3/10/15 */);
1240  }
1241 #else
1242  serialize_dap2_data_dds(data_stream, dds, eval, true /* was 'false'. jhrg 3/10/15 */);
1243 #endif
1244 
1245  }
1246  else {
1247  BESDEBUG("dap", "BESDapResponseBuilder::send_dap2_data() - Simple constraint" << endl);
1248 
1249  eval.parse_constraint(get_ce(), **dds); // Throws Error if the ce doesn't parse.
1250 
1251  (*dds)->tag_nested_sequences(); // Tag Sequences as Parent or Leaf node.
1252 
1253  throw_if_dap2_response_too_big(*dds);
1254 
1255  if (with_mime_headers)
1256  set_mime_binary(data_stream, dods_data, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1257 
1258 #if STORE_DAP2_RESULT_FEATURE
1259  // This means: if we are not supposed to store the result, then serialize it.
1260  if (!store_dap2_result(data_stream, **dds, eval)) {
1261  serialize_dap2_data_dds(data_stream, dds, eval);
1262  }
1263 #else
1264  serialize_dap2_data_dds(data_stream, dds, eval);
1265 #endif
1266  }
1267 
1268  data_stream << flush;
1269 
1270  BESDEBUG("dap", "BESDapResponseBuilder::send_dap2_data() - END"<< endl);
1271 
1272 }
1286 void BESDapResponseBuilder::send_ddx(ostream &out, DDS **dds, ConstraintEvaluator &eval, bool with_mime_headers)
1287 {
1288  if (d_dap2ce.empty()) {
1289  if (with_mime_headers)
1290  set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1291 
1292  (*dds)->print_xml_writer(out, false /*constrained */, "");
1293  //dds.print(out);
1294  out << flush;
1295  return;
1296  }
1297 
1298 #if USE_LOCAL_TIMEOUT_SCHEME
1299  // Set up the alarm.
1300  establish_timeout(out);
1301  dds.set_timeout(d_timeout);
1302 #endif
1303 
1304  // Split constraint into two halves
1305  split_ce(eval);
1306 
1307  // If there are functions, parse them and eval.
1308  // Use that DDS and parse the non-function ce
1309  // Serialize using the second ce and the second dds
1310  if (!d_btp_func_ce.empty()) {
1311  BESDapFunctionResponseCache *response_cache = BESDapFunctionResponseCache::get_instance();
1312 
1313  ConstraintEvaluator func_eval;
1314  DDS *fdds = 0; // nulll_ptr
1315  if (response_cache && response_cache->can_be_cached(*dds, get_btp_func_ce())) {
1316  fdds = response_cache->get_or_cache_dataset(*dds, get_btp_func_ce());
1317  }
1318  else {
1319  func_eval.parse_constraint(get_btp_func_ce(), **dds);
1320  fdds = func_eval.eval_function_clauses(**dds);
1321  }
1322 
1323  delete *dds; *dds = 0;
1324  *dds = fdds;
1325 
1326  (*dds)->mark_all(false);
1327 
1328  promote_function_output_structures(*dds);
1329 
1330  eval.parse_constraint(d_dap2ce, **dds);
1331 
1332  if (with_mime_headers)
1333  set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1334 
1335  conditional_timeout_cancel();
1336 
1337  (*dds)->print_xml_writer(out, true, "");
1338  }
1339  else {
1340  eval.parse_constraint(d_dap2ce, **dds); // Throws Error if the ce doesn't parse.
1341 
1342  if (with_mime_headers)
1343  set_mime_text(out, dods_ddx, x_plain, last_modified_time(d_dataset), (*dds)->get_dap_version());
1344 
1345  conditional_timeout_cancel();
1346 
1347 
1348  // dds.print_constrained(out);
1349  (*dds)->print_xml_writer(out, true, "");
1350  }
1351 
1352  out << flush;
1353 }
1354 
1355 void BESDapResponseBuilder::send_dmr(ostream &out, DMR &dmr, bool with_mime_headers)
1356 {
1357  // If the CE is not empty, parse it. The projections, etc., are set as a side effect.
1358  // If the parser returns false, the expression did not parse. The parser may also
1359  // throw Error
1360  if (!d_dap4ce.empty()) {
1361 
1362  BESDEBUG("dap", "BESDapResponseBuilder::send_dmr() - Parsing DAP4 constraint: '"<< d_dap4ce << "'"<< endl);
1363 
1364  D4ConstraintEvaluator parser(&dmr);
1365  bool parse_ok = parser.parse(d_dap4ce);
1366  if (!parse_ok) throw Error(malformed_expr, "Constraint Expression (" + d_dap4ce + ") failed to parse.");
1367  }
1368  // with an empty CE, send everything. Even though print_dap4() and serialize()
1369  // don't need this, other code may depend on send_p being set. This may change
1370  // if DAP4 has a separate function evaluation phase. jhrg 11/25/13
1371  else {
1372  dmr.root()->set_send_p(true);
1373  }
1374 
1375  if (with_mime_headers) set_mime_text(out, dap4_dmr, x_plain, last_modified_time(d_dataset), dmr.dap_version());
1376 
1377  conditional_timeout_cancel();
1378 
1379 
1380  XMLWriter xml;
1381  dmr.print_dap4(xml, /*constrained &&*/!d_dap4ce.empty() /* true == constrained */);
1382  out << xml.get_doc() << flush;
1383 }
1384 
1385 void BESDapResponseBuilder::send_dap4_data_using_ce(ostream &out, DMR &dmr, bool with_mime_headers)
1386 {
1387  if (!d_dap4ce.empty()) {
1388  D4ConstraintEvaluator parser(&dmr);
1389  bool parse_ok = parser.parse(d_dap4ce);
1390  if (!parse_ok) throw Error(malformed_expr, "Constraint Expression (" + d_dap4ce + ") failed to parse.");
1391  }
1392  // with an empty CE, send everything. Even though print_dap4() and serialize()
1393  // don't need this, other code may depend on send_p being set. This may change
1394  // if DAP4 has a separate function evaluation phase. jhrg 11/25/13
1395  else {
1396  dmr.root()->set_send_p(true);
1397  }
1398 
1399  if (dmr.response_limit() != 0 && (dmr.request_size(true) > dmr.response_limit())) {
1400  string msg = "The Request for " + long_to_string(dmr.request_size(true))
1401  + "KB is too large; requests for this server are limited to " + long_to_string(dmr.response_limit())
1402  + "KB.";
1403  throw Error(msg);
1404  }
1405 
1406  if (!store_dap4_result(out, dmr)) {
1407  serialize_dap4_data(out, dmr, with_mime_headers);
1408  }
1409 }
1410 
1411 void BESDapResponseBuilder::send_dap4_data(ostream &out, DMR &dmr, bool with_mime_headers)
1412 {
1413  // If a function was passed in with this request, evaluate it and use that DMR
1414  // for the remainder of this request.
1415  // TODO Add caching for these function invocations
1416  if (!d_dap4function.empty()) {
1417  D4BaseTypeFactory d4_factory;
1418  DMR function_result(&d4_factory, "function_results");
1419 
1420  // Function modules load their functions onto this list. The list is
1421  // part of libdap, not the BES.
1422  if (!ServerFunctionsList::TheList())
1423  throw Error(
1424  "The function expression could not be evaluated because there are no server functions defined on this server");
1425 
1426  D4FunctionEvaluator parser(&dmr, ServerFunctionsList::TheList());
1427  bool parse_ok = parser.parse(d_dap4function);
1428  if (!parse_ok) throw Error("Function Expression (" + d_dap4function + ") failed to parse.");
1429 
1430  parser.eval(&function_result);
1431 
1432  // Now use the results of running the functions for the remainder of the
1433  // send_data operation.
1434  send_dap4_data_using_ce(out, function_result, with_mime_headers);
1435  }
1436  else {
1437  send_dap4_data_using_ce(out, dmr, with_mime_headers);
1438  }
1439 }
1440 
1444 void BESDapResponseBuilder::serialize_dap4_data(std::ostream &out, libdap::DMR &dmr, bool with_mime_headers)
1445 {
1446  BESDEBUG("dap", "BESDapResponseBuilder::serialize_dap4_data() - BEGIN" << endl);
1447 
1448  if (with_mime_headers) set_mime_binary(out, dap4_data, x_plain, last_modified_time(d_dataset), dmr.dap_version());
1449 
1450  // Write the DMR
1451  XMLWriter xml;
1452  dmr.print_dap4(xml, !d_dap4ce.empty());
1453 
1454  // now make the chunked output stream; set the size to be at least chunk_size
1455  // but make sure that the whole of the xml plus the CRLF can fit in the first
1456  // chunk. (+2 for the CRLF bytes).
1457  chunked_ostream cos(out, max((unsigned int) CHUNK_SIZE, xml.get_doc_size() + 2));
1458 
1459  conditional_timeout_cancel();
1460 
1461  // using flush means that the DMR and CRLF are in the first chunk.
1462  cos << xml.get_doc() << CRLF << flush;
1463 
1464  // Write the data, chunked with checksums
1465  D4StreamMarshaller m(cos);
1466  dmr.root()->serialize(m, dmr, !d_dap4ce.empty());
1467 #ifdef CLEAR_LOCAL_DATA
1468  dmr.root()->clear_local_data();
1469 #endif
1470  cos << flush;
1471 
1472  BESDEBUG("dap", "BESDapResponseBuilder::serialize_dap4_data() - END" << endl);
1473 }
1474 
1489 bool BESDapResponseBuilder::store_dap4_result(ostream &out, libdap::DMR &dmr)
1490 {
1491  if (get_store_result().length() != 0) {
1492  string serviceUrl = get_store_result();
1493 
1494  D4AsyncUtil d4au;
1495  XMLWriter xmlWrtr;
1496 
1497  // FIXME See above comment for store dap2 result
1498  bool found;
1499  string *stylesheet_ref = 0, ss_ref_value;
1500  TheBESKeys::TheKeys()->get_value(D4AsyncUtil::STYLESHEET_REFERENCE_KEY, ss_ref_value, found);
1501  if (found && ss_ref_value.length() > 0) {
1502  stylesheet_ref = &ss_ref_value;
1503  }
1504 
1506  if (resultCache == NULL) {
1507 
1513  string msg = "The Stored Result request cannot be serviced. ";
1514  msg += "Unable to acquire StoredResultCache instance. ";
1515  msg += "This is most likely because the StoredResultCache is not (correctly) configured.";
1516 
1517  BESDEBUG("dap", "[WARNING] " << msg << endl);
1518  d4au.writeD4AsyncResponseRejected(xmlWrtr, UNAVAILABLE, msg, stylesheet_ref);
1519  out << xmlWrtr.get_doc();
1520  out << flush;
1521  BESDEBUG("dap", "BESDapResponseBuilder::store_dap4_result() - Sent AsyncRequestRejected" << endl);
1522 
1523  return true;
1524  }
1525 
1526  if (get_async_accepted().length() != 0) {
1527 
1531  BESDEBUG("dap", "BESDapResponseBuilder::store_dap4_result() - serviceUrl="<< serviceUrl << endl);
1532 
1533  string storedResultId = "";
1534  storedResultId = resultCache->store_dap4_result(dmr, get_ce(), this);
1535 
1536  BESDEBUG("dap",
1537  "BESDapResponseBuilder::store_dap4_result() - storedResultId='"<< storedResultId << "'" << endl);
1538 
1539  string targetURL = BESUtil::assemblePath(serviceUrl, storedResultId);
1540  BESDEBUG("dap", "BESDapResponseBuilder::store_dap4_result() - targetURL='"<< targetURL << "'" << endl);
1541 
1542  d4au.writeD4AsyncAccepted(xmlWrtr, 0, 0, targetURL, stylesheet_ref);
1543  out << xmlWrtr.get_doc();
1544  out << flush;
1545  BESDEBUG("dap", "BESDapResponseBuilder::store_dap4_result() - sent AsyncAccepted" << endl);
1546 
1547  }
1548  else {
1553  d4au.writeD4AsyncRequired(xmlWrtr, 0, 0, stylesheet_ref);
1554  out << xmlWrtr.get_doc();
1555  out << flush;
1556  BESDEBUG("dap", "BESDapResponseBuilder::store_dap4_result() - sent AsyncAccepted" << endl);
1557  }
1558 
1559  return true;
1560  }
1561 
1562  return false;
1563 }
BESRequestHandler
Represents a specific data type request handler.
Definition: BESRequestHandler.h:74
BESDataHandlerInterface::container
BESContainer * container
pointer to current container in this interface
Definition: BESDataHandlerInterface.h:75
BESDapResponseBuilder::establish_timeout
virtual void establish_timeout(std::ostream &stream) const
Definition: BESDapResponseBuilder.cc:363
BESDapResponseBuilder::conditional_timeout_cancel
void conditional_timeout_cancel()
Definition: BESDapResponseBuilder.cc:332
BESDapResponseBuilder::timeout_on
void timeout_on() const
Definition: BESDapResponseBuilder.cc:294
BESStopWatch::start
virtual bool start(std::string name)
Definition: BESStopWatch.cc:58
BESDapResponseBuilder::store_dap4_result
virtual bool store_dap4_result(ostream &out, libdap::DMR &dmr)
Definition: BESDapResponseBuilder.cc:1489
BESInternalFatalError
exception thrown if an internal error is found and is fatal to the BES
Definition: BESInternalFatalError.h:43
BESDapResponseBuilder::get_dataset_name
virtual std::string get_dataset_name() const
Get the dataset name.
Definition: BESDapResponseBuilder.cc:251
BESDapResponseBuilder::send_ddx
virtual void send_ddx(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool with_mime_headers=true)
Definition: BESDapResponseBuilder.cc:1286
BESDapResponseBuilder::register_timeout
void register_timeout() const
Definition: BESDapResponseBuilder.cc:346
BESDapResponseBuilder::split_ce
virtual void split_ce(libdap::ConstraintEvaluator &eval, const std::string &expr="")
Definition: BESDapResponseBuilder.cc:418
BESDataDDSResponse::set_dds
void set_dds(libdap::DDS *ddsIn)
Definition: BESDataDDSResponse.h:73
BESDapResponseBuilder::get_dap4ce
virtual std::string get_dap4ce() const
Get the DAP4 constraint expression.
Definition: BESDapResponseBuilder.cc:177
BESContainer::get_container_type
std::string get_container_type() const
retrieve the type of data this container holds, such as cedar or netcdf.
Definition: BESContainer.h:232
BESDDSResponse::set_dds
void set_dds(libdap::DDS *ddsIn)
Definition: BESDDSResponse.h:71
BESDDSResponse::get_dds
libdap::DDS * get_dds()
Definition: BESDDSResponse.h:80
BESDapResponseBuilder::send_dds
virtual void send_dds(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool constrained=false, bool with_mime_headers=true)
Transmit a DDS.
Definition: BESDapResponseBuilder.cc:605
BESDDSResponse::get_ce
libdap::ConstraintEvaluator & get_ce()
Definition: BESDDSResponse.h:92
BESDapResponseBuilder::initialize
void initialize()
Definition: BESDapResponseBuilder.cc:125
BESStoredDapResultCache::store_dap4_result
virtual string store_dap4_result(libdap::DMR &dmr, const string &constraint, BESDapResponseBuilder *rb)
Definition: BESStoredDapResultCache.cc:739
BESDapFunctionResponseCache::get_or_cache_dataset
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.
Definition: BESDapFunctionResponseCache.cc:320
BESUtil::assemblePath
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.
Definition: BESUtil.cc:821
BESDapResponseBuilder::get_timeout
int get_timeout() const
Definition: BESDapResponseBuilder.cc:282
libdap
Definition: BESDapFunctionResponseCache.h:35
TheBESKeys::TheKeys
static TheBESKeys * TheKeys()
Definition: TheBESKeys.cc:62
BESResponseHandler::get_response_object
virtual BESResponseObject * get_response_object()
return the current response object
Definition: BESResponseHandler.cc:82
BESDapResponseBuilder::set_dap4function
virtual void set_dap4function(std::string _func)
Definition: BESDapResponseBuilder.cc:216
BESDataHandlerInterface::data
std::map< std::string, std::string > data
the map of string data that will be required for the current request.
Definition: BESDataHandlerInterface.h:90
BESDapResponseBuilder::set_dataset_name
virtual void set_dataset_name(const std::string _dataset)
Set the dataset pathname.
Definition: BESDapResponseBuilder.cc:266
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
BESStoredDapResultCache::get_instance
static BESStoredDapResultCache * get_instance()
Definition: BESStoredDapResultCache.cc:240
BESStopWatch
Definition: BESStopWatch.h:55
TheBESKeys::get_value
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: TheBESKeys.cc:272
BESDDSResponse
Holds a DDS object within the BES.
Definition: BESDDSResponse.h:50
BESDapResponseBuilder::set_ce
virtual void set_ce(std::string _ce)
Definition: BESDapResponseBuilder.cc:169
BESStoredDapResultCache
Definition: BESStoredDapResultCache.h:52
BESDapResponseBuilder::intern_dap2_data
virtual libdap::DDS * intern_dap2_data(BESResponseObject *obj, BESDataHandlerInterface &dhi)
Definition: BESDapResponseBuilder.cc:980
BESDapResponseBuilder::serialize_dap4_data
virtual void serialize_dap4_data(std::ostream &out, libdap::DMR &dmr, bool with_mime_headers=true)
Definition: BESDapResponseBuilder.cc:1444
BESDapResponseBuilder::set_timeout
void set_timeout(int timeout=0)
Definition: BESDapResponseBuilder.cc:276
BESDataDDSResponse
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
Definition: BESDataDDSResponse.h:46
BESDapResponseBuilder::get_dap4function
virtual std::string get_dap4function() const
Get the DAP4 server side function expression.
Definition: BESDapResponseBuilder.cc:200
BESDapResponseBuilder::set_dap4ce
virtual void set_dap4ce(std::string _ce)
Definition: BESDapResponseBuilder.cc:192
Error
BESDapResponseBuilder::timeout_off
void timeout_off()
Definition: BESDapResponseBuilder.cc:309
BESDataHandlerInterface::first_container
void first_container()
set the container pointer to the first container in the containers list
Definition: BESDataHandlerInterface.h:135
BESDapResponseBuilder::process_dap2_dds
virtual libdap::DDS * process_dap2_dds(BESResponseObject *obj, BESDataHandlerInterface &dhi)
Process a DDS (i.e., apply a constraint) for a non-DAP transmitter.
Definition: BESDapResponseBuilder.cc:911
BESDapResponseBuilder::get_ce
virtual std::string get_ce() const
Get the constraint expression.
Definition: BESDapResponseBuilder.cc:154
BESDataHandlerInterface
Structure storing information used by the BES to handle the request.
Definition: BESDataHandlerInterface.h:56
BESRequestHandlerList::find_handler
virtual BESRequestHandler * find_handler(const std::string &handler_name)
find and return the specified request handler
Definition: BESRequestHandlerList.cc:95
BESDapFunctionResponseCache
Cache the results from server functions.
Definition: BESDapFunctionResponseCache.h:72
BESResponseObject
Abstract base class representing a specific set of information in response to a request to the BES.
Definition: BESResponseObject.h:45
BESDapResponseBuilder::serialize_dap2_data_dds
virtual void serialize_dap2_data_dds(std::ostream &out, libdap::DDS **dds, libdap::ConstraintEvaluator &eval, bool ce_eval=true)
Definition: BESDapResponseBuilder.cc:791
BESDapResponseBuilder::remove_timeout
virtual void remove_timeout() const
Transmit data.
Definition: BESDapResponseBuilder.cc:890