bes  Updated for version 3.20.6
h5dds.cc
Go to the documentation of this file.
1 // This file is part of hdf5_handler a HDF5 file handler for the OPeNDAP
2 // data server.
3 
4 // Copyright (c) 2007-2015 The HDF Group, Inc. and OPeNDAP, Inc.
5 //
6 // This is free software; you can redistribute it and/or modify it under the
7 // terms of the GNU Lesser General Public License as published by the Free
8 // Software Foundation; either version 2.1 of the License, or (at your
9 // option) any later version.
10 //
11 // This software is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 // License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 //
20 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
21 // You can contact The HDF Group, Inc. at 1800 South Oak Street,
22 // Suite 203, Champaign, IL 61820
23 
37 
38 #include "config_hdf5.h"
39 
40 #include <InternalErr.h>
41 #include <BESDebug.h>
42 
43 #include <mime_util.h>
44 
45 #include "hdf5_handler.h"
46 #include "HDF5Int32.h"
47 #include "HDF5UInt32.h"
48 #include "HDF5UInt16.h"
49 #include "HDF5Int16.h"
50 #include "HDF5Byte.h"
51 #include "HDF5Array.h"
52 #include "HDF5Str.h"
53 #include "HDF5Float32.h"
54 #include "HDF5Float64.h"
55 #include "HDF5Url.h"
56 #include "HDF5Structure.h"
57 
58 //#include "h5get.h"
59 #include "HDF5CFUtil.h"
60 //#endif
61 
62 using namespace std;
63 using namespace libdap;
64 
66 static DS_t dt_inst;
67 
89 bool depth_first(hid_t pid, char *gname, DDS & dds, const char *fname)
90 {
91  BESDEBUG("h5",
92  ">depth_first()"
93  << " pid: " << pid
94  << " gname: " << gname
95  << " fname: " << fname
96  << endl);
97 
98  // Iterate through the file to see the members of the group from the root.
99  H5G_info_t g_info;
100  hsize_t nelems = 0;
101  if(H5Gget_info(pid,&g_info) <0) {
102  string msg =
103  "h5_dds handler: counting hdf5 group elements error for ";
104  msg += gname;
105  throw InternalErr(__FILE__, __LINE__, msg);
106  }
107 
108  nelems = g_info.nlinks;
109 
110  ssize_t oname_size;
111  for (hsize_t i = 0; i < nelems; i++) {
112 
113  vector <char>oname;
114 
115  // Query the length of object name.
116  oname_size =
117  H5Lget_name_by_idx(pid,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,NULL,
118  (size_t)DODS_NAMELEN, H5P_DEFAULT);
119  if (oname_size <= 0) {
120  string msg = "h5_dds handler: Error getting the size of the hdf5 object from the group: ";
121  msg += gname;
122  throw InternalErr(__FILE__, __LINE__, msg);
123  }
124 
125  // Obtain the name of the object
126  oname.resize((size_t) oname_size + 1);
127 
128  if (H5Lget_name_by_idx(pid,".",H5_INDEX_NAME,H5_ITER_NATIVE,i,&oname[0],
129  (size_t)(oname_size+1), H5P_DEFAULT) < 0){
130  string msg =
131  "h5_dds handler: Error getting the hdf5 object name from the group: ";
132  msg += gname;
133  throw InternalErr(__FILE__, __LINE__, msg);
134  }
135 
136  // Check if it is the hard link or the soft link
137  H5L_info_t linfo;
138  if (H5Lget_info(pid,&oname[0],&linfo,H5P_DEFAULT)<0) {
139  string msg = "hdf5 link name error from: ";
140  msg += gname;
141  throw InternalErr(__FILE__, __LINE__, msg);
142  }
143 
144  // External links are not supported in this release
145  if(linfo.type == H5L_TYPE_EXTERNAL)
146  continue;
147 
148  // Remember the information of soft links in DAS, not in DDS
149  if(linfo.type == H5L_TYPE_SOFT)
150  continue;
151 
152  // Obtain the object type, such as group or dataset.
153  H5O_info_t oinfo;
154 
155  if (H5Oget_info_by_idx(pid, ".", H5_INDEX_NAME, H5_ITER_NATIVE,
156  i, &oinfo, H5P_DEFAULT)<0) {
157  string msg = "h5_dds handler: Error obtaining the info for the object";
158  msg += string(oname.begin(),oname.end());
159  throw InternalErr(__FILE__, __LINE__, msg);
160  }
161 
162  H5O_type_t obj_type = oinfo.type;
163  switch (obj_type) {
164 
165  case H5O_TYPE_GROUP:
166  {
167 
168  // Obtain the full path name
169  string full_path_name =
170  string(gname) + string(oname.begin(),oname.end()-1) + "/";
171 
172  BESDEBUG("h5", "=depth_first():H5G_GROUP " << full_path_name
173  << endl);
174 
175  vector <char>t_fpn;
176  t_fpn.resize(full_path_name.length()+1);
177  copy(full_path_name.begin(),full_path_name.end(),t_fpn.begin());
178 
179  t_fpn[full_path_name.length()] = '\0';
180 
181  hid_t cgroup = H5Gopen(pid, &t_fpn[0],H5P_DEFAULT);
182  if (cgroup < 0){
183  throw InternalErr(__FILE__, __LINE__, "h5_dds handler: H5Gopen() failed.");
184  }
185 
186  // Check the hard link loop and break the loop if it exists.
187  // Note the function get_hardlink is defined in h5das.cc
188  string oid = get_hardlink(pid, &oname[0]);
189  if (oid == "") {
190  try {
191  depth_first(cgroup, &t_fpn[0], dds, fname);
192  }
193  catch(...) {
194  H5Gclose(cgroup);
195  throw;
196  }
197  }
198 
199  if (H5Gclose(cgroup) < 0){
200  throw InternalErr(__FILE__, __LINE__, "Could not close the group.");
201  }
202  break;
203  }
204 
205  case H5O_TYPE_DATASET:
206  {
207 
208  // Obtain the absolute path of the HDF5 dataset
209  string full_path_name = string(gname) + string(oname.begin(),oname.end()-1);
210 
211  // Obtain the hdf5 dataset handle stored in the structure dt_inst.
212  // All the metadata information in the handler is stored in dt_inst.
213  // Don't consider the dim. scale support for DAP2 now.
214  get_dataset(pid, full_path_name, &dt_inst,false);
215 
216  // Put the hdf5 dataset structure into DODS dds.
217  read_objects(dds, full_path_name, fname);
218  break;
219  }
220 
221  case H5O_TYPE_NAMED_DATATYPE:
222  // ignore the named datatype
223  break;
224  default:
225  break;
226  }
227 
228  } // for i is 0 ... nelems
229 
230  BESDEBUG("h5", "<depth_first() " << endl);
231  return true;
232 }
233 
255 void
256 read_objects_base_type(DDS & dds_table, const string & varname,
257  const string & filename)
258 {
259  // Obtain the DDS dataset name.
260  dds_table.set_dataset_name(name_path(filename));
261 
262  // Get a base type. It should be atomic datatype
263  // DDS: varname is the absolute path
264  BaseType *bt = Get_bt(varname, varname,filename, dt_inst.type,false);
265 
266  if (!bt) {
267  // NB: We're throwing InternalErr even though it's possible that
268  // someone might ask for an HDF5 varaible which this server cannot
269  // handle.
270  throw
271  InternalErr(__FILE__, __LINE__,
272  "Unable to convert hdf5 datatype to dods basetype");
273  }
274 
275  // First deal with scalar data.
276  if (dt_inst.ndims == 0) {
277  dds_table.add_var(bt);
278  delete bt; bt = 0;
279  }
280  else {
281 
282  // Next, deal with Array data. This 'else clause' runs to
283  // the end of the method. jhrg
284  HDF5Array *ar = new HDF5Array(varname, filename, bt);
285  delete bt; bt = 0;
286  ar->set_memneed(dt_inst.need);
287  ar->set_numdim(dt_inst.ndims);
288  ar->set_numelm((int) (dt_inst.nelmts));
289  for (int dim_index = 0; dim_index < dt_inst.ndims; dim_index++)
290  ar->append_dim(dt_inst.size[dim_index]);
291  dds_table.add_var(ar);
292  delete ar; ar = 0;
293  }
294 
295  BESDEBUG("h5", "<read_objects_base_type(dds)" << endl);
296 }
297 
309 void
310 read_objects_structure(DDS & dds_table, const string & varname,
311  const string & filename)
312 {
313  dds_table.set_dataset_name(name_path(filename));
314 
315  Structure *structure = Get_structure(varname, varname,filename, dt_inst.type,false);
316 
317  try {
318  // Assume Get_structure() uses exceptions to signal an error. jhrg
319  BESDEBUG("h5", "=read_objects_structure(): Dimension is "
320  << dt_inst.ndims << endl);
321 
322  if (dt_inst.ndims != 0) { // Array of Structure
323  BESDEBUG("h5", "=read_objects_structure(): array of size " <<
324  dt_inst.nelmts << endl);
325  BESDEBUG("h5", "=read_objects_structure(): memory needed = " <<
326  dt_inst.need << endl);
327  HDF5Array *ar = new HDF5Array(varname, filename, structure);
328  delete structure; structure = 0;
329  try {
330  ar->set_memneed(dt_inst.need);
331  ar->set_numdim(dt_inst.ndims);
332  ar->set_numelm((int) (dt_inst.nelmts));
333  ar->set_length((int) (dt_inst.nelmts));
334 
335  for (int dim_index = 0; dim_index < dt_inst.ndims; dim_index++) {
336  ar->append_dim(dt_inst.size[dim_index]);
337  BESDEBUG("h5", "=read_objects_structure(): append_dim = " <<
338  dt_inst.size[dim_index] << endl);
339  }
340 
341  dds_table.add_var(ar);
342  delete ar; ar = 0;
343  } // try Array *ar
344  catch (...) {
345  delete ar;
346  throw;
347  }
348  }
349  else {// A scalar structure
350 
351  dds_table.add_var(structure);
352  delete structure; structure = 0;
353  }
354 
355  } // try Structure *structure is Get_structure(...)
356  catch (...) {
357  delete structure;
358  throw;
359  }
360 }
361 
373 void
374 read_objects(DDS & dds_table, const string &varname, const string &filename)
375 {
376 
377  switch (H5Tget_class(dt_inst.type)) {
378 
379  // HDF5 compound maps to DAP structure.
380  case H5T_COMPOUND:
381  read_objects_structure(dds_table, varname, filename);
382  break;
383 
384  case H5T_ARRAY:
385  {
386  H5Tclose(dt_inst.type);
387  throw InternalErr(__FILE__, __LINE__, "Currently don't support accessing data of Array datatype when array datatype is not inside the compound.");
388  }
389  default:
390  read_objects_base_type(dds_table, varname, filename);
391  break;
392  }
393  // We must close the datatype obtained in the get_dataset routine since this is the end of reading DDS.
394  if(H5Tclose(dt_inst.type)<0) {
395  throw InternalErr(__FILE__, __LINE__, "Cannot close the HDF5 datatype.");
396  }
397 }
398 
read_objects_structure
void read_objects_structure(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:310
DODS_NAMELEN
const int DODS_NAMELEN
Maximum length of variable or attribute name(default option only).
Definition: hdf5_handler.h:64
HDF5Float32.h
A class for mapping HDF5 32-bit float to DAP for the default option.
HDF5Byte.h
This class provides a way to map HDF5 byte to DAP Byte for the default option.
depth_first
bool depth_first(hid_t pid, char *gname, DDS &dds, const char *fname)
Definition: h5dds.cc:89
DS
A structure for DDS generation.
Definition: hdf5_handler.h:70
HDF5CFUtil.h
This file includes several helper functions for translating HDF5 to CF-compliant.
HDF5UInt16.h
This class provides a way to map unsigned HDF5 16 bit integer to DAP UInt16 for the default option.
read_objects_base_type
void read_objects_base_type(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:256
HDF5Float64.h
A class for mapping HDF5 64-bit float to DAP for the default option.
HDF5UInt32.h
This class provides a way to map unsigned HDF5 32 bit integer to DAP UInt32.
HDF5Array::set_numdim
void set_numdim(int ndims)
remembers number of dimensions of this array.
Definition: HDF5Array.cc:1450
HDF5Array.h
A class for handling all types of array in HDF5 for the default option.
HDF5Int16.h
A class for HDF5 signed 16 bit integer type.
DS::need
hsize_t need
Space needed.
Definition: hdf5_handler.h:89
libdap
Definition: BESDapFunctionResponseCache.h:35
HDF5Array::set_memneed
void set_memneed(size_t need)
remembers memory size needed.
Definition: HDF5Array.cc:1446
HDF5Int32.h
This class provides a way to map HDF5 32 bit integer to DAP Int32 for the default option.
DS::ndims
int ndims
HDF5 data space id.
Definition: hdf5_handler.h:82
HDF5Array::set_numelm
void set_numelm(int nelms)
remembers number of elements in this array.
Definition: HDF5Array.cc:1454
DS::size
int size[DODS_MAX_RANK]
Size of each dimension.
Definition: hdf5_handler.h:84
get_hardlink
string get_hardlink(hid_t pgroup, const string &oname)
Definition: h5das.cc:614
read_objects
void read_objects(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:374
DS::type
hid_t type
HDF5 data set id.
Definition: hdf5_handler.h:78
HDF5Structure.h
This class converts HDF5 compound type into DAP structure for the default option.
HDF5Str.h
This class that translates HDF5 string into DAP string for the default option.
DS::nelmts
hsize_t nelmts
Number of elements.
Definition: hdf5_handler.h:87
HDF5Array
Definition: HDF5Array.h:48
HDF5Url.h
This class generates DAP URL type for the default option.
hdf5_handler.h
The main header of the HDF5 OPeNDAP handler.