bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
DmrppStructure.cc
1
2// -*- mode: c++; c-basic-offset:4 -*-
3
4// This file is part of the BES
5
6// Copyright (c) 2016 OPeNDAP, Inc.
7// Author: James Gallagher <jgallagher@opendap.org>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24
25#include "config.h"
26
27#include <string>
28
29#include <libdap/XMLWriter.h>
30#include <libdap/util.h>
31#include <libdap/Array.h>
32
33#include <BESError.h>
34#include <BESDebug.h>
35
36#include "DmrppStructure.h"
37#include "byteswap_compat.h"
38#include "float_byteswap.h"
39#include "Base64.h"
40
41using namespace libdap;
42using namespace std;
43
44namespace dmrpp {
45
47DmrppStructure::operator=(const DmrppStructure &rhs)
48{
49 if (this == &rhs)
50 return *this;
51
52 dynamic_cast<Structure &>(*this) = rhs; // run Constructor=
53
54 dynamic_cast<DmrppCommon &>(*this) = rhs;
55
56 return *this;
57}
58
59bool
60DmrppStructure::read()
61{
62 BESDEBUG("dmrpp", "Entering " <<__PRETTY_FUNCTION__ << " for '" << name() << "'" << endl);
63 if (!get_chunks_loaded())
64 load_chunks(this);
65
66 if (read_p())
67 return true;
68
69 size_t value_size = 0;
70 char *buf_value = read_atomic(name(),value_size);
71 // Note for scalar, the buffer size is the storage size of this variable, which for HDF5, is always the correct size to store the buffer.
72 // We don't need to retrieve this in a different way.
73 vector<char> values(buf_value,buf_value+value_size);
74
75 size_t values_offset = 0;
76 structure_read(values, values_offset,this->twiddle_bytes());
77 set_read_p(true);
78
79 return true;
80
81
82}
83
84void DmrppStructure::structure_read(vector<char> &values, size_t &values_offset, bool byte_swap) {
85
86 BESDEBUG("dmrpp", "Entering " <<__PRETTY_FUNCTION__ << " for '" << name() << "'" << endl);
87
88 // Remember the value offset.
89 size_t temp_values_offset = values_offset;
90
91 Constructor::Vars_iter vi = this->var_begin();
92 Constructor::Vars_iter ve = this->var_end();
93
94 vector<unsigned int> s_offs = this->get_struct_offsets();
95 unsigned int offset_counter = 0;
96 unsigned int s_offs_size = s_offs.size();
97 BESDEBUG("dmrpp", "s_offs_size: " << s_offs_size << "'" << endl);
98
99 for (; vi != ve; vi++) {
100 BaseType *bt = *vi;
101 Type t_bt = bt->type();
102 if (libdap::is_simple_type(t_bt) && t_bt != dods_str_c && t_bt != dods_url_c && t_bt!= dods_enum_c && t_bt!=dods_opaque_c) {
103
104 BESDEBUG("dmrpp", "var name is: " << bt->name() << "'" << endl);
105 BESDEBUG("dmrpp", "var values_offset is: " << values_offset << "'" << endl);
106#if 0
107 if(t_bt == dods_int32_c) {
108 Int32 *val_int = static_cast<Int32 *>(bt);
109 val_int->set_value(*((dods_int32*)(values.data()+values_offset)));
110 BESDEBUG("dmrpp", "int value is: " << *((dods_int32*)(values.data()+values_offset)) << "'" << endl);
111 }
112 else if (t_bt == dods_float32_c) {
113 Float32 *val_float = static_cast<Float32 *>(bt);
114 val_float->set_value(*((dods_float32*)(values.data()+values_offset)));
115 BESDEBUG("dmrpp", "float value is: " << *((dods_float32*)(values.data()+values_offset)) << "'" << endl);
116 }
117 else
118 bt->val2buf(values.data() + values_offset);
119#endif
120
121 if (byte_swap) {
122 // Need to swap the bytes.
123 auto stored_value = values.data() + values_offset;
124 BESDEBUG("dmrpp", "swap bytes " << endl);
125 swap_bytes_in_structure(stored_value,t_bt,1);
126 bt->val2buf(stored_value);
127 }
128 else
129 bt->val2buf(values.data() + values_offset);
130
131 // Update values_offset
132 // With the old dmrpp file, it is possible that the data value is not retrieved correctly.
133 // In order not to interrupt the operational service, we don't throw the error. This needs to be evaluated.
134 if (s_offs_size == 0)
135 values_offset += bt->width_ll();
136 // s_offs_size should always be greater than offset_counter.
137 else if (s_offs_size <=offset_counter)
138 throw InternalErr(__FILE__, __LINE__, "The size of offset should always be greater than the offset_counter");
139 else {
140 values_offset = temp_values_offset + s_offs[offset_counter];
141 offset_counter++;
142 }
143 }
144 else if (t_bt == dods_array_c) {
145
146 auto t_a = dynamic_cast<Array *>(bt);
147 Type t_array_var = t_a->var()->type();
148 if (libdap::is_simple_type(t_array_var) && t_array_var != dods_str_c && t_array_var != dods_url_c && t_array_var!= dods_enum_c && t_array_var!=dods_opaque_c) {
149 if (byte_swap) {
150 // Need to swap the bytes.
151 BESDEBUG("dmrpp", "swap array bytes " << endl);
152 auto stored_value = values.data() + values_offset;
153 swap_bytes_in_structure(stored_value,t_array_var,t_a->length_ll());
154 bt->val2buf(stored_value);
155 }
156 else
157 t_a->val2buf(values.data()+values_offset);
158
159 // Update values_offset.
160 // With the old dmrpp file, it is possible that the data value is not retrieved correctly.
161 // In order not to interrupt the operational service, we don't throw the error. This needs to be evaluated.
162 if (s_offs_size == 0)
163 values_offset += t_a->width_ll();
164 // s_offs_size should always be greater than offset_counter.
165 else if (s_offs_size <=offset_counter)
166 throw InternalErr(__FILE__, __LINE__, "The size of offset should always be greater than the offset_counter");
167 else {
168 values_offset = temp_values_offset + s_offs[offset_counter];
169 offset_counter++;
170 }
171
172 }
173 else
174 throw InternalErr(__FILE__, __LINE__, "The base type of this structure is not integer or float. Currently it is not supported.");
175 }
176 else
177 throw InternalErr(__FILE__, __LINE__, "The base type of this structure is not integer or float. Currently it is not supported.");
178 }
179
180}
181void
182DmrppStructure::swap_bytes_in_structure(char *stored_value,Type dap_type,int64_t num) const{
183
184 BESDEBUG("dmrpp", "Entering " <<__PRETTY_FUNCTION__ << " for '" << name() << "'" << endl);
185 switch (dap_type) {
186 case dods_int16_c:
187 case dods_uint16_c: {
188 auto *local = reinterpret_cast<dods_uint16*>(stored_value);
189 while (num--) {
190 *local = bswap_16(*local);
191 local++;
192 }
193 break;
194 }
195 case dods_int32_c:
196 case dods_uint32_c: {
197 auto *local = reinterpret_cast<dods_uint32*>(stored_value);
198 while (num--) {
199 *local = bswap_32(*local);
200 local++;
201 }
202 break;
203 }
204 case dods_int64_c:
205 case dods_uint64_c: {
206 auto *local = reinterpret_cast<dods_uint64*>(stored_value);
207 while (num--) {
208 *local = bswap_64(*local);
209 local++;
210 }
211 break;
212 }
213 case dods_float32_c: {
214 swap_float32(stored_value, num);
215 break;
216 }
217 case dods_float64_c: {
218 swap_float64(stored_value, num);
219 break;
220 }
221 default: break; // Do nothing for all other types.
222 }
223
224
225}
226void
227DmrppStructure::set_send_p(bool state)
228{
230 load_attributes(this);
231
232 Structure::set_send_p(state);
233}
234
235void special_structure_data_xml_element(const XMLWriter &xml, DmrppStructure *ds) {
236
237 if (ds->type() == dods_structure_c) {
238 vector<char> struct_str_buf = ds->get_structure_str_buffer();
239 string final_encoded_str = base64::Base64::encode((uint8_t*)(struct_str_buf.data()),struct_str_buf.size());
240
241 ds->print_special_structure_element(xml, DmrppCommon::d_ns_prefix, final_encoded_str);
242
243 }
244
245}
246
247
248void
249DmrppStructure::print_dap4(libdap::XMLWriter &writer, bool constrained) {
250
251 if (constrained && !this->send_p())
252 return;
253
254 if (xmlTextWriterStartElement(writer.get_writer(), (const xmlChar*)this->type_name().c_str()) < 0)
255 throw InternalErr(__FILE__, __LINE__, "Could not write " + this->type_name() + " element");
256
257 if (!this->name().empty()) {
258 if (xmlTextWriterWriteAttribute(writer.get_writer(), (const xmlChar*) "name", (const xmlChar*)this->name().c_str()) < 0)
259 throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
260 }
261
262
263 if (this->is_dap4())
264 this->attributes()->print_dap4(writer);
265
266 if (!this->is_dap4() && this->get_attr_table().get_size() > 0)
267 this->get_attr_table().print_xml_writer(writer);
268
269 Constructor::Vars_iter vi = this->var_begin();
270 Constructor::Vars_iter ve = this->var_end();
271
272 for (; vi != ve; vi++) {
273 BaseType *bt = *vi;
274 bt->print_dap4(writer);
275 }
276
279
280 // Special structure string array.
281 if (DmrppCommon::d_print_chunks && get_special_structure_flag() && read_p()) {
282 special_structure_data_xml_element(writer, this);
283 }
284
285 // print scalar value for compact storage.
286 // TODO: add this later.
287 if (xmlTextWriterEndElement(writer.get_writer()) < 0)
288 throw InternalErr(__FILE__, __LINE__, "Could not end " + this->type_name() + " element");
289
290}
291
292
293void DmrppStructure::dump(ostream & strm) const
294{
295 strm << BESIndent::LMarg << "DmrppStructure::dump - (" << (void *) this << ")" << endl;
296 BESIndent::Indent();
297 DmrppCommon::dump(strm);
298 Structure::dump(strm);
299 strm << BESIndent::LMarg << "value: " << "----" << /*d_buf <<*/ endl;
300 BESIndent::UnIndent();
301}
302
303} // namespace dmrpp
304
static std::string d_ns_prefix
The XML namespace prefix to use.
virtual bool twiddle_bytes() const
Returns true if this object utilizes shuffle compression.
static bool d_print_chunks
if true, print_dap4() prints chunk elements
virtual void load_attributes(libdap::BaseType *btp)
Load the attribute information for this variable.
virtual bool get_chunks_loaded() const
Have the chunks been loaded?
virtual size_t get_chunks_size() const
Use this when the number of chunks is needed.
void print_chunks_element(libdap::XMLWriter &xml, const std::string &name_space="")
Print the Chunk information.
virtual bool get_uses_fill_value() const
virtual void load_chunks(libdap::BaseType *btp)
Load chunk information for this variable.
virtual bool get_attributes_loaded() const
Have the attributes been loaded?
virtual char * read_atomic(const std::string &name)
read method for the atomic types
Type
Type of JSON value.
Definition rapidjson.h:664