27 #include "config_nc.h"
35 #include <mime_util.h>
36 #include <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 <InternalErr.h>
60 #include <Ancillary.h>
62 #include "NCRequestHandler.h"
63 #include "GlobalMetadataStore.h"
69 bool NCRequestHandler::_show_shared_dims =
true;
70 bool NCRequestHandler::_show_shared_dims_set =
false;
72 bool NCRequestHandler::_ignore_unknown_types =
false;
73 bool NCRequestHandler::_ignore_unknown_types_set =
false;
75 bool NCRequestHandler::_promote_byte_to_short =
false;
76 bool NCRequestHandler::_promote_byte_to_short_set =
false;
77 bool NCRequestHandler::_use_mds =
false;
79 unsigned int NCRequestHandler::_cache_entries = 100;
80 float NCRequestHandler::_cache_purge_level = 0.2;
87 extern void nc_read_dataset_attributes(DAS & das,
const string & filename);
88 extern void nc_read_dataset_variables(DDS & dds,
const string & filename);
96 static bool version_ge(
const string &version,
float value)
100 istringstream iss(version);
115 static bool get_bool_key(
const string &key,
bool def_val)
119 const string dosettrue =
"true";
120 const string dosetyes =
"yes";
125 return (dosettrue == doset || dosetyes == doset);
130 static unsigned int get_uint_key(
const string &key,
unsigned int def_val)
137 return atoi(doset.c_str());
144 static float get_float_key(
const string &key,
float def_val)
151 return atof(doset.c_str());
158 NCRequestHandler::NCRequestHandler(
const string &name) :
161 BESDEBUG(NC_NAME,
"In NCRequestHandler::NCRequestHandler" << endl);
163 add_method(DAS_RESPONSE, NCRequestHandler::nc_build_das);
164 add_method(DDS_RESPONSE, NCRequestHandler::nc_build_dds);
165 add_method(DATA_RESPONSE, NCRequestHandler::nc_build_data);
167 add_method(DMR_RESPONSE, NCRequestHandler::nc_build_dmr);
168 add_method(DAP4DATA_RESPONSE, NCRequestHandler::nc_build_dmr);
170 add_method(HELP_RESPONSE, NCRequestHandler::nc_build_help);
171 add_method(VERS_RESPONSE, NCRequestHandler::nc_build_version);
175 if (NCRequestHandler::_show_shared_dims_set ==
false) {
176 bool key_found =
false;
181 NCRequestHandler::_show_shared_dims_set =
true;
184 if (doset ==
"true" || doset ==
"yes") {
185 NCRequestHandler::_show_shared_dims =
true;
188 NCRequestHandler::_show_shared_dims =
false;
192 if (NCRequestHandler::_ignore_unknown_types_set ==
false) {
193 bool key_found =
false;
198 if (doset ==
"true" || doset ==
"yes")
199 NCRequestHandler::_ignore_unknown_types =
true;
201 NCRequestHandler::_ignore_unknown_types =
false;
203 NCRequestHandler::_ignore_unknown_types_set =
true;
207 if (NCRequestHandler::_promote_byte_to_short_set ==
false) {
208 bool key_found =
false;
213 if (doset ==
"true" || doset ==
"yes")
214 NCRequestHandler::_promote_byte_to_short =
true;
216 NCRequestHandler::_promote_byte_to_short =
false;
218 NCRequestHandler::_promote_byte_to_short_set =
true;
222 NCRequestHandler::_use_mds = get_bool_key(
"NC.UseMDS",
false);
223 NCRequestHandler::_cache_entries = get_uint_key(
"NC.CacheEntries", 0);
224 NCRequestHandler::_cache_purge_level = get_float_key(
"NC.CachePurgeLevel", 0.2);
226 if (get_cache_entries()) {
227 das_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
228 dds_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
229 datadds_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
230 dmr_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
233 BESDEBUG(NC_NAME,
"Exiting NCRequestHandler::NCRequestHandler" << endl);
236 NCRequestHandler::~NCRequestHandler()
240 delete datadds_cache;
247 if (BESISDEBUG( TIMING_LOG ))
248 sw.
start(
"NCRequestHandler::nc_build_das", dhi.
data[REQUEST_ID]);
250 BESDEBUG(NC_NAME,
"In NCRequestHandler::nc_build_das" << endl);
260 DAS *das = bdas->get_das();
261 if (!container_name.empty()) das->container_name(container_name);
265 DAS *cached_das_ptr = 0;
266 if (das_cache && (cached_das_ptr =
static_cast<DAS*
>(das_cache->
get(accessed)))) {
268 BESDEBUG(NC_NAME,
"DAS Cached hit for : " << accessed << endl);
269 *das = *cached_das_ptr;
272 nc_read_dataset_attributes(*das, accessed);
273 Ancillary::read_ancillary_das(*das, accessed);
276 BESDEBUG(NC_NAME,
"DAS added to the cache for : " << accessed << endl);
277 das_cache->
add(
new DAS(*das), accessed);
286 catch (InternalErr & e) {
287 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
291 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
294 catch (std::exception &e) {
295 string s = string(
"C++ Exception: ") + e.what();
300 string s =
"unknown exception caught building DAS";
305 BESDEBUG(NC_NAME,
"Exiting NCRequestHandler::nc_build_das" << endl);
315 void NCRequestHandler::get_dds_with_attributes(
const string& dataset_name,
const string& container_name, DDS* dds)
318 DDS* cached_dds_ptr = 0;
319 if (dds_cache && (cached_dds_ptr =
static_cast<DDS*
>(dds_cache->
get(dataset_name)))) {
322 BESDEBUG(NC_NAME,
"DDS Cached hit for : " << dataset_name << endl);
323 *dds = *cached_dds_ptr;
326 if (!container_name.empty()) dds->container_name(container_name);
327 dds->filename(dataset_name);
329 nc_read_dataset_variables(*dds, dataset_name);
332 if (das_cache && (das =
static_cast<DAS*
>(das_cache->
get(dataset_name)))) {
333 BESDEBUG(NC_NAME,
"DAS Cached hit for : " << dataset_name << endl);
334 dds->transfer_attributes(das);
340 if (!container_name.empty()) das->container_name(container_name);
342 nc_read_dataset_attributes(*das, dataset_name);
343 Ancillary::read_ancillary_das(*das, dataset_name);
345 dds->transfer_attributes(das);
350 BESDEBUG(NC_NAME,
"DAS added to the cache for : " << dataset_name << endl);
351 das_cache->
add(das, dataset_name);
360 BESDEBUG(NC_NAME,
"DDS added to the cache for : " << dataset_name << endl);
361 dds_cache->
add(
new DDS(*dds), dataset_name);
366 void NCRequestHandler::get_dds_without_attributes(
const string& dataset_name,
const string& container_name, DDS* dds)
369 DDS* cached_datadds_ptr = 0;
370 if (datadds_cache && (cached_datadds_ptr =
static_cast<DDS*
>(datadds_cache->
get(dataset_name)))) {
372 BESDEBUG(NC_NAME,
"DataDDS Cached hit for : " << dataset_name << endl);
373 *dds = *cached_datadds_ptr;
376 if (!container_name.empty()) dds->container_name(container_name);
377 dds->filename(dataset_name);
379 nc_read_dataset_variables(*dds, dataset_name);
383 BESDEBUG(NC_NAME,
"DataDDS added to the cache for : " << dataset_name << endl);
384 datadds_cache->
add(
new DDS(*dds), dataset_name);
394 if (BESISDEBUG( TIMING_LOG ))
395 sw.
start(
"NCRequestHandler::nc_build_dds", dhi.
data[REQUEST_ID]);
406 if (NCRequestHandler::_show_shared_dims_set ==
false) {
407 bool context_found =
false;
408 string context_value = BESContextManager::TheManager()->
get_context(
"xdap_accept", context_found);
410 BESDEBUG(NC_NAME,
"xdap_accept: " << context_value << endl);
411 if (version_ge(context_value, 3.2))
412 NCRequestHandler::_show_shared_dims =
false;
414 NCRequestHandler::_show_shared_dims =
true;
430 catch (InternalErr & e) {
431 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
435 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
438 catch (std::exception &e) {
439 string s = string(
"C++ Exception: ") + e.what();
444 string s =
"unknown exception caught building DDS";
455 if (BESISDEBUG( TIMING_LOG ))
456 sw.
start(
"NCRequestHandler::nc_build_data", dhi.
data[REQUEST_ID]);
464 if (NCRequestHandler::_show_shared_dims_set ==
false) {
465 bool context_found =
false;
466 string context_value = BESContextManager::TheManager()->
get_context(
"xdap_accept", context_found);
468 BESDEBUG(NC_NAME,
"xdap_accept: " << context_value << endl);
469 if (version_ge(context_value, 3.2))
470 NCRequestHandler::_show_shared_dims =
false;
472 NCRequestHandler::_show_shared_dims =
true;
477 DDS *dds = bdds->get_dds();
480 get_dds_without_attributes(dhi.
container->
access(), container_name, dds);
483 BESDEBUG(NC_NAME,
"Data ACCESS build_data(): set the including attribute flag to false: "<<dhi.
container->
access() << endl);
484 bdds->set_ia_flag(
false);
490 catch (InternalErr & e) {
491 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
495 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
498 catch (std::exception &e) {
499 string s = string(
"C++ Exception: ") + e.what();
504 string s =
"unknown exception caught building DAS";
515 if (BESISDEBUG( TIMING_LOG ))
516 sw.
start(
"NCRequestHandler::nc_build_dmr", dhi.
data[REQUEST_ID]);
531 DMR *dmr = bdmr.get_dmr();
534 DMR* cached_dmr_ptr = 0;
535 if (dmr_cache && (cached_dmr_ptr =
static_cast<DMR*
>(dmr_cache->
get(dataset_name)))) {
537 BESDEBUG(NC_NAME,
"DMR Cached hit for : " << dataset_name << endl);
538 *dmr = *cached_dmr_ptr;
543 BaseTypeFactory factory;
544 DDS dds(&factory, name_path(dataset_name),
"3.2");
547 get_dds_with_attributes(dataset_name,
"", &dds);
549 dmr->set_factory(
new D4BaseTypeFactory);
550 dmr->build_using_dds(dds);
554 dmr->set_factory(
new D4BaseTypeFactory);
557 if (dds_cache && (dds_ptr =
static_cast<DDS*
>(dds_cache->
get(dataset_name)))) {
559 BESDEBUG(NC_NAME,
"DDS Cached hit (while building DMR) for : " << dataset_name << endl);
561 dmr->build_using_dds(*dds_ptr);
566 BaseTypeFactory factory;
567 DDS dds(&factory, name_path(dataset_name),
"3.2");
569 dds.filename(dataset_name);
570 nc_read_dataset_variables(dds, dataset_name);
574 nc_read_dataset_attributes(das, dataset_name);
575 Ancillary::read_ancillary_das(das, dataset_name);
577 dds.transfer_attributes(&das);
578 dmr->build_using_dds(dds);
584 BESDEBUG(NC_NAME,
"DMR added to the cache for : " << dataset_name << endl);
585 dmr_cache->
add(
new DMR(*dmr), dataset_name);
597 catch (InternalErr &e) {
598 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
601 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
604 throw BESDapError(
"Caught unknown error build NC DMR response",
true, unknown_error, __FILE__, __LINE__);
613 if (BESISDEBUG( TIMING_LOG ))
614 sw.
start(
"NCRequestHandler::nc_build_help", dhi.
data[REQUEST_ID]);
621 map < string, string > attrs;
622 attrs[
"name"] = MODULE_NAME ;
623 attrs[
"version"] = MODULE_VERSION ;
625 attrs[
"name"] = PACKAGE_NAME;
626 attrs[
"version"] = PACKAGE_VERSION;
628 list < string > services;
630 if (services.size() > 0) {
632 attrs[
"handles"] = handles;
634 info->begin_tag(
"module", &attrs);
635 info->end_tag(
"module");
643 if (BESISDEBUG( TIMING_LOG ))
644 sw.
start(
"NCRequestHandler::nc_build_version", dhi.
data[REQUEST_ID]);
652 info->add_module(PACKAGE_NAME, PACKAGE_VERSION);
654 info->add_module(MODULE_NAME, MODULE_VERSION);
665 DDS *dds = bdds->get_dds();
669 if (das_cache && (das =
static_cast<DAS*
>(das_cache->
get(dataset_name)))) {
670 BESDEBUG(NC_NAME,
"DAS Cached hit for : " << dataset_name << endl);
671 dds->transfer_attributes(das);
677 if (!container_name.empty()) das->container_name(container_name);
680 if(
true == get_use_mds()) {
683 bool valid_mds =
true;
688 if(
true ==valid_mds) {
693 BESDEBUG(
"nc",
"Using MDS to generate DAS in the data response for file " << dataset_name << endl);
694 mds->parse_das_from_mds(das,rel_file_path);
697 nc_read_dataset_attributes(*das, dataset_name);
699 mds_das_lock.clearLock();
702 nc_read_dataset_attributes(*das, dataset_name);
706 nc_read_dataset_attributes(*das, dataset_name);
708 Ancillary::read_ancillary_das(*das, dataset_name);
710 dds->transfer_attributes(das);
715 BESDEBUG(NC_NAME,
"DAS added to the cache for : " << dataset_name << endl);
716 das_cache->
add(das, dataset_name);
722 BESDEBUG(NC_NAME,
"Data ACCESS in add_attributes(): set the including attribute flag to true: "<<dataset_name << endl);
723 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?
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
Abstract 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()