OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
HDF4RequestHandler.cc
Go to the documentation of this file.
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 //
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 <unistd.h>
33 
34 #include <string>
35 
36 //#undef USE_DAP4
37 //#define USE_DAP4 1
38 #ifdef USE_DAP4
39 #include <DMR.h>
40 #include <D4BaseTypeFactory.h>
41 #include <BESDMRResponse.h>
42 #endif
43 #include <mime_util.h>
44 #include <InternalErr.h>
45 #include <Ancillary.h>
46 #include <debug.h>
47 
48 #include "HDF4RequestHandler.h"
49 #include <BESResponseNames.h>
50 #include <BESDapNames.h>
51 #include <BESDASResponse.h>
52 #include <BESDDSResponse.h>
53 #include <BESDataDDSResponse.h>
54 #include <BESInfo.h>
55 #include <BESResponseHandler.h>
56 #include <BESVersionInfo.h>
57 #include <BESServiceRegistry.h>
58 #include <BESUtil.h>
59 #include <TheBESKeys.h>
60 #include <InternalErr.h>
61 #include <BESInternalError.h>
62 #include <BESDapError.h>
63 //#include <ConstraintEvaluator.h>
64 #include <Ancillary.h>
65 #include "config_hdf.h"
66 
67 #define HDF4_NAME "h4"
68 #include "HE2CF.h"
69 #include "HDF4_DDS.h"
70 
71 #ifdef USE_DAP4
72 #include "HDF4_DMR.h"
73 #endif
74 
75 #include "HDFCFUtil.h"
76 
77 //#define KENT2
78 #undef KENT2
79 #ifdef KENT2
80 #include <sys/time.h>
81 #endif
82 
83 extern void read_das(DAS & das, const string & filename);
84 extern void read_dds(DDS & dds, const string & filename);
85 
86 extern bool read_dds_hdfsp(DDS & dds, const string & filename,int32 sdfd, int32 fileid,HDFSP::File*h4file);
87 
88 extern bool read_das_hdfsp(DAS & das, const string & filename,int32 sdfd, int32 fileid,HDFSP::File**h4fileptr);
89 
90 
91 #ifdef USE_HDFEOS2_LIB
92 
93 void 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);
94 void read_dds_use_eos2lib(DDS & dds, const string & filename,int32 sdfd,int32 fileid, int32 gridfd, int32 swathfd,HDFSP::File*h4file,HDFEOS2::File*eosfile);
95 void close_fileid(const int sdfd, const int fileid,const int gridfd, const int swathfd,HDFSP::File*h4file,HDFEOS2::File*eosfile);
96 
97 #endif
98 
99 void close_hdf4_fileid(const int sdfd,const int fileid,HDFSP::File*h4file);
100 //void test_func(HDFSP::File**h4file);
101 
103  BESRequestHandler(name) {
107 #ifdef USE_DAP4
108  add_handler(DMR_RESPONSE, HDF4RequestHandler::hdf4_build_dmr);
109  add_handler(DAP4DATA_RESPONSE, HDF4RequestHandler::hdf4_build_dmr);
110 #endif
113 }
114 
116 }
117 
119 
120  bool found = false;
121  bool usecf = false;
122 
123  string key="H4.EnableCF";
124  string doset;
125 
126  TheBESKeys::TheKeys()->get_value( key, doset, found ) ;
127  if( true == found )
128  {
129  doset = BESUtil::lowercase( doset ) ;
130  if( doset == "true" || doset == "yes" ) {
131 
132  // This is the CF option, go to the CF function
133  usecf = true;
134  }
135  }
136 
138  BESDASResponse *bdas = dynamic_cast<BESDASResponse *> (response);
139  if (!bdas)
140  throw BESInternalError("cast error", __FILE__, __LINE__);
141 
142  try {
144  DAS *das = bdas->get_das();
145 
146  string accessed = dhi.container->access();
147 
148  if (true == usecf) {
149 
150  int32 sdfd = -1;
151  int32 fileid = -1;
152 
153  HDFSP::File *h4file = NULL;
154 
155  // Obtain HDF4 file IDs
156  //SDstart
157  sdfd = SDstart (const_cast < char *>(accessed.c_str()), DFACC_READ);
158  if( -1 == sdfd)
159  throw Error(cannot_read_file,"HDF4 SDstart error");
160 
161  // H open
162  fileid = Hopen(const_cast<char *>(accessed.c_str()), DFACC_READ,0);
163  if (-1 == fileid) {
164  SDend(sdfd);
165  throw Error(cannot_read_file,"HDF4 Hopen error");
166  }
167 
168 
169 #ifdef USE_HDFEOS2_LIB
170 
171  int32 gridfd = -1;
172  int32 swathfd = -1;
173  HDFEOS2::File *eosfile = NULL;
174  // Obtain HDF-EOS2 file IDs with the file open APIs.
175 
176  // Grid open
177  gridfd = GDopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
178  if (-1 == gridfd) {
179  SDend(sdfd);
180  Hclose(fileid);
181  throw Error(cannot_read_file,"HDF-EOS GDopen error");
182  }
183 
184  // Swath open
185  swathfd = SWopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
186  if (-1 == swathfd) {
187  SDend(sdfd);
188  Hclose(fileid);
189  GDclose(gridfd);
190  throw Error(cannot_read_file,"HDF-EOS SWopen error");
191  }
192 
193  try {
194  bool ecs_metadata = !(HDFCFUtil::check_beskeys("H4.DisableECSMetaDataAll"));
195 #if 0
196 if(ecs_metadata == true)
197 cerr<<"output ecs metadata "<<endl;
198 else
199 cerr<<"Don't output ecs metadata "<<endl;
200 #endif
201  read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
202  }
203  catch(...) {
204  close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
205  throw;
206  //throw InternalErr(__FILE__,__LINE__,"read_das_use_eos2lib error");
207  }
208  if(eosfile != NULL)
209  delete eosfile;
210  GDclose(gridfd);
211  SWclose(swathfd);
212 
213 #else
214  try {
215  read_das_hdfsp(*das,accessed,sdfd,fileid,&h4file);
216  }
217  catch(...) {
218  close_hdf4_fileid(sdfd,fileid,h4file);
219  throw;
220  //throw InternalErr(__FILE__,__LINE__,"read_das_hdfsp error");
221  }
222 #endif
223  close_hdf4_fileid(sdfd,fileid,h4file);
224  }
225  else
226  read_das(*das,accessed);
227 
228  Ancillary::read_ancillary_das(*das, accessed);
229  bdas->clear_container();
230  }
231 
232  catch (BESError & e) {
233  throw;
234  }
235  catch (InternalErr & e) {
236  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
237  __FILE__, __LINE__);
238  }
239  catch (Error & e) {
240  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
241  __FILE__, __LINE__);
242  }
243  catch (...) {
244  string s = "unknown exception caught building HDF4 DAS";
245  throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
246  }
247 
248  return true;
249 }
250 
252 
253  bool found = false;
254  bool usecf = false;
255 
256  string key="H4.EnableCF";
257  string doset;
258 
259  TheBESKeys::TheKeys()->get_value( key, doset, found ) ;
260  if( true == found )
261  {
262  doset = BESUtil::lowercase( doset ) ;
263  if( doset == "true" || doset == "yes" ) {
264  // This is the CF option, go to the CF function
265  usecf = true;
266  }
267  }
268 
269 // This is for the performance check. Leave it now for future use. KY 2014-10-23
270 #ifdef KENT2
271 struct timeval start_time,end_time;
272 gettimeofday(&start_time,NULL);
273 #endif
274 
276  BESDDSResponse *bdds = dynamic_cast<BESDDSResponse *> (response);
277  if (!bdds)
278  throw BESInternalError("cast error", __FILE__, __LINE__);
279 
280  try {
282  DDS *dds = bdds->get_dds();
283  //ConstraintEvaluator & ce = bdds->get_ce();
284 
285  string accessed = dhi.container->access();
286  dds->filename(accessed);
287 
288  DAS *das = new DAS;
289  BESDASResponse bdas(das);
291 
292  if (true == usecf) {
293 
294  int32 sdfd = -1;
295  int32 fileid = -1;
296  HDFSP::File *h4file = NULL;
297 
298  // Obtain HDF4 file IDs
299  //SDstart
300  sdfd = SDstart (const_cast < char *>(accessed.c_str()), DFACC_READ);
301  if( -1 == sdfd)
302  throw Error(cannot_read_file,"HDF4 SDstart error");
303 
304  // H open
305  fileid = Hopen(const_cast<char *>(accessed.c_str()), DFACC_READ,0);
306  if (-1 == fileid) {
307  SDend(sdfd);
308  throw Error(cannot_read_file,"HDF4 Hopen error");
309  }
310 
311 
312 
313 #ifdef USE_HDFEOS2_LIB
314 
315  int32 gridfd = -1;
316  int32 swathfd = -1;
317 
318  HDFEOS2::File *eosfile = NULL;
319 
320  // Obtain HDF-EOS2 file IDs with the file open APIs.
321  // Grid open
322  gridfd = GDopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
323  if (-1 == gridfd) {
324  SDend(sdfd);
325  Hclose(fileid);
326  throw Error(cannot_read_file,"HDF-EOS GDopen error");
327  }
328 
329  // Swath open
330  swathfd = SWopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
331  if (-1 == swathfd) {
332  SDend(sdfd);
333  Hclose(fileid);
334  GDclose(gridfd);
335  throw Error(cannot_read_file,"HDF-EOS SWopen error");
336  }
337 
338  try {
339  bool ecs_metadata = !(HDFCFUtil::check_beskeys("H4.DisableECSMetaDataAll"));
340  read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
341  //read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,true);
342  Ancillary::read_ancillary_das(*das, accessed);
343 
344 #if 0
345 if(eosfile == NULL)
346 cerr<<"HDFEOS2 file pointer is NULL "<<endl;
347 if(h4file == NULL)
348 cerr<<"HDF4 file pointer is NULL"<<endl;
349 #endif
350  // Pass file pointer(h4file, eosfile) from DAS to DDS.
351  read_dds_use_eos2lib(*dds, accessed,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
352  }
353  catch(...) {
354  close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
355  throw;
356  }
357 
358  if(eosfile != NULL)
359  delete eosfile;
360 
361  GDclose(gridfd);
362  SWclose(swathfd);
363 
364 #else
365  try {
366  read_das_hdfsp(*das, accessed,sdfd,fileid,&h4file);
367  Ancillary::read_ancillary_das(*das, accessed);
368 
369  // Pass file pointer(h4file) from DAS to DDS.
370  read_dds_hdfsp(*dds, accessed,sdfd,fileid,h4file);
371  }
372  catch(...) {
373  close_hdf4_fileid(sdfd,fileid,h4file);
374  throw;
375  //throw InternalErr(__FILE__,__LINE__,"read_dds_hdfsp error");
376  }
377 
378 #endif
379  close_hdf4_fileid(sdfd,fileid,h4file);
380  }
381  else {
382  read_das(*das, accessed);
383  Ancillary::read_ancillary_das(*das, accessed);
384  read_dds(*dds, accessed);
385  }
386 
387 // Leave it for future performance tests. KY 2014-10-23
388 #ifdef KENT2
389 gettimeofday(&end_time,NULL);
390 int total_time_spent = (end_time.tv_sec - start_time.tv_sec)*1000000 +end_time.tv_usec-start_time.tv_usec;
391 cerr<<"total time spent for DDS buld is "<<total_time_spent<< "micro seconds "<<endl;
392 #endif
393 
394  Ancillary::read_ancillary_dds(*dds, accessed);
395 
396  dds->transfer_attributes(das);
397 
398  bdds->set_constraint(dhi);
399 
400  bdds->clear_container();
401  }
402  catch (BESError & e) {
403  throw;
404  }
405  catch (InternalErr & e) {
406  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
407  __FILE__, __LINE__);
408  }
409  catch (Error & e) {
410  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
411  __FILE__, __LINE__);
412  }
413  catch (...) {
414  string s = "unknown exception caught building HDF4 DDS";
415  throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
416  }
417 
418  return true;
419 }
420 
422 
423  bool found = false;
424  bool usecf = false;
425 
426  string key="H4.EnableCF";
427  string doset;
428 
429  int32 sdfd = -1;
430  int32 fileid = -1;
431 
432 
433  TheBESKeys::TheKeys()->get_value( key, doset, found ) ;
434  if( true == found )
435  {
436  doset = BESUtil::lowercase( doset ) ;
437  if( doset == "true" || doset == "yes" ) {
438 
439  // This is the CF option, go to the CF function
440  usecf = true;
441  }
442  }
443 
444  // Since passing file IDs requires to use the derived class and it
445  // causes the management of code structure messy, we first handle this with
446  // another method.
447  if(true == usecf) {
448 
449  if(true == HDFCFUtil::check_beskeys("H4.EnablePassFileID"))
450  return hdf4_build_data_with_IDs(dhi);
451 
452  }
453 
455  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *> (response);
456 
457  if (!bdds)
458  throw BESInternalError("cast error", __FILE__, __LINE__);
459 
460  try {
462 
463  DataDDS *dds = bdds->get_dds();
464 
465  // Not sure why keep the following line, it is not used.
466  //ConstraintEvaluator & ce = bdds->get_ce();
467 
468  string accessed = dhi.container->access();
469  dds->filename(accessed);
470 
471  DAS *das = new DAS;
472  BESDASResponse bdas(das);
474 
475  if (true == usecf) {
476 
477  HDFSP::File *h4file = NULL;
478 
479  // Obtain HDF4 file IDs
480  //SDstart
481  sdfd = SDstart (const_cast < char *>(accessed.c_str()), DFACC_READ);
482  if( -1 == sdfd)
483  throw Error(cannot_read_file,"HDF4 SDstart error");
484 
485  // H open
486  fileid = Hopen(const_cast<char *>(accessed.c_str()), DFACC_READ,0);
487  if (-1 == fileid) {
488  SDend(sdfd);
489  throw Error(cannot_read_file,"HDF4 Hopen error");
490  }
491 
492 
493 #ifdef USE_HDFEOS2_LIB
494 
495  int32 gridfd = -1;
496  int32 swathfd = -1;
497  HDFEOS2::File *eosfile = NULL;
498  // Obtain HDF-EOS2 file IDs with the file open APIs.
499 
500  // Grid open
501  gridfd = GDopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
502  if (-1 == gridfd) {
503  SDend(sdfd);
504  Hclose(fileid);
505  throw Error(cannot_read_file,"HDF-EOS GDopen error");
506  }
507 
508  // Swath open
509  swathfd = SWopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
510  if (-1 == swathfd) {
511  SDend(sdfd);
512  Hclose(fileid);
513  GDclose(gridfd);
514  throw Error(cannot_read_file,"HDF-EOS SWopen error");
515  }
516 
517  try {
518 
519  // Here we will check if ECS_Metadata key if set. For DataDDS,
520  // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
521  // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
522  bool ecs_metadata = true;
523  if((true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataMin"))
524  || (true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataAll")))
525  ecs_metadata = false;
526 
527  read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
528  Ancillary::read_ancillary_das(*das, accessed);
529 
530  // Pass file pointer(h4file, eosfile) from DAS to DDS.
531  read_dds_use_eos2lib(*dds, accessed,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
532  }
533  catch(...) {
534  close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
535  throw;
536  }
537 
538  if(eosfile != NULL)
539  delete eosfile;
540  GDclose(gridfd);
541  SWclose(swathfd);
542 
543 #else
544  try {
545  read_das_hdfsp(*das, accessed,sdfd,fileid,&h4file);
546  Ancillary::read_ancillary_das(*das, accessed);
547 
548  // Pass file pointer(h4file) from DAS to DDS.
549  read_dds_hdfsp(*dds, accessed,sdfd,fileid,h4file);
550  }
551  catch(...) {
552  close_hdf4_fileid(sdfd,fileid,h4file);
553  throw;
554  }
555 #endif
556  close_hdf4_fileid(sdfd,fileid,h4file);
557  }
558  else {
559  read_das(*das, accessed);
560  Ancillary::read_ancillary_das(*das, accessed);
561  read_dds(*dds, accessed);
562  }
563 
564  Ancillary::read_ancillary_dds(*dds, accessed);
565  dds->transfer_attributes(das);
566  bdds->set_constraint(dhi);
567  bdds->clear_container();
568 
569  }
570 
571  catch (BESError & e) {
572  throw;
573  }
574  catch (InternalErr & e) {
575  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
576  __FILE__, __LINE__);
577  }
578  catch (Error & e) {
579  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
580  __FILE__, __LINE__);
581  }
582  catch (...) {
583  string s = "unknown exception caught building HDF4 DataDDS";
584  throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
585  }
586 
587  return true;
588 }
589 
591 
592 
593  int32 sdfd = -1;
594  int32 fileid = -1;
595  HDFSP::File *h4file = NULL;
596 #ifdef USE_HDFEOS2_LIB
597  int32 gridfd = -1;
598  int32 swathfd = -1;
599  HDFEOS2::File *eosfile = NULL;
600 #endif
601 
603  BESDataDDSResponse *bdds = dynamic_cast<BESDataDDSResponse *> (response);
604 
605  if (!bdds)
606  throw BESInternalError("cast error", __FILE__, __LINE__);
607 
608  try {
610 
611  HDF4DDS *hdds = new HDF4DDS(bdds->get_dds());
612 
613  delete bdds->get_dds();
614 
615  bdds->set_dds(hdds);
616 
617  //ConstraintEvaluator & ce = bdds->get_ce();
618 
619  string accessed = dhi.container->access();
620  hdds->filename(accessed);
621 
622  DAS *das = new DAS;
623  BESDASResponse bdas(das);
625 
626 
627  // Obtain HDF4 file IDs
628  //SDstart
629  sdfd = SDstart (const_cast < char *>(accessed.c_str()), DFACC_READ);
630  if( -1 == sdfd)
631  throw Error(cannot_read_file,"HDF4 SDstart error");
632 
633  // H open
634  fileid = Hopen(const_cast<char *>(accessed.c_str()), DFACC_READ,0);
635  if (-1 == fileid) {
636  SDend(sdfd);
637  throw Error(cannot_read_file,"HDF4 Hopen error");
638  }
639 
640 #ifdef USE_HDFEOS2_LIB
641 
642 
643  // Obtain HDF-EOS2 file IDs with the file open APIs.
644 
645  // Grid open
646  gridfd = GDopen(const_cast < char *>(accessed.c_str()), DFACC_READ);
647  if (-1 == gridfd) {
648  SDend(sdfd);
649  Hclose(fileid);
650  throw Error(cannot_read_file,"HDF-EOS GDopen error");
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  throw Error(cannot_read_file,"HDF-EOS SWopen error");
660  }
661 
662  hdds->setHDF4Dataset(sdfd,fileid,gridfd,swathfd);
663 
664  // Here we will check if ECS_Metadata key if set. For DataDDS,
665  // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
666  // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
667  bool ecs_metadata = true;
668  if((true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataMin"))
669  || (true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataAll")))
670  ecs_metadata = false;
671 
672 
673  read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
674  //read_das_use_eos2lib(*das, accessed,sdfd,fileid,gridfd,swathfd,true);
675 
676  Ancillary::read_ancillary_das(*das, accessed);
677 
678  // Pass file pointer(h4file, eosfile) from DAS to DDS.
679  read_dds_use_eos2lib(*hdds, accessed,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
680 
681  if(eosfile != NULL)
682  delete eosfile;
683 
684 #else
685  hdds->setHDF4Dataset(sdfd,fileid);
686  read_das_hdfsp(*das, accessed,sdfd,fileid,&h4file);
687  Ancillary::read_ancillary_das(*das, accessed);
688 
689  // Pass file pointer(h4file) from DAS to DDS.
690  read_dds_hdfsp(*hdds, accessed,sdfd,fileid,h4file);
691 #endif
692  if(h4file != NULL)
693  delete h4file;
694 
695  Ancillary::read_ancillary_dds(*hdds, accessed);
696 
697  hdds->transfer_attributes(das);
698 
699  bdds->set_constraint(dhi);
700 
701  bdds->clear_container();
702 
703 
704 // File IDs are closed by the derived class.
705 #if 0
706  if(true == usecf) {
707 #ifdef USE_HDFEOS2_LIB
708  GDclose(gridfd);
709  SWclose(swathfd);
710 
711 #endif
712  SDend(sdfd);
713  Hclose(fileid);
714  }
715 #endif
716  }
717 
718  catch (BESError & e) {
719  throw;
720  }
721  catch (InternalErr & e) {
722  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
723  __FILE__, __LINE__);
724  }
725  catch (Error & e) {
726  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
727  __FILE__, __LINE__);
728  }
729  catch (...) {
730 #ifdef USE_HDFEOS2_LIB
731  close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
732 #else
733  close_hdf4_fileid(sdfd,fileid,h4file);
734 #endif
735  string s = "unknown exception caught building HDF4 DataDDS";
736  throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
737  }
738 
739  return true;
740 }
741 
742 #ifdef USE_DAP4
743 bool HDF4RequestHandler::hdf4_build_dmr(BESDataHandlerInterface &dhi)
744 {
745 
746  // Because this code does not yet know how to build a DMR directly, use
747  // the DMR ctor that builds a DMR using a 'full DDS' (a DDS with attributes).
748  // First step, build the 'full DDS'
749  string data_path = dhi.container->access();
750 
751  BaseTypeFactory factory;
752  DDS dds(&factory, name_path(data_path), "3.2");
753  dds.filename(data_path);
754 
755  DAS das;
756 
757  bool found = false;
758  bool usecf = false;
759 
760  string key="H4.EnableCF";
761  string doset;
762 
763  int32 sdfd = -1;
764  int32 fileid = -1;
765  int32 gridfd = -1;
766  int32 swathfd = -1;
767 
768 
769  // Check if CF option is turned on.
770  TheBESKeys::TheKeys()->get_value( key, doset, found ) ;
771  if( true == found )
772  {
773  doset = BESUtil::lowercase( doset ) ;
774  if( doset == "true" || doset == "yes" ) {
775 
776  // This is the CF option, go to the CF function
777  usecf = true;
778  }
779  }
780  // Since passing file IDs requires to use the derived class and it
781  // causes the management of code structure messy, we first handle this with
782  // another method.
783  if(true == usecf) {
784 
785  if(true == HDFCFUtil::check_beskeys("H4.EnablePassFileID"))
786  return hdf4_build_dmr_with_IDs(dhi);
787 
788  }
789 
790 
791  try {
792 
793  if (true == usecf) {
794 
795  HDFSP::File *h4file = NULL;
796 
797  // Obtain HDF4 file IDs
798  //SDstart
799  sdfd = SDstart (const_cast < char *>(data_path.c_str()), DFACC_READ);
800  if( -1 == sdfd)
801  throw Error(cannot_read_file,"HDF4 SDstart error");
802 
803  // H open
804  fileid = Hopen(const_cast<char *>(data_path.c_str()), DFACC_READ,0);
805  if (-1 == fileid) {
806  SDend(sdfd);
807  throw Error(cannot_read_file,"HDF4 Hopen error");
808  }
809 
810 #ifdef USE_HDFEOS2_LIB
811 
812  HDFEOS2::File *eosfile = NULL;
813 
814  // Obtain HDF-EOS2 file IDs with the file open APIs.
815  // Grid open
816  gridfd = GDopen(const_cast < char *>(data_path.c_str()), DFACC_READ);
817  if (-1 == gridfd) {
818  SDend(sdfd);
819  Hclose(fileid);
820  throw Error(cannot_read_file,"HDF-EOS GDopen error");
821  }
822 
823  // Swath open
824  swathfd = SWopen(const_cast < char *>(data_path.c_str()), DFACC_READ);
825  if (-1 == swathfd) {
826  SDend(sdfd);
827  Hclose(fileid);
828  GDclose(gridfd);
829  throw Error(cannot_read_file,"HDF-EOS SWopen error");
830  }
831 
832 
833  // Here we will check if ECS_Metadata key if set. For DAP4's DMR,
834  // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
835  // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
836  // This is one difference between DAP2 and DAP4 mapping. Since
837  // people can use BES key to turn on the ECS metadata, so this is okay.
838  // KY 2014-10-23
839  bool ecs_metadata = true;
840  if((true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataMin"))
841  || (true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataAll")))
842  ecs_metadata = false;
843 
844  try {
845 
846  read_das_use_eos2lib(das, data_path,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
847 
848  //read_das_use_eos2lib(*das, data_path,sdfd,fileid,gridfd,swathfd,true);
849  Ancillary::read_ancillary_das(das, data_path);
850 
851  // Pass file pointer(h4file, eosfile) from DAS to DDS
852  read_dds_use_eos2lib(dds, data_path,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
853  }
854 
855  catch(...) {
856  close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
857  throw;
858  }
859  if(eosfile != NULL)
860  delete eosfile;
861  GDclose(gridfd);
862  SWclose(swathfd);
863 
864 #else
865  try {
866  read_das_hdfsp(das, data_path,sdfd,fileid,&h4file);
867  Ancillary::read_ancillary_das(das, data_path);
868 
869  // Pass file pointer(h4file) from DAS to DDS.
870  read_dds_hdfsp(dds, data_path,sdfd,fileid,h4file);
871  }
872  catch(...) {
873  close_hdf4_fileid(sdfd,fileid,h4file);
874  throw;
875  //throw InternalErr(__FILE__,__LINE__,"read_dds_hdfsp error");
876  }
877 #endif
878  close_hdf4_fileid(sdfd,fileid,h4file);
879 
880  }
881  else {
882  read_das(das, data_path);
883  Ancillary::read_ancillary_das(das, data_path);
884  read_dds(dds, data_path);
885  }
886 
887 
888  Ancillary::read_ancillary_dds(dds, data_path);
889 
890  dds.transfer_attributes(&das);
891 
892  }
893 
894  catch (BESError & e) {
895  throw;
896  }
897  catch (InternalErr & e) {
898  throw BESDapError(e.get_error_message(), true, e.get_error_code(),
899  __FILE__, __LINE__);
900  }
901  catch (Error & e) {
902  throw BESDapError(e.get_error_message(), false, e.get_error_code(),
903  __FILE__, __LINE__);
904  }
905  catch (...) {
906  string s = "unknown exception caught building HDF4 DataDDS";
907  throw BESDapError(s, true, unknown_error, __FILE__, __LINE__);
908  }
909 
910 
911 //dds.print(cout);
912 //dds.print_das(cout);
913  //
914  // Extract the DMR Response object - this holds the DMR used by the
915  // other parts of the framework.
917  BESDMRResponse &bes_dmr = dynamic_cast<BESDMRResponse &>(*response);
918 
919  DMR *dmr = bes_dmr.get_dmr();
920 #if 0
921  D4BaseTypeFactory* MyD4TypeFactory = NULL;
922  MyD4TypeFactory = new D4BaseTypeFactory;
923  dmr->set_factory(MyD4TypeFactory);
924 #endif
925 
926  D4BaseTypeFactory MyD4TypeFactory;
927  dmr->set_factory(&MyD4TypeFactory);
928  //dmr->set_factory(new D4BaseTypeFactory);
929  dmr->build_using_dds(dds);
930 
931 //dmr->print(cout);
932 
933  // Instead of fiddling with the internal storage of the DHI object,
934  // (by setting dhi.data[DAP4_CONSTRAINT], etc., directly) use these
935  // methods to set the constraints. But, why? Ans: from Patrick is that
936  // in the 'container' mode of BES each container can have a different
937  // CE.
938  bes_dmr.set_dap4_constraint(dhi);
939  bes_dmr.set_dap4_function(dhi);
940  dmr->set_factory(0);
941 
942 #if 0
943  if(MyD4TypeFactory !=NULL)
944  delete MyD4TypeFactory;
945 #endif
946 
947  return true;
948 }
949 
950 bool HDF4RequestHandler::hdf4_build_dmr_with_IDs(BESDataHandlerInterface & dhi) {
951 
952  // Because this code does not yet know how to build a DMR directly, use
953  // the DMR ctor that builds a DMR using a 'full DDS' (a DDS with attributes).
954  // First step, build the 'full DDS'
955  string data_path = dhi.container->access();
956 
957  BaseTypeFactory factory;
958  DDS dds(&factory, name_path(data_path), "3.2");
959  dds.filename(data_path);
960 
961  DAS das;
962 
963  int32 sdfd = -1;
964  int32 fileid = -1;
965  int32 gridfd = -1;
966  int32 swathfd = -1;
967 
968  HDFSP::File *h4file = NULL;
969 
970  // Obtain HDF4 file IDs
971  //SDstart
972  sdfd = SDstart (const_cast < char *>(data_path.c_str()), DFACC_READ);
973  if( -1 == sdfd)
974  throw Error(cannot_read_file,"HDF4 SDstart error");
975 
976  // H open
977  fileid = Hopen(const_cast<char *>(data_path.c_str()), DFACC_READ,0);
978  if (-1 == fileid) {
979  SDend(sdfd);
980  throw Error(cannot_read_file,"HDF4 Hopen error");
981  }
982 
983 
984 #ifdef USE_HDFEOS2_LIB
985 
986  HDFEOS2::File *eosfile = NULL;
987  // Obtain HDF-EOS2 file IDs with the file open APIs.
988  // Grid open
989  gridfd = GDopen(const_cast < char *>(data_path.c_str()), DFACC_READ);
990  if (-1 == gridfd) {
991  SDend(sdfd);
992  Hclose(fileid);
993  throw Error(cannot_read_file,"HDF-EOS GDopen error");
994  }
995 
996  // Swath open
997  swathfd = SWopen(const_cast < char *>(data_path.c_str()), DFACC_READ);
998  if (-1 == swathfd) {
999  SDend(sdfd);
1000  Hclose(fileid);
1001  GDclose(gridfd);
1002  throw Error(cannot_read_file,"HDF-EOS SWopen error");
1003  }
1004 
1005  // Here we will check if ECS_Metadata key if set. For DAP4's DMR,
1006  // if either H4.DisableECSMetaDataMin or H4.DisableECSMetaDataAll is set,
1007  // the HDF-EOS2 coremetadata or archivemetadata will not be passed to DAP.
1008  // This is one difference between DAP2 and DAP4 mapping. Since
1009  // people can use BES key to turn on the ECS metadata, so this is okay.
1010  // KY 2014-10-23
1011  bool ecs_metadata = true;
1012  if((true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataMin"))
1013  || (true == HDFCFUtil::check_beskeys("H4.DisableECSMetaDataAll")))
1014  ecs_metadata = false;
1015 
1016  try {
1017 
1018  read_das_use_eos2lib(das, data_path,sdfd,fileid,gridfd,swathfd,ecs_metadata,&h4file,&eosfile);
1019  //read_das_use_eos2lib(*das, data_path,sdfd,fileid,gridfd,swathfd,true);
1020  Ancillary::read_ancillary_das(das, data_path);
1021 
1022  // Pass file pointer(h4file, eosfile) from DAS to DDS.
1023  read_dds_use_eos2lib(dds, data_path,sdfd,fileid,gridfd,swathfd,h4file,eosfile);
1024  }
1025 
1026  catch(...) {
1027  close_fileid(sdfd,fileid,gridfd,swathfd,h4file,eosfile);
1028  throw;
1029  }
1030  if(eosfile != NULL)
1031  delete eosfile;
1032 
1033 #else
1034  try {
1035  read_das_hdfsp(das, data_path,sdfd,fileid,&h4file);
1036  Ancillary::read_ancillary_das(das, data_path);
1037 
1038  // Pass file pointer(h4file) from DAS to DDS.
1039  read_dds_hdfsp(dds, data_path,sdfd,fileid,h4file);
1040  }
1041  catch(...) {
1042  close_hdf4_fileid(sdfd,fileid,h4file);
1043  throw;
1044  }
1045 #endif
1046  if(h4file != NULL)
1047  delete h4file;
1048 
1049  Ancillary::read_ancillary_dds(dds, data_path);
1050 
1051  dds.transfer_attributes(&das);
1052 
1053 
1054 // File IDs are closed by the derived class.
1055 #if 0
1056  if(true == usecf) {
1057 #ifdef USE_HDFEOS2_LIB
1058  GDclose(gridfd);
1059  SWclose(swathfd);
1060 
1061 #endif
1062  SDend(sdfd);
1063  Hclose(fileid);
1064  }
1065 #endif
1066 
1067  //dds.print(cout);
1068  //dds.print_das(cout);
1069  // Extract the DMR Response object - this holds the DMR used by the
1070  // other parts of the framework.
1072  BESDMRResponse &bes_dmr = dynamic_cast<BESDMRResponse &>(*response);
1073 
1074  // In this handler we use a different pattern since the handler specializes the DDS/DMR.
1075  // First, build the DMR adding the open handle to the HDF4 dataset, then free the DMR
1076  // the BES built and add this one. The HDF4DMR object will close the open dataset when
1077  // the BES runs the DMR's destructor.
1078  DMR *dmr = bes_dmr.get_dmr();
1079  D4BaseTypeFactory MyD4TypeFactory;
1080  dmr->set_factory(&MyD4TypeFactory);
1081  dmr->build_using_dds(dds);
1082  HDF4DMR *hdf4_dmr = new HDF4DMR(dmr);
1083 #ifdef USE_HDFEOS2_LIB
1084  hdf4_dmr->setHDF4Dataset(sdfd,fileid,gridfd,swathfd);
1085 #else
1086  hdf4_dmr->setHDF4Dataset(sdfd,fileid);
1087 #endif
1088  delete dmr; // The call below will make 'dmr' unreachable; delete it now to avoid a leak.
1089  bes_dmr.set_dmr(hdf4_dmr); // BESDMRResponse will delete hdf4_dmr
1090 
1091  // Instead of fiddling with the internal storage of the DHI object,
1092  // (by setting dhi.data[DAP4_CONSTRAINT], etc., directly) use these
1093  // methods to set the constraints. But, why? Ans: from Patrick is that
1094  // in the 'container' mode of BES each container can have a different
1095  // CE.
1096  bes_dmr.set_dap4_constraint(dhi);
1097  bes_dmr.set_dap4_function(dhi);
1098  hdf4_dmr->set_factory(0);
1099 
1100  return true;
1101 
1102 }
1103 
1104 #endif
1107  BESInfo *info = dynamic_cast<BESInfo *> (response);
1108  if (!info)
1109  throw BESInternalError("cast error", __FILE__, __LINE__);
1110 
1111  map < string, string > attrs;
1112  attrs["name"] = MODULE_NAME ;
1113  attrs["version"] = MODULE_VERSION ;
1114 #if 0
1115  attrs["name"] = PACKAGE_NAME;
1116  attrs["version"] = PACKAGE_VERSION;
1117 #endif
1118  list < string > services;
1120  if (services.size() > 0) {
1121  string handles = BESUtil::implode(services, ',');
1122  attrs["handles"] = handles;
1123  }
1124  info->begin_tag("module", &attrs);
1125  info->end_tag("module");
1126 
1127  return true;
1128 }
1129 
1132  BESVersionInfo *info = dynamic_cast<BESVersionInfo *> (response);
1133  if (!info)
1134  throw BESInternalError("cast error", __FILE__, __LINE__);
1135 
1136 #if 0
1138 #endif
1139  info->add_module(MODULE_NAME, MODULE_VERSION);
1140 
1141  return true;
1142 }
1143 
1144 #ifdef USE_HDFEOS2_LIB
1145 void close_fileid(int sdfd, int fileid,int gridfd, int swathfd,HDFSP:: File* h4file, HDFEOS2::File*eosfile) {
1146  if(h4file !=NULL)
1147  delete h4file;
1148  if(sdfd != -1)
1149  SDend(sdfd);
1150  if(fileid != -1)
1151  Hclose(fileid);
1152 
1153 
1154  if(eosfile !=NULL)
1155  delete eosfile;
1156  if(gridfd != -1)
1157  GDclose(gridfd);
1158  if(swathfd != -1)
1159  SWclose(swathfd);
1160 
1161 }
1162 #endif
1163 void close_hdf4_fileid(int sdfd, int fileid,HDFSP::File*h4file) {
1164 
1165  if(h4file !=NULL)
1166  delete h4file;
1167 
1168  if(sdfd != -1)
1169  SDend(sdfd);
1170  if(fileid != -1)
1171  Hclose(fileid);
1172 
1173 }
1174 
1175 
1176 #if 0
1177 void test_func(HDFSP::File**h4file) {
1178 cerr<<"OK to pass pointer of a NULL pointer "<<endl;
1179 
1180 }
1181 #endif
brief represents simple text information in a response object, such as version and help inforamtion...
void read_dds(DDS &dds, const string &filename)
Definition: hdfdesc.cc:3900
#define DAP4DATA_RESPONSE
Definition: BESDapNames.h:86
static bool hdf4_build_version(BESDataHandlerInterface &dhi)
void set_dds(DataDDS *ddsIn)
Set the response object's DDS.
static bool hdf4_build_data_with_IDs(BESDataHandlerInterface &dhi)
exception thrown if inernal error encountered
#define DMR_RESPONSE
Definition: BESDapNames.h:81
#define HDF4_NAME
string get_symbolic_name() const
retrieve the symbolic name for this container
Definition: BESContainer.h:197
static string lowercase(const string &s)
Convert a string to all lower case.
Definition: BESUtil.cc:182
Represents an OPeNDAP DDS DAP2 data object within the BES.
virtual void clear_container()
clear the container in the DAP response object
static bool hdf4_build_dds(BESDataHandlerInterface &dhi)
void setHDF4Dataset(const int sdfd_in, const int fileid_in, const int gridfd_in, const int swathfd_in)
Definition: HDF4_DDS.h:86
HDF4RequestHandler(const string &name)
This class retrieves all information from an HDF4 file. It is a container for SDS and Vdata...
Definition: HDFSP.h:727
virtual void set_dap4_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
bool read_das_hdfsp(DAS &das, const string &filename, int32 sdfd, int32 fileid, HDFSP::File **h4fileptr)
Definition: hdfdesc.cc:2251
bool read_dds_hdfsp(DDS &dds, const string &filename, int32 sdfd, int32 fileid, HDFSP::File *h4file)
Definition: hdfdesc.cc:2158
virtual string access()=0
returns the true name of this container
virtual void clear_container()
clear the container in the DAP response object
#define HELP_RESPONSE
virtual void set_dap4_function(BESDataHandlerInterface &dhi)
set the constraint depending on the context
informational response object
Definition: BESInfo.h:68
static string implode(const list< string > &values, char delim)
implode a list of values into a single string delimited by delim
Definition: BESUtil.cc:602
void close_hdf4_fileid(const int sdfd, const int fileid, HDFSP::File *h4file)
virtual BESResponseObject * get_response_object()
return the current response object
Abstract exception class for the BES with basic string message.
Definition: BESError.h:51
#define PACKAGE_NAME
Definition: config.h:244
#define DATA_RESPONSE
Definition: BESDapNames.h:70
static BESServiceRegistry * TheRegistry()
BESResponseHandler * response_handler
#define NULL
Definition: wcsUtil.h:65
virtual void set_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
virtual void begin_tag(const string &tag_name, map< string, string > *attrs=0)
Definition: BESInfo.cc:127
Represents an OPeNDAP DMR DAP4 data object within the BES.
virtual void set_container(const string &cn)
set the container in the DAP response object
error object created from libdap error objects and can handle those errors
Definition: BESDapError.h:51
void read_das(DAS &das, const string &filename)
Definition: hdfdesc.cc:3913
Represents an OPeNDAP DataDDS DAP2 data object within the BES.
static bool hdf4_build_help(BESDataHandlerInterface &dhi)
static bool hdf4_build_data(BESDataHandlerInterface &dhi)
virtual ~HDF4RequestHandler(void)
void close_fileid(hid_t fid)
closes HDF5 file reffered by fid.
Definition: h5get.cc:356
virtual void clear_container()
clear the container in the DAP response object
Represents a specific data type request handler.
void get_value(const string &s, string &val, bool &found)
Retrieve the value of a given key, if set.
Definition: BESKeys.cc:453
void set_dmr(DMR *dmr)
Structure storing information used by the BES to handle the request.
static bool hdf4_build_das(BESDataHandlerInterface &dhi)
This specialization of DDS is used to manage the 'resource' of the open HDF4 dataset handle so that t...
Definition: HDF4_DDS.h:40
static bool check_beskeys(const std::string &key)
Check the BES key. This function will check a BES key specified at the file h4.conf.in. If the key's value is either true or yes. The handler claims to find a key and will do some operations. Otherwise, will do different operations. For example, One may find a line H4.EnableCF=true at h4.conf.in. That means, the HDF4 handler will handle the HDF4 files by following CF conventions.
Definition: HDFCFUtil.cc:17
#define VERS_RESPONSE
virtual void set_container(const string &cn)
set the container in the DAP response object
virtual bool add_handler(const string &handler_name, p_request_handler handler_method)
add a handler method to the request handler that knows how to fill in a specific response object ...
#define PACKAGE_VERSION
Definition: config.h:256
Represents an OPeNDAP DAS DAP2 data object within the BES.
static BESKeys * TheKeys()
Definition: TheBESKeys.cc:48
virtual void set_container(const string &cn)
set the container in the DAP response object
virtual void add_module(const string &n, const string &v)
Abstract base class representing a specific set of information in response to a request to the BES...
#define DDS_RESPONSE
Definition: BESDapNames.h:60
BESContainer * container
pointer to current container in this interface
#define DAS_RESPONSE
Definition: BESDapNames.h:55
virtual void end_tag(const string &tag_name)
Definition: BESInfo.cc:132
virtual void services_handled(const string &handler, list< string > &services)
returns the list of servies provided by the handler in question