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