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 
HDF5Structure::read
virtual bool read()
Reads HDF5 structure data by calling each member's read method in this structure.
Definition: HDF5Structure.cc:69
HDF5Structure::ptr_duplicate
virtual libdap::BaseType * ptr_duplicate()
Definition: HDF5Structure.cc:41
h5dds.h
Data structure and retrieval processing header for the default option.
libdap
Definition: BESDapFunctionResponseCache.h:35
HDF5Structure
Definition: HDF5Structure.h:43
HDF5Structure.h
This class converts HDF5 compound type into DAP structure for the default option.
HDF5Array
Definition: HDF5Array.h:48
HDF5Structure::operator=
HDF5Structure & operator=(const HDF5Structure &rhs)
Assignment operator for dynamic cast into generic Structure.
Definition: HDF5Structure.cc:58
HDF5Structure::HDF5Structure
HDF5Structure(const std::string &n, const std::string &vpath, const std::string &d)
Constructor.
Definition: HDF5Structure.cc:46