bes Updated for version 3.20.10
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()
52{
53}
54HDF5Structure::HDF5Structure(const HDF5Structure &rhs) : Structure(rhs)
55{
56}
57
59{
60 if (this == &rhs)
61 return *this;
62
63 dynamic_cast < Structure & >(*this) = rhs; // run Structure assignment
64
65
66 return *this;
67}
68
70{
71
72 BESDEBUG("h5",
73 ">read() dataset=" << dataset()<<endl);
74
75 if (read_p())
76 return true;
77
78 hid_t file_id = H5Fopen(dataset().c_str(),H5F_ACC_RDONLY,H5P_DEFAULT);
79 if(file_id < 0) {
80 throw InternalErr(__FILE__,__LINE__, "Fail to obtain the HDF5 file ID .");
81 }
82
83 hid_t dset_id = -1;
84 if(true == is_dap4())
85 dset_id = H5Dopen2(file_id,var_path.c_str(),H5P_DEFAULT);
86 else
87 dset_id = H5Dopen2(file_id,name().c_str(),H5P_DEFAULT);
88
89 if(dset_id < 0) {
90 H5Fclose(file_id);
91 throw InternalErr(__FILE__,__LINE__, "Fail to obtain the datatype .");
92 }
93 vector<char> values;
94 hid_t dtypeid = H5Dget_type(dset_id);
95 if(dtypeid < 0) {
96 H5Dclose(dset_id);
97 H5Fclose(file_id);
98 throw InternalErr(__FILE__,__LINE__, "Fail to obtain the datatype .");
99 }
100 try {
101 do_structure_read(dset_id,dtypeid,values,false,0);
102 }
103 catch(...) {
104 H5Tclose(dtypeid);
105 H5Dclose(dset_id);
106 H5Fclose(file_id);
107 throw;
108 }
109 set_read_p(true);
110
111 H5Tclose(dtypeid);
112 H5Dclose(dset_id);
113 H5Fclose(file_id);
114
115 return true;
116}
117
118void HDF5Structure::do_structure_read(hid_t dsetid, hid_t dtypeid,vector <char> &values,bool has_values, int values_offset) {
119
120 hid_t memtype = -1;
121 hid_t mspace = -1;
122
123 if ((memtype = H5Tget_native_type(dtypeid, H5T_DIR_ASCEND))<0) {
124 throw InternalErr (__FILE__, __LINE__, "Fail to obtain memory datatype.");
125 }
126
127 if(false == has_values) {
128
129 if((mspace = H5Dget_space(dsetid))<0) {
130 throw InternalErr (__FILE__, __LINE__, "Fail to obtain memory datatype.");
131 }
132
133 size_t ty_size = H5Tget_size(memtype);
134 if (ty_size == 0) {
135 H5Tclose(memtype);
136 throw InternalErr (__FILE__, __LINE__,"Fail to obtain the size of HDF5 compound datatype.");
137 }
138
139 values.resize(ty_size);
140 hid_t read_ret = -1;
141 read_ret = H5Dread(dsetid,memtype,mspace,mspace,H5P_DEFAULT,(void*)&values[0]);
142 if (read_ret < 0) {
143 H5Tclose(memtype);
144 throw InternalErr (__FILE__, __LINE__, "Fail to read the HDF5 compound datatype dataset.");
145 }
146
147 has_values = true;
148 }
149
150 hid_t memb_id = -1;
151 H5T_class_t memb_cls = H5T_NO_CLASS;
152 int nmembs = 0;
153 size_t memb_offset = 0;
154 unsigned int u = 0;
155 char* memb_name = NULL;
156
157 try {
158 if((nmembs = H5Tget_nmembers(memtype)) < 0) {
159 throw InternalErr (__FILE__, __LINE__, "Fail to obtain number of HDF5 compound datatype.");
160 }
161
162 for(u = 0; u < (unsigned)nmembs; u++) {
163
164 if((memb_id = H5Tget_member_type(memtype, u)) < 0)
165 throw InternalErr (__FILE__, __LINE__, "Fail to obtain the datatype of an HDF5 compound datatype member.");
166
167 // Get member type class
168 if((memb_cls = H5Tget_member_class (memtype, u)) < 0)
169 throw InternalErr (__FILE__, __LINE__, "Fail to obtain the datatype class of an HDF5 compound datatype member.");
170
171 // Get member offset
172 memb_offset= H5Tget_member_offset(memtype,u);
173
174 // Get member name
175 memb_name = H5Tget_member_name(memtype,u);
176 if(memb_name == NULL)
177 throw InternalErr (__FILE__, __LINE__, "Fail to obtain the name of an HDF5 compound datatype member.");
178
179 if (memb_cls == H5T_COMPOUND) {
180 HDF5Structure &memb_h5s = dynamic_cast<HDF5Structure&>(*var(memb_name));
181 memb_h5s.do_structure_read(dsetid,memb_id,values,has_values,memb_offset+values_offset);
182 }
183 else if(memb_cls == H5T_ARRAY) {
184
185 // memb_id, obtain the number of dimensions
186 int at_ndims = H5Tget_array_ndims(memb_id);
187 if(at_ndims <= 0)
188 throw InternalErr (__FILE__, __LINE__, "Fail to obtain number of dimensions of the array datatype.");
189
190 HDF5Array &h5_array_type = dynamic_cast<HDF5Array&>(*var(memb_name));
191 vector<int> at_offset(at_ndims,0);
192 vector<int> at_count(at_ndims,0);
193 vector<int> at_step(at_ndims,0);
194
195 int at_nelms = h5_array_type.format_constraint(&at_offset[0],&at_step[0],&at_count[0]);
196
197 // Read the array data
198 h5_array_type.do_h5_array_type_read(dsetid, memb_id,values,has_values,memb_offset+values_offset,
199 at_nelms,&at_offset[0],&at_count[0],&at_step[0]);
200
201 }
202 else if(memb_cls == H5T_INTEGER || memb_cls == H5T_FLOAT) {
203 if(true == promote_char_to_short(memb_cls,memb_id)) {
204 void *src = (void*)(&values[0] + values_offset +memb_offset);
205 char val_int8;
206 memcpy(&val_int8,src,1);
207 short val_short=(short)val_int8;
208 var(memb_name)->val2buf(&val_short);
209 }
210 else {
211 var(memb_name)->val2buf(&values[0] + values_offset +memb_offset);
212
213 }
214 }
215 else if(memb_cls == H5T_STRING) {
216
217 // distinguish between variable length and fixed length
218 if(true == H5Tis_variable_str(memb_id)) {
219
220 void *src = (void*)(&values[0]+values_offset + memb_offset);
221 char*temp_bp = (char*)src;
222 string final_str ="";
223 get_vlen_str_data(temp_bp,final_str);
224 var(memb_name)->val2buf((void*)&final_str);
225
226 }
227 else {// Obtain string
228
229 void *src = (void*)(&values[0]+values_offset + memb_offset);
230 vector<char> str_val;
231 size_t memb_size = H5Tget_size(memb_id);
232 if (memb_size == 0) {
233 H5Tclose(memb_id);
234 free(memb_name);
235 throw InternalErr (__FILE__, __LINE__,"Fail to obtain the size of HDF5 compound datatype.");
236 }
237 str_val.resize(memb_size);
238 memcpy(&str_val[0],src,memb_size);
239 string temp_string(str_val.begin(),str_val.end());
240 var(memb_name)->val2buf(&temp_string);
241#if 0
242 // This doesn't work either. var(memb_name)->val2buf(&str_val[0]);
243
244 // We may just pass the string, (maybe string pad is preserved.)
245 // Probably not, DAP string may not keep the size. This doesn't work.
246 //var(memb_name)->val2buf(&values[0]+value_offset + memb_offset);
247#endif
248 }
249 }
250 else {
251 free(memb_name);
252 H5Tclose(memb_id);
253 throw InternalErr (__FILE__, __LINE__,
254 "Only support the field of compound datatype when the field type class is integer, float, string, array or compound..");
255
256 }
257 // Close member type ID
258 H5Tclose(memb_id);
259 var(memb_name)->set_read_p(true);
260 free(memb_name);
261 } // end for
262
263 }
264
265 catch(...) {
266 if((memtype != -1) && (mspace !=-1)) {
267 if(H5Dvlen_reclaim(memtype,mspace,H5P_DEFAULT,(void*)&values[0])<0)
268 throw InternalErr(__FILE__, __LINE__, "Unable to reclaim the compound datatype array.");
269 }
270 if(memtype != -1)
271 H5Tclose(memtype);
272 if(mspace != -1)
273 H5Sclose(mspace);
274
275 if(memb_id != -1)
276 H5Tclose(memb_id);
277
278 if(memb_name != NULL)
279 free(memb_name);
280 throw;
281 }
282
283 if((memtype != -1) && (mspace !=-1)) {
284 if(H5Dvlen_reclaim(memtype,mspace,H5P_DEFAULT,(void*)&values[0])<0)
285 throw InternalErr(__FILE__, __LINE__, "Unable to reclaim the compound datatype array.");
286 }
287 if(memtype != -1)
288 H5Tclose(memtype);
289 if(mspace != -1)
290 H5Sclose(mspace);
291}
292
This class converts HDF5 compound type into DAP structure for the default option.
virtual bool read()
Reads HDF5 structure data by calling each member's read method in this structure.
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.
virtual libdap::BaseType * ptr_duplicate()
Data structure and retrieval processing header for the default option.