bes  Updated for version 3.20.6
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 "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()
52 {
53 }
54 HDF5Structure::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 
118 void 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.