29 #include <curl/curl.h>
32 #include <Ancillary.h>
33 #include <ObjMemCache.h>
38 #include <InternalErr.h>
39 #include <mime_util.h>
41 #include <BESResponseHandler.h>
42 #include <BESResponseNames.h>
43 #include <BESDapNames.h>
44 #include <BESDataNames.h>
45 #include <BESDASResponse.h>
46 #include <BESDDSResponse.h>
47 #include <BESDataDDSResponse.h>
48 #include <BESVersionInfo.h>
49 #include <BESTextInfo.h>
50 #include <BESContainer.h>
52 #include <BESDMRResponse.h>
54 #include <BESConstraintFuncs.h>
55 #include <BESServiceRegistry.h>
58 #include <TheBESKeys.h>
60 #include <BESDapError.h>
61 #include <BESInternalFatalError.h>
63 #include <BESStopWatch.h>
66 #include "DmrppTypeFactory.h"
67 #include "DmrppParserSax2.h"
68 #include "DmrppRequestHandler.h"
69 #include "CurlHandlePool.h"
70 #include "DmrppMetadataStore.h"
71 #include "CredentialsManager.h"
77 #define prolog std::string("DmrppRequestHandler::").append(__func__).append("() - ")
78 #define MODULE "dmrpp"
89 CurlHandlePool *DmrppRequestHandler::curl_handle_pool = 0;
91 bool DmrppRequestHandler::d_use_parallel_transfers =
true;
92 unsigned int DmrppRequestHandler::d_max_parallel_transfers = 8;
95 unsigned int DmrppRequestHandler::d_min_size = 2097152;
97 static void read_key_value(
const std::string &key_name,
bool &key_value)
99 bool key_found =
false;
104 key_value = (value ==
"true" || value ==
"yes");
108 static void read_key_value(
const std::string &key_name,
unsigned int &key_value)
110 bool key_found =
false;
114 istringstream iss(value);
123 DmrppRequestHandler::DmrppRequestHandler(
const string &name) :
127 add_method(DAP4DATA_RESPONSE, dap_build_dap4data);
135 read_key_value(
"DMRPP.UseParallelTransfers", d_use_parallel_transfers);
136 read_key_value(
"DMRPP.MaxParallelTransfers", d_max_parallel_transfers);
138 #if !HAVE_CURL_MULTI_API
139 if (DmrppRequestHandler::d_use_parallel_transfers)
140 ERROR_LOG(
"The DMR++ handler is configured to use parallel transfers, but the libcurl Multi API is not present, defaulting to serial transfers");
145 if (!curl_handle_pool)
150 curl_global_init(CURL_GLOBAL_DEFAULT);
153 DmrppRequestHandler::~DmrppRequestHandler()
155 delete curl_handle_pool;
156 curl_global_cleanup();
159 void DmrppRequestHandler::build_dmr_from_file(
BESContainer *container, DMR* dmr)
161 string data_pathname = container->
access();
163 dmr->set_filename(data_pathname);
164 dmr->set_name(name_path(data_pathname));
166 DmrppTypeFactory BaseFactory;
167 dmr->set_factory(&BaseFactory);
169 DmrppParserSax2 parser;
170 ifstream in(data_pathname.c_str(), ios::in);
172 parser.intern(in, dmr);
191 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
195 if (!bdmr)
throw BESInternalError(
"Cast error, expected a BESDDSResponse object.", __FILE__, __LINE__);
198 build_dmr_from_file(dhi.
container, bdmr->get_dmr());
206 catch (InternalErr & e) {
207 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
210 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
216 BESDEBUG(MODULE, prolog <<
"END" << endl);
226 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
230 if (!bdmr)
throw BESInternalError(
"Cast error, expected a BESDMRResponse object.", __FILE__, __LINE__);
237 throw BESInternalError(
"MDS configuration error: The DMR++ module could not find the MDS", __FILE__, __LINE__);
241 throw BESInternalError(
"DMR++ module error: Null DMR++ object read from the MDS", __FILE__, __LINE__);
243 delete bdmr->get_dmr();
244 bdmr->set_dmr(dmrpp);
247 build_dmr_from_file(dhi.
container, bdmr->get_dmr());
256 catch (InternalErr & e) {
257 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
260 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
263 throw BESInternalFatalError(
"Unknown exception caught building DAP4 Data response", __FILE__, __LINE__);
266 BESDEBUG(MODULE, prolog <<
"END" << endl);
279 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
283 if (!bdds)
throw BESInternalError(
"Cast error, expected a BESDataDDSResponse object.", __FILE__, __LINE__);
288 DDS *dds = bdds->get_dds();
289 if (!container_name_str.empty()) dds->container_name(container_name_str);
293 DDS *cached_dds_ptr = 0;
294 if (dds_cache && (cached_dds_ptr =
static_cast<DDS*
>(dds_cache->
get(accessed)))) {
296 BESDEBUG(MODULE, prolog <<
"DDS Cached hit for : " << accessed << endl);
297 *dds = *cached_dds_ptr;
308 throw BESInternalError(
"MDS configuration error: The DMR++ module could not find the MDS", __FILE__, __LINE__);
312 throw BESInternalError(
"DMR++ module error: Null DMR++ object read from the MDS", __FILE__, __LINE__);
332 dds_cache->
add(
new DDS(*dds), accessed);
341 catch (InternalErr & e) {
342 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
346 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
349 catch (std::exception &e) {
350 string s = string(
"C++ Exception: ") + e.what();
355 string s =
"unknown exception caught building DDS";
360 BESDEBUG(MODULE, prolog <<
"END" << endl);
372 BESDEBUG(MODULE, prolog <<
"BEGIN" << endl);
376 if (!bdds)
throw BESInternalError(
"Cast error, expected a BESDDSResponse object.", __FILE__, __LINE__);
382 if (!container_name_str.empty()) dds->container_name(container_name_str);
386 DDS *cached_dds_ptr = 0;
387 if (dds_cache && (cached_dds_ptr =
static_cast<DDS*
>(dds_cache->
get(accessed)))) {
389 BESDEBUG(MODULE, prolog <<
"DDS Cached hit for : " << accessed << endl);
390 *dds = *cached_dds_ptr;
394 DMR *dmr =
new DMR();
410 dds_cache->
add(
new DDS(*dds), accessed);
419 catch (InternalErr & e) {
420 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
424 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
427 catch (std::exception &e) {
428 string s = string(
"C++ Exception: ") + e.what();
433 string s =
"unknown exception caught building DDS";
438 BESDEBUG(MODULE, prolog <<
"END" << endl);
453 if (!bdas)
throw BESInternalError(
"Cast error, expected a BESDASResponse object.", __FILE__, __LINE__);
458 DAS *das = bdas->get_das();
459 if (!container_name_str.empty()) das->container_name(container_name_str);
463 DAS *cached_das_ptr = 0;
464 if (das_cache && (cached_das_ptr =
static_cast<DAS*
>(das_cache->
get(accessed)))) {
466 *das = *cached_das_ptr;
471 DMR *dmr =
new DMR();
475 DDS *dds = dmr->getDDS();
483 Ancillary::read_ancillary_das(*das, accessed);
486 das_cache->
add(
new DAS(*das), accessed);
495 catch (InternalErr & e) {
496 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
500 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
503 catch (std::exception &e) {
504 string s = string(
"C++ Exception: ") + e.what();
509 string s =
"unknown exception caught building DAS";
514 BESDEBUG(MODULE, prolog <<
"END" << endl);
524 info->add_module(MODULE_NAME, MODULE_VERSION);
535 map<string, string> attrs;
536 attrs[
"name"] = MODULE_NAME ;
537 attrs[
"version"] = MODULE_VERSION ;
538 list<string> services;
540 if (services.size() > 0) {
542 attrs[
"handles"] = handles;
544 info->begin_tag(
"module", &attrs);
545 info->end_tag(
"module");
552 strm << BESIndent::LMarg <<
"DmrppRequestHandler::dump - (" << (
void *)
this <<
")" << endl;
555 BESIndent::UnIndent();
A container is something that holds data. E.G., a netcdf file or a database entry.
std::string get_attributes() const
retrieve the attributes desired from this container
std::string get_symbolic_name() const
retrieve the symbolic name for this container
std::string get_relative_name() const
Get the relative name of the object in this container.
virtual std::string access()=0
returns the true name of this container
Represents an OPeNDAP DAS DAP2 data object within the BES.
virtual void clear_container()
clear the container in the DAP response object
Holds a DDS object within the BES.
void set_dds(libdap::DDS *ddsIn)
virtual void clear_container()
clear the container in the DAP response object
Represents an OPeNDAP DMR DAP4 data object within the BES.
error object created from libdap error objects and can handle those errors
virtual void set_dap4_function(BESDataHandlerInterface &dhi)
set the constraint depending on the context
virtual void set_dap4_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
virtual void set_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
bool get_explicit_containers() const
Should containers be explicitly represented in the DD* responses?
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
void set_dds(libdap::DDS *ddsIn)
virtual void clear_container()
clear the container in the DAP response object
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.
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
Abstract exception class for the BES with basic string message.
informational response object
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
Represents a specific data type request handler.
virtual bool add_method(const std::string &name, p_request_handler_method method)
add a handler method to the request handler that knows how to fill in a specific response object
virtual void dump(std::ostream &strm) const
dumps information about this object
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 void services_handled(const std::string &handler, std::list< std::string > &services)
returns the list of servies provided by the handler in question
virtual bool start(std::string name)
static std::string lowercase(const std::string &s)
static std::string implode(const std::list< std::string > &values, char delim)
An in-memory cache for DapObj (DAS, DDS, ...) objects.
virtual void add(libdap::DapObj *obj, const std::string &key)
Add an object to the cache and associate it with a key.
virtual libdap::DapObj * get(const std::string &key)
Get the cached pointer.
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
Provide a way to print the DMR++ response.
static bool dap_build_dds(BESDataHandlerInterface &dhi)
static bool dap_build_dap2data(BESDataHandlerInterface &dhi)
static bool dap_build_dmr(BESDataHandlerInterface &dhi)
static bool dap_build_das(BESDataHandlerInterface &dhi)
virtual void dump(std::ostream &strm) const
dumps information about this object