bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
HDF4RequestHandler.cc
1
2// -*- mode: c++; c-basic-offset:4 -*-
3
4// This file is part of hdf4_handler, a data handler for the OPeNDAP data
5// server.
6
7// Copyright (c) 2002,2003 OPeNDAP, Inc.
8// Author: James Gallagher <jgallagher@opendap.org>
9// Author: Kent Yang <myang6@opendap.org>
10// This is free software; you can redistribute it and/or modify it under the
11// terms of the GNU Lesser General Public License as published by the Free
12// Software Foundation; either version 2.1 of the License, or (at your
13// option) any later version.
14//
15// This software is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18// License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public
21// License along with this library; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23//
24// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25
26// HDF4RequestHandler.cc
27
28#include <cstdlib>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <cerrno>
33#include <unistd.h>
34#include <iostream>
35#include <sstream>
36
37#include <libdap/DMR.h>
38#include <libdap/D4BaseTypeFactory.h>
39#include <BESDMRResponse.h>
40#include <libdap/mime_util.h>
41#include <libdap/InternalErr.h>
42#include <libdap/Ancillary.h>
43#include <libdap/debug.h>
44
45#include "HDF4RequestHandler.h"
46#include <BESResponseNames.h>
47#include <BESDapNames.h>
48#include <BESDASResponse.h>
49#include <BESDDSResponse.h>
50#include <BESDataDDSResponse.h>
51#include <BESInfo.h>
52#include <BESResponseHandler.h>
53#include <BESVersionInfo.h>
54#include <BESServiceRegistry.h>
55#include <BESUtil.h>
56#include <TheBESKeys.h>
57#include <libdap/InternalErr.h>
58#include <BESInternalError.h>
59#include <BESDapError.h>
60#include <BESStopWatch.h>
61#include <BESDebug.h>
62#include "BESDataNames.h"
63#include <libdap/Ancillary.h>
64#include "config_hdf.h"
65
66#include "HE2CF.h"
67#include "HDF4_DDS.h"
68
69#include "HDF4_DMR.h"
70
71#include "HDFSPArray_RealField.h"
72
73#include "dodsutil.h"
74
75using namespace std;
76using namespace libdap;
77
78const string HDF4_NAME="h4";
79#define prolog std::string("HDF4RequestHandler::").append(__func__).append("() - ")
80
81bool check_beskeys(const string &);
82bool get_beskeys(const string &,string &);
83bool is_beskey_exist(const string &key);
84
85extern void read_das(DAS & das, const string & filename);
86extern void read_dds(DDS & dds, const string & filename);
87extern void read_dmr(DMR * dmr, const string & filename);
88
89extern bool read_dds_hdfsp(DDS & dds, const string & filename,int32 sdfd, int32 fileid,HDFSP::File*h4file);
90
91extern bool read_das_hdfsp(DAS & das, const string & filename,int32 sdfd, int32 fileid,HDFSP::File**h4fileptr);
92
93extern void read_das_sds(DAS & das, const string & filename,int32 sdfd, bool ecs_metadata,HDFSP::File**h4fileptr);
94extern void read_dds_sds(DDS &dds, const string & filename,int32 sdfd, HDFSP::File*h4file,bool dds_set_cache);
95
96#ifdef USE_HDFEOS2_LIB
97
98void read_das_use_eos2lib(DAS & das, const string & filename,int32 sdfd,int32 fileid, int32 gridfd, int32 swathfd,bool ecs_metadata,HDFSP::File**h4file,HDFEOS2::File**eosfile);
99void read_dds_use_eos2lib(DDS & dds, const string & filename,int32 sdfd,int32 fileid, int32 gridfd, int32 swathfd,HDFSP::File*h4file,HDFEOS2::File*eosfile);
100void close_fileid(const int sdfd, const int fileid,const int gridfd, const int swathfd,HDFSP::File*h4file,HDFEOS2::File*eosfile);
101
102#endif
103
104void close_hdf4_fileid(const int sdfd,const int fileid,HDFSP::File*h4file);
105bool rw_das_cache_file(const string & filename, DAS *das_ptr,bool rw_flag);
106bool r_dds_cache_file(const string & cache_filename, DDS *dds_ptr,const string & hdf4_filename);
107
108bool HDF4RequestHandler::_direct_dmr = false;
109
110// CF key
111bool HDF4RequestHandler::_usecf = false;
112
113// Keys to tune the performance -general
114bool HDF4RequestHandler::_pass_fileid = false;
115bool HDF4RequestHandler::_disable_structmeta = false;
116bool HDF4RequestHandler::_enable_special_eos = false;
117bool HDF4RequestHandler::_disable_scaleoffset_comp = false;
118bool HDF4RequestHandler::_disable_ecsmetadata_min = false;
119bool HDF4RequestHandler::_disable_ecsmetadata_all = false;
120
121
122// Keys to tune the performance - cache
123bool HDF4RequestHandler::_enable_eosgeo_cachefile = false;
124bool HDF4RequestHandler::_enable_data_cachefile = false;
125bool HDF4RequestHandler::_enable_metadata_cachefile= false;
126
127// Keys to handle vdata and vgroups
128bool HDF4RequestHandler::_enable_hybrid_vdata = false;
129bool HDF4RequestHandler::_enable_ceres_vdata = false;
130bool HDF4RequestHandler::_enable_vdata_attr = false;
131bool HDF4RequestHandler::_enable_vdata_desc_attr = false;
132bool HDF4RequestHandler::_disable_vdata_nameclashing_check = false;
133bool HDF4RequestHandler::_enable_vgroup_attr = false;
134
135// Misc. keys
136bool HDF4RequestHandler::_enable_check_modis_geo_file = false;
137bool HDF4RequestHandler::_enable_swath_grid_attr = false;
138bool HDF4RequestHandler::_enable_ceres_merra_short_name = false;
139bool HDF4RequestHandler::_enable_check_scale_offset_type = false;
140bool HDF4RequestHandler::_disable_swath_dim_map = false;
141
142// Cache path,prefix and size
143bool HDF4RequestHandler::_cache_latlon_path_exist =false;
144string HDF4RequestHandler::_cache_latlon_path ="";
145bool HDF4RequestHandler::_cache_latlon_prefix_exist =false;
146string HDF4RequestHandler::_cache_latlon_prefix ="";
147bool HDF4RequestHandler::_cache_latlon_size_exist =false;
148long HDF4RequestHandler::_cache_latlon_size =0;
149bool HDF4RequestHandler::_cache_metadata_path_exist =false;
150string HDF4RequestHandler::_cache_metadata_path ="";
151
152HDF4RequestHandler::HDF4RequestHandler(const string & name) :
153 BESRequestHandler(name) {
154
155 BESRequestHandler::add_method(DAS_RESPONSE, HDF4RequestHandler::hdf4_build_das);
156 BESRequestHandler::add_method(DDS_RESPONSE, HDF4RequestHandler::hdf4_build_dds);
157 BESRequestHandler::add_method(DATA_RESPONSE, HDF4RequestHandler::hdf4_build_data);
158 BESRequestHandler::add_method(DMR_RESPONSE, HDF4RequestHandler::hdf4_build_dmr);
159 BESRequestHandler::add_method(DAP4DATA_RESPONSE, HDF4RequestHandler::hdf4_build_dmr);
160 BESRequestHandler::add_method(HELP_RESPONSE, HDF4RequestHandler::hdf4_build_help);
161 BESRequestHandler::add_method(VERS_RESPONSE, HDF4RequestHandler::hdf4_build_version);
162
163 if (true == is_beskey_exist("H4.EnableDirectDMR"))
164 _direct_dmr=check_beskeys("H4.EnableDirectDMR");
165 _usecf = check_beskeys("H4.EnableCF");
166
167 // The following keys are only effective when usecf is true.
168 // Keys to tune the performance -general
169 _pass_fileid = check_beskeys("H4.EnablePassFileID");
170 _disable_structmeta = check_beskeys("H4.DisableStructMetaAttr");
171 _enable_special_eos = check_beskeys("H4.EnableSpecialEOS");
172 _disable_scaleoffset_comp = check_beskeys("H4.DisableScaleOffsetComp");
173 _disable_ecsmetadata_min = check_beskeys("H4.DisableECSMetaDataMin");
174 _disable_ecsmetadata_all = check_beskeys("H4.DisableECSMetaDataAll");
175
176 // Keys to tune the performance - cache
177 _enable_eosgeo_cachefile = check_beskeys("H4.EnableEOSGeoCacheFile");
178 _enable_data_cachefile = check_beskeys("H4.EnableDataCacheFile");
179 _enable_metadata_cachefile = check_beskeys("H4.EnableMetaDataCacheFile");
180
181 // Keys to handle vdata and vgroups
182 _enable_hybrid_vdata = check_beskeys("H4.EnableHybridVdata");
183 _enable_ceres_vdata = check_beskeys("H4.EnableCERESVdata");
184 _enable_vdata_attr = check_beskeys("H4.EnableVdata_to_Attr");
185 _enable_vdata_desc_attr = check_beskeys("H4.EnableVdataDescAttr");
186 _disable_vdata_nameclashing_check = check_beskeys("H4.DisableVdataNameclashingCheck");
187 _enable_vgroup_attr = check_beskeys("H4.EnableVgroupAttr");
188
189 // Misc. keys
190 _enable_check_modis_geo_file = check_beskeys("H4.EnableCheckMODISGeoFile");
191 _enable_swath_grid_attr = check_beskeys("H4.EnableSwathGridAttr");
192 _enable_ceres_merra_short_name = check_beskeys("H4.EnableCERESMERRAShortName");
193 _enable_check_scale_offset_type = check_beskeys("H4.EnableCheckScaleOffsetType");
194
195 _disable_swath_dim_map = check_beskeys("H4.DisableSwathDimMap");
196
197 // Cache path etc.
198 _cache_latlon_path_exist =get_beskeys("HDF4.Cache.latlon.path",_cache_latlon_path);
199 _cache_latlon_prefix_exist =get_beskeys("HDF4.Cache.latlon.prefix",_cache_latlon_prefix);
200 string temp_cache_latlon_size;
201 _cache_latlon_size_exist =get_beskeys("HDF4.Cache.latlon.size",temp_cache_latlon_size);
202 if (_cache_latlon_size_exist == true) {
203 istringstream iss(temp_cache_latlon_size);
204 iss >> _cache_latlon_size;
205 }
206
207 _cache_metadata_path_exist =get_beskeys("H4.Cache.metadata.path",_cache_metadata_path);
208
209}
210
211bool HDF4RequestHandler::hdf4_build_das(BESDataHandlerInterface & dhi) {
212
213
214 BES_STOPWATCH_START_DHI(HDF4_NAME, prolog + "Timer", &dhi);
215
216 if (true == _usecf) {
217
218 // We first check if we can optimize the access of some special NASA HDF4 files.
219 // Build the DAP response only based on the HDF4 SD interfaces. Doing this
220 // way will save the use of other library open calls. Other library open
221 // calls may be expensive
222 // for an HDF4 file that only has variables created by SD interfaces.
223 // This optimization may be very useful for the aggreagation case that
224 // has many variables.
225 // Currently we only handle AIRS version 6 products. AIRS products
226 // are identified by their file names.
227 // We only obtain the filename. The path is stripped off.
228
229 string base_file_name = basename(dhi.container->access());
230
231 //AIRS.2015.01.24.L3.RetStd_IR008.v6.0.11.0.G15041143400.hdf
232 // Identify this file from product name: AIRS, product level: .L3. or .L2. and version .v6.
233 if ((base_file_name.size() >12) && (base_file_name.compare(0,4,"AIRS") == 0)
234 && ((base_file_name.find(".L3.")!=string::npos) || (base_file_name.find(".L2.")!=string::npos))
235 && (base_file_name.find(".v6.")!=string::npos)) {
236 return hdf4_build_das_cf_sds(dhi);
237 }
238 }
239
240 BESResponseObject *response = dhi.response_handler->get_response_object();
241 auto bdas = dynamic_cast<BESDASResponse *> (response);
242 if (!bdas)
243 throw BESInternalError("cast error", __FILE__, __LINE__);
244
245 try {
246 bdas->set_container(dhi.container->get_symbolic_name());
247 DAS *das = bdas->get_das();
248
249 string base_file_name = basename(dhi.container->access());
250
251 string accessed = dhi.container->access();
252
253 if (true == _usecf) {
254
255 int32 sdfd = -1;
256 int32 fileid = -1;
257
258 HDFSP::File *h4file = nullptr;
259
260 // Obtain HDF4 file IDs
261 // SDstart
262 sdfd = SDstart (accessed.c_str(), DFACC_READ);
263 if ( -1 == sdfd){
264 string invalid_file_msg="HDF4 SDstart error for the file ";
265 invalid_file_msg +=accessed;
266 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
267 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
268 }
269
270 // Hopen
271 fileid = Hopen(accessed.c_str(), DFACC_READ,0);
272 if (-1 == fileid) {
273 SDend(sdfd);
274 string invalid_file_msg="HDF4 Hopen error for the file ";
275 invalid_file_msg +=accessed;
276 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
277 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
278 }
279
280#ifdef USE_HDFEOS2_LIB
281
282 int32 gridfd = -1;
283 int32 swathfd = -1;
284
285 HDFEOS2::File *eosfile = nullptr;
286
287 // Obtain HDF-EOS2 file IDs with the file open APIs.
288 // Grid open
289 gridfd = GDopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
290 if (-1 == gridfd) {
291 SDend(sdfd);
292 Hclose(fileid);
293 string invalid_file_msg="HDF-EOS GDopen error for the file ";
294 invalid_file_msg +=accessed;
295 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
296 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
297 }
298
299 // Swath open
300 swathfd = SWopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
301 if (-1 == swathfd) {
302 SDend(sdfd);
303 Hclose(fileid);
304 GDclose(gridfd);
305 string invalid_file_msg="HDF-EOS SWopen error for the file ";
306 invalid_file_msg +=accessed;
307 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
308 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
309 }
310
311 try {
312 bool ecs_metadata = !_disable_ecsmetadata_all;
313 read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
314 }
315 catch(...) {
316 close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
317 throw;
318 }
319 if (eosfile != nullptr)
320 delete eosfile;
321 GDclose(gridfd);
322 SWclose(swathfd);
323
324#else
325 try {
326 read_das_hdfsp(*das,accessed,sdfd,fileid,&h4file);
327 }
328 catch(...) {
329 close_hdf4_fileid(sdfd,fileid,h4file);
330 throw;
331 //throw InternalErr(__FILE__,__LINE__,"read_das_hdfsp error");
332 }
333#endif
334 close_hdf4_fileid(sdfd,fileid,h4file);
335 }
336 else
337 read_das(*das,accessed);
338
339 Ancillary::read_ancillary_das(*das, accessed);
340 bdas->clear_container();
341 }
342
343 catch (BESError & e) {
344 throw BESError(e.what(), e.get_bes_error_type(),
345 __FILE__, __LINE__);
346 }
347 catch (InternalErr & e) {
348 throw BESDapError(e.get_error_message(), true, e.get_error_code(),
349 __FILE__, __LINE__);
350 }
351 catch (Error & e) {
352 throw BESDapError(e.get_error_message(), false, e.get_error_code(),
353 __FILE__, __LINE__);
354 }
355 catch (...) {
356 string s = "unknown exception caught building HDF4 DAS";
357 throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
358 }
359
360 return true;
361}
362
363bool HDF4RequestHandler::hdf4_build_dds(BESDataHandlerInterface & dhi) {
364
365 BES_STOPWATCH_START_DHI(HDF4_NAME, prolog + "Timer", &dhi);
366
367 if (true == _usecf) {
368
369 // We first check if we can optimize the access of some special NASA HDF4 files.
370 // Try to build the DAP response only based on the HDF4 SD interfaces. Doing this
371 // way will save the use of other library open calls. Other library open
372 // calls may be expensive
373 // for an HDF4 file that only has variables created by SD interfaces.
374 // This optimization may be very useful for the aggreagation case that
375 // has many variables.
376 // Currently we only handle AIRS version 6 products. AIRS products
377 // are identified by their file names.
378 // We only obtain the filename. The path is stripped off.
379
380 string base_file_name = basename(dhi.container->access());
381
382 //AIRS.2015.01.24.L3.RetStd_IR008.v6.0.11.0.G15041143400.hdf
383 // Identify this file from product name: AIRS, product level: .L3. or .L2. and version .v6.
384 if ((base_file_name.size() >12) && (base_file_name.compare(0,4,"AIRS") == 0)
385 && ((base_file_name.find(".L3.")!=string::npos) || (base_file_name.find(".L2.")!=string::npos))
386 && (base_file_name.find(".v6.")!=string::npos)) {
387 return hdf4_build_dds_cf_sds(dhi);
388 }
389 }
390
391// This is for the performance check. Leave it now for future use. KY 2014-10-23
392#if 0
393struct timeval start_time,end_time;
394gettimeofday(&start_time,nullptr);
395#endif
396
397 BESResponseObject *response = dhi.response_handler->get_response_object();
398 auto bdds = dynamic_cast<BESDDSResponse *> (response);
399 if (!bdds)
400 throw BESInternalError("cast error", __FILE__, __LINE__);
401
402 try {
403
404 bdds->set_container(dhi.container->get_symbolic_name());
405 DDS *dds = bdds->get_dds();
406 string accessed = dhi.container->access();
407 dds->filename(accessed);
408
409 auto das = new DAS;
410 BESDASResponse bdas(das);
411 bdas.set_container(dhi.container->get_symbolic_name());
412
413 if (true == _usecf) {
414
415 int32 sdfd = -1;
416 int32 fileid = -1;
417 HDFSP::File *h4file = nullptr;
418
419 // Obtain HDF4 file IDs
420 //SDstart
421 sdfd = SDstart (accessed.c_str(), DFACC_READ);
422 if( -1 == sdfd){
423 string invalid_file_msg="HDF4 SDstart error for the file ";
424 invalid_file_msg +=accessed;
425 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
426 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
427 }
428
429 // Hopen
430 fileid = Hopen(accessed.c_str(), DFACC_READ,0);
431 if (-1 == fileid) {
432 SDend(sdfd);
433 string invalid_file_msg="HDF4 Hopen error for the file ";
434 invalid_file_msg +=accessed;
435 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
436 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
437 }
438
439#ifdef USE_HDFEOS2_LIB
440
441 int32 gridfd = -1;
442 int32 swathfd = -1;
443
444 HDFEOS2::File *eosfile = nullptr;
445
446 // Obtain HDF-EOS2 file IDs with the file open APIs.
447 // Grid open
448 gridfd = GDopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
449 if (-1 == gridfd) {
450 SDend(sdfd);
451 Hclose(fileid);
452 string invalid_file_msg="HDF-EOS GDopen error for the file ";
453 invalid_file_msg +=accessed;
454 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
455 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
456 }
457
458 // Swath open
459 swathfd = SWopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
460 if (-1 == swathfd) {
461 SDend(sdfd);
462 Hclose(fileid);
463 GDclose(gridfd);
464 string invalid_file_msg="HDF-EOS SWopen error for the file ";
465 invalid_file_msg +=accessed;
466 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
467 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
468 }
469
470 try {
471 bool ecs_metadata = !_disable_ecsmetadata_all;
472 read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
473 Ancillary::read_ancillary_das(*das, accessed);
474
475 // Pass file pointer(h4file, eosfile) from DAS to DDS.
476 read_dds_use_eos2lib(*dds, accessed,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
477 }
478 catch(...) {
479 close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
480 throw;
481 }
482
483 if(eosfile != nullptr)
484 delete eosfile;
485
486 GDclose(gridfd);
487 SWclose(swathfd);
488
489#else
490 try {
491 read_das_hdfsp(*das, accessed,sdfd,fileid,&h4file);
492 Ancillary::read_ancillary_das(*das, accessed);
493
494 // Pass file pointer(h4file) from DAS to DDS.
495 read_dds_hdfsp(*dds, accessed,sdfd,fileid,h4file);
496 }
497 catch(...) {
498 close_hdf4_fileid(sdfd,fileid,h4file);
499 throw;
500 }
501
502#endif
503 close_hdf4_fileid(sdfd,fileid,h4file);
504 }
505 else {
506 read_das(*das, accessed);
507 Ancillary::read_ancillary_das(*das, accessed);
508 read_dds(*dds, accessed);
509 }
510
511// Leave it for future performance tests. KY 2014-10-23
512#if 0
513gettimeofday(&end_time,nullptr);
514int total_time_spent = (end_time.tv_sec - start_time.tv_sec)*1000000 +end_time.tv_usec-start_time.tv_usec;
515cerr<<"total time spent for DDS buld is "<<total_time_spent<< "micro seconds "<<endl;
516#endif
517
518 Ancillary::read_ancillary_dds(*dds, accessed);
519
520 dds->transfer_attributes(das);
521
522 bdds->set_constraint(dhi);
523
524 bdds->clear_container();
525 }
526 catch (BESError & e) {
527 throw BESError(e.what(), e.get_bes_error_type(),
528 __FILE__, __LINE__);
529 }
530 catch (InternalErr & e) {
531 throw BESDapError(e.get_error_message(), true, e.get_error_code(),
532 __FILE__, __LINE__);
533 }
534 catch (Error & e) {
535 throw BESDapError(e.get_error_message(), false, e.get_error_code(),
536 __FILE__, __LINE__);
537 }
538 catch (...) {
539 string s = "unknown exception caught building HDF4 DDS";
540 throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
541 }
542
543 return true;
544}
545
546bool HDF4RequestHandler::hdf4_build_data(BESDataHandlerInterface & dhi) {
547
548 BES_STOPWATCH_START_DHI(HDF4_NAME, prolog + "Timer", &dhi);
549
550
551 int32 sdfd = -1;
552 int32 fileid = -1;
553
554 // Since passing file IDs requires to use the derived class and it
555 // causes the management of code structure messy, we first handle this with
556 // another method.
557 if (true == _usecf) {
558
559 // We first check if we can optimize the access of some special NASA HDF4 files.
560 // Build the DAP response only based on the HDF4 SD interfaces. Doing this
561 // way will save the use of other library open calls. Other library open
562 // calls may be expensive
563 // for an HDF4 file that only has variables created by SD interfaces.
564 // This optimization may be very useful for the aggreagation case that
565 // has many variables.
566 // Currently we only handle AIRS version 6 products. AIRS products
567 // are identified by their file names.
568 // We only obtain the filename. The path is stripped off.
569
570 string base_file_name = basename(dhi.container->access());
571 //AIRS.2015.01.24.L3.RetStd_IR008.v6.0.11.0.G15041143400.hdf
572 // Identify this file from product name: AIRS, product level: .L3. or .L2. and version .v6.
573 if ((base_file_name.size() >12) && (base_file_name.compare(0,4,"AIRS") == 0)
574 && ((base_file_name.find(".L3.")!=string::npos) || (base_file_name.find(".L2.")!=string::npos))
575 && (base_file_name.find(".v6.")!=string::npos)) {
576
577 BESDEBUG("h4", "Coming to read the data of AIRS level 3 or level 2 products." << endl);
578
579 if (true == _pass_fileid)
580 return hdf4_build_data_cf_sds_with_IDs(dhi);
581 else
582 return hdf4_build_data_cf_sds(dhi);
583
584 }
585
586 if (true == _pass_fileid)
587 return hdf4_build_data_with_IDs(dhi);
588
589 }
590
591 BESResponseObject *response = dhi.response_handler->get_response_object();
592 auto bdds = dynamic_cast<BESDataDDSResponse *> (response);
593
594 if (!bdds)
595 throw BESInternalError("cast error", __FILE__, __LINE__);
596
597 try {
598 bdds->set_container(dhi.container->get_symbolic_name());
599
600 DDS *dds = bdds->get_dds();
601
602 string accessed = dhi.container->access();
603 dds->filename(accessed);
604
605 auto das = new DAS;
606 BESDASResponse bdas(das);
607 bdas.set_container(dhi.container->get_symbolic_name());
608
609 if (true == _usecf) {
610
611 HDFSP::File *h4file = nullptr;
612
613 // Obtain HDF4 file IDs
614 //SDstart
615 sdfd = SDstart (accessed.c_str(), DFACC_READ);
616 if( -1 == sdfd) {
617 string invalid_file_msg="HDF4 SDstart error for the file ";
618 invalid_file_msg +=accessed;
619 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
620 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
621 }
622
623 // Hopen
624 fileid = Hopen(accessed.c_str(), DFACC_READ,0);
625 if (-1 == fileid) {
626 SDend(sdfd);
627 string invalid_file_msg="HDF4 Hopen error for the file ";
628 invalid_file_msg +=accessed;
629 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
630 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
631 }
632
633
634#ifdef USE_HDFEOS2_LIB
635
636 int32 gridfd = -1;
637 int32 swathfd = -1;
638 HDFEOS2::File *eosfile = nullptr;
639
640 // Obtain HDF-EOS2 file IDs with the file open APIs.
641
642 // Grid open
643 gridfd = GDopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
644 if (-1 == gridfd) {
645 SDend(sdfd);
646 Hclose(fileid);
647 string invalid_file_msg="HDF-EOS GDopen error for the file ";
648 invalid_file_msg +=accessed;
649 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
650 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
651 }
652
653 // Swath open
654 swathfd = SWopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
655 if (-1 == swathfd) {
656 SDend(sdfd);
657 Hclose(fileid);
658 GDclose(gridfd);
659 string invalid_file_msg="HDF-EOS SWopen error for the file ";
660 invalid_file_msg +=accessed;
661 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
662 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
663
664 }
665
666 try {
667
668 // Here we will check if ECS_Metadata key if set. For DataDDS,
669 // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
670 // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
671 bool ecs_metadata = true;
672 if ((true == _disable_ecsmetadata_min)
673 || (true == _disable_ecsmetadata_all))
674 ecs_metadata = false;
675
676 read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
677 Ancillary::read_ancillary_das(*das, accessed);
678
679 // Pass file pointer(h4file, eosfile) from DAS to DDS.
680 read_dds_use_eos2lib(*dds, accessed,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
681 }
682 catch(...) {
683 close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
684 throw;
685 }
686
687 if(eosfile != nullptr)
688 delete eosfile;
689 GDclose(gridfd);
690 SWclose(swathfd);
691
692#else
693 try {
694 read_das_hdfsp(*das, accessed,sdfd,fileid,&h4file);
695 Ancillary::read_ancillary_das(*das, accessed);
696
697 // Pass file pointer(h4file) from DAS to DDS.
698 read_dds_hdfsp(*dds, accessed,sdfd,fileid,h4file);
699 }
700 catch(...) {
701 close_hdf4_fileid(sdfd,fileid,h4file);
702 throw;
703 }
704#endif
705 close_hdf4_fileid(sdfd,fileid,h4file);
706 }
707 else {
708 read_das(*das, accessed);
709 Ancillary::read_ancillary_das(*das, accessed);
710 read_dds(*dds, accessed);
711 }
712
713 Ancillary::read_ancillary_dds(*dds, accessed);
714 dds->transfer_attributes(das);
715 bdds->set_constraint(dhi);
716 bdds->clear_container();
717
718 }
719
720 catch (BESError & e) {
721 throw BESError(e.what(), e.get_bes_error_type(),
722 __FILE__, __LINE__);
723 }
724 catch (InternalErr & e) {
725 throw BESDapError(e.get_error_message(), true, e.get_error_code(),
726 __FILE__, __LINE__);
727 }
728 catch (Error & e) {
729 throw BESDapError(e.get_error_message(), false, e.get_error_code(),
730 __FILE__, __LINE__);
731 }
732 catch (...) {
733 string s = "unknown exception caught building DAP2 Data Response from an HDF4 data resource";
734 throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
735 }
736
737 return true;
738}
739
740bool HDF4RequestHandler::hdf4_build_data_with_IDs(BESDataHandlerInterface & dhi) {
741
742 BES_STOPWATCH_START_DHI(HDF4_NAME, prolog + "Timer", &dhi);
743
744 int32 sdfd = -1;
745 int32 fileid = -1;
746 HDFSP::File *h4file = nullptr;
747#ifdef USE_HDFEOS2_LIB
748 int32 gridfd = -1;
749 int32 swathfd = -1;
750 HDFEOS2::File *eosfile = nullptr;
751#endif
752
753 BESResponseObject *response = dhi.response_handler->get_response_object();
754 auto bdds = dynamic_cast<BESDataDDSResponse *> (response);
755
756 if (!bdds)
757 throw BESInternalError("cast error", __FILE__, __LINE__);
758
759 try {
760 bdds->set_container(dhi.container->get_symbolic_name());
761
762 // Create a new HDF4DDS object.
763 auto hdds = new HDF4DDS(bdds->get_dds());
764
765 // delete the old object.
766 delete bdds->get_dds();
767
768 bdds->set_dds(hdds);
769
770 string accessed = dhi.container->access();
771 hdds->filename(accessed);
772
773 auto das = new DAS;
774 BESDASResponse bdas(das);
775 bdas.set_container(dhi.container->get_symbolic_name());
776
777 // Obtain HDF4 file IDs
778 //SDstart
779 sdfd = SDstart (accessed.c_str(), DFACC_READ);
780 if ( -1 == sdfd) {
781 string invalid_file_msg="HDF4 SDstart error for the file ";
782 invalid_file_msg +=accessed;
783 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
784 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
785 }
786
787 // Hopen
788 fileid = Hopen(accessed.c_str(), DFACC_READ,0);
789 if (-1 == fileid) {
790 SDend(sdfd);
791 string invalid_file_msg="HDF4 Hopen error for the file ";
792 invalid_file_msg +=accessed;
793 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
794 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
795 }
796
797#ifdef USE_HDFEOS2_LIB
798
799 // Obtain HDF-EOS2 file IDs with the file open APIs.
800
801 // Grid open
802 gridfd = GDopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
803 if (-1 == gridfd) {
804 SDend(sdfd);
805 Hclose(fileid);
806 string invalid_file_msg="HDF-EOS GDopen error for the file ";
807 invalid_file_msg +=accessed;
808 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
809 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
810 }
811
812 // Swath open
813 swathfd = SWopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
814 if (-1 == swathfd) {
815 SDend(sdfd);
816 Hclose(fileid);
817 GDclose(gridfd);
818 string invalid_file_msg="HDF-EOS SWopen error for the file ";
819 invalid_file_msg +=accessed;
820 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
821 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
822 }
823
824 hdds->setHDF4Dataset(sdfd,fileid,gridfd,swathfd);
825
826 // Here we will check if ECS_Metadata key if set. For DataDDS,
827 // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
828 // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
829 bool ecs_metadata = true;
830 if ((true == _disable_ecsmetadata_min)
831 || (true == _disable_ecsmetadata_all))
832 ecs_metadata = false;
833
834 read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
835
836 Ancillary::read_ancillary_das(*das, accessed);
837
838 // Pass file pointer(h4file, eosfile) from DAS to DDS.
839 read_dds_use_eos2lib(*hdds, accessed,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
840
841 if(eosfile != nullptr)
842 delete eosfile;
843
844#else
845 hdds->setHDF4Dataset(sdfd,fileid);
846 read_das_hdfsp(*das, accessed,sdfd,fileid,&h4file);
847 Ancillary::read_ancillary_das(*das, accessed);
848
849 // Pass file pointer(h4file) from DAS to DDS.
850 read_dds_hdfsp(*hdds, accessed,sdfd,fileid,h4file);
851#endif
852 if(h4file != nullptr)
853 delete h4file;
854
855 Ancillary::read_ancillary_dds(*hdds, accessed);
856
857 hdds->transfer_attributes(das);
858
859 bdds->set_constraint(dhi);
860
861 bdds->clear_container();
862
863 }
864
865 catch (InternalErr & e) {
866 throw BESDapError(e.get_error_message(), true, e.get_error_code(),
867 __FILE__, __LINE__);
868 }
869 catch (Error & e) {
870 throw BESDapError(e.get_error_message(), false, e.get_error_code(),
871 __FILE__, __LINE__);
872 }
873 catch (...) {
874#ifdef USE_HDFEOS2_LIB
875 close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
876#else
877 close_hdf4_fileid(sdfd,fileid,h4file);
878#endif
879 string s = "unknown exception caught building DAP2 data response from an HDF4 data resource";
880 throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
881 }
882
883 // Note: HDF4 file IDs are closed by the HDF4_DDS derived class.
884 // See the #if 0 #endif block of the method hdf4_build_dmr_with_IDs for the IDs.
885
886 return true;
887}
888
889// Special function to build DDS for HDF4 SDS-only DDS. One can turn
890// on cache for this function. Currently only AIRS version 6 is supported.
891bool HDF4RequestHandler::hdf4_build_dds_cf_sds(BESDataHandlerInterface &dhi){
892
893 int32 sdfd = -1;
894 HDFSP::File *h4file = nullptr;
895
896 BESResponseObject *response = dhi.response_handler->get_response_object();
897 auto bdds = dynamic_cast<BESDDSResponse *> (response);
898
899 if (!bdds)
900 throw BESInternalError("cast error", __FILE__, __LINE__);
901
902 try {
903 bdds->set_container(dhi.container->get_symbolic_name());
904
905 DDS *dds = bdds->get_dds();
906
907 string accessed = dhi.container->access();
908 dds->filename(accessed);
909
910 auto das = new DAS;
911 BESDASResponse bdas(das);
912
913 // Check and set up dds and das cache files.
914 string base_file_name = basename(dhi.container->access());
915 bool das_set_cache = false;
916 bool dds_set_cache = false;
917 bool dds_das_get_cache = false;
918 string das_filename;
919 string dds_filename;
920
921 // Check if the EnableMetaData key is set.
922
923 if(true == _enable_metadata_cachefile) {// the EnableMetaData key is set
924
925 if(true == _cache_metadata_path_exist) {// the metadata.path key is set
926
927 // Create DAS and DDS cache file names
928 das_filename = _cache_metadata_path + "/" + base_file_name +"_das";
929 dds_filename = _cache_metadata_path + "/" + base_file_name +"_dds";
930
931 // When the returned value das_set_cache is false, read DAS from the cache file.
932 // Otherwise, do nothing.
933 das_set_cache = rw_das_cache_file(das_filename,das,false);
934
935 // When the returned value dds_set_cache is false, read DDS from the cache file.
936 // Otherwise, do nothing.
937 dds_set_cache = r_dds_cache_file(dds_filename,dds,accessed);
938
939 // Set the flag to obtain DDS and DAS from the cache files.
940 // Here, we require that both DDS and DAS should be cached.
941 // We don't support caching one and not caching another.
942 if((false == das_set_cache)&&(false == dds_set_cache))
943 dds_das_get_cache = true;
944 }
945 }
946
947 // We need to go back to retrieve DDS, DAS from the HDF file.
948 if(false == dds_das_get_cache) {
949
950 // Obtain SD ID, this is the only ID we need to use.
951 sdfd = SDstart (accessed.c_str(), DFACC_READ);
952 if( -1 == sdfd) {
953
954 string invalid_file_msg="HDF4 SDstart error for the file ";
955 invalid_file_msg +=accessed;
956 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
957 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
958 }
959
960 // Here we will check if ECS_Metadata key if set. For DDS and DAS,
961 // only when the DisableECSMetaDataAll key is set, ecs_metadata is off.
962 bool ecs_metadata = !_disable_ecsmetadata_all;
963
964 read_das_sds(*das, accessed,sdfd,ecs_metadata,&h4file);
965
966 Ancillary::read_ancillary_das(*das, accessed);
967
968 // Pass the file pointer(h4file) from DAS to DDS, also pass the flag
969 // dds_set_cache to indicate if the handler needs to cache DDS.
970 read_dds_sds(*dds, accessed,sdfd,h4file,dds_set_cache);
971
972 // We also need to cache DAS if das_set_cache is set.
973 if (true == das_set_cache) {
974 if (das_filename =="")
975 throw InternalErr(__FILE__,__LINE__,"DAS cache file name should be set ");
976 rw_das_cache_file(das_filename,das,true);
977 }
978 }
979
980 Ancillary::read_ancillary_dds(*dds, accessed);
981 dds->transfer_attributes(das);
982 bdds->set_constraint(dhi);
983
984 bdds->clear_container();
985
986 if(h4file != nullptr)
987 delete h4file;
988
989 if(sdfd != -1)
990 SDend(sdfd);
991
992 }
993
994 catch (BESError & e) {
995 throw BESError(e.what(), e.get_bes_error_type(),
996 __FILE__, __LINE__);
997 }
998 catch (InternalErr & e) {
999 throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1000 __FILE__, __LINE__);
1001 }
1002 catch (Error & e) {
1003 throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1004 __FILE__, __LINE__);
1005 }
1006 catch (...) {
1007 if(sdfd != -1)
1008 SDend(sdfd);
1009 if(h4file != nullptr)
1010 delete h4file;
1011 string s = "unknown exception caught building HDF4 DataDDS";
1012 throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
1013 }
1014
1015 return true;
1016}
1017
1018// Special function to build DAS for HDF4 SDS-only DDS. One can turn
1019// on cache for this function. Currently only AIRS version 6 is supported.
1020bool HDF4RequestHandler::hdf4_build_das_cf_sds(BESDataHandlerInterface &dhi){
1021
1022 int32 sdfd = -1;
1023 HDFSP::File *h4file = nullptr;
1024
1025 BESResponseObject *response = dhi.response_handler->get_response_object();
1026 auto bdas = dynamic_cast<BESDASResponse *> (response);
1027
1028 if (!bdas)
1029 throw BESInternalError("cast error", __FILE__, __LINE__);
1030
1031 try {
1032 bdas->set_container(dhi.container->get_symbolic_name());
1033
1034 auto das = bdas->get_das();
1035 string base_file_name = basename(dhi.container->access());
1036
1037 string accessed = dhi.container->access();
1038
1039 // Check if the enable metadata cache key is set and set the key appropriate.
1040 bool das_set_cache = false;
1041 bool das_get_cache = false;
1042 string das_filename;
1043 if (true == _enable_metadata_cachefile) { // find the metadata cache key.
1044 if (true == _cache_metadata_path_exist) {
1045
1046 // Create the DAS cache file name.
1047 das_filename = _cache_metadata_path + "/" + base_file_name +"_das";
1048
1049 // Read the DAS from the cached file, if das_set_cache is false.
1050 // When the das_set_cache is true, need to create a das cache file.
1051 das_set_cache = rw_das_cache_file(das_filename,das,false);
1052
1053 // Not set cache, must get the das from cache, so das_get_cache should be true.
1054 if (false == das_set_cache)
1055 das_get_cache = true;
1056 }
1057 }
1058
1059 // Need to retrieve DAS from the HDF4 file.
1060 if (false == das_get_cache) {
1061
1062 // Obtain SD ID.
1063 sdfd = SDstart (accessed.c_str(), DFACC_READ);
1064 if ( -1 == sdfd){
1065 string invalid_file_msg="HDF4 SDstart error for the file ";
1066 invalid_file_msg +=accessed;
1067 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
1068 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1069 }
1070
1071 // Here we will check if ECS_Metadata key if set. For DDS and DAS,
1072 // only when the DisableECSMetaDataAll key is set, ecs_metadata is off.
1073 bool ecs_metadata = !_disable_ecsmetadata_all;
1074
1075 read_das_sds(*das, accessed,sdfd,ecs_metadata,&h4file);
1076 Ancillary::read_ancillary_das(*das, accessed);
1077
1078 // Generate DAS cache file if the cache flag is set.
1079 if(true == das_set_cache)
1080 rw_das_cache_file(das_filename,das,true);
1081
1082 }
1083
1084 bdas->clear_container();
1085
1086 if(h4file != nullptr)
1087 delete h4file;
1088
1089 if(sdfd != -1)
1090 SDend(sdfd);
1091
1092 }
1093
1094 catch (BESError & e) {
1095 throw BESError(e.what(), e.get_bes_error_type(),
1096 __FILE__, __LINE__);
1097 }
1098 catch (InternalErr & e) {
1099 throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1100 __FILE__, __LINE__);
1101 }
1102 catch (Error & e) {
1103 throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1104 __FILE__, __LINE__);
1105 }
1106 catch (...) {
1107 if(sdfd != -1)
1108 SDend(sdfd);
1109 if(h4file != nullptr)
1110 delete h4file;
1111 string s = "unknown exception caught building HDF4 DataDDS";
1112 throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
1113 }
1114 return true;
1115}
1116
1117// Special function to build data for HDF4 SDS-only DDS. One can turn
1118// on cache for this function. Currently only AIRS version 6 is supported.
1119bool HDF4RequestHandler::hdf4_build_data_cf_sds(BESDataHandlerInterface &dhi){
1120
1121 int32 sdfd = -1;
1122 HDFSP::File *h4file = nullptr;
1123
1124 BESResponseObject *response = dhi.response_handler->get_response_object();
1125 auto bdds = dynamic_cast<BESDataDDSResponse *> (response);
1126
1127 if (!bdds)
1128 throw BESInternalError("cast error", __FILE__, __LINE__);
1129
1130 try {
1131 bdds->set_container(dhi.container->get_symbolic_name());
1132
1133 DDS *dds = bdds->get_dds();
1134
1135 string accessed = dhi.container->access();
1136 dds->filename(accessed);
1137
1138 auto das = new DAS;
1139 BESDASResponse bdas(das);
1140 bdas.set_container(dhi.container->get_symbolic_name());
1141
1142 string base_file_name = basename(dhi.container->access());
1143
1144 bool das_set_cache = false;
1145 bool dds_set_cache = false;
1146 bool dds_das_get_cache = false;
1147 string das_filename;
1148 string dds_filename;
1149
1150 if (true == _enable_metadata_cachefile) {
1151
1152 if (true == _cache_metadata_path_exist) {
1153 BESDEBUG("h4", "H4.Cache.metadata.path key is set and metadata cache key is set." << endl);
1154
1155 // Notice, since the DAS output may be different between DAS/DDS service and DataDDS service.
1156 // See comments about ecs_metadata below.
1157 // So we create a different DAS file. This can be optimized in the future if necessary.
1158 das_filename = _cache_metadata_path + "/" + base_file_name +"_das_dd";
1159 dds_filename = _cache_metadata_path + "/" + base_file_name +"_dds";
1160
1161 // If das_set_cache is true, data is read from the DAS cache.
1162 das_set_cache = rw_das_cache_file(das_filename,das,false);
1163
1164 // If dds_set_cache is true, data is read from the DDS cache.
1165 dds_set_cache = r_dds_cache_file(dds_filename,dds,accessed);
1166
1167 // Need to set a flag to generate DAS and DDS cache files
1168 if((false == das_set_cache)&&(false == dds_set_cache))
1169 dds_das_get_cache = true;
1170 }
1171 }
1172 if(false == dds_das_get_cache) {
1173
1174 // Obtain HDF4 SD ID
1175 sdfd = SDstart (accessed.c_str(), DFACC_READ);
1176 if( -1 == sdfd){
1177 string invalid_file_msg="HDF4 SDstart error for the file ";
1178 invalid_file_msg +=accessed;
1179 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
1180 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1181 }
1182
1183 // Here we will check if ECS_Metadata key if set. For DataDDS,
1184 // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
1185 // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
1186 bool ecs_metadata = true;
1187 if ((true == _disable_ecsmetadata_min)
1188 || (true == _disable_ecsmetadata_all))
1189 ecs_metadata = false;
1190
1191 read_das_sds(*das, accessed,sdfd,ecs_metadata,&h4file);
1192
1193 Ancillary::read_ancillary_das(*das, accessed);
1194
1195 // Need to write DAS to a cache file.
1196 if(true == das_set_cache) {
1197 rw_das_cache_file(das_filename,das,true);
1198 }
1199
1200 // Pass file pointer h4file from DAS to DDS. Also need to pass the
1201 // flag that indicates if a DDS file needs to be created.
1202 read_dds_sds(*dds, accessed,sdfd,h4file,dds_set_cache);
1203
1204 }
1205
1206 Ancillary::read_ancillary_dds(*dds, accessed);
1207
1208 dds->transfer_attributes(das);
1209
1210 bdds->set_constraint(dhi);
1211
1212 bdds->clear_container();
1213
1214 if (h4file != nullptr)
1215 delete h4file;
1216
1217 if (sdfd != -1)
1218 SDend(sdfd);
1219 }
1220
1221 catch (BESError & e) {
1222 throw BESError(e.what(), e.get_bes_error_type(),
1223 __FILE__, __LINE__);
1224 }
1225 catch (InternalErr & e) {
1226 throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1227 __FILE__, __LINE__);
1228 }
1229 catch (Error & e) {
1230 throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1231 __FILE__, __LINE__);
1232 }
1233 catch (...) {
1234 if(sdfd != -1)
1235 SDend(sdfd);
1236 if(h4file != nullptr)
1237 delete h4file;
1238 string s = "unknown exception caught building HDF4 DataDDS";
1239 throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
1240 }
1241
1242 return true;
1243}
1244
1245// Notice the metadata cache doesn't apply when the EnableFileID key is set.
1246// This is because the file ID generated by creating DDS/DAS WO cache is needed to access the data.
1247// So to make this work at any time, we have to create SDS ID even when the EnableFileID key is set.
1248// This is against the purpose of EnableFileID key. To acheieve the same purpose for AIRS,
1249// one can set the DataCache key, the performance is similar or even better than just using the EnableFileID key.
1250bool HDF4RequestHandler::hdf4_build_data_cf_sds_with_IDs(BESDataHandlerInterface &dhi){
1251
1252 int32 sdfd = -1;
1253 HDFSP::File *h4file = nullptr;
1254
1255 BESResponseObject *response = dhi.response_handler->get_response_object();
1256 auto bdds = dynamic_cast<BESDataDDSResponse *> (response);
1257
1258 if (!bdds)
1259 throw BESInternalError("cast error", __FILE__, __LINE__);
1260
1261 try {
1262 bdds->set_container(dhi.container->get_symbolic_name());
1263
1264 auto hdds = new HDF4DDS(bdds->get_dds());
1265
1266
1267 delete bdds->get_dds();
1268
1269 bdds->set_dds(hdds);
1270
1271
1272 string accessed = dhi.container->access();
1273 hdds->filename(accessed);
1274
1275 auto das = new DAS;
1276 BESDASResponse bdas(das);
1277 bdas.set_container(dhi.container->get_symbolic_name());
1278
1279 //Obtain SD ID.
1280 sdfd = SDstart (accessed.c_str(), DFACC_READ);
1281 if( -1 == sdfd) {
1282 string invalid_file_msg="HDF4 SDstart error for the file ";
1283 invalid_file_msg +=accessed;
1284 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
1285 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1286 }
1287
1288 hdds->setHDF4Dataset(sdfd,-1);
1289
1290 // Here we will check if ECS_Metadata key if set. For DataDDS,
1291 // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
1292 // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
1293 bool ecs_metadata = true;
1294#if 0
1295 if((true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataMin"))
1296 || (true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataAll")))
1297#endif
1298 if((true == _disable_ecsmetadata_min)
1299 || (true == _disable_ecsmetadata_all))
1300 ecs_metadata = false;
1301
1302 read_das_sds(*das, accessed,sdfd,ecs_metadata,&h4file);
1303#if 0
1304 //read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,true);
1305#endif
1306
1307 Ancillary::read_ancillary_das(*das, accessed);
1308
1309 // Pass file pointer(h4file, eosfile) from DAS to DDS.
1310 read_dds_sds(*hdds, accessed,sdfd,h4file,false);
1311
1312 if(h4file != nullptr)
1313 delete h4file;
1314
1315 Ancillary::read_ancillary_dds(*hdds, accessed);
1316
1317 hdds->transfer_attributes(das);
1318
1319 bdds->set_constraint(dhi);
1320
1321 bdds->clear_container();
1322
1323 }
1324
1325 catch (BESError & e) {
1326 throw BESError(e.what(), e.get_bes_error_type(),
1327 __FILE__, __LINE__);
1328 }
1329 catch (InternalErr & e) {
1330 throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1331 __FILE__, __LINE__);
1332 }
1333 catch (Error & e) {
1334 throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1335 __FILE__, __LINE__);
1336 }
1337 catch (...) {
1338 if(sdfd != -1)
1339 SDend(sdfd);
1340 if(h4file != nullptr)
1341 delete h4file;
1342 string s = "unknown exception caught building HDF4 DataDDS";
1343 throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
1344 }
1345
1346 // Note: HDF4 file IDs are closed by the HDF4_DDS derived class.
1347 // See the #if 0 #endif block of the method hdf4_build_dmr_with_IDs for the IDs.
1348
1349 return true;
1350}
1351bool HDF4RequestHandler::hdf4_build_dmr(BESDataHandlerInterface &dhi)
1352{
1353
1354 BES_STOPWATCH_START_DHI(HDF4_NAME, prolog + "Timer", &dhi);
1355
1356 if (true == _direct_dmr)
1357 return hdf4_build_direct_dmr(dhi);
1358
1359 // Because this code does not yet know how to build a DMR directly, use
1360 // the DMR ctor that builds a DMR using a 'full DDS' (a DDS with attributes).
1361 // First step, build the 'full DDS'
1362 string data_path = dhi.container->access();
1363
1364
1365 BaseTypeFactory factory;
1366 DDS dds(&factory, name_path(data_path), "3.2");
1367 dds.filename(data_path);
1368
1369 DAS das;
1370
1371 int32 sdfd = -1;
1372 int32 fileid = -1;
1373
1374 // Since passing file IDs requires to use the derived class and it
1375 // causes the management of code structure messy, we first handle this with
1376 // another method.
1377 if(true == _usecf) {
1378
1379 if(true == _pass_fileid)
1380 return hdf4_build_dmr_with_IDs(dhi);
1381
1382 }
1383
1384
1385 try {
1386
1387 if (true == _usecf) {
1388
1389 HDFSP::File *h4file = nullptr;
1390
1391 // Obtain HDF4 file IDs
1392 //SDstart
1393 sdfd = SDstart (data_path.c_str(), DFACC_READ);
1394 if( -1 == sdfd){
1395 string invalid_file_msg="HDF4 SDstart error for the file ";
1396 invalid_file_msg +=data_path;
1397 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
1398 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1399 }
1400
1401 // H open
1402 fileid = Hopen(data_path.c_str(), DFACC_READ,0);
1403 if (-1 == fileid) {
1404 SDend(sdfd);
1405 string invalid_file_msg="HDF4 Hopen error for the file ";
1406 invalid_file_msg +=data_path;
1407 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
1408 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1409 }
1410
1411#ifdef USE_HDFEOS2_LIB
1412
1413 int32 gridfd = -1;
1414 int32 swathfd = -1;
1415
1416 HDFEOS2::File *eosfile = nullptr;
1417
1418 // Obtain HDF-EOS2 file IDs with the file open APIs.
1419 // Grid open
1420 gridfd = GDopen(const_cast < char *>(data_path.c_str()), DFACC_READ);
1421 if (-1 == gridfd) {
1422 SDend(sdfd);
1423 Hclose(fileid);
1424 string invalid_file_msg="HDF-EOS GDopen error for the file ";
1425 invalid_file_msg +=data_path;
1426 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
1427 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1428 }
1429
1430 // Swath open
1431 swathfd = SWopen(const_cast < char *>(data_path.c_str()), DFACC_READ);
1432 if (-1 == swathfd) {
1433 SDend(sdfd);
1434 Hclose(fileid);
1435 GDclose(gridfd);
1436 string invalid_file_msg="HDF-EOS SWopen error for the file ";
1437 invalid_file_msg +=data_path;
1438 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
1439 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1440 }
1441
1442
1443 // Here we will check if ECS_Metadata key if set. For DAP4's DMR,
1444 // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
1445 // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
1446 // This is one difference between DAP2 and DAP4 mapping. Since
1447 // people can use BES key to turn on the ECS metadata, so this is okay.
1448 // KY 2014-10-23
1449 bool ecs_metadata = true;
1450#if 0
1451 if((true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataMin"))
1452 || (true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataAll")))
1453#endif
1454 if((true == _disable_ecsmetadata_min)
1455 || (true == _disable_ecsmetadata_all))
1456 ecs_metadata = false;
1457
1458 try {
1459
1460 read_das_use_eos2lib(das, data_path,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
1461#if 0
1462 //read_das_use_eos2lib(*das, data_path,sdfd,fileid,gridfd,swathfd,true);
1463#endif
1464 Ancillary::read_ancillary_das(das, data_path);
1465
1466 // Pass file pointer(h4file, eosfile) from DAS to DDS
1467 read_dds_use_eos2lib(dds, data_path,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
1468 }
1469
1470 catch(...) {
1471 close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
1472 throw;
1473 }
1474 if(eosfile != nullptr)
1475 delete eosfile;
1476 GDclose(gridfd);
1477 SWclose(swathfd);
1478
1479#else
1480 try {
1481 read_das_hdfsp(das, data_path,sdfd,fileid,&h4file);
1482 Ancillary::read_ancillary_das(das, data_path);
1483
1484 // Pass file pointer(h4file) from DAS to DDS.
1485 read_dds_hdfsp(dds, data_path,sdfd,fileid,h4file);
1486 }
1487 catch(...) {
1488 close_hdf4_fileid(sdfd,fileid,h4file);
1489 throw;
1490 //throw InternalErr(__FILE__,__LINE__,"read_dds_hdfsp error");
1491 }
1492#endif
1493 close_hdf4_fileid(sdfd,fileid,h4file);
1494
1495 }
1496 else {
1497 read_das(das, data_path);
1498 Ancillary::read_ancillary_das(das, data_path);
1499 read_dds(dds, data_path);
1500 }
1501
1502
1503 Ancillary::read_ancillary_dds(dds, data_path);
1504
1505 dds.transfer_attributes(&das);
1506
1507 }
1508
1509 catch (InternalErr & e) {
1510 throw BESDapError(e.get_error_message(), true, e.get_error_code(),
1511 __FILE__, __LINE__);
1512 }
1513 catch (Error & e) {
1514 throw BESDapError(e.get_error_message(), false, e.get_error_code(),
1515 __FILE__, __LINE__);
1516 }
1517 catch (...) {
1518 string s = "unknown exception caught building HDF4 DataDDS";
1519 throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
1520 }
1521
1522#if 0
1523 //dds.print(cout);
1524 //dds.print_das(cout);
1525#endif
1526 //
1527 // Extract the DMR Response object - this holds the DMR used by the
1528 // other parts of the framework.
1529 BESResponseObject *response = dhi.response_handler->get_response_object();
1530 BESDMRResponse &bes_dmr = dynamic_cast<BESDMRResponse &>(*response);
1531
1532 DMR *dmr = bes_dmr.get_dmr();
1533
1534 D4BaseTypeFactory MyD4TypeFactory;
1535 dmr->set_factory(&MyD4TypeFactory);
1536#if 0
1537 //dmr->set_factory(new D4BaseTypeFactory);
1538#endif
1539 dmr->build_using_dds(dds);
1540
1541#if 0
1542 //dmr->print(cout);
1543#endif
1544
1545 // Instead of fiddling with the internal storage of the DHI object,
1546 // (by setting dhi.data[DAP4_CONSTRAINT], etc., directly) use these
1547 // methods to set the constraints. But, why? Ans: from Patrick is that
1548 // in the 'container' mode of BES each container can have a different
1549 // CE.
1550 bes_dmr.set_dap4_constraint(dhi);
1551 bes_dmr.set_dap4_function(dhi);
1552 dmr->set_factory(nullptr);
1553
1554 return true;
1555}
1556
1557bool HDF4RequestHandler::hdf4_build_direct_dmr(BESDataHandlerInterface & dhi) {
1558
1559 // Extract the DMR Response object - this holds the DMR used by the
1560 // other parts of the framework.
1561 BESResponseObject *response = dhi.response_handler->get_response_object();
1562 BESDMRResponse &bes_dmr_response = dynamic_cast<BESDMRResponse &>(*response);
1563
1564 string filename = dhi.container->access();
1565
1566 BESDEBUG("h4", "build_direct_dmr - filename"<< filename <<endl);
1567 DMR *dmr = bes_dmr_response.get_dmr();
1568 dmr->set_name(name_path(filename));
1569 dmr->set_filename(name_path(filename));
1570 D4BaseTypeFactory MyD4TypeFactory;
1571 dmr->set_factory(&MyD4TypeFactory);
1572
1573
1574 BESDEBUG("h4", "build_direct_dmr - begin"<< endl);
1575 read_dmr(dmr, filename);
1576 BESDEBUG("h4", "build_direct_dmr - end"<< endl);
1577
1578 bes_dmr_response.set_dap4_constraint(dhi);
1579 bes_dmr_response.set_dap4_function(dhi);
1580 dmr->set_factory(nullptr);
1581
1582 return false;
1583
1584
1585}
1586
1587bool HDF4RequestHandler::hdf4_build_dmr_with_IDs(BESDataHandlerInterface & dhi) {
1588
1589 BES_STOPWATCH_START_DHI(HDF4_NAME, prolog + "Timer", &dhi);
1590
1591 // Because this code does not yet know how to build a DMR directly, use
1592 // the DMR ctor that builds a DMR using a 'full DDS' (a DDS with attributes).
1593 // First step, build the 'full DDS'
1594 string data_path = dhi.container->access();
1595
1596 BaseTypeFactory factory;
1597 DDS dds(&factory, name_path(data_path), "3.2");
1598 dds.filename(data_path);
1599
1600 DAS das;
1601
1602 int32 sdfd = -1;
1603 int32 fileid = -1;
1604
1605 HDFSP::File *h4file = nullptr;
1606
1607 // Obtain HDF4 file IDs
1608 //SDstart
1609 sdfd = SDstart (data_path.c_str(), DFACC_READ);
1610 if( -1 == sdfd){
1611 string invalid_file_msg="HDF4 SDstart error for the file ";
1612 invalid_file_msg +=data_path;
1613 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
1614 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1615 }
1616
1617 // H open
1618 fileid = Hopen(data_path.c_str(), DFACC_READ,0);
1619 if (-1 == fileid) {
1620 SDend(sdfd);
1621 string invalid_file_msg="HDF4 SDstart error for the file ";
1622 invalid_file_msg +=data_path;
1623 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
1624 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1625 }
1626
1627
1628#ifdef USE_HDFEOS2_LIB
1629
1630 int32 gridfd = -1;
1631 int32 swathfd = -1;
1632
1633 HDFEOS2::File *eosfile = nullptr;
1634 // Obtain HDF-EOS2 file IDs with the file open APIs.
1635 // Grid open
1636 gridfd = GDopen(const_cast < char *>(data_path.c_str()), DFACC_READ);
1637 if (-1 == gridfd) {
1638 SDend(sdfd);
1639 Hclose(fileid);
1640 string invalid_file_msg="HDF4 SDstart error for the file ";
1641 invalid_file_msg +=data_path;
1642 invalid_file_msg +=". It is very possible that this file is not an HDF4 file. ";
1643 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1644
1645 }
1646
1647 // Swath open
1648 swathfd = SWopen(const_cast < char *>(data_path.c_str()), DFACC_READ);
1649 if (-1 == swathfd) {
1650 SDend(sdfd);
1651 Hclose(fileid);
1652 GDclose(gridfd);
1653 string invalid_file_msg="HDF-EOS SWopen error for the file ";
1654 invalid_file_msg +=data_path;
1655 invalid_file_msg +=". It is very possible that this file is not an HDF-EOS2 file. ";
1656 throw BESInternalError(invalid_file_msg,__FILE__,__LINE__);
1657
1658 }
1659
1660 // Here we will check if ECS_Metadata key if set. For DAP4's DMR,
1661 // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
1662 // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
1663 // This is one difference between DAP2 and DAP4 mapping. Since
1664 // people can use BES key to turn on the ECS metadata, so this is okay.
1665 // KY 2014-10-23
1666 bool ecs_metadata = true;
1667#if 0
1668 if((true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataMin"))
1669 || (true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataAll")))
1670#endif
1671 if((true == _disable_ecsmetadata_min)
1672 || (true == _disable_ecsmetadata_all))
1673 ecs_metadata = false;
1674
1675 try {
1676
1677 read_das_use_eos2lib(das, data_path,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
1678#if 0
1679 //read_das_use_eos2lib(*das, data_path,sdfd,fileid,gridfd,swathfd,true);
1680#endif
1681 Ancillary::read_ancillary_das(das, data_path);
1682
1683 // Pass file pointer(h4file, eosfile) from DAS to DDS.
1684 read_dds_use_eos2lib(dds, data_path,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
1685 }
1686
1687 catch(...) {
1688 close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
1689 throw;
1690 }
1691 if(eosfile != nullptr)
1692 delete eosfile;
1693
1694#else
1695 try {
1696 read_das_hdfsp(das, data_path,sdfd,fileid,&h4file);
1697 Ancillary::read_ancillary_das(das, data_path);
1698
1699 // Pass file pointer(h4file) from DAS to DDS.
1700 read_dds_hdfsp(dds, data_path,sdfd,fileid,h4file);
1701 }
1702 catch(...) {
1703 close_hdf4_fileid(sdfd,fileid,h4file);
1704 throw;
1705 }
1706#endif
1707 if(h4file != nullptr)
1708 delete h4file;
1709
1710 Ancillary::read_ancillary_dds(dds, data_path);
1711
1712 dds.transfer_attributes(&das);
1713
1714
1715 // Note: HDF4 file IDs are closed by the HDF4_DDS derived class.
1716#if 0
1717 if(true == usecf) {
1718#ifdef USE_HDFEOS2_LIB
1719 GDclose(gridfd);
1720 SWclose(swathfd);
1721
1722#endif
1723 SDend(sdfd);
1724 Hclose(fileid);
1725 }
1726#endif
1727
1728 // Extract the DMR Response object - this holds the DMR used by the
1729 // other parts of the framework.
1730 BESResponseObject *response = dhi.response_handler->get_response_object();
1731 BESDMRResponse &bes_dmr = dynamic_cast<BESDMRResponse &>(*response);
1732
1733 // In this handler we use a different pattern since the handler specializes the DDS/DMR.
1734 // First, build the DMR adding the open handle to the HDF4 dataset, then free the DMR
1735 // the BES built and add this one. The HDF4DMR object will close the open dataset when
1736 // the BES runs the DMR's destructor.
1737 DMR *dmr = bes_dmr.get_dmr();
1738 D4BaseTypeFactory MyD4TypeFactory;
1739 dmr->set_factory(&MyD4TypeFactory);
1740 dmr->build_using_dds(dds);
1741 auto hdf4_dmr = new HDF4DMR(dmr);
1742#ifdef USE_HDFEOS2_LIB
1743 hdf4_dmr->setHDF4Dataset(sdfd,fileid,gridfd,swathfd);
1744#else
1745 hdf4_dmr->setHDF4Dataset(sdfd,fileid);
1746#endif
1747 delete dmr; // The call below will make 'dmr' unreachable; delete it now to avoid a leak.
1748 bes_dmr.set_dmr(hdf4_dmr); // BESDMRResponse will delete hdf4_dmr
1749
1750 // Instead of fiddling with the internal storage of the DHI object,
1751 // (by setting dhi.data[DAP4_CONSTRAINT], etc., directly) use these
1752 // methods to set the constraints. But, why? Ans: from Patrick is that
1753 // in the 'container' mode of BES each container can have a different
1754 // CE.
1755 bes_dmr.set_dap4_constraint(dhi);
1756 bes_dmr.set_dap4_function(dhi);
1757 hdf4_dmr->set_factory(nullptr);
1758
1759 return true;
1760
1761}
1762
1763bool HDF4RequestHandler::hdf4_build_help(BESDataHandlerInterface & dhi) {
1764 BESResponseObject *response = dhi.response_handler->get_response_object();
1765 auto info = dynamic_cast<BESInfo *> (response);
1766 if (!info)
1767 throw BESInternalError("cast error", __FILE__, __LINE__);
1768
1769 map < string, string, std::less<> > attrs;
1770 attrs["name"] = MODULE_NAME ;
1771 attrs["version"] = MODULE_VERSION ;
1772 list < string > services;
1773 BESServiceRegistry::TheRegistry()->services_handled(HDF4_NAME, services);
1774 if (services.empty() == false) {
1775 string handles = BESUtil::implode(services, ',');
1776 attrs["handles"] = handles;
1777 }
1778 info->begin_tag("module", &attrs);
1779 info->end_tag("module");
1780
1781 return true;
1782}
1783
1784bool HDF4RequestHandler::hdf4_build_version(BESDataHandlerInterface & dhi) {
1785 BESResponseObject *response = dhi.response_handler->get_response_object();
1786 auto info = dynamic_cast<BESVersionInfo *> (response);
1787 if (!info)
1788 throw BESInternalError("cast error", __FILE__, __LINE__);
1789
1790 info->add_module(MODULE_NAME, MODULE_VERSION);
1791
1792 return true;
1793}
1794
1795#ifdef USE_HDFEOS2_LIB
1796void close_fileid(int sdfd, int fileid,int gridfd, int swathfd,HDFSP:: File* h4file, HDFEOS2::File*eosfile) {
1797 if (h4file !=nullptr)
1798 delete h4file;
1799 if (sdfd != -1)
1800 SDend(sdfd);
1801 if (fileid != -1)
1802 Hclose(fileid);
1803
1804
1805 if (eosfile !=nullptr)
1806 delete eosfile;
1807 if (gridfd != -1)
1808 GDclose(gridfd);
1809 if (swathfd != -1)
1810 SWclose(swathfd);
1811
1812}
1813#endif
1814void close_hdf4_fileid(int sdfd, int fileid,HDFSP::File*h4file) {
1815
1816 if (h4file !=nullptr)
1817 delete h4file;
1818
1819 if (sdfd != -1)
1820 SDend(sdfd);
1821 if (fileid != -1)
1822 Hclose(fileid);
1823
1824}
1825
1826// Handling DAS and DDS cache. Currently we only apply the cache to special products(AIRS version 6 level 3 or 2).
1827// read or write DAS from/to a cache file.
1828bool rw_das_cache_file(const string & filename, DAS *das_ptr,bool w_flag) {
1829
1830 bool das_set_cache = false;
1831 FILE *das_file = nullptr;
1832
1833 if(false == w_flag) // open a cache file for reading.
1834 das_file = fopen(filename.c_str(),"r");
1835 else
1836 das_file = fopen(filename.c_str(),"w");
1837
1838 if(nullptr == das_file) {
1839 if(ENOENT == errno) {
1840 // Since the das service always tries to read the data from a cache and if the cache file doesn't exist,
1841 // it will generates a cache file, so here we set a flag to indicate if a cache file needs to be generated.
1842 if(false == w_flag) {
1843 BESDEBUG("h4", "DAS set cache key is true." << endl);
1844 das_set_cache = true;
1845 }
1846 }
1847 else
1848 throw BESInternalError( "An error occurred trying to open a das cache file " + get_errno(), __FILE__, __LINE__);
1849 }
1850 else {
1851
1852 int fd_das = fileno(das_file);
1853
1854 // Set a corresponding read(shared) or write(exclusive) lock.
1855 struct flock *l_das;
1856 if(false == w_flag)
1857 l_das = lock(F_RDLCK);
1858 else
1859 l_das = lock(F_WRLCK);
1860
1861 // Hold a lock.
1862 if(fcntl(fd_das,F_SETLKW,l_das) == -1) {
1863 fclose(das_file);
1864 ostringstream oss;
1865 oss << "cache process: " << l_das->l_pid << " triggered a locking error: " << get_errno();
1866 throw BESInternalError( oss.str(), __FILE__, __LINE__);
1867 }
1868
1869 if(false == w_flag){
1870 // Read DAS from a cache file
1871 BESDEBUG("h4", "Obtaining DAS from the cache file" << endl);
1872 try {
1873 das_ptr->parse(das_file);
1874 }
1875 catch(...) {
1876 if(fcntl(fd_das,F_SETLK,lock(F_UNLCK)) == -1) {
1877 fclose(das_file);
1878 throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1879 }
1880 fclose(das_file);
1881 throw InternalErr(__FILE__,__LINE__,"Fail to parse the das from a das file.");
1882 }
1883 }
1884 else {
1885 // Write DAS to a cache file
1886 BESDEBUG("h4", "write DAS to a cache file" << endl);
1887 try {
1888 das_ptr->print(das_file);
1889 }
1890 catch(...) {
1891 if(fcntl(fd_das,F_SETLK,lock(F_UNLCK)) == -1) {
1892 fclose(das_file);
1893 throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1894 }
1895 fclose(das_file);
1896 throw InternalErr(__FILE__,__LINE__,"Fail to generate a das cache file.");
1897 }
1898
1899 }
1900
1901 // Unlock the cache file
1902 if(fcntl(fd_das,F_SETLK,lock(F_UNLCK)) == -1) {
1903 fclose(das_file);
1904 throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1905 }
1906 fclose(das_file);
1907
1908 }
1909
1910 return das_set_cache;
1911
1912}
1913
1914// Read dds from a cache file.
1915bool r_dds_cache_file(const string & cache_filename, DDS *dds_ptr,const string & hdf4_filename) {
1916
1917 bool dds_set_cache = false;
1918 FILE *dds_file = nullptr;
1919 dds_file = fopen(cache_filename.c_str(),"rb");
1920
1921 if(nullptr == dds_file) {
1922 if(ENOENT == errno) {
1923 // Since the das service always tries to read the data from a cache and if the cache file doesn't exist,
1924 // it is supposed that the handler should generate a cache file,
1925 // so set a flag to indicate if a cache file needs to be generated.
1926 dds_set_cache = true;
1927 }
1928 else
1929 throw BESInternalError( "An error occurred trying to open a dds cache file " + get_errno(), __FILE__, __LINE__);
1930 }
1931 else {
1932
1933 int fd_dds = fileno(dds_file);
1934 struct flock *l_dds;
1935 l_dds = lock(F_RDLCK);
1936
1937 // hold a read(shared) lock to read dds from a file.
1938 if(fcntl(fd_dds,F_SETLKW,l_dds) == -1) {
1939 fclose(dds_file);
1940 ostringstream oss;
1941 oss << "cache process: " << l_dds->l_pid << " triggered a locking error: " << get_errno();
1942 throw BESInternalError( oss.str(), __FILE__, __LINE__);
1943 }
1944
1945 try {
1946 HDFCFUtil::read_sp_sds_dds_cache(dds_file,dds_ptr,cache_filename,hdf4_filename);
1947 }
1948 catch(...) {
1949 if(fcntl(fd_dds,F_SETLK,lock(F_UNLCK)) == -1) {
1950 fclose(dds_file);
1951 throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1952 }
1953
1954 fclose(dds_file);
1955 throw InternalErr(__FILE__,__LINE__,"Fail to generate a dds cache file.");
1956 }
1957
1958 if(fcntl(fd_dds,F_SETLK,lock(F_UNLCK)) == -1) {
1959 fclose(dds_file);
1960 throw BESInternalError( "An error occurred trying to unlock the file" + get_errno(), __FILE__, __LINE__);
1961 }
1962
1963 fclose(dds_file);
1964
1965 }
1966
1967 return dds_set_cache;
1968
1969}
1970
1971bool check_beskeys(const string & key) {
1972
1973 bool found = false;
1974 string doset ="";
1975 const string dosettrue ="true";
1976 const string dosetyes = "yes";
1977
1978 TheBESKeys::TheKeys()->get_value( key, doset, found ) ;
1979 if( true == found ) {
1980 doset = BESUtil::lowercase( doset ) ;
1981 if( dosettrue == doset || dosetyes == doset )
1982 return true;
1983 }
1984 return false;
1985
1986}
1987
1988bool is_beskey_exist(const string &key) {
1989
1990 bool found = false;
1991 string doset ="";
1992 TheBESKeys::TheKeys()->get_value( key, doset, found ) ;
1993 return found;
1994}
1995
1996bool get_beskeys(const string & key,string &key_value) {
1997
1998 bool found = false;
1999
2000 TheBESKeys::TheKeys()->get_value( key, key_value, found ) ;
2001 return found;
2002
2003}
2004
2005#if 0
2006void test_func(HDFSP::File**h4file) {
2007cerr<<"OK to pass pointer of a nullptr pointer "<<endl;
2008}
2009#endif
std::string get_symbolic_name() const
retrieve the symbolic name for this container
virtual std::string access()=0
returns the true name of this container
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
Structure storing information used by the BES to handle the request.
BESContainer * container
pointer to current container in this interface
unsigned int get_bes_error_type() const
Return the return code for this error class.
Definition BESError.h:174
const char * what() const noexcept override
Return a brief message about the exception.
Definition BESError.h:184
exception thrown if internal error encountered
Represents a specific data type request handler.
virtual bool add_method(const std::string &name, p_request_handler_method method)
add a handler method to the request handler that knows how to fill in a specific response object
virtual 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)
Definition BESUtil.cc:257
static std::string implode(const std::list< std::string > &values, char delim)
Definition BESUtil.cc:620
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.
Definition TheBESKeys.cc:85