bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
HDFCFStrField.cc
1
2// 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.
4// This file is used when the CF option of the handler is turned on.
5// Authors: Kent Yang <myang6@hdfgroup.org>
6// Copyright (c) The HDF Group
8
9#include "config.h"
10#include "config_hdf.h"
11
12#include <iostream>
13#include <sstream>
14#include <cassert>
15#include <libdap/debug.h>
16#include <libdap/InternalErr.h>
17#include <BESDebug.h>
18#include <BESLog.h>
19
20#include "HDFCFUtil.h"
21#include "HDFCFStrField.h"
22#include "HDF4RequestHandler.h"
23
24using namespace std;
25using namespace libdap;
26
27
28bool
29HDFCFStrField::read ()
30{
31
32 BESDEBUG("h4","Coming to HDFCFStrField read "<<endl);
33 if(length() == 0)
34 return true;
35
36 bool check_pass_fileid_key = HDF4RequestHandler::get_pass_fileid();
37
38 // Note that one dimensional character array is one string,
39 // so the rank for character arrays should be rank from string+1
40 // offset32,step32 and count32 will be new subsetting parameters for
41 // character arrays.
42 vector<int32>offset32;
43 offset32.resize(rank+1);
44 vector<int32>count32;
45 count32.resize(rank+1);
46 vector<int32>step32;
47 step32.resize(rank+1);
48 int nelms = 1;
49
50 if (rank != 0) {
51
52 // Declare offset, count and step,
53 vector<int>offset;
54 offset.resize(rank);
55 vector<int>count;
56 count.resize(rank);
57 vector<int>step;
58 step.resize(rank);
59
60 // Declare offset, count and step,
61 // Note that one dimensional character array is one string,
62 // so the rank for character arrays should be rank from string+1
63 // Obtain offset,step and count from the client expression constraint
64 nelms = format_constraint (offset.data(), step.data(), count.data());
65
66 // Assign the offset32,count32 and step32 up to the dimension rank-1.
67 // Will assign the dimension rank later.
68 for (int i = 0; i < rank; i++) {
69 offset32[i] = (int32) offset[i];
70 count32[i] = (int32) count[i];
71 step32[i] = (int32) step[i];
72 }
73 }
74
75
76 // Initialize the temp. returned value.
77 int32 r = 0;
78
79 // First SDS
80 if(false == is_vdata) {
81
82 int32 sdid = -1;
83 if(false == check_pass_fileid_key) {
84 sdid = SDstart (filename.c_str (), DFACC_READ);
85 if (sdid < 0) {
86 ostringstream eherr;
87 eherr << "File " << filename.c_str () << " cannot be open.";
88 throw InternalErr (__FILE__, __LINE__, eherr.str ());
89 }
90 }
91 else
92 sdid = h4fd;
93
94 int32 sdsid = 0;
95
96 int32 sdsindex = SDreftoindex (sdid, fieldref);
97 if (sdsindex == -1) {
98 HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
99 ostringstream eherr;
100 eherr << "SDS index " << sdsindex << " is not right.";
101 throw InternalErr (__FILE__, __LINE__, eherr.str ());
102 }
103
104 // Obtain this SDS ID.
105 sdsid = SDselect (sdid, sdsindex);
106 if (sdsid < 0) {
107 HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
108 ostringstream eherr;
109 eherr << "SDselect failed.";
110 throw InternalErr (__FILE__, __LINE__, eherr.str ());
111 }
112
113 int32 dim_sizes[H4_MAX_VAR_DIMS];
114 int32 sds_rank;
115 int32 data_type;
116 int32 n_attrs;
117 char name[H4_MAX_NC_NAME];
118
119 r = SDgetinfo (sdsid, name, &sds_rank, dim_sizes,
120 &data_type, &n_attrs);
121 if(r == FAIL) {
122 SDendaccess(sdsid);
123 HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
124 ostringstream eherr;
125 eherr << "SDgetinfo failed.";
126 throw InternalErr (__FILE__, __LINE__, eherr.str ());
127 }
128
129 if(sds_rank != (rank+1)) {
130 SDendaccess(sdsid);
131 HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
132 ostringstream eherr;
133 eherr << "The rank of string doesn't match with the rank of character array";
134 throw InternalErr (__FILE__, __LINE__, eherr.str ());
135
136 }
137 offset32[rank] = 0;
138 count32[rank] = dim_sizes[rank];
139 step32[rank] = 1;
140 int32 last_dim_size = dim_sizes[rank];
141
142 vector<char>val;
143 val.resize(nelms*count32[rank]);
144
145 r = SDreaddata (sdsid, offset32.data(), step32.data(), count32.data(), val.data());
146 if (r != 0) {
147 SDendaccess (sdsid);
148 HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
149 ostringstream eherr;
150 eherr << "SDreaddata failed.";
151 throw InternalErr (__FILE__, __LINE__, eherr.str ());
152 }
153
154 vector<string>final_val;
155 final_val.resize(nelms);
156 vector<char> temp_buf;
157 temp_buf.resize(last_dim_size+1);
158
159 // Since the number of the dimension for a string is reduced by 1,
160 // the value of each string is the subset of the whole last dimension
161 // of the original array.
162 for (int i = 0; i<nelms;i++) {
163 strncpy(temp_buf.data(),val.data()+last_dim_size*i,last_dim_size);
164 temp_buf[last_dim_size]='\0';
165 final_val[i] = temp_buf.data();
166 }
167 set_value(final_val.data(),nelms);
168 SDendaccess(sdsid);
169 HDFCFUtil::close_fileid(sdid,-1,-1,-1,check_pass_fileid_key);
170
171 }
172 else {
173
174 int32 file_id = -1;
175
176 if(true == check_pass_fileid_key)
177 file_id = h4fd;
178 else {
179 // Open the file
180 file_id = Hopen (filename.c_str (), DFACC_READ, 0);
181 if (file_id < 0) {
182 ostringstream eherr;
183 eherr << "File " << filename.c_str () << " cannot be open.";
184 throw InternalErr (__FILE__, __LINE__, eherr.str ());
185 }
186 }
187
188 // Start the Vdata interface
189 if (Vstart (file_id) < 0) {
190 HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
191 ostringstream eherr;
192 eherr << "This file cannot be open.";
193 throw InternalErr (__FILE__, __LINE__, eherr.str ());
194 }
195
196 // Attach the vdata
197 int32 vdata_id = VSattach (file_id, fieldref, "r");
198 if (vdata_id == -1) {
199 Vend (file_id);
200 HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
201 ostringstream eherr;
202 eherr << "Vdata cannot be attached.";
203 throw InternalErr (__FILE__, __LINE__, eherr.str ());
204 }
205
206
207 // Seek the position of the starting point
208 if (VSseek (vdata_id, offset32[0]) == -1) {
209 VSdetach (vdata_id);
210 Vend (file_id);
211 HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
212 ostringstream eherr;
213 eherr << "VSseek failed at " << offset32[0];
214 throw InternalErr (__FILE__, __LINE__, eherr.str ());
215 }
216
217 // Prepare the vdata field
218 if (VSsetfields (vdata_id, fieldname.c_str ()) == -1) {
219 VSdetach (vdata_id);
220 Vend (file_id);
221 HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
222 ostringstream eherr;
223 eherr << "VSsetfields failed with the name " << fieldname;
224 throw InternalErr (__FILE__, __LINE__, eherr.str ());
225 }
226
227 int32 vdfelms = fieldorder * count32[0] * step32[0];
228
229 vector<char> val;
230 val.resize(vdfelms);
231
232 // Read the data
233 r = VSread (vdata_id, (uint8 *) val.data(), 1+(count32[0] -1)* step32[0],
234 FULL_INTERLACE);
235
236 if (r == -1) {
237 VSdetach (vdata_id);
238 Vend (file_id);
239 HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
240 ostringstream eherr;
241 eherr << "VSread failed.";
242 throw InternalErr (__FILE__, __LINE__, eherr.str ());
243 }
244
245 vector<string>final_val;
246 final_val.resize(nelms);
247
248 vector<char> temp_buf;
249 temp_buf.resize(fieldorder+1);
250 for (int i = 0; i<nelms;i++) {
251 strncpy(temp_buf.data(),val.data()+fieldorder*i*step32[0],fieldorder);
252 temp_buf[fieldorder]='\0';
253 final_val[i] = temp_buf.data();
254 }
255 set_value(final_val.data(),nelms);
256 VSdetach(vdata_id);
257 Vend(file_id);
258 HDFCFUtil::close_fileid(-1,file_id,-1,-1,check_pass_fileid_key);
259
260 }
261
262 return false;
263}
264
265int
266HDFCFStrField::format_constraint (int *offset, int *step, int *count)
267{
268 int nels = 1;
269 int id = 0;
270
271 Dim_iter p = dim_begin ();
272 while (p != dim_end ()) {
273
274 int start = dimension_start (p, true);
275 int stride = dimension_stride (p, true);
276 int stop = dimension_stop (p, true);
277
278 // Check for illegal constraint
279 if (start > stop) {
280 ostringstream oss;
281 oss << "Array/Grid hyperslab start point "<< start <<
282 " is greater than stop point " << stop <<".";
283 throw Error(malformed_expr, oss.str());
284 }
285
286 offset[id] = start;
287 step[id] = stride;
288 count[id] = ((stop - start) / stride) + 1; // count of elements
289 nels *= count[id]; // total number of values for variable
290
291 BESDEBUG ("h4",
292 "=format_constraint():"
293 << "id=" << id << " offset=" << offset[id]
294 << " step=" << step[id]
295 << " count=" << count[id]
296 << endl);
297
298 id++;
299 p++;
300 }// while
301
302 return nels;
303}
304
305
306#if 0
307 while (p != dim_end ()) {
308
309 int start = dimension_start (p, true);
310 int stride = dimension_stride (p, true);
311 int stop = dimension_stop (p, true);
312
313
314 // Check for illegical constraint
315 if (stride < 0 || start < 0 || stop < 0 || start > stop) {
316 ostringstream oss;
317
318 oss << "Array/Grid hyperslab indices are bad: [" << start <<
319 ":" << stride << ":" << stop << "]";
320 throw Error (malformed_expr, oss.str ());
321 }
322
323 // Check for an empty constraint and use the whole dimension if so.
324 if (start == 0 && stop == 0 && stride == 0) {
325 start = dimension_start (p, false);
326 stride = dimension_stride (p, false);
327 stop = dimension_stop (p, false);
328 }
329
330 offset[id] = start;
331 step[id] = stride;
332 count[id] = ((stop - start) / stride) + 1;// count of elements
333 nels *= count[id];// total number of values for variable
334
335 BESDEBUG ("h4",
336 "=format_constraint():"
337 << "id=" << id << " offset=" << offset[id]
338 << " step=" << step[id]
339 << " count=" << count[id]
340 << endl);
341
342 id++;
343 p++;
344 }
345
346 return nels;
347}
348
349#endif
350
static void close_fileid(int32 sdfd, int32 file_id, int32 gridfd, int32 swathfd, bool pass_fileid_key)