bes  Updated for version 3.20.6
HDF5RequestHandler.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of hdf5_handler, a data handler for the OPeNDAP data
5 // server.
6 
7 // Copyright (c) 2002,2003 OPeNDAP, Inc.
8 // Copyright (c) 2007-2016 The HDF Group, Inc. and OPeNDAP, Inc.
9 // Author: James Gallagher <jgallagher@opendap.org>
10 //
11 // This is free software; you can redistribute it and/or modify it under the
12 // terms of the GNU Lesser General Public License as published by the Free
13 // Software Foundation; either version 2.1 of the License, or (at your
14 // option) any later version.
15 //
16 // This software is distributed in the hope that it will be useful, but
17 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19 // License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
26 
27 // HDF5RequestHandler.cc
33 
34 
35 #include <iostream>
36 #include <fstream>
37 #include <sstream>
38 #include <string>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #include <unistd.h>
43 
44 #include <DMR.h>
45 #include <D4BaseTypeFactory.h>
46 #include <BESDMRResponse.h>
47 #include <ObjMemCache.h>
48 #include "HDF5_DMR.h"
49 
50 #include <mime_util.h>
51 #include "hdf5_handler.h"
52 #include "HDF5RequestHandler.h"
53 #include "HDF5_DDS.h"
54 
55 #include <BESDASResponse.h>
56 #include <BESDDSResponse.h>
57 #include <BESDataDDSResponse.h>
58 #include <Ancillary.h>
59 #include <BESInfo.h>
60 #include <BESDapNames.h>
61 #include <BESResponseNames.h>
62 #include <BESContainer.h>
63 #include <BESResponseHandler.h>
64 #include <BESVersionInfo.h>
65 #include <BESServiceRegistry.h>
66 #include <BESUtil.h>
67 #include <BESDapError.h>
68 #include <BESInternalFatalError.h>
69 #include <TheBESKeys.h>
70 #include <BESDebug.h>
71 #include "h5get.h"
72 #include "config_hdf5.h"
73 
74 #define HDF5_NAME "h5"
75 #include "h5cfdaputil.h"
76 
77 using namespace std;
78 using namespace libdap;
79 
80 // The debug function to dump all the contents of a DAS table.
81 void get_attr_contents(AttrTable* temp_table);
82 
83 // Five functions to generate a DAS cache file.
84 // 1. The wrapper function to call write_das_table_to_file to generate the cache.
85 void write_das_to_file(DAS*das_ptr,FILE* das_file);
86 
87 // 2. The main function to generate the DAS cache.
88 void write_das_table_to_file(AttrTable*temp_table,FILE* das_file);
89 
90 // 3. The function to write the DAS container/table name to the cache
91 void write_container_name_to_file(const string&,FILE* das_file);
92 
93 // 4. The function to write the DAS attribute name,type and values to the cache
94 void write_das_attr_info(AttrTable* dtp,const string&,const string&,FILE * das_file);
95 
96 // 5. The function to copy a string to a memory buffer.
97 char* copy_str(char *temp_ptr,const string & str);
98 
99 // These two functions are for reading the DAS from the DAS cache file
100 // 1. Obtain the string from a memory buffer.
101 char* obtain_str(char*temp_ptr,string & str);
102 
103 // 2. The main function to obtain DAS info from the cache.
104 char* get_attr_info_from_dc(char*temp_pointer,DAS *das,AttrTable *at);
105 
106 // Check if the BES key is set.
107 bool check_beskeys(const string);
108 
109 // Obtain the BES key as an integer
110 static unsigned int get_uint_key(const string &key,unsigned int def_val);
111 static unsigned long get_ulong_key(const string &key,unsigned long def_val);
112 
113 // Obtain the BES key as a floating-pointer number.
114 static float get_float_key(const string &key, float def_val);
115 
116 // Obtain the BES key as a string.
117 static string get_beskeys(const string&);
118 
119 // For the CF option
120 extern void read_cfdas(DAS &das, const string & filename,hid_t fileid);
121 extern void read_cfdds(DDS &dds, const string & filename,hid_t fileid);
122 
123 
124 // Check the description of cache_entries and cache_purge_level at h5.conf.in.
125 unsigned int HDF5RequestHandler::_mdcache_entries = 500;
126 unsigned int HDF5RequestHandler::_lrdcache_entries = 0;
127 unsigned int HDF5RequestHandler::_srdcache_entries = 0;
128 float HDF5RequestHandler::_cache_purge_level = 0.2;
129 
130 // Metadata object cache at DAS,DDS and DMR.
131 ObjMemCache *HDF5RequestHandler::das_cache = 0;
132 ObjMemCache *HDF5RequestHandler::dds_cache = 0;
133 ObjMemCache *HDF5RequestHandler::datadds_cache = 0;
134 ObjMemCache *HDF5RequestHandler::dmr_cache = 0;
135 
136 ObjMemCache *HDF5RequestHandler::lrdata_mem_cache = 0;
137 ObjMemCache *HDF5RequestHandler::srdata_mem_cache = 0;
138 
139 // Set default values of all BES keys be false.
140 bool HDF5RequestHandler::_usecf = false;
141 bool HDF5RequestHandler::_pass_fileid = false;
142 bool HDF5RequestHandler::_disable_structmeta = false;
143 bool HDF5RequestHandler::_disable_ecsmeta = false;
144 bool HDF5RequestHandler::_keep_var_leading_underscore = false;
145 bool HDF5RequestHandler::_check_name_clashing = false;
146 bool HDF5RequestHandler::_add_path_attrs = false;
147 bool HDF5RequestHandler::_drop_long_string = false;
148 bool HDF5RequestHandler::_fillvalue_check = false;
149 bool HDF5RequestHandler::_check_ignore_obj = false;
150 bool HDF5RequestHandler::_flatten_coor_attr = false;
151 bool HDF5RequestHandler::_default_handle_dimension = false;
152 bool HDF5RequestHandler::_eos5_rm_convention_attr_path = true;
153 
154 bool HDF5RequestHandler::_common_cache_dirs = false;
155 
156 bool HDF5RequestHandler::_use_disk_cache =false;
157 bool HDF5RequestHandler::_use_disk_dds_cache =false;
158 string HDF5RequestHandler::_disk_cache_dir ="";
159 string HDF5RequestHandler::_disk_cachefile_prefix ="";
160 unsigned long long HDF5RequestHandler::_disk_cache_size =0;
161 
162 
163 bool HDF5RequestHandler::_disk_cache_comp_data =false;
164 bool HDF5RequestHandler::_disk_cache_float_only_comp_data =false;
165 float HDF5RequestHandler::_disk_cache_comp_threshold =1.0;
166 unsigned long HDF5RequestHandler::_disk_cache_var_size =0;
167 
168 bool HDF5RequestHandler::_use_disk_meta_cache = false;
169 string HDF5RequestHandler::_disk_meta_cache_path ="";
170 
171 bool HDF5RequestHandler::_use_latlon_disk_cache = false;
172 long HDF5RequestHandler::_latlon_disk_cache_size =0;
173 string HDF5RequestHandler::_latlon_disk_cache_dir ="";
174 string HDF5RequestHandler::_latlon_disk_cachefile_prefix="";
175 
176 DMR* HDF5RequestHandler::dmr_int64 = 0;
177 
178 
179 #if 0
180 //BaseTypeFactory factory;
181 //libdap::DDS HDF5RequestHandler::hd_dds(&factory,"");
182 #endif
183 string HDF5RequestHandler::_stp_east_filename;
184 string HDF5RequestHandler::_stp_north_filename;
185 vector<string> HDF5RequestHandler::lrd_cache_dir_list;
186 vector<string> HDF5RequestHandler::lrd_non_cache_dir_list;
187 vector<string> HDF5RequestHandler::lrd_var_cache_file_list;
188 
189 #if 0
190 //libdap::DDS*cache_dds;
191 #endif
192 
193 
194 HDF5RequestHandler::HDF5RequestHandler(const string & name)
195  :BESRequestHandler(name)
196 {
197 
198  BESDEBUG(HDF5_NAME, "In HDF5RequestHandler::HDF5RequestHandler" << endl);
199 
200  add_handler(DAS_RESPONSE, HDF5RequestHandler::hdf5_build_das);
201  add_handler(DDS_RESPONSE, HDF5RequestHandler::hdf5_build_dds);
202  add_handler(DATA_RESPONSE, HDF5RequestHandler::hdf5_build_data);
203  add_handler(DMR_RESPONSE, HDF5RequestHandler::hdf5_build_dmr);
204  add_handler(DAP4DATA_RESPONSE, HDF5RequestHandler::hdf5_build_dmr);
205 
206  add_handler(HELP_RESPONSE, HDF5RequestHandler::hdf5_build_help);
207  add_handler(VERS_RESPONSE, HDF5RequestHandler::hdf5_build_version);
208 
209  // Obtain the metadata cache entries and purge level.
210  HDF5RequestHandler::_mdcache_entries = get_uint_key("H5.MetaDataMemCacheEntries", 0);
211  HDF5RequestHandler::_lrdcache_entries = get_uint_key("H5.LargeDataMemCacheEntries", 0);
212  HDF5RequestHandler::_srdcache_entries = get_uint_key("H5.SmallDataMemCacheEntries", 0);
213  HDF5RequestHandler::_cache_purge_level = get_float_key("H5.CachePurgeLevel", 0.2);
214 
215  if (get_mdcache_entries()) { // else it stays at its default of null
216  das_cache = new ObjMemCache(get_mdcache_entries(), get_cache_purge_level());
217  dds_cache = new ObjMemCache(get_mdcache_entries(), get_cache_purge_level());
218  datadds_cache = new ObjMemCache(get_mdcache_entries(), get_cache_purge_level());
219  dmr_cache = new ObjMemCache(get_mdcache_entries(), get_cache_purge_level());
220  }
221 
222  // Check if the EnableCF key is set.
223  _usecf = check_beskeys("H5.EnableCF");
224 
225  // The following keys are only effective when usecf is true.
226  _pass_fileid = check_beskeys("H5.EnablePassFileID");
227  _disable_structmeta = check_beskeys("H5.DisableStructMetaAttr");
228  _disable_ecsmeta = check_beskeys("H5.DisableECSMetaAttr");
229  _keep_var_leading_underscore = check_beskeys("H5.KeepVarLeadingUnderscore");
230  _check_name_clashing = check_beskeys("H5.EnableCheckNameClashing");
231  _add_path_attrs = check_beskeys("H5.EnableAddPathAttrs");
232  _drop_long_string = check_beskeys("H5.EnableDropLongString");
233  _fillvalue_check = check_beskeys("H5.EnableFillValueCheck");
234  _check_ignore_obj = check_beskeys("H5.CheckIgnoreObj");
235  _flatten_coor_attr = check_beskeys("H5.ForceFlattenNDCoorAttr");
236  _default_handle_dimension = check_beskeys("H5.DefaultHandleDimension");
237  _eos5_rm_convention_attr_path= check_beskeys("H5.RmConventionAttrPath");
238 
239  _use_disk_cache = check_beskeys("H5.EnableDiskDataCache");
240  _disk_cache_dir = get_beskeys("H5.DiskCacheDataPath");
241  _disk_cachefile_prefix = get_beskeys("H5.DiskCacheFilePrefix");
242  _disk_cache_size = get_ulong_key("H5.DiskCacheSize",0);
243 
244  _disk_cache_comp_data = check_beskeys("H5.DiskCacheComp");
245  _disk_cache_float_only_comp_data = check_beskeys("H5.DiskCacheFloatOnlyComp");
246  _disk_cache_comp_threshold = get_float_key("H5.DiskCacheCompThreshold",1.0);
247  _disk_cache_var_size = 1024*get_uint_key("H5.DiskCacheCompVarSize",0);
248 
249  _use_disk_meta_cache = check_beskeys("H5.EnableDiskMetaDataCache");
250  _use_disk_dds_cache = check_beskeys("H5.EnableDiskDDSCache");
251  _disk_meta_cache_path = get_beskeys("H5.DiskMetaDataCachePath");
252 
253  _use_latlon_disk_cache = check_beskeys("H5.EnableEOSGeoCacheFile");
254  _latlon_disk_cache_size = get_uint_key("H5.Cache.latlon.size",0);
255  _latlon_disk_cache_dir = get_beskeys("H5.Cache.latlon.path");
256  _latlon_disk_cachefile_prefix= get_beskeys("H5.Cache.latlon.prefix");
257 
258  if(get_usecf()) {
259  if(get_lrdcache_entries()) {
260  lrdata_mem_cache = new ObjMemCache(get_lrdcache_entries(), get_cache_purge_level());
261  if(true == check_beskeys("H5.LargeDataMemCacheConfig")) {
262  _common_cache_dirs =obtain_lrd_common_cache_dirs();
263 #if 0
264 if(false == _common_cache_dirs)
265 cerr<<"No specific cache info"<<endl;
266 #endif
267 
268  }
269  }
270  if(get_srdcache_entries()) {
271 
272  BESDEBUG(HDF5_NAME, "Generate memory cache for smaller coordinate variables" << endl);
273  srdata_mem_cache = new ObjMemCache(get_srdcache_entries(),get_cache_purge_level());
274 
275  }
276 
277  if(_disk_cache_comp_data == true && _use_disk_cache == true) {
278  if(_disk_cache_comp_threshold < 1.0) {
279  ostringstream ss;
280  ss<< _disk_cache_comp_threshold;
281  string _comp_threshold_str(ss.str());
282  string invalid_comp_threshold ="The Compression Threshold is the total size of the variable array";
283  invalid_comp_threshold+=" divided by the storage size of compressed array. It should always be >1";
284  invalid_comp_threshold+=" The current threhold set at h5.conf is ";
285  invalid_comp_threshold+=_comp_threshold_str;
286  invalid_comp_threshold+=" . Go back to h5.conf and change the H5.DiskCacheCompThreshold to a >1.0 number.";
287  throw BESInternalError(invalid_comp_threshold,__FILE__,__LINE__);
288  }
289  }
290  _stp_east_filename = get_beskeys("H5.STPEastFileName");
291  _stp_north_filename = get_beskeys("H5.STPNorthFileName");
292  }
293 
294 
295  BESDEBUG(HDF5_NAME, "Exiting HDF5RequestHandler::HDF5RequestHandler" << endl);
296 }
297 
298 HDF5RequestHandler::~HDF5RequestHandler()
299 {
300  // delete the cache.
301  delete das_cache;
302  delete dds_cache;
303  delete datadds_cache;
304  delete dmr_cache;
305  delete lrdata_mem_cache;
306  delete srdata_mem_cache;
307 
308 }
309 
310 // Build DAS
311 bool HDF5RequestHandler::hdf5_build_das(BESDataHandlerInterface & dhi)
312 {
313 
314  // For the time being, separate CF file ID from the default file ID(mainly for debugging)
315  hid_t cf_fileid = -1;
316 
317  // Obtain the HDF5 file name.
318  string filename = dhi.container->access();
319 
320  // Obtain the BES object from the client
321  BESResponseObject *response = dhi.response_handler->get_response_object() ;
322 
323  // Convert to the BES DAS response
324  BESDASResponse *bdas = dynamic_cast < BESDASResponse * >(response) ;
325  if( !bdas )
326  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
327 
328  try {
329  bdas->set_container( dhi.container->get_symbolic_name() ) ;
330  DAS *das = bdas->get_das();
331 
332  // Look inside the memory cache to see if it's initialized
333  DAS *cached_das_ptr = 0;
334  bool use_das_cache = false;
335  if (das_cache)
336  cached_das_ptr = static_cast<DAS*>(das_cache->get(filename));
337  if (cached_das_ptr)
338  use_das_cache = true;
339 
340  if (true == use_das_cache) {
341 
342  // copy the cached DAS into the BES response object
343  BESDEBUG(HDF5_NAME, "DAS Cached hit for : " << filename << endl);
344  *das = *cached_das_ptr;
345  }
346  else {
347 
348  bool das_from_dc = false;
349  string das_cache_fname;
350 
351  // If the use_disk_meta_cache is set, check if the cache file exists and sets the flag.
352  if(_use_disk_meta_cache == true) {
353 
354  string base_filename = HDF5CFUtil::obtain_string_after_lastslash(filename);
355  das_cache_fname = _disk_meta_cache_path+"/" +base_filename+"_das";
356 
357  if(access(das_cache_fname.c_str(),F_OK) !=-1)
358  das_from_dc = true;
359 
360  }
361 
362  // If reading DAS from the disk cache, call the corresponding function
363  if(true == das_from_dc) {
364  read_das_from_disk_cache(das_cache_fname,das);
365 
366  // If the memory cache is set, adding the DAS copy to the memory cache
367  if (das_cache) {
368  // add a copy
369  BESDEBUG(HDF5_NAME, "HDF5 DAS reading DAS from the disk cache. For memory cache, DAS added to the cache for : " << filename << endl);
370  das_cache->add(new DAS(*das), filename);
371  }
372  }
373 
374  else {// Need to build from the HDF5 file
375  H5Eset_auto2(H5E_DEFAULT,NULL,NULL);
376  if (true == _usecf) {//CF option
377 
378  cf_fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
379  if (cf_fileid < 0){
380  string invalid_file_msg="Could not open this HDF5 file ";
381  invalid_file_msg +=filename;
382  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
383  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
384  invalid_file_msg +=" distributor.";
385  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
386  }
387  // Need to check if DAP4 DMR CF 64-bit integer mapping is on.
388  if(HDF5RequestHandler::get_dmr_64bit_int()!=NULL)
389  HDF5RequestHandler::set_dmr_64bit_int(NULL);
390  read_cfdas( *das,filename,cf_fileid);
391  H5Fclose(cf_fileid);
392  }
393  else {// Default option
394  hid_t fileid = get_fileid(filename.c_str());
395  if (fileid < 0) {
396  string invalid_file_msg="Could not open this HDF5 file ";
397  invalid_file_msg +=filename;
398  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
399  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
400  invalid_file_msg +=" distributor.";
401  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
402 
403  }
404 
405  find_gloattr(fileid, *das);
406  depth_first(fileid, "/", *das);
407  close_fileid(fileid);
408  }
409 
410  Ancillary::read_ancillary_das( *das, filename ) ;
411 
412 #if 0
413 // Dump all attribute contents
414 AttrTable* top_table = das->get_top_level_attributes();
415 get_attr_contents(top_table);
416 
417 // Dump all variable contents
418 AttrTable::Attr_iter start_aiter=das->var_begin();
419 AttrTable::Attr_iter it = start_aiter;
420 AttrTable::Attr_iter end_aiter = das->var_end();
421 while(it != end_aiter) {
422 AttrTable* temp_table = das->get_table(it);
423 if(temp_table!=0){
424 cerr<<"var_begin"<<endl;
425 temp_table->print(cerr);
426 }
427 ++it;
428 }
429 #endif
430  // If the memory cache is turned on
431  if(das_cache) {
432  // add a copy
433  BESDEBUG(HDF5_NAME, "DAS added to the cache for : " << filename << endl);
434  das_cache->add(new DAS(*das), filename);
435  }
436 
437  // DAS disk cache fname will be set only when the metadata disk cache is turned on
438  // So if it comes here, the das cache should be generated.
439  if(das_cache_fname!="") {
440  BESDEBUG(HDF5_NAME, "HDF5 Build DAS: Write DAS to disk cache " << das_cache_fname << endl);
441  write_das_to_disk_cache(das_cache_fname,das);
442  }
443  }
444  }
445 
446  bdas->clear_container() ;
447  }
448  catch(InternalErr & e) {
449 
450  if(cf_fileid !=-1)
451  H5Fclose(cf_fileid);
452  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
453  __FILE__, __LINE__);
454  }
455  catch(Error & e) {
456 
457  if(cf_fileid !=-1)
458  H5Fclose(cf_fileid);
459  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
460  __FILE__, __LINE__);
461  }
462  catch(...) {
463 
464  if(cf_fileid !=-1)
465  H5Fclose(cf_fileid);
466  string s = "unknown exception caught building HDF5 DAS";
467  throw BESInternalFatalError(s, __FILE__, __LINE__);
468  }
469 
470  return true;
471 }
472 
473 // Convenient function that helps build DDS and Data
474 // Since this function will be used by both the DDS and Data services, we need to pass both BESDDSResponse and BESDataDDSResponse.
475 // This two parameters are necessary for the future DDS disk cache feature.
476 void HDF5RequestHandler::get_dds_with_attributes( BESDDSResponse*bdds,BESDataDDSResponse*data_bdds,const string &container_name, const string& filename,const string &dds_cache_fname, const string &das_cache_fname,bool dds_from_dc,bool das_from_dc, bool build_data)
477 {
478  DDS *dds;
479  if(true == build_data)
480  dds = data_bdds->get_dds();
481  else dds = bdds->get_dds();
482 
483  // For the time being, separate CF file ID from the default file ID(mainly for debugging)
484  hid_t fileid = -1;
485  hid_t cf_fileid = -1;
486 
487  try {
488 
489  // Look in memory cache to see if it's initialized
490  DDS* cached_dds_ptr = 0;
491  bool use_dds_cache = false;
492  if (dds_cache)
493  cached_dds_ptr = static_cast<DDS*>(dds_cache->get(filename));
494  if (cached_dds_ptr)
495  use_dds_cache = true;
496  if (true == use_dds_cache) {
497  // copy the cached DDS into the BES response object. Assume that any cached DDS
498  // includes the DAS information.
499  BESDEBUG(HDF5_NAME, "DDS Metadata Cached hit for : " << filename << endl);
500  *dds = *cached_dds_ptr; // Copy the referenced object
501  }
502  else if (true ==dds_from_dc) {//Currently the dds_from_ds is always false by default.
503  read_dds_from_disk_cache(bdds,data_bdds,build_data,container_name,filename,dds_cache_fname,das_cache_fname,-1,das_from_dc);
504  }
505  else {
506  BESDEBUG(HDF5_NAME, "Build DDS from the HDF5 file. " << filename << endl);
507  H5Eset_auto2(H5E_DEFAULT,NULL,NULL);
508  dds->filename(filename);
509 
510  // For the time being, not mess up CF's fileID with Default's fileID
511  if(true == _usecf) {
512 
513  cf_fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
514  if (cf_fileid < 0){
515  string invalid_file_msg="Could not open this HDF5 file ";
516  invalid_file_msg +=filename;
517  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
518  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
519  invalid_file_msg +=" distributor.";
520  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
521  }
522  // The following is for DAP4 CF(DMR) 64-bit mapping, we need to set the flag
523  // to let the handler map the 64-bit integer.
524  if(HDF5RequestHandler::get_dmr_64bit_int() != NULL)
525  HDF5RequestHandler::set_dmr_64bit_int(NULL);
526  read_cfdds(*dds,filename,cf_fileid);
527  }
528  else {
529 
530  fileid = get_fileid(filename.c_str());
531  if (fileid < 0) {
532  string invalid_file_msg="Could not open this HDF5 file ";
533  invalid_file_msg +=filename;
534  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
535  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
536  invalid_file_msg +=" distributor.";
537  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
538  }
539 
540  depth_first(fileid, (char*)"/", *dds, filename.c_str());
541 
542  }
543  // Check semantics
544  if (!dds->check_semantics()) { // DDS didn't comply with the semantics
545  dds->print(cerr);
546  throw InternalErr(__FILE__, __LINE__,
547  "DDS check_semantics() failed. This can happen when duplicate variable names are defined. ");
548  }
549 
550  Ancillary::read_ancillary_dds( *dds, filename ) ;
551 
552  // Generate the DDS cached file if needed,currently this is always false by default
553  if(dds_cache_fname!="" && dds_from_dc == false)
554  write_dds_to_disk_cache(dds_cache_fname,dds);
555 
556  // Add attributes
557  {
558  hid_t h5_fd = -1;
559  if(_usecf == true)
560  h5_fd = cf_fileid;
561  else
562  h5_fd = fileid;
563  add_das_to_dds(dds,container_name,filename,das_cache_fname,h5_fd,das_from_dc);
564  }
565 
566  // Add memory cache if possible
567  if (dds_cache) {
568  // add a copy
569  BESDEBUG(HDF5_NAME, "DDS added to the cache for : " << filename << endl);
570  dds_cache->add(new DDS(*dds), filename);
571  }
572 
573  if(cf_fileid != -1)
574  H5Fclose(cf_fileid);
575  if(fileid != -1)
576  H5Fclose(fileid);
577 
578  }
579 
580  }
581  catch(InternalErr & e) {
582 
583  if(cf_fileid !=-1)
584  H5Fclose(cf_fileid);
585 
586  if(fileid != -1)
587  H5Fclose(fileid);
588 
589  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
590  __FILE__, __LINE__);
591  }
592  catch(Error & e) {
593 
594  if(cf_fileid !=-1)
595  H5Fclose(cf_fileid);
596  if(fileid !=-1)
597  H5Fclose(fileid);
598 
599  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
600  __FILE__, __LINE__);
601  }
602  catch(...) {
603 
604  if(cf_fileid !=-1)
605  H5Fclose(cf_fileid);
606  if(fileid !=-1)
607  H5Fclose(fileid);
608 
609  string s = "unknown exception caught building HDF5 DDS";
610  throw BESInternalFatalError(s, __FILE__, __LINE__);
611  }
612 
613 }
614 
615 void HDF5RequestHandler::get_dds_without_attributes_datadds(BESDataDDSResponse*data_bdds,const string &container_name, const string& filename)
616 {
617  DDS *dds = data_bdds->get_dds();
618 
619  // For the time being, separate CF file ID from the default file ID(mainly for debugging)
620  hid_t fileid = -1;
621  hid_t cf_fileid = -1;
622 
623  try {
624 
625  // Look in memory cache to see if it's initialized
626  DDS* cached_dds_ptr = 0;
627  bool use_datadds_cache = false;
628  if (datadds_cache)
629  cached_dds_ptr = static_cast<DDS*>(datadds_cache->get(filename));
630  if (cached_dds_ptr)
631  use_datadds_cache = true;
632  if (true == use_datadds_cache) {
633  // copy the cached DDS into the BES response object.
634  // The DAS information is not included.
635  BESDEBUG(HDF5_NAME, "DataDDS Metadata Cached hit for : " << filename << endl);
636  *dds = *cached_dds_ptr; // Copy the referenced object
637  }
638  else {
639  BESDEBUG(HDF5_NAME, "Build DDS from the HDF5 file. " << filename << endl);
640  H5Eset_auto2(H5E_DEFAULT,NULL,NULL);
641  dds->filename(filename);
642 
643  // For the time being, not mess up CF's fileID with Default's fileID
644  if(true == _usecf) {
645 
646  cf_fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
647  if (cf_fileid < 0){
648  string invalid_file_msg="Could not open this HDF5 file ";
649  invalid_file_msg +=filename;
650  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
651  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
652  invalid_file_msg +=" distributor.";
653  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
654  }
655  // The following is for DAP4 CF(DMR) 64-bit mapping, we need to set the flag
656  // to let the handler map the 64-bit integer.
657  if(HDF5RequestHandler::get_dmr_64bit_int() != NULL)
658  HDF5RequestHandler::set_dmr_64bit_int(NULL);
659  read_cfdds(*dds,filename,cf_fileid);
660  }
661  else {
662 
663  fileid = get_fileid(filename.c_str());
664  if (fileid < 0) {
665  string invalid_file_msg="Could not open this HDF5 file ";
666  invalid_file_msg +=filename;
667  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
668  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
669  invalid_file_msg +=" distributor.";
670  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
671  }
672 
673  depth_first(fileid, (char*)"/", *dds, filename.c_str());
674 
675  }
676  // Check semantics
677  if (!dds->check_semantics()) { // DDS didn't comply with the semantics
678  dds->print(cerr);
679  throw InternalErr(__FILE__, __LINE__,
680  "DDS check_semantics() failed. This can happen when duplicate variable names are defined. ");
681  }
682 
683  Ancillary::read_ancillary_dds( *dds, filename ) ;
684 
685 #if 0
686  // Add attributes
687  {
688  hid_t h5_fd = -1;
689  if(_usecf == true)
690  h5_fd = cf_fileid;
691  else
692  h5_fd = fileid;
693  add_das_to_dds(dds,container_name,filename,das_cache_fname,h5_fd,das_from_dc);
694  }
695 #endif
696 
697  // Add memory cache if possible
698  if (datadds_cache) {
699  // add a copy
700  BESDEBUG(HDF5_NAME, "DataDDS added to the cache for : " << filename << endl);
701  datadds_cache->add(new DDS(*dds), filename);
702  }
703 
704  if(cf_fileid != -1)
705  H5Fclose(cf_fileid);
706  if(fileid != -1)
707  H5Fclose(fileid);
708 
709  }
710  BESDEBUG(HDF5_NAME, "Data ACCESS build_data(): set the including attribute flag to false: "<<filename << endl);
711  data_bdds->set_ia_flag(false);
712 
713  }
714  catch(InternalErr & e) {
715 
716  if(cf_fileid !=-1)
717  H5Fclose(cf_fileid);
718 
719  if(fileid != -1)
720  H5Fclose(fileid);
721 
722  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
723  __FILE__, __LINE__);
724  }
725  catch(Error & e) {
726 
727  if(cf_fileid !=-1)
728  H5Fclose(cf_fileid);
729  if(fileid !=-1)
730  H5Fclose(fileid);
731 
732  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
733  __FILE__, __LINE__);
734  }
735  catch(...) {
736 
737  if(cf_fileid !=-1)
738  H5Fclose(cf_fileid);
739  if(fileid !=-1)
740  H5Fclose(fileid);
741 
742  string s = "unknown exception caught building HDF5 DDS";
743  throw BESInternalFatalError(s, __FILE__, __LINE__);
744  }
745 
746 }
747 
748 
749 #if 0
750 // OLD function: Keep it for a while
751 // Convenient function that helps build DDS and Data
752 void HDF5RequestHandler::get_dds_with_attributes(const string &filename, const string &container_name, DDS*dds) {
753 
754  // For the time being, separate CF file ID from the default file ID(mainly for debugging)
755  hid_t fileid = -1;
756  hid_t cf_fileid = -1;
757 
758  try {
759 
760  // Look in memory cache to see if it's initialized
761  DDS* cached_dds_ptr = 0;
762  if (dds_cache && (cached_dds_ptr = static_cast<DDS*>(dds_cache->get(filename)))) {
763  // copy the cached DDS into the BES response object. Assume that any cached DDS
764  // includes the DAS information.
765  BESDEBUG(HDF5_NAME, "DDS Cached hit for : " << filename << endl);
766  *dds = *cached_dds_ptr; // Copy the referenced object
767  }
768 
769  else {
770 
771  H5Eset_auto2(H5E_DEFAULT,NULL,NULL);
772  if (!container_name.empty())
773  dds->container_name(container_name);
774  dds->filename(filename);
775 
776  // For the time being, not mess up CF's fileID with Default's fileID
777  if(true == _usecf) {
778 // This block cannot be used to cache the data
779 #if 0
780  string base_filename = HDF5CFUtil::obtain_string_after_lastslash(filename);
781  string dds_filename = "/tmp/"+base_filename+"_dds";
782  FILE *dds_file = fopen(dds_filename.c_str(),"r");
783 cerr<<"before parsing "<<endl;
784 BaseTypeFactory tf;
785 DDS tdds(&tf,name_path(filename),"3.2");
786 tdds.filename(filename);
787  //dds->parse(dds_file);
788  tdds.parse(dds_file);
789  //DDS *cache_dds = new DDS(tdds);
790  cache_dds = new DDS(tdds);
791 if(dds!=NULL)
792  delete dds;
793 dds = cache_dds;
794 tdds.print(cout);
795 dds->print(cout);
796 cerr<<"after parsing "<<endl;
797 //dds->print(cout);
798  // fclose(dds_file);
799 //#endif
800 
801 #endif
802 // end of this block
803 
804 
805  cf_fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
806  if (cf_fileid < 0){
807  string invalid_file_msg="Could not open this HDF5 file ";
808  invalid_file_msg +=filename;
809  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
810  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
811  invalid_file_msg +=" distributor.";
812  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
813  }
814 //#if 0
815  read_cfdds(*dds,filename,cf_fileid);
816 //#endif
817  // Generate the DDS cached file
818  string base_filename = HDF5CFUtil::obtain_string_after_lastslash(filename);
819  string dds_filename = "/tmp/"+base_filename+"_dds";
820  FILE *dds_file = fopen(dds_filename.c_str(),"w");
821  dds->print(dds_file);
822  fclose(dds_file);
823 
824  }
825  else {
826 
827  fileid = get_fileid(filename.c_str());
828  if (fileid < 0) {
829  string invalid_file_msg="Could not open this HDF5 file ";
830  invalid_file_msg +=filename;
831  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
832  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
833  invalid_file_msg +=" distributor.";
834  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
835  }
836 
837  depth_first(fileid, (char*)"/", *dds, filename.c_str());
838 
839  }
840 
841 
842  // Check semantics
843  if (!dds->check_semantics()) { // DDS didn't comply with the semantics
844  dds->print(cerr);
845  throw InternalErr(__FILE__, __LINE__,
846  "DDS check_semantics() failed. This can happen when duplicate variable names are defined. ");
847  }
848 
849  Ancillary::read_ancillary_dds( *dds, filename ) ;
850 
851 
852  // Check DAS cache
853  DAS *das = 0 ;
854 
855  if (das_cache && (das = static_cast<DAS*>(das_cache->get(filename)))) {
856  BESDEBUG(HDF5_NAME, "DAS Cached hit for : " << filename << endl);
857  dds->transfer_attributes(das); // no need to copy the cached DAS
858  }
859 
860  else {
861 
862  das = new DAS ;
863 
864  if (!container_name.empty())
865  das->container_name(container_name);
866 
867  if (true == _usecf) {
868 
869  // go to the CF option
870  read_cfdas( *das,filename,cf_fileid);
871 
872  }
873  else {
874 
875  find_gloattr(fileid, *das);
876  depth_first(fileid, "/", *das);
877  close_fileid(fileid);
878  }
879 
880  if(cf_fileid != -1)
881  H5Fclose(cf_fileid);
882 
883  Ancillary::read_ancillary_das( *das, filename ) ;
884 
885  dds->transfer_attributes(das);
886 
887 
888  // Only free the DAS if it's not added to the cache
889  if (das_cache) {
890  // add a copy
891  BESDEBUG(HDF5_NAME, "DAS added to the cache for : " << filename << endl);
892  //das_cache->add(new DAS(*das), filename);
893  das_cache->add(das, filename);
894  }
895  else {
896  delete das;
897  }
898  }
899 
900  if (dds_cache) {
901  // add a copy
902  BESDEBUG(HDF5_NAME, "DDS added to the cache for : " << filename << endl);
903  dds_cache->add(new DDS(*dds), filename);
904  }
905 
906  }
907 
908 //dds->print(cout);
909 
910  }
911  catch(InternalErr & e) {
912 
913  if(cf_fileid !=-1)
914  H5Fclose(cf_fileid);
915 
916  if(fileid != -1)
917  H5Fclose(fileid);
918 
919  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
920  __FILE__, __LINE__);
921  }
922  catch(Error & e) {
923 
924  if(cf_fileid !=-1)
925  H5Fclose(cf_fileid);
926  if(fileid !=-1)
927  H5Fclose(fileid);
928 
929  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
930  __FILE__, __LINE__);
931  }
932  catch(...) {
933 
934  if(cf_fileid !=-1)
935  H5Fclose(cf_fileid);
936  if(fileid !=-1)
937  H5Fclose(fileid);
938 
939  string s = "unknown exception caught building HDF5 DDS";
940  throw BESInternalFatalError(s, __FILE__, __LINE__);
941  }
942 
943 }
944 #endif
945 
946 // Build DDS
947 bool HDF5RequestHandler::hdf5_build_dds(BESDataHandlerInterface & dhi)
948 {
949 
950  // Obtain the HDF5 file name.
951  string filename = dhi.container->access();
952 
953  string container_name = dhi.container->get_symbolic_name();
954  BESResponseObject *response = dhi.response_handler->get_response_object();
955  BESDDSResponse *bdds = dynamic_cast < BESDDSResponse * >(response);
956  if( !bdds )
957  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
958  bdds->set_container(container_name);
959 
960  try {
961 
962  bool dds_from_dc = false;
963  bool das_from_dc = false;
964  bool build_data = false;
965  string dds_cache_fname;
966  string das_cache_fname;
967 
968  if(_use_disk_meta_cache == true) {
969 
970  string base_filename = HDF5CFUtil::obtain_string_after_lastslash(filename);
971 
972  // The _use_disk_dds_cache is always set to false by default
973  if(_use_disk_dds_cache == true) {
974  dds_cache_fname = _disk_meta_cache_path+"/" +base_filename+"_dds";
975  if(access(dds_cache_fname.c_str(),F_OK) !=-1)
976  dds_from_dc = true;
977  }
978 
979  das_cache_fname = _disk_meta_cache_path+"/" +base_filename+"_das";
980  // Check if das files exist
981  if(access(das_cache_fname.c_str(),F_OK) !=-1)
982  das_from_dc = true;
983 
984  }
985 
986  get_dds_with_attributes(bdds, NULL,container_name,filename, dds_cache_fname,das_cache_fname,dds_from_dc,das_from_dc,build_data);
987 
988  // The following block reads dds from a dds cache file.
989 #if 0
990  string base_filename = HDF5CFUtil::obtain_string_after_lastslash(filename);
991  string dds_filename = "/tmp/"+base_filename+"_dds";
992 
993  BaseTypeFactory tf;
994  DDS tdds(&tf,name_path(filename),"3.2");
995  tdds.filename(filename);
996 
997 
998  FILE *dds_file = fopen(dds_filename.c_str(),"r");
999  tdds.parse(dds_file);
1000 //cerr<<"before parsing "<<endl;
1001  DDS* cache_dds = new DDS(tdds);
1002  if(dds != NULL)
1003  delete dds;
1004  bdds->set_dds(cache_dds);
1005  fclose(dds_file);
1006 #endif
1007 
1008  bdds->set_constraint( dhi ) ;
1009  bdds->clear_container() ;
1010 
1011  }
1012  catch(InternalErr & e) {
1013 
1014  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1015  __FILE__, __LINE__);
1016  }
1017  catch(Error & e) {
1018 
1019  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1020  __FILE__, __LINE__);
1021  }
1022  catch(...) {
1023 
1024  string s = "unknown exception caught building HDF5 DDS";
1025  throw BESInternalFatalError(s, __FILE__, __LINE__);
1026  }
1027 
1028  return true;
1029 }
1030 
1031 bool HDF5RequestHandler::hdf5_build_data(BESDataHandlerInterface & dhi)
1032 {
1033 
1034  if(true ==_usecf) {
1035 
1036  if(true == _pass_fileid)
1037  return hdf5_build_data_with_IDs(dhi);
1038  }
1039 
1040  string filename = dhi.container->access();
1041 
1042  string container_name = dhi.container->get_symbolic_name();
1043  BESResponseObject *response = dhi.response_handler->get_response_object();
1044  BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(response);
1045  if( !bdds )
1046  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
1047  bdds->set_container(container_name);
1048 
1049  try {
1050 
1051  bool dds_from_dc = false;
1052  bool das_from_dc = false;
1053  bool build_data = true;
1054  string dds_cache_fname;
1055  string das_cache_fname;
1056 
1057 
1058  // Only DAS is read from the cache. dds_from_dc is always false.
1059  if(_use_disk_meta_cache == true) {
1060 
1061  string base_filename = HDF5CFUtil::obtain_string_after_lastslash(filename);
1062  das_cache_fname = _disk_meta_cache_path+"/" +base_filename+"_das";
1063 
1064  if(access(das_cache_fname.c_str(),F_OK) !=-1)
1065  das_from_dc = true;
1066 
1067  }
1068 
1069  //get_dds_with_attributes(NULL,bdds, container_name,filename, dds_cache_fname,das_cache_fname,dds_from_dc,das_from_dc,build_data);
1070  get_dds_without_attributes_datadds(bdds,container_name,filename);
1071 
1072  bdds->set_constraint( dhi ) ;
1073  bdds->clear_container() ;
1074 
1075  }
1076  catch(InternalErr & e) {
1077 
1078  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1079  __FILE__, __LINE__);
1080  }
1081  catch(Error & e) {
1082 
1083  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1084  __FILE__, __LINE__);
1085  }
1086  catch(...) {
1087 
1088  string s = "unknown exception caught building HDF5 DDS";
1089  throw BESInternalFatalError(s, __FILE__, __LINE__);
1090  }
1091 
1092  return true;
1093 }
1094 
1095 // Obtain data when turning on the pass fileID key.The memory cache is not used.
1096 bool HDF5RequestHandler::hdf5_build_data_with_IDs(BESDataHandlerInterface & dhi)
1097 {
1098 
1099  BESDEBUG("h5","Building DataDDS by passing file IDs. "<<endl);
1100  hid_t cf_fileid = -1;
1101 
1102  string filename = dhi.container->access();
1103 
1104  H5Eset_auto2(H5E_DEFAULT,NULL,NULL);
1105  cf_fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
1106  if (cf_fileid < 0){
1107  string invalid_file_msg="Could not open this HDF5 file ";
1108  invalid_file_msg +=filename;
1109  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
1110  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
1111  invalid_file_msg +=" distributor.";
1112  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1113  }
1114 
1115  BESResponseObject *response = dhi.response_handler->get_response_object();
1116  BESDataDDSResponse *bdds = dynamic_cast < BESDataDDSResponse * >(response);
1117  if( !bdds )
1118  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
1119 
1120  try {
1121 
1122  bdds->set_container( dhi.container->get_symbolic_name() ) ;
1123 
1124  HDF5DDS *hdds = new HDF5DDS(bdds->get_dds());
1125  delete bdds->get_dds();
1126 
1127  bdds->set_dds(hdds);
1128 
1129  hdds->setHDF5Dataset(cf_fileid);
1130 
1131  read_cfdds( *hdds,filename,cf_fileid);
1132 
1133  if (!hdds->check_semantics()) { // DDS didn't comply with the DAP semantics
1134  hdds->print(cerr);
1135  throw InternalErr(__FILE__, __LINE__,
1136  "DDS check_semantics() failed. This can happen when duplicate variable names are defined.");
1137  }
1138 
1139  Ancillary::read_ancillary_dds( *hdds, filename ) ;
1140 
1141  DAS *das = new DAS ;
1142  BESDASResponse bdas( das ) ;
1143  bdas.set_container( dhi.container->get_symbolic_name() ) ;
1144  read_cfdas( *das,filename,cf_fileid);
1145  Ancillary::read_ancillary_das( *das, filename ) ;
1146 
1147  hdds->transfer_attributes(das);
1148  bdds->set_constraint( dhi ) ;
1149  bdds->clear_container() ;
1150 
1151  }
1152 
1153  catch(InternalErr & e) {
1154  if(cf_fileid !=-1)
1155  H5Fclose(cf_fileid);
1156  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1157  __FILE__, __LINE__);
1158  }
1159  catch(Error & e) {
1160  if(cf_fileid !=-1)
1161  H5Fclose(cf_fileid);
1162  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1163  __FILE__, __LINE__);
1164  }
1165  catch(...) {
1166  if(cf_fileid !=-1)
1167  H5Fclose(cf_fileid);
1168  string s = "unknown exception caught building HDF5 DataDDS";
1169  throw BESInternalFatalError(s, __FILE__, __LINE__);
1170  }
1171 
1172  return true;
1173 }
1174 
1175 bool HDF5RequestHandler::hdf5_build_dmr(BESDataHandlerInterface & dhi)
1176 {
1177 
1178 
1179  // Extract the DMR Response object - this holds the DMR used by the
1180  // other parts of the framework.
1181  BESResponseObject *response = dhi.response_handler->get_response_object();
1182  BESDMRResponse &bes_dmr = dynamic_cast<BESDMRResponse &>(*response);
1183 
1184  string filename = dhi.container->access();
1185 
1186  DMR *dmr = bes_dmr.get_dmr();
1187 
1188  // For the time being, separate CF file ID from the default file ID(mainly for debugging)
1189  hid_t fileid = -1;
1190  hid_t cf_fileid = -1;
1191 
1192  try {
1193 
1194  DMR* cached_dmr_ptr = 0;
1195  bool use_dmr_cache = false;
1196  if (dmr_cache)
1197  cached_dmr_ptr = static_cast<DMR*>(dmr_cache->get(filename));
1198  if (cached_dmr_ptr)
1199  use_dmr_cache = true;
1200  if (true == use_dmr_cache) {
1201  // copy the cached DMR into the BES response object
1202  BESDEBUG(HDF5_NAME, "DMR Cached hit for : " << filename << endl);
1203  *dmr = *cached_dmr_ptr; // Copy the referenced object
1204  }
1205  else {// No cache
1206 
1207  H5Eset_auto2(H5E_DEFAULT,NULL,NULL);
1208  D4BaseTypeFactory MyD4TypeFactory;
1209  dmr->set_factory(&MyD4TypeFactory);
1210 
1211  if(true ==_usecf) {// CF option
1212 
1213  if(true == _pass_fileid)
1214  return hdf5_build_dmr_with_IDs(dhi);
1215 
1216  cf_fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
1217  if (cf_fileid < 0){
1218  string invalid_file_msg="Could not open this HDF5 file ";
1219  invalid_file_msg +=filename;
1220  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
1221  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
1222  invalid_file_msg +=" distributor.";
1223  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1224  }
1225 
1226  BaseTypeFactory factory;
1227  DDS dds(&factory, name_path(filename), "3.2");
1228  dds.filename(filename);
1229 
1230  DAS das;
1231 
1232  // For the CF option dmr response, we need to map 64-bit integer separately
1233  // So set the flag to map 64-bit integer.
1234  HDF5RequestHandler::set_dmr_64bit_int(dmr);
1235  read_cfdds( dds,filename,cf_fileid);
1236  if (!dds.check_semantics()) { // DDS didn't comply with the DAP semantics
1237  dds.print(cerr);
1238  throw InternalErr(__FILE__, __LINE__,
1239  "DDS check_semantics() failed. This can happen when duplicate variable names are defined.");
1240  }
1241 
1242  read_cfdas(das,filename,cf_fileid);
1243  Ancillary::read_ancillary_das( das, filename ) ;
1244 
1245  dds.transfer_attributes(&das);
1246 
1248  if(cf_fileid !=-1)
1249  H5Fclose(cf_fileid);
1250 
1251  dmr->build_using_dds(dds);
1252 
1253  }// "if(true == _usecf)"
1254  else {// default option
1255 
1256  // Obtain the HDF5 file ID.
1257  fileid = get_fileid(filename.c_str());
1258  if (fileid < 0) {
1259  string invalid_file_msg="Could not open this HDF5 file ";
1260  invalid_file_msg +=filename;
1261  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
1262  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
1263  invalid_file_msg +=" distributor.";
1264  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1265  }
1266 
1267  bool use_dimscale = false;
1268  if(true == _default_handle_dimension)
1269  use_dimscale = check_dimscale(fileid);
1270  dmr->set_name(name_path(filename));
1271  dmr->set_filename(name_path(filename));
1272 
1273  D4Group* root_grp = dmr->root();
1274  breadth_first(fileid,(char*)"/",root_grp,filename.c_str(),use_dimscale);
1275 
1276 #if 0
1277  if(true == use_dimscale)
1278  //breadth_first(fileid,(char*)"/",*dmr,root_grp,filename.c_str(),true);
1279  breadth_first(fileid,(char*)"/",root_grp,filename.c_str(),true);
1280  else
1281  depth_first(fileid,(char*)"/",root_grp,filename.c_str());
1282  //depth_first(fileid,(char*)"/",*dmr,root_grp,filename.c_str());
1283 #endif
1284 
1285  close_fileid(fileid);
1286 
1287  }// else (default option)
1288 
1289  // If the cache is turned on, add the memory cache.
1290  if (dmr_cache) {
1291  // add a copy
1292  BESDEBUG(HDF5_NAME, "DMR added to the cache for : " << filename << endl);
1293  dmr_cache->add(new DMR(*dmr), filename);
1294  }
1295  }// else no cache
1296  }// try
1297 
1298  catch(InternalErr & e) {
1299 
1300  if(cf_fileid !=-1)
1301  H5Fclose(cf_fileid);
1302  if(fileid !=-1)
1303  H5Fclose(fileid);
1304 
1305  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1306  __FILE__, __LINE__);
1307  }
1308  catch(Error & e) {
1309 
1310  if(cf_fileid !=-1)
1311  H5Fclose(cf_fileid);
1312  if(fileid !=-1)
1313  H5Fclose(fileid);
1314  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1315  __FILE__, __LINE__);
1316  }
1317  catch(...) {
1318 
1319  if(cf_fileid !=-1)
1320  H5Fclose(cf_fileid);
1321  if(fileid !=-1)
1322  H5Fclose(fileid);
1323  string s = "unknown exception caught building HDF5 DMR";
1324  throw BESInternalFatalError(s, __FILE__, __LINE__);
1325  }
1326 
1327  //dmr->print(cout);
1328 
1329  // Instead of fiddling with the internal storage of the DHI object,
1330  // (by setting dhi.data[DAP4_CONSTRAINT], etc., directly) use these
1331  // methods to set the constraints. But, why? Ans: from Patrick is that
1332  // in the 'container' mode of BES each container can have a different
1333  // CE.
1334  bes_dmr.set_dap4_constraint(dhi);
1335  bes_dmr.set_dap4_function(dhi);
1336  dmr->set_factory(0);
1337 
1338  return true;
1339 }
1340 
1341 // This function is only used when EnableCF is true.
1342 bool HDF5RequestHandler::hdf5_build_dmr_with_IDs(BESDataHandlerInterface & dhi)
1343 {
1344 
1345  BESDEBUG("h5","Building DMR with passing file IDs. "<<endl);
1346  string filename = dhi.container->access();
1347  hid_t cf_fileid = -1;
1348 
1349  H5Eset_auto2(H5E_DEFAULT,NULL,NULL);
1350  cf_fileid = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
1351  if (cf_fileid < 0){
1352  string invalid_file_msg="Could not open this HDF5 file ";
1353  invalid_file_msg +=filename;
1354  invalid_file_msg +=". It is very possible that this file is not an HDF5 file ";
1355  invalid_file_msg +=" but with the .h5/.HDF5 suffix. Please check with the data";
1356  invalid_file_msg +=" distributor.";
1357  throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1358  }
1359 
1360  BaseTypeFactory factory;
1361  DDS dds(&factory, name_path(filename), "3.2");
1362  dds.filename(filename);
1363 
1364  DAS das;
1365 
1366  try {
1367 
1368 
1369  // This is the CF option
1370  read_cfdds( dds,filename,cf_fileid);
1371 
1372  if (!dds.check_semantics()) { // DDS didn't comply with the DAP semantics
1373  dds.print(cerr);
1374  throw InternalErr(__FILE__, __LINE__,
1375  "DDS check_semantics() failed. This can happen when duplicate variable names are defined.");
1376  }
1377 
1378  Ancillary::read_ancillary_dds( dds, filename ) ;
1379 
1380 
1381  read_cfdas(das,filename,cf_fileid);
1382 
1383  Ancillary::read_ancillary_das( das, filename ) ;
1384 
1385  dds.transfer_attributes(&das);
1386 
1388  //if(cf_fileid !=-1)
1389  // H5Fclose(cf_fileid);
1390 
1391  }
1392  catch(InternalErr & e) {
1393 
1394  if(cf_fileid !=-1)
1395  H5Fclose(cf_fileid);
1396 
1397  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1398  __FILE__, __LINE__);
1399  }
1400  catch(Error & e) {
1401 
1402  if(cf_fileid !=-1)
1403  H5Fclose(cf_fileid);
1404 
1405  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1406  __FILE__, __LINE__);
1407  }
1408  catch(...) {
1409 
1410  if(cf_fileid !=-1)
1411  H5Fclose(cf_fileid);
1412 
1413  string s = "unknown exception caught building HDF5 DataDDS";
1414  throw BESInternalFatalError(s, __FILE__, __LINE__);
1415  }
1416 
1417  // Extract the DMR Response object - this holds the DMR used by the
1418  // other parts of the framework.
1419  BESResponseObject *response = dhi.response_handler->get_response_object();
1420  BESDMRResponse &bes_dmr = dynamic_cast<BESDMRResponse &>(*response);
1421 
1422  // In this handler we use a different pattern since the handler specializes the DDS/DMR.
1423  // First, build the DMR adding the open handle to the HDF4 dataset, then free the DMR
1424  // the BES built and add this one. The HDF4DMR object will close the open dataset when
1425  // the BES runs the DMR's destructor.
1426 
1427  DMR *dmr = bes_dmr.get_dmr();
1428  D4BaseTypeFactory MyD4TypeFactory;
1429  dmr->set_factory(&MyD4TypeFactory);
1430  dmr->build_using_dds(dds);
1431 
1432  HDF5DMR *hdf5_dmr = new HDF5DMR(dmr);
1433  hdf5_dmr->setHDF5Dataset(cf_fileid);
1434  delete dmr; // The call below will make 'dmr' unreachable; delete it now to avoid a leak.
1435  bes_dmr.set_dmr(hdf5_dmr); // BESDMRResponse will delete hdf5_dmr
1436 
1437  // Instead of fiddling with the internal storage of the DHI object,
1438  // (by setting dhi.data[DAP4_CONSTRAINT], etc., directly) use these
1439  // methods to set the constraints. But, why? Ans: from Patrick is that
1440  // in the 'container' mode of BES each container can have a different
1441  // CE.
1442  bes_dmr.set_dap4_constraint(dhi);
1443  bes_dmr.set_dap4_function(dhi);
1444  hdf5_dmr->set_factory(0);
1445 
1446  return true;
1447 }
1448 
1449 bool HDF5RequestHandler::hdf5_build_help(BESDataHandlerInterface & dhi)
1450 {
1451  BESResponseObject *response = dhi.response_handler->get_response_object();
1452  BESInfo *info = dynamic_cast<BESInfo *>(response);
1453  if( !info )
1454  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
1455 
1456  string add_info="Just for Test";
1457 
1458  map<string,string> attrs ;
1459  attrs["name"] = MODULE_NAME ;
1460  attrs["version"] = MODULE_VERSION ;
1461  list<string> services ;
1462  BESServiceRegistry::TheRegistry()->services_handled( HDF5_NAME, services );
1463  if( services.size() > 0 )
1464  {
1465  string handles = BESUtil::implode( services, ',' ) ;
1466  attrs["handles"] = handles ;
1467  }
1468  info->begin_tag( "module", &attrs ) ;
1469  info->end_tag( "module" ) ;
1470  info->add_data(add_info);
1471 
1472  return true;
1473 }
1474 
1475 bool HDF5RequestHandler::hdf5_build_version(BESDataHandlerInterface & dhi)
1476 {
1477  BESResponseObject *response = dhi.response_handler->get_response_object();
1478  BESVersionInfo *info = dynamic_cast < BESVersionInfo * >(response);
1479  if( !info )
1480  throw BESInternalError( "cast error", __FILE__, __LINE__ ) ;
1481 
1482  info->add_module( MODULE_NAME, MODULE_VERSION ) ;
1483 
1484  return true;
1485 }
1486 
1487 
1488 bool HDF5RequestHandler::obtain_lrd_common_cache_dirs()
1489 {
1490  string lrd_config_fpath;
1491  string lrd_config_fname;
1492 
1493  // Obtain DataCache path
1494  lrd_config_fpath = get_beskeys("H5.DataCachePath");
1495 
1496  // Obtain the configure file name that specifics the large file configuration
1497  lrd_config_fname = get_beskeys("H5.LargeDataMemCacheFileName");
1498 
1499  // If either the configure file path or fname is missing, won't add specific mem. cache dirs.
1500  if(lrd_config_fpath=="" || lrd_config_fname=="")
1501  return false;
1502 
1503  // temp_line for storing info of one line in the config. file
1504  string temp_line;
1505 
1506  // The full path of the configure file
1507  string mcache_config_fname = lrd_config_fpath+"/"+lrd_config_fname;
1508 
1509  //ifstream mcache_config_file("example.txt");
1510  // Open the configure file
1511  ifstream mcache_config_file(mcache_config_fname.c_str());
1512 
1513  // If the configuration file is not open, return false.
1514  if(mcache_config_file.is_open()==false){
1515  BESDEBUG(HDF5_NAME,"The large data memory cache configure file "<<mcache_config_fname );
1516  BESDEBUG(HDF5_NAME," cannot be opened."<<endl);
1517  return false;
1518  }
1519 
1520  // Read the configuration file line by line
1521  while(getline(mcache_config_file,temp_line)) {
1522 
1523  // Only consider lines that is no less than 2 characters and the 2nd character is space.
1524  if(temp_line.size()>1 && temp_line.at(1)==' ') {
1525  char sep=' ';
1526  string subline = temp_line.substr(2);
1527  vector<string> temp_name_list;
1528 
1529  // Include directories to store common latitude and longitude values
1530  if(temp_line.at(0)=='1') {
1531  HDF5CFUtil::Split_helper(temp_name_list,subline,sep);
1532  //lrd_cache_dir_list +=temp_name_list;
1533  lrd_cache_dir_list.insert(lrd_cache_dir_list.end(),temp_name_list.begin(),temp_name_list.end());
1534  }
1535  // Include directories not to store common latitude and longitude values
1536  else if(temp_line.at(0)=='0'){
1537  HDF5CFUtil::Split_helper(temp_name_list,subline,sep);
1538  //lrd_non_cache_dir_list +=temp_name_list;
1539  lrd_non_cache_dir_list.insert(lrd_non_cache_dir_list.end(),temp_name_list.begin(),temp_name_list.end());
1540  }
1541  // Include variable names that the server would like to store in the memory cache
1542  else if(temp_line.at(0)=='2') {
1543 
1544  // We need to handle the space case inside a variable path
1545  // either "" or '' needs to be used to identify a var path
1546  vector<int>dq_pos;
1547  vector<int>sq_pos;
1548  for(unsigned int i = 0; i<subline.size();i++){
1549  if(subline[i]=='"') {
1550  dq_pos.push_back(i);
1551  }
1552  else if(subline[i]=='\'')
1553  sq_pos.push_back(i);
1554  }
1555  if(dq_pos.size()==0 && sq_pos.size()==0)
1556  HDF5CFUtil::Split_helper(temp_name_list,subline,sep);
1557  else if((dq_pos.size()!=0) &&(dq_pos.size()%2==0)&& sq_pos.size()==0) {
1558  unsigned int dq_index= 0;
1559  while(dq_index < dq_pos.size()){
1560  if(dq_pos[dq_index+1]>(dq_pos[dq_index]+1)) {
1561  temp_name_list.push_back
1562  (subline.substr(dq_pos[dq_index]+1,dq_pos[dq_index+1]-dq_pos[dq_index]-1));
1563  }
1564  dq_index = dq_index + 2;
1565  }
1566  }
1567  else if((sq_pos.size()!=0) &&(sq_pos.size()%2==0)&& dq_pos.size()==0) {
1568  unsigned int sq_index= 0;
1569  while(sq_index < sq_pos.size()){
1570  if(sq_pos[sq_index+1]>(sq_pos[sq_index]+1)) {
1571  temp_name_list.push_back
1572  (subline.substr(sq_pos[sq_index]+1,sq_pos[sq_index+1]-sq_pos[sq_index]-1));
1573  }
1574  sq_index = sq_index+2;
1575  }
1576  }
1577 
1578  lrd_var_cache_file_list.insert(lrd_var_cache_file_list.end(),temp_name_list.begin(),temp_name_list.end());
1579  }
1580  }
1581  }
1582 
1583 
1584 #if 0
1585 
1586 for(int i =0; i<lrd_cache_dir_list.size();i++)
1587 cerr<<"lrd cache list is "<<lrd_cache_dir_list[i] <<endl;
1588 for(int i =0; i<lrd_non_cache_dir_list.size();i++)
1589 cerr<<"lrd non cache list is "<<lrd_non_cache_dir_list[i] <<endl;
1590 for(int i =0; i<lrd_var_cache_file_list.size();i++)
1591 cerr<<"lrd var cache file list is "<<lrd_var_cache_file_list[i] <<endl;
1592 #endif
1593 
1594 
1595  mcache_config_file.close();
1596  if(lrd_cache_dir_list.size()==0 && lrd_non_cache_dir_list.size()==0 && lrd_var_cache_file_list.size()==0)
1597  return false;
1598  else
1599  return true;
1600 }
1601 
1602 
1603 bool HDF5RequestHandler::read_das_from_disk_cache(const string & cache_filename,DAS *das_ptr) {
1604 
1605  BESDEBUG(HDF5_NAME, "Coming to read_das_from_disk_cache() " << cache_filename << endl);
1606  bool ret_value = true;
1607  FILE *md_file = NULL;
1608  md_file = fopen(cache_filename.c_str(),"rb");
1609 
1610  if(NULL == md_file) {
1611  string bes_error = "An error occurred trying to open a metadata cache file " + cache_filename;
1612  throw BESInternalError( bes_error, __FILE__, __LINE__);
1613  }
1614  else {
1615 
1616  int fd_md = fileno(md_file);
1617  struct flock *l_md;
1618  l_md = lock(F_RDLCK);
1619 
1620  // hold a read(shared) lock to read metadata from a file.
1621  if(fcntl(fd_md,F_SETLKW,l_md) == -1) {
1622  fclose(md_file);
1623  ostringstream oss;
1624  oss << "cache process: " << l_md->l_pid << " triggered a locking error: " << get_errno();
1625  throw BESInternalError( oss.str(), __FILE__, __LINE__);
1626  }
1627 
1628  try {
1629 
1630  struct stat sb;
1631  if(stat(cache_filename.c_str(),&sb) != 0) {
1632  string bes_error = "An error occurred trying to stat a metadata cache file size " + cache_filename;
1633  throw BESInternalError( bes_error, __FILE__, __LINE__);
1634 
1635  }
1636 
1637 
1638  size_t bytes_expected_read=(size_t)sb.st_size;
1639  BESDEBUG(HDF5_NAME, "DAS Disk cache file size is " << bytes_expected_read << endl);
1640 
1641  vector<char> buf;
1642  buf.resize(bytes_expected_read);
1643  size_t bytes_to_read =fread((void*)&buf[0],1,bytes_expected_read,md_file);
1644  if(bytes_to_read != bytes_expected_read)
1645  throw InternalErr(__FILE__,__LINE__,"Fail to read the data from the das cache file.");
1646 
1647  char* temp_pointer =&buf[0];
1648 
1649  AttrTable*at = NULL;
1650  // recursively build DAS
1651 //#if 0
1652  temp_pointer = get_attr_info_from_dc(temp_pointer,das_ptr,at);
1653 //#endif
1654 
1655 
1656  }
1657  catch(...) {
1658  if(fcntl(fd_md,F_SETLK,lock(F_UNLCK)) == -1) {
1659  fclose(md_file);
1660  throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1661  }
1662 
1663  fclose(md_file);
1664  throw InternalErr(__FILE__,__LINE__,"Fail to parse a das cache file.");
1665  }
1666 
1667  // Unlock the cache file
1668  if(fcntl(fd_md,F_SETLK,lock(F_UNLCK)) == -1) {
1669  fclose(md_file);
1670  throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1671  }
1672  fclose(md_file);
1673  }
1674  return ret_value;
1675 
1676 }
1677 
1678 // This fucntion will NOT be used by default. Leave here for future improvement.
1679 bool HDF5RequestHandler::write_dds_to_disk_cache(const string& dds_cache_fname,DDS *dds_ptr) {
1680 
1681  BESDEBUG(HDF5_NAME, "Write DDS to disk cache " << dds_cache_fname << endl);
1682  FILE *dds_file = fopen(dds_cache_fname.c_str(),"w");
1683 
1684  if(NULL == dds_file) {
1685  string bes_error = "An error occurred trying to open a metadata cache file " + dds_cache_fname;
1686  throw BESInternalError( bes_error, __FILE__, __LINE__);
1687  }
1688  else {
1689 
1690  int fd_md = fileno(dds_file);
1691  struct flock *l_md;
1692  l_md = lock(F_WRLCK);
1693 
1694  // hold a read(shared) lock to read metadata from a file.
1695  if(fcntl(fd_md,F_SETLKW,l_md) == -1) {
1696  fclose(dds_file);
1697  ostringstream oss;
1698  oss << "cache process: " << l_md->l_pid << " triggered a locking error: " << get_errno();
1699  throw BESInternalError( oss.str(), __FILE__, __LINE__);
1700  }
1701 
1702  try {
1703  dds_ptr->print(dds_file);
1704  }
1705  catch(...) {
1706  if(fcntl(fd_md,F_SETLK,lock(F_UNLCK)) == -1) {
1707  fclose(dds_file);
1708  throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1709  }
1710 
1711  fclose(dds_file);
1712  throw InternalErr(__FILE__,__LINE__,"Fail to parse a dds cache file.");
1713  }
1714 
1715  if(fcntl(fd_md,F_SETLK,lock(F_UNLCK)) == -1) {
1716  fclose(dds_file);
1717  throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1718  }
1719 
1720  fclose(dds_file);
1721  }
1722  return true;
1723 
1724 }
1725 
1726 // Write DAS to a binary cached file on disk.
1727 bool HDF5RequestHandler::write_das_to_disk_cache(const string & das_cache_fname, DAS *das_ptr) {
1728 
1729  BESDEBUG(HDF5_NAME, "Write DAS to disk cache " << das_cache_fname << endl);
1730  FILE *das_file = fopen(das_cache_fname.c_str(),"wb");
1731  if(NULL == das_file) {
1732  string bes_error = "An error occurred trying to open a metadata cache file " + das_cache_fname;
1733  throw BESInternalError( bes_error, __FILE__, __LINE__);
1734  }
1735  else {
1736  int fd_md = fileno(das_file);
1737  struct flock *l_md;
1738  l_md = lock(F_WRLCK);
1739 
1740  // hold a write(exclusive) lock to write metadata to a file.
1741  if(fcntl(fd_md,F_SETLKW,l_md) == -1) {
1742  fclose(das_file);
1743  ostringstream oss;
1744  oss << "cache process: " << l_md->l_pid << " triggered a locking error: " << get_errno();
1745  throw BESInternalError( oss.str(), __FILE__, __LINE__);
1746  }
1747 
1748  try {
1749  write_das_to_file(das_ptr,das_file);
1750  }
1751  catch(...) {
1752  if(fcntl(fd_md,F_SETLK,lock(F_UNLCK)) == -1) {
1753  fclose(das_file);
1754  throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1755  }
1756 
1757  fclose(das_file);
1758  throw InternalErr(__FILE__,__LINE__,"Fail to parse a dds cache file.");
1759  }
1760 
1761  if(fcntl(fd_md,F_SETLK,lock(F_UNLCK)) == -1) {
1762  fclose(das_file);
1763  throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1764  }
1765 
1766  fclose(das_file);
1767 
1768  }
1769 
1770  return true;
1771 
1772 }
1773 
1774 // The wrapper function to call write_das_table_to_file to generate the cache.
1775 void write_das_to_file(DAS*das_ptr,FILE* das_file) {
1776 
1777  // When category_flag is 2, it marks the end of the file.
1778  uint8_t category_flag = 2;
1779  AttrTable* top_table = das_ptr->get_top_level_attributes();
1780  write_das_table_to_file(top_table,das_file);
1781 
1782  // Add the final ending flag for retrieving the info.
1783  fwrite((const void*)&category_flag,1,1,das_file);
1784  return;
1785 
1786 }
1787 
1788 // The main function to write DAS to a file
1789 void write_das_table_to_file(AttrTable*temp_table,FILE* das_file) {
1790 
1791  if(temp_table !=NULL) {
1792 
1793  // 2 is the end mark of an attribute table
1794  uint8_t category_flag = 2;
1795 
1796  // Loop through the whole DAS top table
1797  AttrTable::Attr_iter top_startit = temp_table->attr_begin();
1798  AttrTable::Attr_iter top_endit = temp_table->attr_end();
1799  AttrTable::Attr_iter top_it = top_startit;
1800  while(top_it !=top_endit) {
1801  AttrType atype = temp_table->get_attr_type(top_it);
1802  if(atype == Attr_unknown)
1803  throw InternalErr(__FILE__,__LINE__,"Unsupported DAS Attribute type");
1804  else if(atype!=Attr_container) {
1805  BESDEBUG(HDF5_NAME, "DAS to the disk cache, attr name is: "
1806  << temp_table->get_name(top_it) << endl);
1807  BESDEBUG(HDF5_NAME, "DAS to the disk cache, attr type is: "
1808  << temp_table->get_type(top_it) << endl);
1809  // For the debugging purpose
1810  //unsigned int num_attrs = temp_table->get_attr_num(temp_table->get_name(top_it));
1811  //cerr<<"Attribute values are "<<endl;
1812  //for (int i = 0; i <num_attrs;i++)
1813  // cerr<<(*(temp_table->get_attr_vector(temp_table->get_name(top_it))))[i]<<" ";
1814  //cerr<<endl;
1815  //write_das_attr_info(temp_table,top_it,das_file);
1816  // Write DAS attribute info to the file
1817  write_das_attr_info(temp_table,temp_table->get_name(top_it),temp_table->get_type(top_it),das_file);
1818  }
1819  else {
1820  BESDEBUG(HDF5_NAME, "DAS to the disk cache, attr container name is: "
1821  << (*top_it)->name << endl);
1822  // Write the container and then write the info. in this container
1823  AttrTable* sub_table = temp_table->get_attr_table(top_it);
1824  write_container_name_to_file(sub_table->get_name(),das_file);
1825  write_das_table_to_file(sub_table,das_file);
1826 
1827  // Write the end flag
1828  fwrite((const void*)&category_flag,1,1,das_file);
1829 
1830  }
1831  ++top_it;
1832  }
1833 
1834  }
1835 }
1836 
1837 // Write container name to the disk file
1838 void write_container_name_to_file(const string& cont_name,FILE *das_file) {
1839 
1840  // 1 marks the starting of a container
1841  uint8_t category_flag = 1;
1842  vector<char> buf;
1843  size_t bytes_to_write = cont_name.size()+sizeof(size_t)+1;
1844  buf.resize(bytes_to_write);
1845  char*temp_pointer =&buf[0];
1846  memcpy((void*)temp_pointer,(void*)&category_flag,1);
1847  temp_pointer++;
1848  temp_pointer=copy_str(temp_pointer,cont_name);
1849 
1850  size_t bytes_to_be_written = fwrite((const void*)&buf[0],1,bytes_to_write,das_file);
1851  if(bytes_to_be_written != bytes_to_write)
1852  throw InternalErr(__FILE__, __LINE__,"Failed to write a DAS container name to a cache");
1853  return;
1854 }
1855 
1856 
1857 // Write DAS attribute info. to the disk cache file
1858 void write_das_attr_info(AttrTable* dtp,const string& attr_name, const string & attr_type,FILE * das_file) {
1859 
1860  // 0 marks the starting of a DAS attribute
1861  uint8_t category_flag = 0;
1862 
1863  unsigned int num_attr_elems = dtp->get_attr_num(attr_name);
1864  vector<string> attr_values;
1865  size_t total_attr_values_size = 0;
1866  for (unsigned int i = 0; i <num_attr_elems;i++){
1867  attr_values.push_back((*(dtp->get_attr_vector(attr_name)))[i]);
1868  total_attr_values_size += attr_values[i].size();
1869  }
1870  // Need to add a flag, value as 0 to indicate the attribute.
1871  // DAS: category flag, sizeof attirubte name, attribute name, size of attribute type, attribute type
1872  size_t bytes_to_write_attr = 1 + attr_name.size() + attr_type.size() + 2* sizeof(size_t);
1873 
1874  // One unsigned int to store the number of element elements i
1875  // + sizeof(size_t) * number of elements to store the number of characters for each attribute
1876  // (in DAP, every attribute is in string format)
1877  // +total size of all attribute values
1878  bytes_to_write_attr += sizeof(unsigned int) + num_attr_elems*sizeof(size_t)+total_attr_values_size;
1879 
1880  vector<char>attr_buf;
1881  attr_buf.resize(bytes_to_write_attr);
1882  char* temp_attrp =&attr_buf[0];
1883 
1884  // The attribute flag
1885  memcpy((void*)temp_attrp,(void*)&category_flag,1);
1886  temp_attrp++;
1887 
1888  // The attribute name and type
1889  temp_attrp=copy_str(temp_attrp,attr_name);
1890  temp_attrp=copy_str(temp_attrp,attr_type);
1891 
1892  // Number of elements
1893  memcpy((void*)temp_attrp,(void*)&num_attr_elems,sizeof(unsigned int));
1894  temp_attrp+=sizeof(unsigned int);
1895 
1896  // All attributes
1897  for (unsigned int i = 0; i <num_attr_elems;i++)
1898  temp_attrp=copy_str(temp_attrp,(*(dtp->get_attr_vector(attr_name)))[i]);
1899 
1900  size_t bytes_to_be_written = fwrite((const void*)&attr_buf[0],1,bytes_to_write_attr,das_file);
1901  if(bytes_to_be_written != bytes_to_write_attr)
1902  throw InternalErr(__FILE__, __LINE__,"Failed to write a DAS attribute to a cache");
1903 
1904  return;
1905 
1906 }
1907 
1908 // Read DDS from a disk cache, this function is not used by default.
1909 void HDF5RequestHandler::read_dds_from_disk_cache(BESDDSResponse* bdds, BESDataDDSResponse* data_bdds,
1910  bool build_data,const string & container_name,const string & h5_fname,
1911  const string & dds_cache_fname,const string &das_cache_fname, hid_t h5_fd,
1912  bool das_from_dc) {
1913 
1914 
1915  BESDEBUG(HDF5_NAME, "Read DDS from disk cache " << dds_cache_fname << endl);
1916 
1917  DDS *dds;
1918  if(true == build_data)
1919  dds = data_bdds->get_dds();
1920  else
1921  dds = bdds->get_dds();
1922 
1923  // write a function to pass the following with the lock.
1924  BaseTypeFactory tf;
1925  DDS tdds(&tf,name_path(h5_fname),"3.2");
1926  tdds.filename(h5_fname);
1927 
1928  FILE *dds_file = fopen(dds_cache_fname.c_str(),"r");
1929  tdds.parse(dds_file);
1930  DDS* cache_dds = new DDS(tdds);
1931 #if 0
1932 cerr<<"before dds "<<endl;
1933 dds->dump(cerr);
1934 cerr<<"after dds "<<endl;
1935 cerr<<"before tdds "<<endl;
1936 cache_dds->dump(cerr);
1937 cerr<<"after tdds "<<endl;
1938 #endif
1939  if(dds != NULL)
1940  delete dds;
1941 
1942  Ancillary::read_ancillary_dds( *cache_dds, h5_fname ) ;
1943 
1944  add_das_to_dds(cache_dds,container_name,h5_fname,das_cache_fname,h5_fd,das_from_dc);
1945  if(true == build_data)
1946  data_bdds->set_dds(cache_dds);
1947  else
1948  bdds->set_dds(cache_dds);
1949  fclose(dds_file);
1950 
1951  if (dds_cache) {
1952  // add a copy
1953  BESDEBUG(HDF5_NAME, "Reading DDS from Disk Cache routine, For memory cache, DDS added to the cache for : " << h5_fname << endl);
1954  dds_cache->add(new DDS(*cache_dds), h5_fname);
1955  }
1956 
1957 }
1958 
1959 // Add DAS to DDS.
1960 void HDF5RequestHandler::add_das_to_dds(DDS *dds, const string &/*container_name*/, const string &filename,
1961  const string &das_cache_fname, hid_t h5_fd, bool das_from_dc) {
1962 
1963  BESDEBUG(HDF5_NAME, "Coming to add_das_to_dds() " << endl);
1964 
1965  // Check DAS memory cache
1966  DAS *das = 0 ;
1967  bool use_das_cache = false;
1968  if (das_cache)
1969  das = static_cast<DAS*>(das_cache->get(filename));
1970  if (das)
1971  use_das_cache = true;
1972 
1973  if (true == use_das_cache) {
1974  BESDEBUG(HDF5_NAME, "DAS Cached hit for : " << filename << endl);
1975  dds->transfer_attributes(das); // no need to copy the cached DAS
1976  }
1977 
1978  else {
1979 
1980  das = new DAS ;
1981 #if 0
1982  if (!container_name.empty())
1983  das->container_name(container_name);
1984 #endif
1985  if(das_from_dc == true)
1986  read_das_from_disk_cache(das_cache_fname,das);
1987  else {
1988  // This bool is for the case, when DDS is read from a cache then we need to open the HDF5 file.
1989  bool h5_file_open = true;
1990  if(h5_fd == -1)
1991  h5_file_open = false;
1992  if (true == _usecf) {
1993  // go to the CF option
1994  if(h5_file_open == false)
1995  h5_fd = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
1996 
1997  read_cfdas( *das,filename,h5_fd);
1998  if(h5_file_open == false)
1999  H5Fclose(h5_fd);
2000  }
2001  else {
2002  if(h5_file_open == false)
2003  h5_fd = get_fileid(filename.c_str());
2004  find_gloattr(h5_fd, *das);
2005  depth_first(h5_fd, "/", *das);
2006  if(h5_file_open == false)
2007  close_fileid(h5_fd);
2008  }
2009 
2010  Ancillary::read_ancillary_das( *das, filename ) ;
2011 
2012  if(das_cache_fname!="" && das_from_dc == false)
2013  write_das_to_disk_cache(das_cache_fname,das);
2014  }
2015 
2016  dds->transfer_attributes(das);
2017 
2018  if (das_cache) {
2019  // add a copy
2020  BESDEBUG(HDF5_NAME, "Reading DDS from Disk Cache routine, For memory cache, DAS added to the cache for : " << filename << endl);
2021  das_cache->add(new DAS(*das), filename);
2022  }
2023  delete das;
2024 
2025  }
2026 
2027 }
2028 
2029 bool check_beskeys(const string key) {
2030 
2031  bool found = false;
2032  string doset ="";
2033  const string dosettrue ="true";
2034  const string dosetyes = "yes";
2035 
2036  TheBESKeys::TheKeys()->get_value( key, doset, found ) ;
2037  if( true == found ) {
2038  doset = BESUtil::lowercase( doset ) ;
2039  if( dosettrue == doset || dosetyes == doset )
2040  return true;
2041  }
2042  return false;
2043 
2044 }
2045 
2046 // get_uint_key and get_float_key are copied from the netCDF handler.
2047 
2048 static unsigned int get_uint_key(const string &key, unsigned int def_val)
2049 {
2050  bool found = false;
2051  string doset = "";
2052 
2053  TheBESKeys::TheKeys()->get_value(key, doset, found);
2054  if (true == found) {
2055  // In C++11, stoi is better.
2056  return atoi(doset.c_str()); // use better code TODO
2057  }
2058  else {
2059  return def_val;
2060  }
2061 }
2062 
2063 static unsigned long get_ulong_key(const string &key, unsigned long def_val)
2064 {
2065  bool found = false;
2066  string doset = "";
2067 
2068  TheBESKeys::TheKeys()->get_value(key, doset, found);
2069  if (true == found) {
2070  // In C++11, stoull is better.
2071  return atol(doset.c_str()); // use better code TODO
2072  }
2073  else {
2074  return def_val;
2075  }
2076 }
2077 static float get_float_key(const string &key, float def_val)
2078 {
2079  bool found = false;
2080  string doset = "";
2081 
2082  TheBESKeys::TheKeys()->get_value(key, doset, found);
2083  if (true == found) {
2084  return atof(doset.c_str()); // use better code TODO
2085  }
2086  else {
2087  return def_val;
2088  }
2089 }
2090 
2091 static string get_beskeys(const string &key) {
2092 
2093  bool found = false;
2094  string ret_value ="";
2095 
2096  TheBESKeys::TheKeys()->get_value( key, ret_value, found ) ;
2097  return ret_value;
2098 
2099 }
2100 
2101 // The function to copy a string to a memory buffer.
2102 char* copy_str(char*temp_ptr,const string & str) {
2103 
2104  size_t str_size=str.size();
2105  memcpy((void*)temp_ptr,(void*)&str_size,sizeof(size_t));
2106  temp_ptr+=sizeof(size_t);
2107  vector<char>temp_vc2(str.begin(),str.end());
2108  memcpy((void*)temp_ptr,(void*)&temp_vc2[0],str.size());
2109  temp_ptr+=str.size();
2110  return temp_ptr;
2111 
2112 }
2113 
2114 
2115 // Obtain the string from a memory buffer.
2116 // Note: both char* and string(as a reference) will be returned
2117 // The attribute binary first stores the size of the string, then the string itself
2118 char* obtain_str(char*temp_ptr,string & str) {
2119 
2120  size_t oname_size = *((size_t *)temp_ptr);
2121  temp_ptr = temp_ptr + sizeof(size_t);
2122  string oname;
2123  for(unsigned int i =0; i<oname_size; i++){
2124  oname.push_back(*temp_ptr);
2125  ++temp_ptr;
2126  }
2127  str = oname;
2128  return temp_ptr;
2129 
2130 }
2131 
2132 // For our case, there are no global attributes for DAS.
2133 // The global attribures are always under HDF_GLOBAL.
2134 // The main function to obtain the DAS info. from the cache.
2135 char* get_attr_info_from_dc(char*temp_pointer,DAS *das,AttrTable *at_par) {
2136 
2137  // 3 is only for the code to come into the loop.
2138  uint8_t flag =3;
2139  while(flag !=2) {
2140  flag = *((uint8_t*)(temp_pointer));
2141  BESDEBUG(HDF5_NAME, "Build DAS from the disk cache file flag: "
2142  <<" flag = 0, attribute; flag = 1, container; flag =2; end of container;"
2143  <<" flag = 3; the initial value to get the attribute retrieval process started."
2144  <<" The flag value is "
2145  << (int)flag <<endl);
2146  temp_pointer++;
2147 
2148  if(flag ==1) {
2149  string container_name;
2150  temp_pointer = obtain_str(temp_pointer,container_name);
2151  BESDEBUG(HDF5_NAME, "DAS from the disk cache, container name is " << container_name << endl);
2152 
2153  // Remember the current Attribute table state
2154  AttrTable*temp_at_par = at_par;
2155  if(at_par == NULL)
2156  at_par = das->add_table(container_name, new AttrTable);
2157  else
2158  at_par = at_par->append_container(container_name);
2159 
2160  temp_pointer = get_attr_info_from_dc(temp_pointer,das,at_par);
2161  // MUST resume the original state
2162  at_par = temp_at_par;
2163 
2164  }
2165  else if(flag == 0) {
2166  // The attribute must have a table.
2167  if(at_par ==NULL)
2168  throw BESInternalError( "The AttrTable must exist for DAS attributes", __FILE__, __LINE__ ) ;
2169 
2170  // Attribute name
2171  string attr_name;
2172  temp_pointer = obtain_str(temp_pointer,attr_name);
2173  BESDEBUG(HDF5_NAME, "DAS from the disk cache, attr name is: " << attr_name << endl);
2174 
2175  // Attribute type
2176  string attr_type;
2177  temp_pointer = obtain_str(temp_pointer,attr_type);
2178  BESDEBUG(HDF5_NAME, "DAS from the disk cache, attr type is: " << attr_type << endl);
2179 
2180  // Attribute values
2181  unsigned int num_values = *((unsigned int*)(temp_pointer));
2182  BESDEBUG(HDF5_NAME, "DAS from the disk cache, number of attribute values is: " << num_values << endl);
2183  temp_pointer+=sizeof(unsigned int);
2184 
2185  vector <string> attr_values;
2186 
2187  for(unsigned int i = 0; i<num_values; i++) {
2188  string attr_value;
2189  temp_pointer = obtain_str(temp_pointer,attr_value);
2190  attr_values.push_back(attr_value);
2191  BESDEBUG(HDF5_NAME, "DAS from the disk cache, attribute value is: " << attr_value << endl);
2192  }
2193 
2194  at_par->append_attr(attr_name,attr_type,&attr_values);
2195  }
2196 
2197  }
2198  return temp_pointer;
2199 
2200 }
2201 
2202 // The debugging function to get attribute info.
2203 void get_attr_contents(AttrTable*temp_table) {
2204  if(temp_table !=NULL) {
2205  AttrTable::Attr_iter top_startit = temp_table->attr_begin();
2206  AttrTable::Attr_iter top_endit = temp_table->attr_end();
2207  AttrTable::Attr_iter top_it = top_startit;
2208  while(top_it !=top_endit) {
2209  AttrType atype = temp_table->get_attr_type(top_it);
2210  if(atype == Attr_unknown)
2211  cerr<<"unsupported DAS attributes" <<endl;
2212  else if(atype!=Attr_container) {
2213 
2214  cerr<<"Attribute name is "<<temp_table->get_name(top_it)<<endl;
2215  cerr<<"Attribute type is "<<temp_table->get_type(top_it)<<endl;
2216  unsigned int num_attrs = temp_table->get_attr_num(temp_table->get_name(top_it));
2217  cerr<<"Attribute values are "<<endl;
2218  for (unsigned int i = 0; i <num_attrs;i++)
2219  cerr<<(*(temp_table->get_attr_vector(temp_table->get_name(top_it))))[i]<<" ";
2220  cerr<<endl;
2221  }
2222  else {
2223  cerr<<"Coming to the attribute container. "<<endl;
2224  cerr<<"container name is "<<(*top_it)->name <<endl;
2225  AttrTable* sub_table = temp_table->get_attr_table(top_it);
2226  cerr<<"container table name is "<<sub_table->get_name() <<endl;
2227  get_attr_contents(sub_table);
2228  }
2229  ++top_it;
2230  }
2231 
2232  }
2233 }
2234 
2235 
2236 void HDF5RequestHandler::add_attributes(BESDataHandlerInterface &dhi) {
2237 
2238 
2239  BESResponseObject *response = dhi.response_handler->get_response_object();
2240  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *>(response);
2241  if (!bdds)
2242  throw BESInternalError("cast error", __FILE__, __LINE__);
2243  DDS *dds = bdds->get_dds();
2244  string container_name = bdds->get_explicit_containers() ? dhi.container->get_symbolic_name(): "";
2245  string filename = dhi.container->access();
2246  DAS* das = 0;
2247  if (das_cache && (das = static_cast<DAS*>(das_cache->get(filename)))) {
2248  BESDEBUG(HDF5_NAME, "DAS Cached hit for : " << filename << endl);
2249  dds->transfer_attributes(das); // no need to cop the cached DAS
2250  }
2251  else {
2252  das = new DAS;
2253  // This looks at the 'use explicit containers' prop, and if true
2254  // sets the current container for the DAS.
2255  if (!container_name.empty()) das->container_name(container_name);
2256 
2257  hid_t h5_fd =-1;
2258  if (true == _usecf) {
2259  // go to the CF option
2260  h5_fd = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
2261 
2262  read_cfdas( *das,filename,h5_fd);
2263 
2264  H5Fclose(h5_fd);
2265  }
2266  else {
2267  h5_fd = get_fileid(filename.c_str());
2268  find_gloattr(h5_fd, *das);
2269  depth_first(h5_fd, "/", *das);
2270  close_fileid(h5_fd);
2271  }
2272 
2273 
2274  Ancillary::read_ancillary_das(*das, filename);
2275 
2276  dds->transfer_attributes(das);
2277 
2278  // Only free the DAS if it's not added to the cache
2279  if (das_cache) {
2280  // add a copy
2281  BESDEBUG(HDF5_NAME, "DAS added to the cache for : " << filename << endl);
2282  das_cache->add(das, filename);
2283  }
2284  else {
2285  delete das;
2286  }
2287  }
2288  BESDEBUG(HDF5_NAME, "Data ACCESS in add_attributes(): set the including attribute flag to true: "<<filename << endl);
2289  bdds->set_ia_flag(true);
2290  return;
2291 
2292 
2293 }
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
BESServiceRegistry::services_handled
virtual void services_handled(const std::string &handler, std::list< std::string > &services)
returns the list of servies provided by the handler in question
Definition: BESServiceRegistry.cc:334
breadth_first
bool breadth_first(hid_t pid, char *gname, D4Group *par_grp, const char *fname, bool use_dimscale)
Definition: h5dmr.cc:318
BESDapResponse::set_dap4_constraint
virtual void set_dap4_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
Definition: BESDapResponse.cc:137
BESDDSResponse::set_container
virtual void set_container(const std::string &cn)
set the container in the DAP response object
Definition: BESDDSResponse.cc:64
BESInternalFatalError
exception thrown if an internal error is found and is fatal to the BES
Definition: BESInternalFatalError.h:43
ObjMemCache
An in-memory cache for DapObj (DAS, DDS, ...) objects.
Definition: ObjMemCache.h:84
BESDataDDSResponse::set_container
virtual void set_container(const std::string &cn)
set the container in the DAP response object
Definition: BESDataDDSResponse.cc:50
close_fileid
void close_fileid(hid_t fid)
Definition: h5get.cc:414
BESDapResponse::set_dap4_function
virtual void set_dap4_function(BESDataHandlerInterface &dhi)
set the constraint depending on the context
Definition: BESDapResponse.cc:154
BESDataDDSResponse::set_dds
void set_dds(libdap::DDS *ddsIn)
Definition: BESDataDDSResponse.h:73
BESDDSResponse::set_dds
void set_dds(libdap::DDS *ddsIn)
Definition: BESDDSResponse.h:71
BESContainer::get_symbolic_name
std::string get_symbolic_name() const
retrieve the symbolic name for this container
Definition: BESContainer.h:221
BESDDSResponse::clear_container
virtual void clear_container()
clear the container in the DAP response object
Definition: BESDDSResponse.cc:73
BESDDSResponse::get_dds
libdap::DDS * get_dds()
Definition: BESDDSResponse.h:80
BESDASResponse
Represents an OPeNDAP DAS DAP2 data object within the BES.
Definition: BESDASResponse.h:44
get_fileid
hid_t get_fileid(const char *filename)
Definition: h5get.cc:392
HDF5DDS
Definition: HDF5_DDS.h:37
BESInfo
informational response object
Definition: BESInfo.h:63
ObjMemCache::add
virtual void add(libdap::DapObj *obj, const std::string &key)
Add an object to the cache and associate it with a key.
Definition: ObjMemCache.cc:63
find_gloattr
void find_gloattr(hid_t file, DAS &das)
Definition: h5das.cc:482
BESDASResponse::set_container
virtual void set_container(const std::string &cn)
set the container in the DAP response object
Definition: BESDASResponse.cc:49
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
BESVersionInfo
Definition: BESVersionInfo.h:47
HDF5RequestHandler.h
include the entry functions to execute the handlers
BESContainer::access
virtual std::string access()=0
returns the true name of this container
BESDapResponse::get_explicit_containers
bool get_explicit_containers() const
Should containers be explicitly represented in the DD* responses?
Definition: BESDapResponse.h:70
BESDataDDSResponse::clear_container
virtual void clear_container()
clear the container in the DAP response object
Definition: BESDataDDSResponse.cc:59
BESInternalError
exception thrown if internal error encountered
Definition: BESInternalError.h:43
HDF5DMR
Definition: HDF5_DMR.h:40
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
BESInfo::add_data
virtual void add_data(const std::string &s)
add data to this informational object. If buffering is not set then the information is output directl...
Definition: BESInfo.cc:160
BESDASResponse::clear_container
virtual void clear_container()
clear the container in the DAP response object
Definition: BESDASResponse.cc:58
h5cfdaputil.h
Helper functions for generating DAS attributes and a function to check BES Key.
BESDapResponse::set_constraint
virtual void set_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
Definition: BESDapResponse.cc:115
BESDataDDSResponse
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
Definition: BESDataDDSResponse.h:46
h5get.h
Error
BESUtil::lowercase
static std::string lowercase(const std::string &s)
Definition: BESUtil.cc:200
BESUtil::implode
static std::string implode(const std::list< std::string > &values, char delim)
Definition: BESUtil.cc:638
depth_first
void depth_first(hid_t pid, const char *gname, DAS &das)
Definition: h5das.cc:62
BESDapError
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:59
BESDataHandlerInterface
Structure storing information used by the BES to handle the request.
Definition: BESDataHandlerInterface.h:56
hdf5_handler.h
The main header of the HDF5 OPeNDAP handler.
BESResponseObject
Abstract base class representing a specific set of information in response to a request to the BES.
Definition: BESResponseObject.h:45
ObjMemCache::get
virtual libdap::DapObj * get(const std::string &key)
Get the cached pointer.
Definition: ObjMemCache.cc:105
BESDMRResponse
Represents an OPeNDAP DMR DAP4 data object within the BES.
Definition: BESDMRResponse.h:39