bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
HDFDMRArray_VD.cc
1
2// This file is part of the hdf4 data handler for the OPeNDAP data server.
3// It retrieves HDF4 Vdata values for a direct DMR-mapping DAP4 response.
4// Each Vdata will be mapped to a DAP variable.
5
6// Authors: Kent Yang <myang6@hdfgroup.org>
7// Copyright (c) The HDF Group
9
10
11#include "HDFDMRArray_VD.h"
12#include "HDFStructure.h"
13#include "HDFCFUtil.h"
14#include <iostream>
15#include <sstream>
16#include <libdap/debug.h>
17#include <libdap/InternalErr.h>
18#include <BESDebug.h>
19
20using namespace std;
21using namespace libdap;
22
23
24bool
25HDFDMRArray_VD::read ()
26{
27
28 BESDEBUG("h4","Coming to HDFDMRArray_VD read "<<endl);
29 if (length() == 0)
30 return true;
31
32
33 // Declaration of offset,count and step
34 vector<int>offset;
35 offset.resize(rank);
36 vector<int>count;
37 count.resize(rank);
38 vector<int>step;
39 step.resize(rank);
40
41 // Obtain offset,step and count from the client expression constraint
42 int nelms = format_constraint(offset.data(),step.data(),count.data());
43
44 // Open the file
45 int32 file_id = Hopen (filename.c_str (), DFACC_READ, 0);
46 if (file_id < 0) {
47 ostringstream eherr;
48 eherr << "File " << filename.c_str () << " cannot be open.";
49 throw InternalErr (__FILE__, __LINE__, eherr.str ());
50 }
51
52 // Start the Vdata interface
53 int32 vdata_id = 0;
54 if (Vstart (file_id) < 0) {
55 Hclose(file_id);
56 ostringstream eherr;
57 eherr << "This file cannot be open.";
58 throw InternalErr (__FILE__, __LINE__, eherr.str ());
59 }
60
61 // Attach the vdata
62 vdata_id = VSattach (file_id, vdref, "r");
63 if (vdata_id == -1) {
64 Vend (file_id);
65 Hclose(file_id);
66 ostringstream eherr;
67 eherr << "Vdata cannot be attached.";
68 throw InternalErr (__FILE__, __LINE__, eherr.str ());
69 }
70
71 int32 vs_nflds = VFnfields(vdata_id);
72 if (vs_nflds == FAIL) {
73 VSdetach(vdata_id);
74 Vend (file_id);
75 Hclose(file_id);
76 throw InternalErr(__FILE__, __LINE__, "Cannot get the number of fields of a vdata.");
77 }
78
79 try {
80 if (vs_nflds == 1)
81 read_one_field_vdata(vdata_id, offset,count,step,nelms);
82 else
83 read_multi_fields_vdata(vdata_id,offset, count,step,nelms);
84 VSdetach(vdata_id);
85 Vend(file_id);
86 Hclose(file_id);
87
88 }
89 catch(...) {
90 VSdetach(vdata_id);
91 Vend(file_id);
92 Hclose(file_id);
93 throw;
94 }
95 return true;
96
97}
98
99void
100HDFDMRArray_VD::read_one_field_vdata(int32 vdata_id,const vector<int>&offset, const vector<int>&count, const vector<int>&step, int nelms) {
101
102 int32 fdorder = VFfieldorder(vdata_id,0);
103 if (fdorder == FAIL) {
104 throw InternalErr(__FILE__, __LINE__, "VFfieldorder failed");
105 }
106
107 const char *fieldname = VFfieldname(vdata_id,0);
108 if (fieldname == nullptr) {
109 throw InternalErr(__FILE__, __LINE__, "Cannot get vdata field name.");
110 }
111
112 int32 fdtype = VFfieldtype(vdata_id,0);
113 if (fdtype == FAIL) {
114 throw InternalErr(__FILE__, __LINE__, "VFfieldtype failed");
115 }
116
117 // Seek the position of the starting point
118 if (VSseek (vdata_id, offset[0]) == -1) {
119 ostringstream eherr;
120 eherr << "VSseek failed at " << offset[0];
121 throw InternalErr (__FILE__, __LINE__, eherr.str ());
122 }
123
124 // Prepare the vdata field
125 if (VSsetfields (vdata_id, fieldname) == -1) {
126 ostringstream eherr;
127 eherr << "VSsetfields failed with the name " << fieldname;
128 throw InternalErr (__FILE__, __LINE__, eherr.str ());
129 }
130
131 int32 vdfelms = fdorder * count[0] * step[0];
132 int32 fieldtype = VFfieldtype(vdata_id,0);
133 if (fieldtype == -1)
134 throw InternalErr (__FILE__, __LINE__, "VFfieldtype failed");
135
136 int32 r = -1;
137 // TODO: reduce the following code by not checking each datatype.
138
139 // Loop through each data type
140 switch (fieldtype) {
141 case DFNT_INT8:
142 case DFNT_NINT8:
143 case DFNT_CHAR8:
144 {
145 vector<int8> val;
146 val.resize(nelms);
147
148 vector<int8>orival;
149 orival.resize(vdfelms);
150
151 // Read the data
152 r = VSread (vdata_id, (uint8 *) orival.data(), 1+(count[0] -1)* step[0],FULL_INTERLACE);
153 if (r == -1) {
154 ostringstream eherr;
155 eherr << "VSread failed.";
156 throw InternalErr (__FILE__, __LINE__, eherr.str ());
157 }
158
159 // Obtain the subset portion of the data
160 if (fdorder > 1) {
161 for (int i = 0; i < count[0]; i++)
162 for (int j = 0; j < count[1]; j++)
163 val[i * count[1] + j] =
164 orival[i * fdorder * step[0] + offset[1] + j * step[1]];
165 }
166 else {
167 for (int i = 0; i < count[0]; i++)
168 val[i] = orival[i * step[0]];
169 }
170
171 set_value ((dods_int8 *) val.data(), nelms);
172 }
173
174 break;
175 case DFNT_UINT8:
176 case DFNT_NUINT8:
177 case DFNT_UCHAR8:
178 {
179
180 vector<uint8>val;
181 val.resize(nelms);
182
183 vector<uint8>orival;
184 orival.resize(vdfelms);
185
186 r = VSread (vdata_id, orival.data(), 1+(count[0] -1)* step[0], FULL_INTERLACE);
187 if (r == -1) {
188 ostringstream eherr;
189 eherr << "VSread failed.";
190 throw InternalErr (__FILE__, __LINE__, eherr.str ());
191 }
192
193 if (fdorder > 1) {
194 for (int i = 0; i < count[0]; i++)
195 for (int j = 0; j < count[1]; j++)
196 val[i * count[1] + j] = orival[i * fdorder * step[0] + offset[1] + j * step[1]];
197 }
198 else {
199 for (int i = 0; i < count[0]; i++)
200 val[i] = orival[i * step[0]];
201 }
202
203 set_value ((dods_byte *) val.data(), nelms);
204 }
205
206 break;
207
208 case DFNT_INT16:
209 {
210 vector<int16>val;
211 val.resize(nelms);
212 vector<int16>orival;
213 orival.resize(vdfelms);
214
215 r = VSread (vdata_id, (uint8 *) orival.data(), 1+(count[0] -1)* step[0],
216 FULL_INTERLACE);
217 if (r == -1) {
218 ostringstream eherr;
219 eherr << "VSread failed.";
220 throw InternalErr (__FILE__, __LINE__, eherr.str ());
221 }
222
223 if (fdorder > 1) {
224 for (int i = 0; i < count[0]; i++)
225 for (int j = 0; j < count[1]; j++)
226 val[i * count[1] + j] = orival[i * fdorder * step[0] + offset[1] + j * step[1]];
227 }
228 else {
229 for (int i = 0; i < count[0]; i++)
230 val[i] = orival[i * step[0]];
231 }
232
233 set_value ((dods_int16 *) val.data(), nelms);
234 }
235 break;
236
237 case DFNT_UINT16:
238
239 {
240 vector<uint16>val;
241 val.resize(nelms);
242
243 vector<uint16>orival;
244 orival.resize(vdfelms);
245
246 r = VSread (vdata_id, (uint8 *) orival.data(), 1+(count[0] -1)* step[0],
247 FULL_INTERLACE);
248 if (r == -1) {
249 ostringstream eherr;
250 eherr << "VSread failed.";
251 throw InternalErr (__FILE__, __LINE__, eherr.str ());
252 }
253
254 if (fdorder > 1) {
255 for (int i = 0; i < count[0]; i++)
256 for (int j = 0; j < count[1]; j++)
257 val[i * count[1] + j] = orival[i * fdorder * step[0] + offset[1] + j * step[1]];
258 }
259 else {
260 for (int i = 0; i < count[0]; i++)
261 val[i] = orival[i * step[0]];
262 }
263
264 set_value ((dods_uint16 *) val.data(), nelms);
265 }
266 break;
267 case DFNT_INT32:
268 {
269 vector<int32>val;
270 val.resize(nelms);
271 vector<int32>orival;
272 orival.resize(vdfelms);
273
274 r = VSread (vdata_id, (uint8 *) orival.data(), 1+(count[0] -1)* step[0],
275 FULL_INTERLACE);
276 if (r == -1) {
277 ostringstream eherr;
278 eherr << "VSread failed.";
279 throw InternalErr (__FILE__, __LINE__, eherr.str ());
280 }
281
282 if (fdorder > 1) {
283 for (int i = 0; i < count[0]; i++)
284 for (int j = 0; j < count[1]; j++)
285 val[i * count[1] + j] = orival[i * fdorder * step[0] + offset[1] + j * step[1]];
286 }
287 else {
288 for (int i = 0; i < count[0]; i++)
289 val[i] = orival[i * step[0]];
290 }
291
292 set_value ((dods_int32 *) val.data(), nelms);
293 }
294 break;
295
296 case DFNT_UINT32:
297 {
298
299 vector<uint32>val;
300 val.resize(nelms);
301
302 vector<uint32>orival;
303 orival.resize(vdfelms);
304
305 r = VSread (vdata_id, (uint8 *) orival.data(), 1+(count[0] -1)* step[0],
306 FULL_INTERLACE);
307 if (r == -1) {
308 ostringstream eherr;
309 eherr << "VSread failed.";
310 throw InternalErr (__FILE__, __LINE__, eherr.str ());
311 }
312
313 if (fdorder > 1) {
314 for (int i = 0; i < count[0]; i++)
315 for (int j = 0; j < count[1]; j++)
316 val[i * count[1] + j] = orival[i * fdorder * step[0] + offset[1] + j * step[1]];
317 }
318 else {
319 for (int i = 0; i < count[0]; i++)
320 val[i] = orival[i * step[0]];
321 }
322
323 set_value ((dods_uint32 *) val.data(), nelms);
324 }
325 break;
326 case DFNT_FLOAT32:
327 {
328 vector<float32>val;
329 val.resize(nelms);
330 vector<float32>orival;
331 orival.resize(vdfelms);
332
333 r = VSread (vdata_id, (uint8 *) orival.data(), 1+(count[0] -1)* step[0],
334 FULL_INTERLACE);
335 if (r == -1) {
336 ostringstream eherr;
337 eherr << "VSread failed.";
338 throw InternalErr (__FILE__, __LINE__, eherr.str ());
339 }
340
341 if (fdorder > 1) {
342 for (int i = 0; i < count[0]; i++)
343 for (int j = 0; j < count[1]; j++)
344 val[i * count[1] + j] = orival[i * fdorder * step[0] + offset[1] + j * step[1]];
345 }
346 else {
347 for (int i = 0; i < count[0]; i++)
348 val[i] = orival[i * step[0]];
349 }
350
351 set_value ((dods_float32 *) val.data(), nelms);
352 }
353 break;
354 case DFNT_FLOAT64:
355 {
356
357 vector<float64>val;
358 val.resize(nelms);
359
360 vector<float64>orival;
361 orival.resize(vdfelms);
362
363 r = VSread (vdata_id, (uint8 *) orival.data(), 1+(count[0] -1)* step[0],
364 FULL_INTERLACE);
365 if (r == -1) {
366 ostringstream eherr;
367 eherr << "VSread failed.";
368 throw InternalErr (__FILE__, __LINE__, eherr.str ());
369 }
370
371 if (fdorder > 1) {
372 for (int i = 0; i < count[0]; i++)
373 for (int j = 0; j < count[1]; j++)
374 val[i * count[1] + j] = orival[i * fdorder * step[0] + offset[1] + j * step[1]];
375 }
376 else {
377 for (int i = 0; i < count[0]; i++)
378 val[i] = orival[i * step[0]];
379 }
380
381 set_value ((dods_float64 *) val.data(), nelms);
382 }
383 break;
384 default:
385 throw InternalErr (__FILE__, __LINE__, "unsupported data type.");
386 }
387
388}
389void
390HDFDMRArray_VD::read_multi_fields_vdata(int32 vdata_id,const vector<int>&offset, const vector<int>&count, const vector<int>&step, int nelms) {
391
392 // Read the subset's vdata values
393 int32 n_records = 0;
394 int32 vdata_size = 0;
395 if (VSQueryvsize(vdata_id,&vdata_size)==FAIL)
396 throw InternalErr(__FILE__,__LINE__,"unable to query vdata size");
397
398 if (VSQuerycount(vdata_id,&n_records) == FAIL)
399 throw InternalErr(__FILE__,__LINE__,"unable to query number of records of vdata");
400
401 char field_name_list[VSFIELDMAX*FIELDNAMELENMAX];
402 if(VSinquire(vdata_id,nullptr,nullptr,
403 field_name_list,nullptr,nullptr) == FAIL) {
404 throw InternalErr(__FILE__,__LINE__,"unable to query number of records of vdata");
405 }
406 if(VSsetfields(vdata_id,field_name_list) == FAIL)
407 throw InternalErr(__FILE__,__LINE__,"unable to set vdata fields");
408
409 vector<uint8_t> data_buf;
410 data_buf.resize(n_records * vdata_size);
411 if (VSread (vdata_id, (uint8 *)data_buf.data(),n_records,FULL_INTERLACE)<0)
412 throw InternalErr(__FILE__,__LINE__,"unable to read vdata");
413
414 vector<uint8_t> subset_buf;
415 subset_buf.resize(nelms*vdata_size);
416 if (rank !=1)
417 throw InternalErr(__FILE__,__LINE__,"vdata must be 1-D array of structure");
418
419 const uint8_t *tmp_buf = data_buf.data() + offset[0]*vdata_size;
420 uint8_t *tmp_subset_buf = subset_buf.data();
421 if (step[0] == 1)
422 memcpy((void*)tmp_subset_buf,(const void*)tmp_buf,count[0]*vdata_size);
423 else {
424 for (int i = 0; i<count[0]; i++) {
425 memcpy((void*)tmp_subset_buf,(const void*)tmp_buf,vdata_size);
426 tmp_subset_buf +=vdata_size;
427 tmp_buf +=step[0]*vdata_size;
428 }
429 }
430
431 vector<string> field_names;
432 char sep =',';
433 HDFCFUtil::Split(field_name_list,sep,field_names);
434 for (auto &fn:field_names)
436#if 0
437for (const auto &fn:field_names)
438 cerr<<fn<<endl;
439#endif
440
441 unsigned num_fields = field_names.size();
442 size_t values_offset = 0;
443
444 HDFStructure *vdata_s = nullptr;
445
446 // Write the values to the DAP4
447 for (int64_t element = 0; element < nelms; ++element) {
448
449 //auto vdata_s = dynamic_cast<HDFStructure*>(var(element));
450 vdata_s = dynamic_cast<HDFStructure*>(var()->ptr_duplicate());
451 size_t struct_elem_offset = values_offset + vdata_size*element;
452
453 if(!vdata_s)
454 throw InternalErr(__FILE__, __LINE__, "Cannot obtain the structure pointer.");
455
456 try {
457 int field_offset = 0;
458 for (unsigned u =0;u<num_fields;u++) {
459
460 BaseType * field = vdata_s->var(field_names[u]);
461 int field_size = VFfieldisize(vdata_id,u);
462 field->val2buf(subset_buf.data() + struct_elem_offset + field_offset);
463 field_offset +=field_size;
464 field->set_read_p(true);
465
466 }
467#if 0
468 vdata_s->read_from_value(subset_buf,values_offset);
469#endif
470
471
472 }
473 catch(...) {
474 delete vdata_s;
475 string err_msg = "Cannot read the data of a vdata " + var()->name();
476 throw InternalErr(__FILE__, __LINE__, err_msg);
477 }
478 vdata_s->set_read_p(true);
479 set_vec_ll((uint64_t)element,vdata_s);
480 delete vdata_s;
481 }
482
483 set_read_p(true);
484
485}
486
487// Standard way of DAP handlers to pass the coordinates of the subsetted region to the handlers
488// Return the number of elements to read.
489int
490HDFDMRArray_VD::format_constraint (int *offset, int *step, int *count)
491{
492 int nels = 1;
493 int id = 0;
494
495 Dim_iter p = dim_begin ();
496 while (p != dim_end ()) {
497
498 int start = dimension_start (p, true);
499 int stride = dimension_stride (p, true);
500 int stop = dimension_stop (p, true);
501
502 // Check for illegal constraint
503 if (start > stop) {
504 ostringstream oss;
505 oss << "Array/Grid hyperslab start point "<< start <<
506 " is greater than stop point " << stop <<".";
507 throw Error(malformed_expr, oss.str());
508 }
509
510 offset[id] = start;
511 step[id] = stride;
512 count[id] = ((stop - start) / stride) + 1; // count of elements
513 nels *= count[id]; // total number of values for variable
514
515 BESDEBUG ("h4",
516 "=format_constraint():"
517 << "id=" << id << " offset=" << offset[id]
518 << " step=" << step[id]
519 << " count=" << count[id]
520 << endl);
521
522 id++;
523 p++;
524 }
525
526 return nels;
527}
528
529
static std::string get_CF_string(std::string s)
Change special characters to "_".
Definition HDFCFUtil.cc:100
static void Split(const char *s, int len, char sep, std::vector< std::string > &names)
Definition HDFCFUtil.cc:58