bes  Updated for version 3.20.10
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 <libdap/InternalErr.h>
41 #include <BESDebug.h>
42 
43 #include <libdap/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  get_dataset(pid, full_path_name, &dt_inst);
216 
217  // Put the hdf5 dataset structure into DODS dds.
218  read_objects(dds, full_path_name, fname);
219  break;
220  }
221 
222  case H5O_TYPE_NAMED_DATATYPE:
223  // ignore the named datatype
224  break;
225  default:
226  break;
227  }
228 
229  } // for i is 0 ... nelems
230 
231  BESDEBUG("h5", "<depth_first() " << endl);
232  return true;
233 }
234 
256 void
257 read_objects_base_type(DDS & dds_table, const string & varname,
258  const string & filename)
259 {
260  // Obtain the DDS dataset name.
261  dds_table.set_dataset_name(name_path(filename));
262 
263  // Get a base type. It should be atomic datatype
264  // DDS: varname is the absolute path
265  BaseType *bt = Get_bt(varname, varname,filename, dt_inst.type,false);
266 
267  if (!bt) {
268  // NB: We're throwing InternalErr even though it's possible that
269  // someone might ask for an HDF5 varaible which this server cannot
270  // handle.
271  throw
272  InternalErr(__FILE__, __LINE__,
273  "Unable to convert hdf5 datatype to dods basetype");
274  }
275 
276  // First deal with scalar data.
277  if (dt_inst.ndims == 0) {
278  dds_table.add_var(bt);
279  delete bt; bt = 0;
280  }
281  else {
282 
283  // Next, deal with Array data. This 'else clause' runs to
284  // the end of the method. jhrg
285  HDF5Array *ar = new HDF5Array(varname, filename, bt);
286  delete bt; bt = 0;
287  ar->set_memneed(dt_inst.need);
288  ar->set_numdim(dt_inst.ndims);
289  ar->set_numelm((int) (dt_inst.nelmts));
290  for (int dim_index = 0; dim_index < dt_inst.ndims; dim_index++)
291  ar->append_dim(dt_inst.size[dim_index]);
292  dds_table.add_var(ar);
293  delete ar; ar = 0;
294  }
295 
296  BESDEBUG("h5", "<read_objects_base_type(dds)" << endl);
297 }
298 
310 void
311 read_objects_structure(DDS & dds_table, const string & varname,
312  const string & filename)
313 {
314  dds_table.set_dataset_name(name_path(filename));
315 
316  Structure *structure = Get_structure(varname, varname,filename, dt_inst.type,false);
317 
318  try {
319  // Assume Get_structure() uses exceptions to signal an error. jhrg
320  BESDEBUG("h5", "=read_objects_structure(): Dimension is "
321  << dt_inst.ndims << endl);
322 
323  if (dt_inst.ndims != 0) { // Array of Structure
324  BESDEBUG("h5", "=read_objects_structure(): array of size " <<
325  dt_inst.nelmts << endl);
326  BESDEBUG("h5", "=read_objects_structure(): memory needed = " <<
327  dt_inst.need << endl);
328  HDF5Array *ar = new HDF5Array(varname, filename, structure);
329  delete structure; structure = 0;
330  try {
331  ar->set_memneed(dt_inst.need);
332  ar->set_numdim(dt_inst.ndims);
333  ar->set_numelm((int) (dt_inst.nelmts));
334  ar->set_length((int) (dt_inst.nelmts));
335 
336  for (int dim_index = 0; dim_index < dt_inst.ndims; dim_index++) {
337  ar->append_dim(dt_inst.size[dim_index]);
338  BESDEBUG("h5", "=read_objects_structure(): append_dim = " <<
339  dt_inst.size[dim_index] << endl);
340  }
341 
342  dds_table.add_var(ar);
343  delete ar; ar = 0;
344  } // try Array *ar
345  catch (...) {
346  delete ar;
347  throw;
348  }
349  }
350  else {// A scalar structure
351 
352  dds_table.add_var(structure);
353  delete structure; structure = 0;
354  }
355 
356  } // try Structure *structure is Get_structure(...)
357  catch (...) {
358  delete structure;
359  throw;
360  }
361 }
362 
374 void
375 read_objects(DDS & dds_table, const string &varname, const string &filename)
376 {
377 
378  switch (H5Tget_class(dt_inst.type)) {
379 
380  // HDF5 compound maps to DAP structure.
381  case H5T_COMPOUND:
382  read_objects_structure(dds_table, varname, filename);
383  break;
384 
385  case H5T_ARRAY:
386  {
387  H5Tclose(dt_inst.type);
388  throw InternalErr(__FILE__, __LINE__, "Currently don't support accessing data of Array datatype when array datatype is not inside the compound.");
389  }
390  default:
391  read_objects_base_type(dds_table, varname, filename);
392  break;
393  }
394  // We must close the datatype obtained in the get_dataset routine since this is the end of reading DDS.
395  if(H5Tclose(dt_inst.type)<0) {
396  throw InternalErr(__FILE__, __LINE__, "Cannot close the HDF5 datatype.");
397  }
398 }
399 
A class for handling all types of array in HDF5 for the default option.
This class provides a way to map HDF5 byte to DAP Byte for the default option.
This file includes several helper functions for translating HDF5 to CF-compliant.
A class for mapping HDF5 32-bit float to DAP for the default option.
A class for mapping HDF5 64-bit float to DAP for the default option.
A class for HDF5 signed 16 bit integer type.
This class provides a way to map HDF5 32 bit integer to DAP Int32 for the default option.
This class that translates HDF5 string into DAP string for the default option.
This class converts HDF5 compound type into DAP structure for the default option.
This class provides a way to map unsigned HDF5 16 bit integer to DAP UInt16 for the default option.
This class provides a way to map unsigned HDF5 32 bit integer to DAP UInt32.
This class generates DAP URL type for the default option.
void set_numdim(int ndims)
remembers number of dimensions of this array.
Definition: HDF5Array.cc:1737
void set_numelm(int nelms)
remembers number of elements in this array.
Definition: HDF5Array.cc:1741
void set_memneed(size_t need)
remembers memory size needed.
Definition: HDF5Array.cc:1733
string get_hardlink(hid_t pgroup, const string &oname)
Definition: h5das.cc:619
void read_objects_base_type(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:257
bool depth_first(hid_t pid, char *gname, DDS &dds, const char *fname)
Definition: h5dds.cc:89
void read_objects(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:375
void read_objects_structure(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:311
void get_dataset(hid_t pid, const string &dname, DS_t *dt_inst_ptr)
Definition: h5get.cc:452
The main header of the HDF5 OPeNDAP handler.
const int DODS_NAMELEN
Maximum length of variable or attribute name(default option only).
Definition: hdf5_handler.h:65
A structure for DDS generation.
Definition: hdf5_handler.h:71
hsize_t nelmts
Number of elements.
Definition: hdf5_handler.h:89
hsize_t need
Space needed.
Definition: hdf5_handler.h:91
hid_t type
HDF5 data set id.
Definition: hdf5_handler.h:79
int size[DODS_MAX_RANK]
Size of each dimension.
Definition: hdf5_handler.h:85
int ndims
HDF5 data space id.
Definition: hdf5_handler.h:83