bes  Updated for version 3.20.13
HDF5Structure.cc
Go to the documentation of this file.
1 // 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 
38 using namespace std;
39 using namespace libdap;
40 
42 {
43  return new HDF5Structure(*this);
44 }
45 
46 HDF5Structure::HDF5Structure(const string & n, const string &vpath, const string &d)
47  : Structure(n, d),var_path(vpath)
48 {
49 }
50 
51 HDF5Structure::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 
120 void 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.