bes Updated for version 3.20.13
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
62using namespace std;
63using namespace libdap;
64
66static DS_t dt_inst;
67
89bool depth_first(hid_t pid,const 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,nullptr,
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.data(),
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.data(),&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.data(),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.data());
189 if (oid == "") {
190 try {
191 depth_first(cgroup, t_fpn.data(), 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#if 0
215 //get_dataset(pid, full_path_name, &dt_inst,false);
216#endif
217 get_dataset(pid, full_path_name, &dt_inst);
218
219 // Put the hdf5 dataset structure into DODS dds.
220 read_objects(dds, full_path_name, fname);
221 break;
222 }
223
224 case H5O_TYPE_NAMED_DATATYPE:
225 // ignore the named datatype
226 break;
227 default:
228 break;
229 }
230
231 } // for i is 0 ... nelems
232
233 BESDEBUG("h5", "<depth_first() " << endl);
234 return true;
235}
236
258void
259read_objects_base_type(DDS & dds_table, const string & varname,
260 const string & filename)
261{
262 // Obtain the DDS dataset name.
263 dds_table.set_dataset_name(name_path(filename));
264
265 // Get a base type. It should be atomic datatype
266 // DDS: varname is the absolute path
267 BaseType *bt = Get_bt(varname, varname,filename, dt_inst.type,false);
268
269 if (!bt) {
270 // NB: We're throwing InternalErr even though it's possible that
271 // someone might ask for an HDF5 varaible which this server cannot
272 // handle.
273 throw
274 InternalErr(__FILE__, __LINE__,
275 "Unable to convert hdf5 datatype to dods basetype");
276 }
277
278 // First deal with scalar data.
279 if (dt_inst.ndims == 0) {
280 dds_table.add_var(bt);
281 delete bt; bt = nullptr;
282 }
283 else {
284
285 // Next, deal with Array data. This 'else clause' runs to
286 // the end of the method. jhrg
287 auto ar = new HDF5Array(varname, filename, bt);
288 delete bt; bt = 0;
289 ar->set_memneed(dt_inst.need);
290 ar->set_numdim(dt_inst.ndims);
291 ar->set_numelm((int) (dt_inst.nelmts));
292 for (int dim_index = 0; dim_index < dt_inst.ndims; dim_index++)
293 ar->append_dim(dt_inst.size[dim_index]);
294 dds_table.add_var(ar);
295 delete ar; ar = nullptr;
296 }
297
298 BESDEBUG("h5", "<read_objects_base_type(dds)" << endl);
299}
300
312void
313read_objects_structure(DDS & dds_table, const string & varname,
314 const string & filename)
315{
316 dds_table.set_dataset_name(name_path(filename));
317
318 Structure *structure = Get_structure(varname, varname,filename, dt_inst.type,false);
319
320 try {
321 // Assume Get_structure() uses exceptions to signal an error. jhrg
322 BESDEBUG("h5", "=read_objects_structure(): Dimension is "
323 << dt_inst.ndims << endl);
324
325 if (dt_inst.ndims != 0) { // Array of Structure
326 BESDEBUG("h5", "=read_objects_structure(): array of size " <<
327 dt_inst.nelmts << endl);
328 BESDEBUG("h5", "=read_objects_structure(): memory needed = " <<
329 dt_inst.need << endl);
330 auto ar = new HDF5Array(varname, filename, structure);
331 delete structure; structure = nullptr;
332 try {
333 ar->set_memneed(dt_inst.need);
334 ar->set_numdim(dt_inst.ndims);
335 ar->set_numelm((int) (dt_inst.nelmts));
336 ar->set_length((int) (dt_inst.nelmts));
337
338 for (int dim_index = 0; dim_index < dt_inst.ndims; dim_index++) {
339 ar->append_dim(dt_inst.size[dim_index]);
340 BESDEBUG("h5", "=read_objects_structure(): append_dim = " <<
341 dt_inst.size[dim_index] << endl);
342 }
343
344 dds_table.add_var(ar);
345 delete ar; ar = nullptr;
346 } // try Array *ar
347 catch (...) {
348 delete ar;
349 throw;
350 }
351 }
352 else {// A scalar structure
353
354 dds_table.add_var(structure);
355 delete structure; structure = nullptr;
356 }
357
358 } // try Structure *structure is Get_structure(...)
359 catch (...) {
360 delete structure;
361 throw;
362 }
363}
364
376void
377read_objects(DDS & dds_table, const string &varname, const string &filename)
378{
379
380 switch (H5Tget_class(dt_inst.type)) {
381
382 // HDF5 compound maps to DAP structure.
383 case H5T_COMPOUND:
384 read_objects_structure(dds_table, varname, filename);
385 break;
386
387 case H5T_ARRAY:
388 {
389 H5Tclose(dt_inst.type);
390 throw InternalErr(__FILE__, __LINE__, "Currently don't support accessing data of Array datatype when array datatype is not inside the compound.");
391 }
392 default:
393 read_objects_base_type(dds_table, varname, filename);
394 break;
395 }
396 // We must close the datatype obtained in the get_dataset routine since this is the end of reading DDS.
397 if(H5Tclose(dt_inst.type)<0) {
398 throw InternalErr(__FILE__, __LINE__, "Cannot close the HDF5 datatype.");
399 }
400}
401
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.
string get_hardlink(hid_t pgroup, const string &oname)
Definition: h5das.cc:604
bool depth_first(hid_t pid, const char *gname, DDS &dds, const char *fname)
Definition: h5dds.cc:89
void read_objects_base_type(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:259
void read_objects(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:377
void read_objects_structure(DDS &dds_table, const string &varname, const string &filename)
Definition: h5dds.cc:313
void get_dataset(hid_t pid, const string &dname, DS_t *dt_inst_ptr)
Definition: h5get.cc:453
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:91
hsize_t need
Space needed.
Definition: hdf5_handler.h:93
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:87
int ndims
HDF5 data space id.
Definition: hdf5_handler.h:85