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
62using namespace std;
63using namespace libdap;
64
66static DS_t dt_inst;
67
89bool 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
256void
257read_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
310void
311read_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
374void
375read_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