33#include <libdap/DMR.h>
34#include <libdap/DataDDS.h>
35#include <libdap/mime_util.h>
36#include <libdap/D4BaseTypeFactory.h>
38#include <BESResponseHandler.h>
39#include <BESResponseNames.h>
40#include <BESDapNames.h>
41#include <BESDASResponse.h>
42#include <BESDDSResponse.h>
43#include <BESDataDDSResponse.h>
44#include <BESVersionInfo.h>
46#include <BESDapError.h>
47#include <BESInternalFatalError.h>
48#include <BESDataNames.h>
49#include <TheBESKeys.h>
50#include <BESServiceRegistry.h>
53#include <BESStopWatch.h>
54#include <BESContextManager.h>
55#include <BESDMRResponse.h>
57#include <ObjMemCache.h>
59#include <libdap/InternalErr.h>
60#include <libdap/Ancillary.h>
62#include "NCRequestHandler.h"
63#include "GlobalMetadataStore.h"
69#define prolog std::string("NCRequestHandler::").append(__func__).append("() - ")
72bool NCRequestHandler::_show_shared_dims =
true;
73bool NCRequestHandler::_show_shared_dims_set =
false;
75bool NCRequestHandler::_ignore_unknown_types =
false;
76bool NCRequestHandler::_ignore_unknown_types_set =
false;
78bool NCRequestHandler::_promote_byte_to_short =
false;
79bool NCRequestHandler::_promote_byte_to_short_set =
false;
80bool NCRequestHandler::_use_mds =
false;
82unsigned int NCRequestHandler::_cache_entries = 100;
83float NCRequestHandler::_cache_purge_level = 0.2;
90extern void nc_read_dataset_attributes(DAS & das,
const string & filename);
91extern void nc_read_dataset_variables(DDS & dds,
const string & filename);
99static bool version_ge(
const string &version,
float value)
103 istringstream iss(version);
118static bool get_bool_key(
const string &key,
bool def_val)
122 const string dosettrue =
"true";
123 const string dosetyes =
"yes";
128 return (dosettrue == doset || dosetyes == doset);
133static unsigned int get_uint_key(
const string &key,
unsigned int def_val)
140 return atoi(doset.c_str());
147static float get_float_key(
const string &key,
float def_val)
154 return atof(doset.c_str());
161NCRequestHandler::NCRequestHandler(
const string &name) :
164 BESDEBUG(NC_NAME, prolog <<
"BEGIN" << endl);
166 add_method(DAS_RESPONSE, NCRequestHandler::nc_build_das);
167 add_method(DDS_RESPONSE, NCRequestHandler::nc_build_dds);
168 add_method(DATA_RESPONSE, NCRequestHandler::nc_build_data);
170 add_method(DMR_RESPONSE, NCRequestHandler::nc_build_dmr);
171 add_method(DAP4DATA_RESPONSE, NCRequestHandler::nc_build_dmr);
173 add_method(HELP_RESPONSE, NCRequestHandler::nc_build_help);
174 add_method(VERS_RESPONSE, NCRequestHandler::nc_build_version);
178 if (NCRequestHandler::_show_shared_dims_set ==
false) {
179 bool key_found =
false;
184 NCRequestHandler::_show_shared_dims_set =
true;
187 if (doset ==
"true" || doset ==
"yes") {
188 NCRequestHandler::_show_shared_dims =
true;
191 NCRequestHandler::_show_shared_dims =
false;
195 if (NCRequestHandler::_ignore_unknown_types_set ==
false) {
196 bool key_found =
false;
201 if (doset ==
"true" || doset ==
"yes")
202 NCRequestHandler::_ignore_unknown_types =
true;
204 NCRequestHandler::_ignore_unknown_types =
false;
206 NCRequestHandler::_ignore_unknown_types_set =
true;
210 if (NCRequestHandler::_promote_byte_to_short_set ==
false) {
211 bool key_found =
false;
216 if (doset ==
"true" || doset ==
"yes")
217 NCRequestHandler::_promote_byte_to_short =
true;
219 NCRequestHandler::_promote_byte_to_short =
false;
221 NCRequestHandler::_promote_byte_to_short_set =
true;
225 NCRequestHandler::_use_mds = get_bool_key(
"NC.UseMDS",
false);
226 NCRequestHandler::_cache_entries = get_uint_key(
"NC.CacheEntries", 0);
227 NCRequestHandler::_cache_purge_level = get_float_key(
"NC.CachePurgeLevel", 0.2);
229 if (get_cache_entries()) {
230 das_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
231 dds_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
232 datadds_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
233 dmr_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
236 BESDEBUG(NC_NAME, prolog <<
"END" << endl);
239NCRequestHandler::~NCRequestHandler()
243 delete datadds_cache;
251 sw.
start(
"NCRequestHandler::nc_build_das", dhi.
data[REQUEST_ID]);
253 BESDEBUG(NC_NAME, prolog <<
"BEGIN" << endl);
263 DAS *das = bdas->get_das();
264 if (!container_name.empty()) das->container_name(container_name);
268 DAS *cached_das_ptr = 0;
269 if (das_cache && (cached_das_ptr =
static_cast<DAS*
>(das_cache->
get(accessed)))) {
271 BESDEBUG(NC_NAME, prolog <<
"DAS Cached hit for : " << accessed << endl);
272 *das = *cached_das_ptr;
275 nc_read_dataset_attributes(*das, accessed);
276 Ancillary::read_ancillary_das(*das, accessed);
279 BESDEBUG(NC_NAME, prolog <<
"DAS added to the cache for : " << accessed << endl);
280 das_cache->
add(
new DAS(*das), accessed);
289 catch (InternalErr & e) {
290 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
294 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
297 catch (std::exception &e) {
298 string s = string(
"C++ Exception: ") + e.what();
303 string s =
"Unknown exception caught building DAS";
308 BESDEBUG(NC_NAME, prolog <<
"END" << endl);
318void NCRequestHandler::get_dds_with_attributes(
const string& dataset_name,
const string& container_name, DDS* dds)
321 DDS* cached_dds_ptr = 0;
322 if (dds_cache && (cached_dds_ptr =
static_cast<DDS*
>(dds_cache->
get(dataset_name)))) {
325 BESDEBUG(NC_NAME, prolog <<
"DDS Cached hit for : " << dataset_name << endl);
326 *dds = *cached_dds_ptr;
329 if (!container_name.empty()) dds->container_name(container_name);
330 dds->filename(dataset_name);
332 nc_read_dataset_variables(*dds, dataset_name);
335 if (das_cache && (das =
static_cast<DAS*
>(das_cache->
get(dataset_name)))) {
336 BESDEBUG(NC_NAME, prolog <<
"DAS Cached hit for : " << dataset_name << endl);
337 dds->transfer_attributes(das);
343 if (!container_name.empty()) das->container_name(container_name);
345 nc_read_dataset_attributes(*das, dataset_name);
346 Ancillary::read_ancillary_das(*das, dataset_name);
348 dds->transfer_attributes(das);
353 BESDEBUG(NC_NAME, prolog <<
"DAS added to the cache for : " << dataset_name << endl);
354 das_cache->
add(das, dataset_name);
363 BESDEBUG(NC_NAME, prolog <<
"DDS added to the cache for : " << dataset_name << endl);
364 dds_cache->
add(
new DDS(*dds), dataset_name);
369void NCRequestHandler::get_dds_without_attributes(
const string& dataset_name,
const string& container_name, DDS* dds)
372 DDS* cached_datadds_ptr = 0;
373 if (datadds_cache && (cached_datadds_ptr =
static_cast<DDS*
>(datadds_cache->
get(dataset_name)))) {
375 BESDEBUG(NC_NAME, prolog <<
"DataDDS Cached hit for : " << dataset_name << endl);
376 *dds = *cached_datadds_ptr;
379 if (!container_name.empty()) dds->container_name(container_name);
380 dds->filename(dataset_name);
382 nc_read_dataset_variables(*dds, dataset_name);
386 BESDEBUG(NC_NAME, prolog <<
"DataDDS added to the cache for : " << dataset_name << endl);
387 datadds_cache->
add(
new DDS(*dds), dataset_name);
398 sw.
start(
"NCRequestHandler::nc_build_dds", dhi.
data[REQUEST_ID]);
409 if (NCRequestHandler::_show_shared_dims_set ==
false) {
410 bool context_found =
false;
411 string context_value = BESContextManager::TheManager()->
get_context(
"xdap_accept", context_found);
413 BESDEBUG(NC_NAME, prolog <<
"xdap_accept: " << context_value << endl);
414 if (version_ge(context_value, 3.2))
415 NCRequestHandler::_show_shared_dims =
false;
417 NCRequestHandler::_show_shared_dims =
true;
426 get_dds_with_attributes(filename, container_name, dds);
434 catch (InternalErr & e) {
435 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
439 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
442 catch (std::exception &e) {
443 string s = string(
"C++ Exception: ") + e.what();
448 string s =
"Unknown exception caught building DDS";
460 sw.
start(
"NCRequestHandler::nc_build_data", dhi.
data[REQUEST_ID]);
468 if (NCRequestHandler::_show_shared_dims_set ==
false) {
469 bool context_found =
false;
470 string context_value = BESContextManager::TheManager()->
get_context(
"xdap_accept", context_found);
472 BESDEBUG(NC_NAME, prolog <<
"xdap_accept: " << context_value << endl);
473 if (version_ge(context_value, 3.2))
474 NCRequestHandler::_show_shared_dims =
false;
476 NCRequestHandler::_show_shared_dims =
true;
481 DDS *dds = bdds->get_dds();
484 get_dds_without_attributes(dhi.
container->
access(), container_name, dds);
487 BESDEBUG(NC_NAME, prolog <<
"Data ACCESS build_data(): set the including attribute flag to false: "<<dhi.
container->
access() << endl);
488 bdds->set_ia_flag(
false);
494 catch (InternalErr & e) {
495 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
499 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
502 catch (std::exception &e) {
503 string s = string(
"C++ Exception: ") + e.what();
508 string s =
"Unknown exception caught building DAS";
520 sw.
start(
"NCRequestHandler::nc_build_dmr", dhi.
data[REQUEST_ID]);
535 DMR *dmr = bdmr.get_dmr();
538 DMR* cached_dmr_ptr = 0;
539 if (dmr_cache && (cached_dmr_ptr =
static_cast<DMR*
>(dmr_cache->
get(dataset_name)))) {
541 BESDEBUG(NC_NAME, prolog <<
"DMR Cached hit for : " << dataset_name << endl);
542 *dmr = *cached_dmr_ptr;
549 DDS dds(&factory, name_path(dataset_name),
"3.2");
552 get_dds_with_attributes(dataset_name,
"", &dds);
554 dmr->set_factory(
new D4BaseTypeFactory);
555 dmr->build_using_dds(dds);
559 dmr->set_factory(
new D4BaseTypeFactory);
562 if (dds_cache && (dds_ptr =
static_cast<DDS*
>(dds_cache->
get(dataset_name)))) {
564 BESDEBUG(NC_NAME, prolog <<
"DDS Cached hit (while building DMR) for : " << dataset_name << endl);
566 dmr->build_using_dds(*dds_ptr);
572 DDS dds(&factory, name_path(dataset_name),
"3.2");
574 dds.filename(dataset_name);
575 nc_read_dataset_variables(dds, dataset_name);
579 nc_read_dataset_attributes(das, dataset_name);
580 Ancillary::read_ancillary_das(das, dataset_name);
582 dds.transfer_attributes(&das);
583 dmr->build_using_dds(dds);
589 BESDEBUG(NC_NAME, prolog <<
"DMR added to the cache for : " << dataset_name << endl);
590 dmr_cache->
add(
new DMR(*dmr), dataset_name);
602 catch (InternalErr &e) {
603 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
606 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
609 throw BESDapError(
"Caught unknown error build NC DMR response",
true, unknown_error, __FILE__, __LINE__);
619 sw.
start(
"NCRequestHandler::nc_build_help", dhi.
data[REQUEST_ID]);
626 map < string, string > attrs;
627 attrs[
"name"] = MODULE_NAME ;
628 attrs[
"version"] = MODULE_VERSION ;
630 attrs[
"name"] = PACKAGE_NAME;
631 attrs[
"version"] = PACKAGE_VERSION;
633 list < string > services;
635 if (services.size() > 0) {
637 attrs[
"handles"] = handles;
639 info->begin_tag(
"module", &attrs);
640 info->end_tag(
"module");
649 sw.
start(
"NCRequestHandler::nc_build_version", dhi.
data[REQUEST_ID]);
657 info->add_module(PACKAGE_NAME, PACKAGE_VERSION);
659 info->add_module(MODULE_NAME, MODULE_VERSION);
670 DDS *dds = bdds->get_dds();
674 if (das_cache && (das =
static_cast<DAS*
>(das_cache->
get(dataset_name)))) {
675 BESDEBUG(NC_NAME, prolog <<
"DAS Cached hit for : " << dataset_name << endl);
676 dds->transfer_attributes(das);
682 if (!container_name.empty()) das->container_name(container_name);
685 if(
true == get_use_mds()) {
688 bool valid_mds =
true;
693 if(
true ==valid_mds) {
698 BESDEBUG(NC_NAME, prolog <<
"Using MDS to generate DAS in the data response for file " << dataset_name << endl);
699 mds->parse_das_from_mds(das,rel_file_path);
702 nc_read_dataset_attributes(*das, dataset_name);
704 mds_das_lock.clearLock();
707 nc_read_dataset_attributes(*das, dataset_name);
711 nc_read_dataset_attributes(*das, dataset_name);
713 Ancillary::read_ancillary_das(*das, dataset_name);
715 dds->transfer_attributes(das);
720 BESDEBUG(NC_NAME, prolog <<
"DAS added to the cache for : " << dataset_name << endl);
721 das_cache->
add(das, dataset_name);
727 BESDEBUG(NC_NAME, prolog <<
"Data ACCESS in add_attributes(): set the including attribute flag to true: "<<dataset_name << endl);
728 bdds->set_ia_flag(
true);
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
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
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.
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?
std::string get_request_xml_base() const
Return the xml:base URL for this request.
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
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
Base exception class for the BES with basic string message.
bool cache_enabled() const
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 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()