bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
HDF5Structure.cc
Go to the documentation of this file.
1
2// This file is part of the hdf5 data handler for the OPeNDAP data server.
3//
4// Copyright (c) 2005 OPeNDAP, Inc.
5// Copyright (c) 2007-2023 The HDF Group, Inc.
6// Author: James Gallagher <jgallagher@opendap.org>
7// Hyo-Kyung Lee <hyoklee@hdfgroup.org>
8// Kent Yang <myang6@hdfgroup.org>
9//
10// This is free software; you can redistribute it and/or modify it under the
11// terms of the GNU Lesser General Public License as published by the Free
12// Software Foundation; either version 2.1 of the License, or (at your
13// option) any later version.
14//
15// This software is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18// License for more details.
19//
20// You should have received a copy of the GNU Lesser General Public License
21// along with this software; if not, write to the Free Software Foundation,
22// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
27
28#include <memory>
29#include "hdf5.h"
30#include "h5dds.h"
31#include "HDF5Structure.h"
32#include <libdap/InternalErr.h>
33#include "BESDebug.h"
34
35using namespace std;
36using namespace libdap;
37
39{
40 auto HDF5Structure_unique = make_unique<HDF5Structure>(*this);
41 return HDF5Structure_unique.release();
42}
43
44HDF5Structure::HDF5Structure(const string & n, const string &vpath, const string &d)
45 : Structure(n, d),var_path(vpath)
46{
47}
48
49HDF5Structure::HDF5Structure(const HDF5Structure &rhs) : Structure(rhs)
50{
51 m_duplicate(rhs);
52}
53
55{
56 if (this == &rhs)
57 return *this;
58
59 libdap::Structure::operator=(rhs);
60 m_duplicate(rhs);
61
62 return *this;
63}
64
66{
67
68 BESDEBUG("h5",
69 ">read() dataset=" << dataset()<<endl);
70
71 if (read_p())
72 return true;
73
74 hid_t file_id = H5Fopen(dataset().c_str(),H5F_ACC_RDONLY,H5P_DEFAULT);
75 if (file_id < 0) {
76 throw InternalErr(__FILE__,__LINE__, "Fail to obtain the HDF5 file ID .");
77 }
78
79 hid_t dset_id = -1;
80 if (true == is_dap4())
81 dset_id = H5Dopen2(file_id,var_path.c_str(),H5P_DEFAULT);
82 else
83 dset_id = H5Dopen2(file_id,name().c_str(),H5P_DEFAULT);
84
85 if(dset_id < 0) {
86 H5Fclose(file_id);
87 throw InternalErr(__FILE__,__LINE__, "Fail to obtain the datatype .");
88 }
89
90 vector<char> values;
91 hid_t dtypeid = H5Dget_type(dset_id);
92 if(dtypeid < 0) {
93 H5Dclose(dset_id);
94 H5Fclose(file_id);
95 throw InternalErr(__FILE__,__LINE__, "Fail to obtain the datatype .");
96 }
97 try {
98 do_structure_read(dset_id,dtypeid,values,false,0);
99 }
100 catch(...) {
101 H5Tclose(dtypeid);
102 H5Dclose(dset_id);
103 H5Fclose(file_id);
104 throw;
105 }
106 set_read_p(true);
107
108 H5Tclose(dtypeid);
109 H5Dclose(dset_id);
110 H5Fclose(file_id);
111
112 return true;
113}
114
115void HDF5Structure::do_structure_read(hid_t dsetid, hid_t dtypeid,vector <char> &values,bool has_values, size_t values_offset) {
116
117 hid_t memtype = -1;
118 hid_t mspace = -1;
119
120 if ((memtype = H5Tget_native_type(dtypeid, H5T_DIR_ASCEND)) < 0) {
121 throw InternalErr(__FILE__, __LINE__, "Fail to obtain memory datatype.");
122 }
123
124 if ((mspace = H5Dget_space(dsetid)) < 0) {
125 throw InternalErr(__FILE__, __LINE__, "Fail to obtain memory datatype.");
126 }
127 if (false == has_values) {
128
129 size_t ty_size = H5Tget_size(memtype);
130 values.resize(ty_size);
131
132 hid_t read_ret = H5Dread(dsetid, memtype, mspace, mspace, H5P_DEFAULT, (void *) values.data());
133 if (read_ret < 0) {
134 H5Tclose(memtype);
135 throw InternalErr(__FILE__, __LINE__, "Fail to read the HDF5 compound datatype dataset.");
136 }
137
138 has_values = true;
139 }
140
141 hid_t memb_id = -1;
142 H5T_class_t memb_cls = H5T_NO_CLASS;
143 int nmembs = 0;
144 size_t memb_offset = 0;
145 char *memb_name = nullptr;
146
147 try {
148 if ((nmembs = H5Tget_nmembers(memtype)) < 0) {
149 throw InternalErr(__FILE__, __LINE__, "Fail to obtain number of HDF5 compound datatype.");
150 }
151
152 for (unsigned int u = 0; u < (unsigned) nmembs; u++) {
153
154 if ((memb_id = H5Tget_member_type(memtype, u)) < 0)
155 throw InternalErr(__FILE__, __LINE__,
156 "Fail to obtain the datatype of an HDF5 compound datatype member.");
157
158 // Get member type class
159 memb_cls = H5Tget_member_class(memtype, u);
160
161 // Get member offset
162 memb_offset = H5Tget_member_offset(memtype, u);
163
164 // Get member name
165 memb_name = H5Tget_member_name(memtype, u);
166 if (memb_name == nullptr)
167 throw InternalErr(__FILE__, __LINE__, "Fail to obtain the name of an HDF5 compound datatype member.");
168
169 if (memb_cls == H5T_COMPOUND) {
170 HDF5Structure &memb_h5s = dynamic_cast<HDF5Structure &>(*var(memb_name));
171 memb_h5s.do_structure_read(dsetid, memb_id, values, has_values, memb_offset + values_offset);
172 } else if (memb_cls == H5T_ARRAY) {
173
174 // memb_id, obtain the number of dimensions
175 int at_ndims = H5Tget_array_ndims(memb_id);
176 if (at_ndims <= 0)
177 throw InternalErr(__FILE__, __LINE__, "Fail to obtain number of dimensions of the array datatype.");
178
179 HDF5Array &h5_array_type = dynamic_cast<HDF5Array &>(*var(memb_name));
180 vector<int64_t> at_offset(at_ndims, 0);
181 vector<int64_t> at_count(at_ndims, 0);
182 vector<int64_t> at_step(at_ndims, 0);
183
184 int64_t at_nelms = h5_array_type.format_constraint(at_offset.data(), at_step.data(), at_count.data());
185
186 // Read the array data
187 h5_array_type.do_h5_array_type_read(dsetid, memb_id, values, has_values, memb_offset + values_offset,
188 at_nelms, at_offset.data(), at_count.data(), at_step.data());
189
190 } else if (memb_cls == H5T_INTEGER || memb_cls == H5T_FLOAT || memb_cls == H5T_STRING) {
191 do_structure_read_atomic(memb_id, memb_name, memb_cls, values, values_offset, memb_offset);
192 } else {
193 free(memb_name);
194 H5Tclose(memb_id);
195 throw InternalErr(__FILE__, __LINE__,
196 "Only support the field of compound datatype when the field type class is integer, float, string, array or compound..");
197 }
198 // Close member type ID
199 H5Tclose(memb_id);
200 var(memb_name)->set_read_p(true);
201 free(memb_name);
202 } // end for
203
204 }
205
206 catch (...) {
207 catch_free(memb_name, memb_id, memtype, mspace, values);
208 throw;
209 }
210
211 if (H5Dvlen_reclaim(memtype, mspace, H5P_DEFAULT, (void *) values.data()) < 0)
212 throw InternalErr(__FILE__, __LINE__, "Unable to reclaim the compound datatype array.");
213
214 H5Tclose(memtype);
215 H5Sclose(mspace);
216}
217
218void HDF5Structure::do_structure_read_atomic(hid_t memb_id, char *memb_name, H5T_class_t memb_cls,
219 const vector<char> &values, size_t values_offset,
220 size_t memb_offset) {
221
222
223 if (memb_cls == H5T_INTEGER || memb_cls == H5T_FLOAT) {
224 void *src = (void *) (values.data() + values_offset + memb_offset);
225
226 if (true == promote_char_to_short(memb_cls, memb_id) && is_dap4() == false) {
227 char val_int8;
228 memcpy(&val_int8, src, 1);
229 auto val_short = (short) val_int8;
230 var(memb_name)->val2buf(&val_short);
231 } else {
232 var(memb_name)->val2buf(src);
233 }
234 } else if (memb_cls == H5T_STRING) {
235 do_structure_read_string(memb_id, memb_name, values, values_offset, memb_offset);
236
237 }
238}
239
240void HDF5Structure::do_structure_read_string(hid_t memb_id, char *memb_name,
241 const vector<char> &values, size_t values_offset,
242 size_t memb_offset) {
243
244 void *src = (void *) (values.data() + values_offset + memb_offset);
245
246 // distinguish between variable length and fixed length
247 if (true == H5Tis_variable_str(memb_id)) {
248
249 auto temp_bp = (char *) src;
250 string final_str;
251 get_vlen_str_data(temp_bp, final_str);
252 var(memb_name)->val2buf((void *) &final_str);
253
254 } else {// Obtain string
255
256 vector<char> str_val;
257 size_t memb_size = H5Tget_size(memb_id);
258 if (memb_size == 0) {
259 H5Tclose(memb_id);
260 free(memb_name);
261 throw InternalErr(__FILE__, __LINE__, "Fail to obtain the size of HDF5 compound datatype.");
262 }
263 str_val.resize(memb_size);
264 memcpy(str_val.data(), src, memb_size);
265 string temp_string(str_val.begin(), str_val.end());
266 var(memb_name)->val2buf(&temp_string);
267
268 }
269}
270
271void HDF5Structure::catch_free(char *memb_name, hid_t memb_id, hid_t memtype, hid_t mspace, vector<char>&values) const {
272
273 if ((memtype != -1) && (mspace != -1) && (H5Dvlen_reclaim(memtype, mspace,
274 H5P_DEFAULT, (void *) values.data()) < 0)) {
275 throw InternalErr(__FILE__, __LINE__, "Unable to reclaim the compound datatype array.");
276 }
277 if (memtype != -1)
278 H5Tclose(memtype);
279 if (mspace != -1)
280 H5Sclose(mspace);
281
282 if (memb_id != -1)
283 H5Tclose(memb_id);
284
285 if (memb_name != nullptr)
286 free(memb_name);
287}
This class converts HDF5 compound type into DAP structure for the default option.
HDF5Structure(const std::string &n, const std::string &vpath, const std::string &d)
Constructor.
HDF5Structure & operator=(const HDF5Structure &rhs)
Assignment operator for dynamic cast into generic Structure.
libdap::BaseType * ptr_duplicate() override
bool read() override
Reads HDF5 structure data by calling each member's read method in this structure.
Data structure and retrieval processing header for the default option.