31 #include <curl/curl.h>
34 #include <D4Attributes.h>
35 #include <XMLWriter.h>
37 #include <BESIndent.h>
40 #include <BESInternalError.h>
42 #include "DmrppRequestHandler.h"
43 #include "DmrppCommon.h"
52 static const string dmrpp_3 =
"dmrpp:3";
53 static const string dmrpp_4 =
"dmrpp:4";
55 bool DmrppCommon::d_print_chunks =
false;
56 string DmrppCommon::d_dmrpp_ns =
"http://xml.opendap.org/dap/dmrpp/1.0.0#";
57 string DmrppCommon::d_ns_prefix =
"dmrpp";
69 void join_threads(pthread_t threads[],
unsigned int num_threads)
72 for (
unsigned int i = 0; i < num_threads; ++i) {
74 BESDEBUG(dmrpp_3,
"Join thread " << i <<
" after an exception was caught.");
75 if ((status = pthread_join(threads[i], NULL)) < 0)
76 LOG(
"Failed to join thread " << i <<
"during clean up from an exception: " << strerror(status) << endl);
90 void DmrppCommon::parse_chunk_dimension_sizes(
string chunk_dims)
92 d_chunk_dimension_sizes.clear();
94 if (chunk_dims.empty())
return;
97 if (chunk_dims.find_first_not_of(
"1234567890 ") != string::npos)
98 throw BESInternalError(
"while processing chunk dimension information, illegal character(s)", __FILE__, __LINE__);
107 if (chunk_dims.find(space) != string::npos) {
109 while ((strPos = chunk_dims.find(space)) != string::npos) {
110 strVal = chunk_dims.substr(0, strPos);
112 d_chunk_dimension_sizes.push_back(strtol(strVal.c_str(), NULL, 10));
113 chunk_dims.erase(0, strPos + space.length());
119 d_chunk_dimension_sizes.push_back(strtol(chunk_dims.c_str(), NULL, 10));
128 void DmrppCommon::ingest_compression_type(
string compression_type_string)
130 if (compression_type_string.empty())
return;
136 string deflate(
"deflate");
137 string shuffle(
"shuffle");
140 if (compression_type_string.find(deflate) != string::npos) {
144 if (compression_type_string.find(shuffle) != string::npos) {
153 unsigned long DmrppCommon::add_chunk(
const string &data_url,
unsigned long long size,
unsigned long long offset,
154 string position_in_array)
156 d_chunks.push_back(
Chunk(data_url, size, offset, position_in_array));
158 return d_chunks.size();
161 unsigned long DmrppCommon::add_chunk(
const string &data_url,
unsigned long long size,
unsigned long long offset,
162 const vector<unsigned int> &position_in_array)
164 d_chunks.push_back(
Chunk(data_url, size, offset, position_in_array));
166 return d_chunks.size();
187 DmrppCommon::read_atomic(
const string &name)
189 vector<Chunk> &chunk_refs = get_chunk_vec();
191 if (chunk_refs.size() != 1)
192 throw BESInternalError(
string(
"Expected only a single chunk for variable ") + name, __FILE__, __LINE__);
194 Chunk &chunk = chunk_refs[0];
205 DmrppCommon::print_chunks_element(XMLWriter &xml,
const string &name_space)
208 if (xmlTextWriterStartElementNS(xml.get_writer(), (
const xmlChar*)name_space.c_str(), (
const xmlChar*)
"chunks", NULL) < 0)
209 throw BESInternalError(
"Could not start chunks element.", __FILE__, __LINE__);
211 string compression =
"";
212 if (is_shuffle_compression() && is_deflate_compression())
213 compression =
"deflate shuffle";
214 else if (is_shuffle_compression())
215 compression.append(
"shuffle");
216 else if (is_deflate_compression())
217 compression.append(
"deflate");
219 if (!compression.empty())
220 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"compressionType", (
const xmlChar*) compression.c_str()) < 0)
221 throw BESInternalError(
"Could not write compression attribute.", __FILE__, __LINE__);
223 if (d_chunk_dimension_sizes.size() > 0) {
226 copy(d_chunk_dimension_sizes.begin(), d_chunk_dimension_sizes.end(), ostream_iterator<unsigned int>(oss,
" "));
227 string sizes = oss.str();
228 sizes.erase(sizes.size() - 1, 1);
230 if (xmlTextWriterWriteElementNS(xml.get_writer(), (
const xmlChar*) name_space.c_str(), (
const xmlChar*)
"chunkDimensionSizes", NULL,
231 (
const xmlChar*) sizes.c_str()) < 0)
throw BESInternalError(
"Could not write chunkDimensionSizes attribute.", __FILE__, __LINE__);
235 for (vector<Chunk>::iterator i = get_chunk_vec().begin(), e = get_chunk_vec().end(); i != e; ++i) {
238 if (xmlTextWriterStartElementNS(xml.get_writer(), (
const xmlChar*)name_space.c_str(), (
const xmlChar*)
"chunk", NULL) < 0)
239 throw BESInternalError(
"Could not start element chunk", __FILE__, __LINE__);
242 ostringstream offset;
244 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"offset", (
const xmlChar*) offset.str().c_str()) < 0)
245 throw BESInternalError(
"Could not write attribute offset", __FILE__, __LINE__);
248 ostringstream nBytes;
250 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"nBytes", (
const xmlChar*) nBytes.str().c_str()) < 0)
251 throw BESInternalError(
"Could not write attribute nBytes", __FILE__, __LINE__);
258 copy(pia.begin(), pia.end(), ostream_iterator<unsigned int>(oss,
","));
259 string pia_str = oss.str();
260 if (pia.size() > 0) pia_str.replace(pia_str.size() - 1, 1,
"]");
261 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"chunkPositionInArray", (
const xmlChar*) pia_str.c_str()) < 0)
262 throw BESInternalError(
"Could not write attribute position in array", __FILE__, __LINE__);
266 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
throw BESInternalError(
"Could not end chunk element", __FILE__, __LINE__);
269 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
throw BESInternalError(
"Could not end chunks element", __FILE__, __LINE__);
282 void DmrppCommon::print_dmrpp(XMLWriter &xml,
bool constrained )
284 BaseType &bt =
dynamic_cast<BaseType&
>(*this);
285 if (constrained && !bt.send_p())
288 if (xmlTextWriterStartElement(xml.get_writer(), (
const xmlChar*)bt.type_name().c_str()) < 0)
289 throw InternalErr(__FILE__, __LINE__,
"Could not write " + bt.type_name() +
" element");
291 if (!bt.name().empty())
292 if (xmlTextWriterWriteAttribute(xml.get_writer(), (
const xmlChar*)
"name", (
const xmlChar*)bt.name().c_str()) < 0)
293 throw InternalErr(__FILE__, __LINE__,
"Could not write attribute for name");
296 bt.attributes()->print_dap4(xml);
298 if (!bt.is_dap4() && bt.get_attr_table().get_size() > 0)
299 bt.get_attr_table().print_xml_writer(xml);
302 if (DmrppCommon::d_print_chunks && get_immutable_chunks().size() > 0)
303 print_chunks_element(xml, DmrppCommon::d_ns_prefix);
305 if (xmlTextWriterEndElement(xml.get_writer()) < 0)
306 throw InternalErr(__FILE__, __LINE__,
"Could not end " + bt.type_name() +
" element");
309 void DmrppCommon::dump(ostream & strm)
const
311 strm << BESIndent::LMarg <<
"is_deflate: " << (is_deflate_compression() ?
"true" :
"false") << endl;
312 strm << BESIndent::LMarg <<
"is_shuffle_compression: " << (is_shuffle_compression() ?
"true" :
"false") << endl;
314 const vector<unsigned int> &chunk_dim_sizes = get_chunk_dimension_sizes();
316 strm << BESIndent::LMarg <<
"chunk dimension sizes: [";
317 for (
unsigned int i = 0; i < chunk_dim_sizes.size(); i++) {
318 strm << (i ?
"][" :
"") << chunk_dim_sizes[i];
322 const vector<Chunk> &chunk_refs = get_immutable_chunks();
323 strm << BESIndent::LMarg <<
"Chunks (aka chunks):" << (chunk_refs.size() ?
"" :
"None Found.") << endl;
325 for (
unsigned int i = 0; i < chunk_refs.size(); i++) {
326 strm << BESIndent::LMarg;
327 chunk_refs[i].dump(strm);
331 BESIndent::UnIndent();