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"
68#define prolog std::string("NCRequestHandler::").append(__func__).append("() - ")
71bool NCRequestHandler::_show_shared_dims =
true;
72bool NCRequestHandler::_show_shared_dims_set =
false;
74bool NCRequestHandler::_ignore_unknown_types =
false;
75bool NCRequestHandler::_ignore_unknown_types_set =
false;
77bool NCRequestHandler::_promote_byte_to_short =
false;
78bool NCRequestHandler::_promote_byte_to_short_set =
false;
79bool NCRequestHandler::_use_mds =
false;
81unsigned int NCRequestHandler::_cache_entries = 100;
82float NCRequestHandler::_cache_purge_level = 0.2;
89extern void nc_read_dataset_attributes(DAS & das,
const string & filename);
90extern void nc_read_dataset_variables(DDS & dds,
const string & filename);
98static bool version_ge(
const string &version,
float value)
117static bool get_bool_key(
const string &key,
bool def_val)
121 const string dosettrue =
"true";
122 const string dosetyes =
"yes";
127 return (dosettrue == doset || dosetyes == doset);
132static unsigned int get_uint_key(
const string &key,
unsigned int def_val)
139 return atoi(doset.c_str());
146static float get_float_key(
const string &key,
float def_val)
153 return atof(doset.c_str());
160NCRequestHandler::NCRequestHandler(
const string &name) :
163 BESDEBUG(NC_NAME, prolog <<
"BEGIN" << endl);
165 add_method(DAS_RESPONSE, NCRequestHandler::nc_build_das);
166 add_method(DDS_RESPONSE, NCRequestHandler::nc_build_dds);
167 add_method(DATA_RESPONSE, NCRequestHandler::nc_build_data);
169 add_method(DMR_RESPONSE, NCRequestHandler::nc_build_dmr);
170 add_method(DAP4DATA_RESPONSE, NCRequestHandler::nc_build_dmr);
172 add_method(HELP_RESPONSE, NCRequestHandler::nc_build_help);
173 add_method(VERS_RESPONSE, NCRequestHandler::nc_build_version);
177 if (NCRequestHandler::_show_shared_dims_set ==
false) {
178 bool key_found =
false;
183 NCRequestHandler::_show_shared_dims_set =
true;
186 if (doset ==
"true" || doset ==
"yes") {
187 NCRequestHandler::_show_shared_dims =
true;
190 NCRequestHandler::_show_shared_dims =
false;
194 if (NCRequestHandler::_ignore_unknown_types_set ==
false) {
195 bool key_found =
false;
200 if (doset ==
"true" || doset ==
"yes")
201 NCRequestHandler::_ignore_unknown_types =
true;
203 NCRequestHandler::_ignore_unknown_types =
false;
205 NCRequestHandler::_ignore_unknown_types_set =
true;
209 if (NCRequestHandler::_promote_byte_to_short_set ==
false) {
210 bool key_found =
false;
215 if (doset ==
"true" || doset ==
"yes")
216 NCRequestHandler::_promote_byte_to_short =
true;
218 NCRequestHandler::_promote_byte_to_short =
false;
220 NCRequestHandler::_promote_byte_to_short_set =
true;
224 NCRequestHandler::_use_mds = get_bool_key(
"NC.UseMDS",
false);
225 NCRequestHandler::_cache_entries = get_uint_key(
"NC.CacheEntries", 0);
226 NCRequestHandler::_cache_purge_level = get_float_key(
"NC.CachePurgeLevel", 0.2);
228 if (get_cache_entries()) {
229 das_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
230 dds_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
231 datadds_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
232 dmr_cache =
new ObjMemCache(get_cache_entries(), get_cache_purge_level());
235 BESDEBUG(NC_NAME, prolog <<
"END" << endl);
238NCRequestHandler::~NCRequestHandler()
242 delete datadds_cache;
248 BES_STOPWATCH_START_DHI(NC_NAME, prolog +
"Timer", &dhi);
250 BESDEBUG(NC_NAME, prolog <<
"BEGIN" << endl);
253 BESDASResponse *bdas =
dynamic_cast<BESDASResponse *
> (response);
255 throw BESInternalError(
"cast error", __FILE__, __LINE__);
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, prolog <<
"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, prolog <<
"DAS added to the cache for : " << accessed << endl);
277 das_cache->add(
new DAS(*das), accessed);
283 catch (BESError &e) {
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();
296 BESInternalFatalError ex(s, __FILE__, __LINE__);
300 string s =
"Unknown exception caught building DAS";
301 BESInternalFatalError ex(s, __FILE__, __LINE__);
305 BESDEBUG(NC_NAME, prolog <<
"END" << endl);
315void 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, prolog <<
"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, prolog <<
"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, prolog <<
"DAS added to the cache for : " << dataset_name << endl);
351 das_cache->add(das, dataset_name);
360 BESDEBUG(NC_NAME, prolog <<
"DDS added to the cache for : " << dataset_name << endl);
361 dds_cache->add(
new DDS(*dds), dataset_name);
366void 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, prolog <<
"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, prolog <<
"DataDDS added to the cache for : " << dataset_name << endl);
384 datadds_cache->add(
new DDS(*dds), dataset_name);
393 BES_STOPWATCH_START_DHI(NC_NAME, prolog +
"Timer", &dhi);
396 BESDDSResponse *bdds =
dynamic_cast<BESDDSResponse *
> (response);
398 throw BESInternalError(
"cast error", __FILE__, __LINE__);
404 if (NCRequestHandler::_show_shared_dims_set ==
false) {
405 bool context_found =
false;
406 string context_value = BESContextManager::TheManager()->
get_context(
"xdap_accept", context_found);
408 BESDEBUG(NC_NAME, prolog <<
"xdap_accept: " << context_value << endl);
409 if (version_ge(context_value, 3.2))
410 NCRequestHandler::_show_shared_dims =
false;
412 NCRequestHandler::_show_shared_dims =
true;
421 get_dds_with_attributes(filename, container_name, dds);
426 catch (BESError &e) {
429 catch (InternalErr & e) {
430 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
434 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
437 catch (std::exception &e) {
438 string s = string(
"C++ Exception: ") + e.what();
439 BESInternalFatalError ex(s, __FILE__, __LINE__);
443 string s =
"Unknown exception caught building DDS";
444 BESInternalFatalError ex(s, __FILE__, __LINE__);
453 BES_STOPWATCH_START_DHI(NC_NAME, prolog +
"Timer", &dhi);
456 BESDataDDSResponse *bdds =
dynamic_cast<BESDataDDSResponse *
> (response);
458 throw BESInternalError(
"cast error", __FILE__, __LINE__);
461 if (NCRequestHandler::_show_shared_dims_set ==
false) {
462 bool context_found =
false;
463 string context_value = BESContextManager::TheManager()->
get_context(
"xdap_accept", context_found);
465 BESDEBUG(NC_NAME, prolog <<
"xdap_accept: " << context_value << endl);
466 if (version_ge(context_value, 3.2))
467 NCRequestHandler::_show_shared_dims =
false;
469 NCRequestHandler::_show_shared_dims =
true;
474 DDS *dds = bdds->get_dds();
477 get_dds_without_attributes(dhi.
container->
access(), container_name, dds);
480 BESDEBUG(NC_NAME, prolog <<
"Data ACCESS build_data(): set the including attribute flag to false: "<<dhi.
container->
access() << endl);
481 bdds->set_ia_flag(
false);
484 catch (BESError &e) {
487 catch (InternalErr & e) {
488 BESDapError ex(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
492 BESDapError ex(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
495 catch (std::exception &e) {
496 string s = string(
"C++ Exception: ") + e.what();
497 BESInternalFatalError ex(s, __FILE__, __LINE__);
501 string s =
"Unknown exception caught building DAS";
502 BESInternalFatalError ex(s, __FILE__, __LINE__);
511 BES_STOPWATCH_START_DHI(NC_NAME, prolog +
"Timer", &dhi);
516 BESDMRResponse &bdmr =
dynamic_cast<BESDMRResponse &
>(*response);
526 DMR *dmr = bdmr.get_dmr();
529 DMR* cached_dmr_ptr = 0;
530 if (dmr_cache && (cached_dmr_ptr =
static_cast<DMR*
>(dmr_cache->get(dataset_name)))) {
532 BESDEBUG(NC_NAME, prolog <<
"DMR Cached hit for : " << dataset_name << endl);
533 *dmr = *cached_dmr_ptr;
539 BaseTypeFactory factory;
540 DDS dds(&factory, name_path(dataset_name),
"3.2");
543 get_dds_with_attributes(dataset_name,
"", &dds);
545 D4BaseTypeFactory MyD4TypeFactory;
546 dmr->set_factory(&MyD4TypeFactory);
547 dmr->build_using_dds(dds);
551 D4BaseTypeFactory MyD4TypeFactory;
552 dmr->set_factory(&MyD4TypeFactory);
555 if (dds_cache && (dds_ptr =
static_cast<DDS*
>(dds_cache->get(dataset_name)))) {
557 BESDEBUG(NC_NAME, prolog <<
"DDS Cached hit (while building DMR) for : " << dataset_name << endl);
559 dmr->build_using_dds(*dds_ptr);
564 BaseTypeFactory factory;
565 DDS dds(&factory, name_path(dataset_name),
"3.2");
567 dds.filename(dataset_name);
568 nc_read_dataset_variables(dds, dataset_name);
572 nc_read_dataset_attributes(das, dataset_name);
573 Ancillary::read_ancillary_das(das, dataset_name);
575 dds.transfer_attributes(&das);
576 dmr->build_using_dds(dds);
582 BESDEBUG(NC_NAME, prolog <<
"DMR added to the cache for : " << dataset_name << endl);
583 dmr_cache->add(
new DMR(*dmr), dataset_name);
595 catch (InternalErr &e) {
596 throw BESDapError(e.get_error_message(),
true, e.get_error_code(), __FILE__, __LINE__);
599 throw BESDapError(e.get_error_message(),
false, e.get_error_code(), __FILE__, __LINE__);
602 throw BESDapError(
"Caught unknown error build NC DMR response",
true, unknown_error, __FILE__, __LINE__);
610 BES_STOPWATCH_START_DHI(NC_NAME, prolog +
"Timer", &dhi);
613 BESInfo *info =
dynamic_cast<BESInfo *
> (response);
615 throw BESInternalError(
"cast error", __FILE__, __LINE__);
617 map < string, string, std::less<> > attrs;
618 attrs[
"name"] = MODULE_NAME ;
619 attrs[
"version"] = MODULE_VERSION ;
621 attrs[
"name"] = PACKAGE_NAME;
622 attrs[
"version"] = PACKAGE_VERSION;
624 list < string > services;
626 if (services.size() > 0) {
628 attrs[
"handles"] = handles;
630 info->begin_tag(
"module", &attrs);
631 info->end_tag(
"module");
638 BES_STOPWATCH_START_DHI(NC_NAME, prolog +
"Timer", &dhi);
641 BESVersionInfo *info =
dynamic_cast<BESVersionInfo *
> (response);
643 throw BESInternalError(
"cast error", __FILE__, __LINE__);
646 info->add_module(PACKAGE_NAME, PACKAGE_VERSION);
648 info->add_module(MODULE_NAME, MODULE_VERSION);
656 BESDataDDSResponse *bdds =
dynamic_cast<BESDataDDSResponse *
>(response);
658 throw BESInternalError(
"cast error", __FILE__, __LINE__);
659 DDS *dds = bdds->get_dds();
663 if (das_cache && (das =
static_cast<DAS*
>(das_cache->get(dataset_name)))) {
664 BESDEBUG(NC_NAME, prolog <<
"DAS Cached hit for : " << dataset_name << endl);
665 dds->transfer_attributes(das);
671 if (!container_name.empty()) das->container_name(container_name);
674 if(
true == get_use_mds()) {
677 bool valid_mds =
true;
682 if(
true ==valid_mds) {
685 bes::GlobalMetadataStore::MDSReadLock mds_das_lock = mds->
is_das_available(rel_file_path);
687 BESDEBUG(NC_NAME, prolog <<
"Using MDS to generate DAS in the data response for file " << dataset_name << endl);
688 mds->parse_das_from_mds(das,rel_file_path);
691 nc_read_dataset_attributes(*das, dataset_name);
693 mds_das_lock.clearLock();
696 nc_read_dataset_attributes(*das, dataset_name);
700 nc_read_dataset_attributes(*das, dataset_name);
702 Ancillary::read_ancillary_das(*das, dataset_name);
704 dds->transfer_attributes(das);
709 BESDEBUG(NC_NAME, prolog <<
"DAS added to the cache for : " << dataset_name << endl);
710 das_cache->add(das, dataset_name);
716 BESDEBUG(NC_NAME, prolog <<
"Data ACCESS in add_attributes(): set the including attribute flag to true: "<<dataset_name << endl);
717 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
virtual void clear_container()
clear the container in the DAP response object
virtual void clear_container()
clear the container in the DAP response object
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.
virtual void clear_container()
clear the container in the DAP response object
Structure storing information used by the BES to handle the request.
BESContainer * container
pointer to current container in this interface
bool cache_enabled() const
Represents a specific data type request handler.
virtual BESResponseObject * get_response_object()
return the current response object
virtual void services_handled(const std::string &handler, std::list< std::string > &services)
returns the list of servies provided by the handler in question
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.
void get_value(const std::string &s, std::string &val, bool &found)
Retrieve the value of a given key, if set.
static TheBESKeys * TheKeys()
Access to the singleton.