OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
HDFCFStrField.cc
Go to the documentation of this file.
1 // This file is part of the hdf4 data handler for the OPeNDAP data server.
3 // It retrieves the HDF4 DFNT_CHAR >1D array and then send to DAP as a DAP string array for the CF option.
4 // Authors: MuQun Yang <myang6@hdfgroup.org>
5 // Copyright (c) 2010-2012 The HDF Group
7 
8 #include <iostream>
9 #include <sstream>
10 #include <cassert>
11 #include <debug.h>
12 #include "InternalErr.h"
13 #include <BESDebug.h>
14 #include <BESLog.h>
15 
16 #include "HDFCFUtil.h"
17 #include "HDFCFStrField.h"
18 
19 using namespace std;
20 
21 
22 bool
24 {
25 
26  BESDEBUG("h4","Coming to HDFCFStrField read "<<endl);
27 
28  string check_pass_fileid_key_str="H4.EnablePassFileID";
29  bool check_pass_fileid_key = false;
30  check_pass_fileid_key = HDFCFUtil::check_beskeys(check_pass_fileid_key_str);
31 
32  // Note that one dimensional character array is one string,
33  // so the rank for character arrays should be rank from string+1
34  // offset32,step32 and count32 will be new subsetting parameters for
35  // character arrays.
36  vector<int32>offset32;
37  offset32.resize(rank+1);
38  vector<int32>count32;
39  count32.resize(rank+1);
40  vector<int32>step32;
41  step32.resize(rank+1);
42  int nelms = 1;
43 
44  if (rank != 0) {
45 
46  // Declare offset, count and step,
47  vector<int>offset;
48  offset.resize(rank);
49  vector<int>count;
50  count.resize(rank);
51  vector<int>step;
52  step.resize(rank);
53 
54  // Declare offset, count and step,
55  // Note that one dimensional character array is one string,
56  // so the rank for character arrays should be rank from string+1
57  // Obtain offset,step and count from the client expression constraint
58  nelms = format_constraint (&offset[0], &step[0], &count[0]);
59 
60  // Assign the offset32,count32 and step32 up to the dimension rank-1.
61  // Will assign the dimension rank later.
62  for (int i = 0; i < rank; i++) {
63  offset32[i] = (int32) offset[i];
64  count32[i] = (int32) count[i];
65  step32[i] = (int32) step[i];
66  }
67  }
68 
69 
70  // Initialize the temp. returned value.
71  int32 r = 0;
72 
73  // First SDS
74  if(false == is_vdata) {
75 
76  int32 sdid = -1;
77  if(false == check_pass_fileid_key) {
78  sdid = SDstart (const_cast < char *>(filename.c_str ()), DFACC_READ);
79  if (sdid < 0) {
80  ostringstream eherr;
81  eherr << "File " << filename.c_str () << " cannot be open.";
82  throw InternalErr (__FILE__, __LINE__, eherr.str ());
83  }
84  }
85  else
86  sdid = h4fd;
87 
88  int32 sdsid = 0;
89 
90  int32 sdsindex = SDreftoindex (sdid, fieldref);
91  if (sdsindex == -1) {
92  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
93  ostringstream eherr;
94  eherr << "SDS index " << sdsindex << " is not right.";
95  throw InternalErr (__FILE__, __LINE__, eherr.str ());
96  }
97 
98  // Obtain this SDS ID.
99  sdsid = SDselect (sdid, sdsindex);
100  if (sdsid < 0) {
101  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
102  ostringstream eherr;
103  eherr << "SDselect failed.";
104  throw InternalErr (__FILE__, __LINE__, eherr.str ());
105  }
106 
107  int32 dim_sizes[H4_MAX_VAR_DIMS];
108  int32 sds_rank, data_type, n_attrs;
109  char name[H4_MAX_NC_NAME];
110 
111  r = SDgetinfo (sdsid, name, &sds_rank, dim_sizes,
112  &data_type, &n_attrs);
113  if(r == FAIL) {
114  SDendaccess(sdsid);
115  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
116  ostringstream eherr;
117  eherr << "SDgetinfo failed.";
118  throw InternalErr (__FILE__, __LINE__, eherr.str ());
119  }
120 
121  if(sds_rank != (rank+1)) {
122  SDendaccess(sdsid);
123  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
124  ostringstream eherr;
125  eherr << "The rank of string doesn't match with the rank of character array";
126  throw InternalErr (__FILE__, __LINE__, eherr.str ());
127 
128  }
129  offset32[rank] = 0;
130  count32[rank] = dim_sizes[rank];
131  step32[rank] = 1;
132  int32 last_dim_size = dim_sizes[rank];
133 
134  vector<char>val;
135  val.resize(nelms*count32[rank]);
136 
137  r = SDreaddata (sdsid, &offset32[0], &step32[0], &count32[0], &val[0]);
138  if (r != 0) {
139  SDendaccess (sdsid);
140  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
141  ostringstream eherr;
142  eherr << "SDreaddata failed.";
143  throw InternalErr (__FILE__, __LINE__, eherr.str ());
144  }
145 
146  vector<string>final_val;
147  final_val.resize(nelms);
148  vector<char> temp_buf;
149  temp_buf.resize(last_dim_size+1);
150 
151  // Since the number of the dimension for a string is reduced by 1,
152  // the value of each string is the subset of the whole last dimension
153  // of the original array.
154  for (int i = 0; i<nelms;i++) {
155  strncpy(&temp_buf[0],&val[0]+last_dim_size*i,last_dim_size);
156  temp_buf[last_dim_size]='\0';
157  final_val[i] = &temp_buf[0];
158  }
159  set_value(&final_val[0],nelms);
160  SDendaccess(sdsid);
161  HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
162 
163  }
164  else {
165 
166  int32 file_id = -1;
167 
168  if(true == check_pass_fileid_key)
169  file_id = h4fd;
170  else {
171  // Open the file
172  file_id = Hopen (filename.c_str (), DFACC_READ, 0);
173  if (file_id < 0) {
174  ostringstream eherr;
175  eherr << "File " << filename.c_str () << " cannot be open.";
176  throw InternalErr (__FILE__, __LINE__, eherr.str ());
177  }
178  }
179 
180  // Start the Vdata interface
181  if (Vstart (file_id) < 0) {
182  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
183  ostringstream eherr;
184  eherr << "This file cannot be open.";
185  throw InternalErr (__FILE__, __LINE__, eherr.str ());
186  }
187 
188  // Attach the vdata
189  int32 vdata_id = VSattach (file_id, fieldref, "r");
190  if (vdata_id == -1) {
191  Vend (file_id);
192  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
193  ostringstream eherr;
194  eherr << "Vdata cannot be attached.";
195  throw InternalErr (__FILE__, __LINE__, eherr.str ());
196  }
197 
198  int32 r = -1;
199 
200  // Seek the position of the starting point
201  if (VSseek (vdata_id, (int32) offset32[0]) == -1) {
202  VSdetach (vdata_id);
203  Vend (file_id);
204  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
205  ostringstream eherr;
206  eherr << "VSseek failed at " << offset32[0];
207  throw InternalErr (__FILE__, __LINE__, eherr.str ());
208  }
209 
210  // Prepare the vdata field
211  if (VSsetfields (vdata_id, fieldname.c_str ()) == -1) {
212  VSdetach (vdata_id);
213  Vend (file_id);
214  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
215  ostringstream eherr;
216  eherr << "VSsetfields failed with the name " << fieldname;
217  throw InternalErr (__FILE__, __LINE__, eherr.str ());
218  }
219 
220  int32 vdfelms = fieldorder * count32[0] * step32[0];
221 
222  vector<char> val;
223  val.resize(vdfelms);
224 
225  // Read the data
226  r = VSread (vdata_id, (uint8 *) &val[0], 1+(count32[0] -1)* step32[0],
227  FULL_INTERLACE);
228 
229  if (r == -1) {
230  VSdetach (vdata_id);
231  Vend (file_id);
232  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
233  ostringstream eherr;
234  eherr << "VSread failed.";
235  throw InternalErr (__FILE__, __LINE__, eherr.str ());
236  }
237 
238  vector<string>final_val;
239  final_val.resize(nelms);
240 
241  vector<char> temp_buf;
242  temp_buf.resize(fieldorder+1);
243  for (int i = 0; i<nelms;i++) {
244  strncpy(&temp_buf[0],&val[0]+fieldorder*i*step32[0],fieldorder);
245  temp_buf[fieldorder]='\0';
246  final_val[i] = &temp_buf[0];
247  }
248  set_value(&final_val[0],nelms);
249  VSdetach(vdata_id);
250  Vend(file_id);
251  HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
252 
253  }
254 
255  return false;
256 }
257 
258 int
259 HDFCFStrField::format_constraint (int *offset, int *step, int *count)
260 {
261  long nels = 1;
262  int id = 0;
263 
264  Dim_iter p = dim_begin ();
265 
266  while (p != dim_end ()) {
267 
268  int start = dimension_start (p, true);
269  int stride = dimension_stride (p, true);
270  int stop = dimension_stop (p, true);
271 
272 
273  // Check for illegical constraint
274  if (stride < 0 || start < 0 || stop < 0 || start > stop) {
275  ostringstream oss;
276 
277  oss << "Array/Grid hyperslab indices are bad: [" << start <<
278  ":" << stride << ":" << stop << "]";
279  throw Error (malformed_expr, oss.str ());
280  }
281 
282  // Check for an empty constraint and use the whole dimension if so.
283  if (start == 0 && stop == 0 && stride == 0) {
284  start = dimension_start (p, false);
285  stride = dimension_stride (p, false);
286  stop = dimension_stop (p, false);
287  }
288 
289  offset[id] = start;
290  step[id] = stride;
291  count[id] = ((stop - start) / stride) + 1;// count of elements
292  nels *= count[id];// total number of values for variable
293 
294  BESDEBUG ("h4",
295  "=format_constraint():"
296  << "id=" << id << " offset=" << offset[id]
297  << " step=" << step[id]
298  << " count=" << count[id]
299  << endl);
300 
301  id++;
302  p++;
303  }
304 
305  return nels;
306 }
307 
308 
STL namespace.
static void close_fileid(int32 sdfd, int32 file_id, int32 gridfd, int32 swathfd, bool pass_fileid_key)
Close HDF4 and HDF-EOS2 file IDs. For performance reasons, we want to keep HDF-EOS2/HDF4 IDs open for...
Definition: HDFCFUtil.cc:2881
static bool check_beskeys(const std::string &key)
Check the BES key. This function will check a BES key specified at the file h4.conf.in. If the key's value is either true or yes. The handler claims to find a key and will do some operations. Otherwise, will do different operations. For example, One may find a line H4.EnableCF=true at h4.conf.in. That means, the HDF4 handler will handle the HDF4 files by following CF conventions.
Definition: HDFCFUtil.cc:17
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
int format_constraint(int *cor, int *step, int *edg)
virtual bool read()