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 
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:1450
void set_numelm(int nelms)
remembers number of elements in this array.
Definition: HDF5Array.cc:1454
void set_memneed(size_t need)
remembers memory size needed.
Definition: HDF5Array.cc:1446
string get_hardlink(hid_t pgroup, const string &oname)
Definition: h5das.cc:614
void read_objects_base_type(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:256
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:374
void read_objects_structure(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:310
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:64
A structure for DDS generation.
Definition: hdf5_handler.h:70
hsize_t nelmts
Number of elements.
Definition: hdf5_handler.h:87
hsize_t need
Space needed.
Definition: hdf5_handler.h:89
hid_t type
HDF5 data set id.
Definition: hdf5_handler.h:78
int size[DODS_MAX_RANK]
Size of each dimension.
Definition: hdf5_handler.h:84
int ndims
HDF5 data space id.
Definition: hdf5_handler.h:82