33#include <BESInternalError.h>
34#include <BESSyntaxUserError.h>
35#include <BESForbiddenError.h>
36#include <BESContextManager.h>
39#define PUGIXML_NO_XPATH
40#define PUGIXML_HEADER_ONLY
45#include "CurlHandlePool.h"
46#include "EffectiveUrlCache.h"
47#include "DmrppRequestHandler.h"
48#include "DmrppNames.h"
49#include "byteswap_compat.h"
50#include "float_byteswap.h"
55#define prolog std::string("Chunk::").append(__func__).append("() - ")
57#define FLETCHER32_CHECKSUM 4
58#define ACTUALLY_USE_FLETCHER32_CHECKSUM 1
74size_t chunk_header_callback(
char *buffer,
size_t ,
size_t nitems,
void *data) {
80 string header(buffer, buffer + nitems - 2);
83 if (header.find(
"Content-Type") != string::npos) {
85 auto c_ptr =
reinterpret_cast<Chunk *
>(data);
97void process_s3_error_response(
const shared_ptr<http::url> &data_url,
const string &xml_message)
101 pugi::xml_document error;
102 pugi::xml_parse_result result = error.load_string(xml_message.c_str());
104 throw BESInternalError(
"The underlying data store returned an unintelligible error message.", __FILE__, __LINE__);
106 pugi::xml_node err_elmnt = error.document_element();
107 if (!err_elmnt || (strcmp(err_elmnt.name(),
"Error") != 0))
108 throw BESInternalError(
"The underlying data store returned a bogus error message.", __FILE__, __LINE__);
110 string code = err_elmnt.child_value(
"Code");
111 string message = err_elmnt.child_value(
"Message");
117 if (code ==
"AccessDenied") {
119 msg << prolog <<
"ACCESS DENIED - The underlying object store has refused access to: "
120 << data_url->protocol() << data_url->host() << data_url->path() <<
" Object Store Message: "
122 BESDEBUG(MODULE, msg.str() << endl);
124 throw BESForbiddenError(msg.str(), __FILE__, __LINE__);
128 msg << prolog <<
"The underlying object store returned an error. " <<
"(Tried: " << data_url->protocol()
129 <<
"://" << data_url->host() << data_url->path() <<
") Object Store Message: " << message;
130 BESDEBUG(MODULE, msg.str() << endl);
132 throw BESInternalError(msg.str(), __FILE__, __LINE__);
149size_t chunk_write_data(
void *buffer,
size_t size,
size_t nmemb,
void *data) {
150 BESDEBUG(MODULE, prolog <<
"BEGIN " << endl);
151 size_t nbytes = size * nmemb;
152 auto chunk =
reinterpret_cast<Chunk *
>(data);
155 auto data_url = chunk->get_data_url();
156 BESDEBUG(MODULE, prolog <<
"chunk->get_data_url():" << data_url << endl);
159 BESDEBUG(MODULE, prolog <<
"chunk->get_response_content_type():" << chunk->get_response_content_type() << endl);
160 if (chunk->get_response_content_type().find(
"application/xml") != string::npos) {
163 string xml_message =
reinterpret_cast<const char *
>(buffer);
164 xml_message.erase(xml_message.find_last_not_of(
"\t\n\v\f\r 0") + 1);
169 process_s3_error_response(data_url, xml_message);
176 catch (std::exception &e) {
178 msg << prolog <<
"Caught std::exception when accessing object store data.";
179 msg <<
" (Tried: " << data_url->str() <<
")" <<
" Message: " << e.what();
180 BESDEBUG(MODULE, msg.str() << endl);
181 throw BESSyntaxUserError(msg.str(), __FILE__, __LINE__);
189 unsigned long long bytes_read = chunk->get_bytes_read();
192 if (bytes_read + nbytes > chunk->get_rbuf_size()) {
194 msg << prolog <<
"ERROR! The number of bytes_read: " << bytes_read <<
" plus the number of bytes to read: "
195 << nbytes <<
" is larger than the target buffer size: " << chunk->get_rbuf_size();
196 BESDEBUG(MODULE, msg.str() << endl);
197 throw BESInternalError(msg.str(), __FILE__, __LINE__);
200 memcpy(chunk->get_rbuf() + bytes_read, buffer, nbytes);
201 chunk->set_bytes_read(bytes_read + nbytes);
203 BESDEBUG(MODULE, prolog <<
"END" << endl);
216static void inflate_sanity_check(
char **destp,
unsigned long long dest_len,
const char *src,
unsigned long long src_len) {
218 string msg = prolog +
"ERROR! The number of bytes to inflate is zero.";
219 BESDEBUG(MODULE, msg << endl);
220 throw BESInternalError(msg, __FILE__, __LINE__);
223 string msg = prolog +
"ERROR! The number of bytes to inflate into is zero.";
224 BESDEBUG(MODULE, msg << endl);
225 throw BESInternalError(msg, __FILE__, __LINE__);
227 if (!destp || !*destp) {
228 string msg = prolog +
"ERROR! The destination buffer is NULL.";
229 BESDEBUG(MODULE, msg << endl);
230 throw BESInternalError(msg, __FILE__, __LINE__);
233 string msg = prolog +
"ERROR! The source buffer is NULL.";
234 BESDEBUG(MODULE, msg << endl);
235 throw BESInternalError(msg, __FILE__, __LINE__);
250unsigned long long inflate(
char **destp,
unsigned long long dest_len,
char *src,
unsigned long long src_len) {
251 inflate_sanity_check(destp, dest_len, src, src_len);
257 memset(&z_strm, 0,
sizeof(z_strm));
258 z_strm.next_in = (Bytef *) src;
259 z_strm.avail_in = src_len;
260 z_strm.next_out = (Bytef *) (*destp);
261 z_strm.avail_out = dest_len;
263 size_t nalloc = dest_len;
265 char *outbuf = *destp;
268 if (Z_OK != inflateInit(&z_strm))
269 throw BESError(
"Failed to initialize inflate software.", BES_INTERNAL_ERROR, __FILE__, __LINE__);
275 status = inflate(&z_strm, Z_SYNC_FLUSH);
278 if (Z_STREAM_END == status)
break;
281 if (Z_OK != status) {
282 stringstream err_msg;
283 err_msg <<
"Failed to inflate data chunk.";
284 char const *err_msg_cstr = z_strm.msg;
286 err_msg <<
" zlib message: " << err_msg_cstr;
287 (void) inflateEnd(&z_strm);
288 throw BESError(err_msg.str(), BES_INTERNAL_ERROR, __FILE__, __LINE__);
293 if (0 == z_strm.avail_out) {
296 size_t outbuf_size = nalloc;
298 char *new_outbuf =
new char[nalloc];
299 memcpy((
void*)new_outbuf,(
void*)outbuf,outbuf_size);
304 z_strm.next_out = (
unsigned char*) outbuf + z_strm.total_out;
305 z_strm.avail_out = (uInt) (nalloc - z_strm.total_out);
314 (void) inflateEnd(&z_strm);
316 return z_strm.total_out;
344void unshuffle(
char *dest,
const char *src,
unsigned long long src_size,
unsigned long long width) {
345 unsigned long long elems = src_size / width;
348 if (!(width > 1 && elems > 1)) {
349 memcpy(dest,
const_cast<char *
>(src), src_size);
353 char *_src =
const_cast<char *
>(src);
357 for (
unsigned int i = 0; i < width; i++) {
369 size_t duffs_index = (elems + 7) / 8;
372 throw BESError(
"Internal error in unshuffle().", BES_INTERNAL_ERROR, __FILE__, __LINE__);
377#define DUFF_GUTS *_dest = *_src++; _dest += width;
394 }
while (--duffs_index > 0);
402 size_t leftover = src_size % width;
407 _dest -= (width - 1);
408 memcpy((
void *) _dest, (
void *) _src, leftover);
418static void split_by_comma(
const string &s, vector<unsigned long long> &res)
420 const string delimiter =
",";
421 const size_t delim_len = delimiter.size();
423 size_t pos_start = 0, pos_end;
425 while ((pos_end = s.find (delimiter, pos_start)) != string::npos) {
426 res.push_back (stoull(s.substr(pos_start, pos_end - pos_start)));
427 pos_start = pos_end + delim_len;
430 res.push_back (stoull(s.substr (pos_start)));
433void Chunk::parse_chunk_position_in_array_string(
const string &pia, vector<unsigned long long> &cpia_vect)
435 if (pia.empty())
return;
437 if (!cpia_vect.empty()) cpia_vect.clear();
441 if (pia.find(
'[') == string::npos || pia.find(
']') == string::npos || pia.size() < 3)
442 throw BESInternalError(
"while parsing a DMR++, chunk position string malformed", __FILE__, __LINE__);
444 if (pia.find_first_not_of(
"[]1234567890,") != string::npos)
445 throw BESInternalError(
"while parsing a DMR++, chunk position string illegal character(s)", __FILE__, __LINE__);
448 split_by_comma(pia.substr(1, pia.size() - 2), cpia_vect);
450 catch(
const std::invalid_argument &e) {
451 throw BESInternalError(
string(
"while parsing a DMR++, chunk position string illegal character(s): ").append(e.what()), __FILE__, __LINE__);
470 parse_chunk_position_in_array_string(pia,d_chunk_position_in_array);
482 if (pia.empty())
return;
484 if (!d_chunk_position_in_array.empty()) d_chunk_position_in_array.clear();
486 d_chunk_position_in_array = pia;
497 return curl::get_range_arg_string(d_offset, d_size);
520 if(d_data_url ==
nullptr)
524 string cloudydap_context_value = BESContextManager::TheManager()->get_context(S3_TRACKING_CONTEXT, found);
542 bool add_tracking =
false;
547 string s3_vh_regex_str = R
"(^https?:\/\/([a-z]|[0-9])(([a-z]|[0-9]|\.|-){1,61})([a-z]|[0-9])\.s3((\.|-)us-(east|west)-(1|2))?\.amazonaws\.com\/.*$)";
549 BESRegex s3_vh_regex(s3_vh_regex_str.c_str());
550 int match_result = s3_vh_regex.
match(d_data_url->str().c_str(), d_data_url->str().size());
551 if(match_result>=0) {
552 auto match_length = (
unsigned int) match_result;
553 if (match_length == d_data_url->str().size()) {
555 prolog <<
"FULL MATCH. pattern: " << s3_vh_regex_str <<
" url: " << d_data_url->str() << endl);
556 add_tracking =
true;;
562 string s3_path_regex_str = R
"(^https?:\/\/s3((\.|-)us-(east|west)-(1|2))?\.amazonaws\.com\/([a-z]|[0-9])(([a-z]|[0-9]|\.|-){1,61})([a-z]|[0-9])\/.*$)";
563 BESRegex s3_path_regex(s3_path_regex_str.c_str());
564 match_result = s3_path_regex.match(d_data_url->str().c_str(), d_data_url->str().size());
565 if(match_result>=0) {
566 auto match_length = (
unsigned int) match_result;
567 if (match_length == d_data_url->str().size()) {
569 prolog <<
"FULL MATCH. pattern: " << s3_vh_regex_str <<
" url: " << d_data_url->str() << endl);
570 add_tracking =
true;;
577 d_query_marker.append(S3_TRACKING_CONTEXT).append(
"=").append(cloudydap_context_value);
581static void checksum_fletcher32_sanity_check(
const void *_data,
size_t _len) {
584 string msg = prolog +
"ERROR! checksum_fletcher32_sanity_check: _data is NULL";
585 BESDEBUG(MODULE, msg << endl);
590 string msg = prolog +
"ERROR! checksum_fletcher32_sanity_check: _len is 0";
591 BESDEBUG(MODULE, msg << endl);
603checksum_fletcher32(
const void *_data,
size_t _len)
605 checksum_fletcher32_sanity_check(_data, _len);
607 const auto *data = (
const uint8_t *)_data;
608 size_t len = _len / 2;
609 uint32_t sum1 = 0, sum2 = 0;
614 size_t tlen = len > 360 ? 360 : len;
617 sum1 += (uint32_t)(((uint16_t)data[0]) << 8) | ((uint16_t)data[1]);
621 sum1 = (sum1 & 0xffff) + (sum1 >> 16);
622 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
627 sum1 += (uint32_t)(((uint16_t)*data) << 8);
629 sum1 = (sum1 & 0xffff) + (sum1 >> 16);
630 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
634 sum1 = (sum1 & 0xffff) + (sum1 >> 16);
635 sum2 = (sum2 & 0xffff) + (sum2 >> 16);
637 return ((sum2 << 16) | sum1);
650void Chunk::filter_chunk(
const string &filters,
unsigned long long chunk_size,
unsigned long long elem_width) {
655 chunk_size *= elem_width;
662 bool is_1st_deflate =
true;
663 unsigned cur_deflate_index = 0;
664 unsigned num_deflate = 0;
666 for (
unsigned i = 0; i<filter_array.size(); i++) {
668 if (filter_array[i] ==
"deflate") {
669 if (is_1st_deflate ==
true) {
670 cur_deflate_index = i;
671 is_1st_deflate =
false;
673 else if (i != (cur_deflate_index+1)) {
674 throw BESInternalError(
"The deflate filters must be adjacent to each other",
678 cur_deflate_index = i;
685 unsigned deflate_index = 0;
686 unsigned long long out_buf_size = 0;
687 unsigned long long in_buf_size = 0;
688 char**destp =
nullptr;
689 char* dest_deflate =
nullptr;
690 char* tmp_dest =
nullptr;
692 bool ignore_rest_deflate =
false;
694 for (
auto i = filter_array.rbegin(), e = filter_array.rend(); i != e; ++i) {
698 if (filter ==
"deflate") {
707 if (num_deflate > 1 && !ignore_rest_deflate) {
709 dest_deflate =
new char[chunk_size];
711 destp = &dest_deflate;
712 if (deflate_index == 0) {
723 out_buf_size = inflate(destp, chunk_size, tmp_buf, in_buf_size);
727 out_buf_size = inflate(destp, chunk_size, tmp_dest, in_buf_size);
733 in_buf_size = out_buf_size;
734#if DMRPP_USE_SUPER_CHUNKS
736 if (in_buf_size == chunk_size)
737 ignore_rest_deflate =
true;
738 if (ignore_rest_deflate || deflate_index == num_deflate) {
739 char* newdest = *destp;
745 set_rbuf(dest_deflate, chunk_size);
750 delete[] dest_deflate;
757 else if(num_deflate == 1) {
760 dest_deflate =
new char[chunk_size];
761 destp = &dest_deflate;
764 if (out_buf_size == 0) {
765 throw BESError(
"inflate size should be greater than 0", BES_INTERNAL_ERROR, __FILE__, __LINE__);
768#if DMRPP_USE_SUPER_CHUNKS
769 char* new_dest=*destp;
772 set_rbuf(dest_deflate, chunk_size);
776 delete[] dest_deflate;
781 else if (filter ==
"shuffle"){
786#if DMRPP_USE_SUPER_CHUNKS
797 else if (filter ==
"fletcher32"){
799#if ACTUALLY_USE_FLETCHER32_CHECKSUM
803 throw BESInternalError(
"fletcher32 filter: buffer size is less than the size of the checksum", __FILE__, __LINE__);
811 memcpy(&f_checksum, data_ptr, FLETCHER32_CHECKSUM );
816 uint32_t calc_checksum = checksum_fletcher32((
const void *)
get_rbuf(),
get_rbuf_size() - FLETCHER32_CHECKSUM);
818 BESDEBUG(MODULE, prolog <<
"get_rbuf_size(): " <<
get_rbuf_size() << endl);
819 BESDEBUG(MODULE, prolog <<
"calc_checksum: " << calc_checksum << endl);
820 BESDEBUG(MODULE, prolog <<
"f_checksum: " << f_checksum << endl);
821 if (f_checksum != calc_checksum) {
822 throw BESInternalError(
"Data read from the DMR++ handler did not match the Fletcher32 checksum.",
826 if (d_read_buffer_size > FLETCHER32_CHECKSUM)
827 d_read_buffer_size -= FLETCHER32_CHECKSUM;
829 throw BESInternalError(
"Data filtered with fletcher32 don't include the four-byte checksum.",
834 d_is_inflated =
true;
837unsigned int Chunk::obtain_compound_udf_type_size()
const {
839 unsigned int ret_value = 0;
841 for (
const auto &cudf_type_elm:compound_udf_type_elms) {
843 auto dtype = cudf_type_elm.first;
847 case libdap::dods_int8_c:
848 type_size =
sizeof(int8_t);
851 case libdap::dods_int16_c:
852 type_size =
sizeof(int16_t);
855 case libdap::dods_int32_c:
856 type_size =
sizeof(int32_t);
859 case libdap::dods_int64_c:
860 type_size =
sizeof(int64_t);
863 case libdap::dods_uint8_c:
864 case libdap::dods_byte_c:
865 type_size =
sizeof(uint8_t);
868 case libdap::dods_uint16_c:
869 type_size =
sizeof(uint16_t);
872 case libdap::dods_uint32_c:
873 type_size =
sizeof(uint32_t);
876 case libdap::dods_uint64_c:
877 type_size =
sizeof(uint64_t);
880 case libdap::dods_float32_c:
881 type_size =
sizeof(float);
884 case libdap::dods_float64_c:
885 type_size =
sizeof(double);
889 throw BESInternalError(
"Unsupported user-defined fill value compound base type.", __FILE__, __LINE__);
892 ret_value += cudf_type_elm.second *type_size;
899unsigned int Chunk::get_value_size(libdap::Type type)
902 if (type == libdap::dods_structure_c) {
905 else if (!compound_udf_type_elms.empty())
906 return obtain_compound_udf_type_size();
909 case libdap::dods_int8_c:
910 return sizeof(int8_t);
912 case libdap::dods_int16_c:
913 return sizeof(int16_t);
915 case libdap::dods_int32_c:
916 return sizeof(int32_t);
918 case libdap::dods_int64_c:
919 return sizeof(int64_t);
921 case libdap::dods_uint8_c:
922 case libdap::dods_byte_c:
923 return sizeof(uint8_t);
925 case libdap::dods_uint16_c:
926 return sizeof(uint16_t);
928 case libdap::dods_uint32_c:
929 return sizeof(uint32_t);
931 case libdap::dods_uint64_c:
932 return sizeof(uint64_t);
934 case libdap::dods_float32_c:
935 return sizeof(float);
937 case libdap::dods_float64_c:
938 return sizeof(double);
941 throw BESInternalError(
"Unknown fill value type.", __FILE__, __LINE__);
945void Chunk::get_compound_fvalue(
const string &v, vector<char> &compound_fvalue)
const{
947 vector<string> fv_str;
948 obtain_fv_strs(fv_str,v);
950 char * temp_compound_fvalue = compound_fvalue.data();
951 size_t fvalue_count = 0;
953 for (
const auto &cudf_type_elm:compound_udf_type_elms) {
955 auto dtype = cudf_type_elm.first;
956 auto num_elms = cudf_type_elm.second;
960 case libdap::dods_int8_c:
961 type_size =
sizeof(int8_t);
962 for (
int i = 0; i<num_elms;i++) {
963 auto temp_value = (int8_t)stoi(fv_str[fvalue_count]);
964 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
966 temp_compound_fvalue +=type_size;
970 case libdap::dods_int16_c:
971 type_size =
sizeof(int16_t);
972 for (
int i = 0; i<num_elms;i++) {
973 auto temp_value = (int16_t)stoi(fv_str[fvalue_count]);
974 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
976 temp_compound_fvalue +=type_size;
981 case libdap::dods_int32_c:
982 type_size =
sizeof(int32_t);
983 for (
int i = 0; i<num_elms;i++) {
984 auto temp_value = (int32_t)stoi(fv_str[fvalue_count]);
985 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
987 temp_compound_fvalue +=type_size;
991 case libdap::dods_int64_c:
992 type_size =
sizeof(int64_t);
993 for (
int i = 0; i<num_elms;i++) {
994 auto temp_value = (int64_t)stoll(fv_str[fvalue_count]);
995 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
997 temp_compound_fvalue +=type_size;
1001 case libdap::dods_uint8_c:
1002 case libdap::dods_byte_c:
1003 type_size =
sizeof(uint8_t);
1004 for (
int i = 0; i<num_elms;i++) {
1005 auto temp_value = (uint8_t)stoi(fv_str[fvalue_count]);
1006 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
1008 temp_compound_fvalue +=type_size;
1012 case libdap::dods_uint16_c:
1013 type_size =
sizeof(uint16_t);
1014 for (
int i = 0; i<num_elms;i++) {
1015 auto temp_value = (uint16_t)stoi(fv_str[fvalue_count]);
1016 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
1018 temp_compound_fvalue +=type_size;
1022 case libdap::dods_uint32_c:
1023 type_size =
sizeof(uint32_t);
1024 for (
int i = 0; i<num_elms;i++) {
1025 auto temp_value = (uint32_t)stoul(fv_str[fvalue_count]);
1026 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
1028 temp_compound_fvalue +=type_size;
1032 case libdap::dods_uint64_c:
1033 type_size =
sizeof(uint64_t);
1034 for (
int i = 0; i<num_elms;i++) {
1035 auto temp_value = (uint64_t)stoull(fv_str[fvalue_count]);
1036 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
1038 temp_compound_fvalue +=type_size;
1042 case libdap::dods_float32_c:
1043 type_size =
sizeof(float);
1044 for (
int i = 0; i<num_elms;i++) {
1045 auto temp_value = (float)stof(fv_str[fvalue_count]);
1046 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
1048 temp_compound_fvalue +=type_size;
1052 case libdap::dods_float64_c:
1053 type_size =
sizeof(double);
1054 for (
int i = 0; i<num_elms;i++) {
1055 auto temp_value = (double)stod(fv_str[fvalue_count]);
1056 memcpy(temp_compound_fvalue,(
char *)&temp_value,type_size);
1058 temp_compound_fvalue +=type_size;
1063 throw BESInternalError(
"Unsupported user-defined fill value compound base type.", __FILE__, __LINE__);
1070void Chunk::obtain_fv_strs(vector<string>& fv_str,
const string &v)
const{
1072 string::size_type start = 0;
1073 string::size_type end = 0;
1076 while ((end = v.find(sep, start)) != string::npos) {
1077 fv_str.push_back(v.substr(start, end - start));
1080 fv_str.push_back(v.substr(start));
1085const char * Chunk::get_value_ptr(
fill_value &fv, libdap::Type type,
const string &v,
bool is_big_endian)
1089 case libdap::dods_int8_c:
1090 fv.int8 = (int8_t)stoi(v);
1091 return (
const char *)&fv.int8;
1093 case libdap::dods_int16_c:
1094 fv.int16 = (int16_t)stoi(v);
1096 fv.int16 = bswap_16(fv.int16);
1097 return (
const char *)&fv.int16;
1099 case libdap::dods_int32_c:
1101 fv.int32 = (int32_t)stoi(v);
1103 fv.int32 = bswap_32(fv.int32);
1104 return (
const char *)&fv.int32;
1106 case libdap::dods_int64_c:
1107 fv.int64 = (int64_t)stoll(v);
1109 fv.int64 = bswap_64(fv.int64);
1110 return (
const char *)&fv.int64;
1112 case libdap::dods_uint8_c:
1113 case libdap::dods_byte_c:
1114 fv.uint8 = (uint8_t)stoi(v);
1115 return (
const char *)&fv.uint8;
1117 case libdap::dods_uint16_c:
1118 fv.uint16 = (uint16_t)stoi(v);
1120 fv.uint16 = bswap_16(fv.uint16);
1121 return (
const char *)&fv.uint16;
1123 case libdap::dods_uint32_c:
1124 fv.uint32 = (uint32_t)stoul(v);
1126 fv.uint32 = bswap_32(fv.uint32);
1127 return (
const char *)&fv.uint32;
1129 case libdap::dods_uint64_c:
1130 fv.uint64 = (uint64_t)stoull(v);
1132 fv.uint64 = bswap_32(fv.uint64);
1133 return (
const char *)&fv.uint64;
1135 case libdap::dods_float32_c:
1138 auto fv_float_p=(
char *)&fv.f;
1140 swap_float32(fv_float_p,1);
1141 return (
const char *)fv_float_p;
1144 case libdap::dods_float64_c:
1147 auto fv_double_p=(
char *)&fv.d;
1149 swap_float64 (fv_double_p,1);
1150 return (
const char *)fv_double_p;
1152 case libdap::dods_str_c:
1156 throw BESInternalError(
"Unknown fill value type.", __FILE__, __LINE__);
1166 unsigned int value_size = 0;
1168 if (d_fill_value_type == libdap::dods_str_c)
1169 value_size = (
unsigned int)d_fill_value.size();
1171 value_size = get_value_size(d_fill_value_type);
1173 bool is_big_endian =
false;
1174 if (d_byte_order ==
"BE")
1175 is_big_endian =
true;
1177 const char *value =
nullptr;
1178 vector<char> compound_fvalue;
1180 if (d_fill_value_type == libdap::dods_structure_c && (!compound_udf_type_elms.empty() || struct_size !=0)) {
1182 if (value_size == 0)
1183 throw BESInternalError(
"The size of fill value should NOT be 0.", __FILE__,__LINE__);
1184 compound_fvalue.resize(value_size);
1187 if (d_fill_value !=
"0")
1188 get_compound_fvalue(d_fill_value,compound_fvalue);
1189 value = compound_fvalue.data();
1194 value = get_value_ptr(fv, d_fill_value_type, d_fill_value,is_big_endian);
1197 if(d_fill_value_type == libdap::dods_str_c && d_fill_value==
""){
1202 if (value_size == 0)
1203 throw BESInternalError(
"The size of fill value should NOT be 0.", __FILE__,__LINE__);
1206 unsigned long long num_values =
get_rbuf_size() / value_size;
1211 for (
unsigned long long i = 0; i < num_values; ++i, buffer += value_size) {
1212 memcpy(buffer, value, value_size);
1233 if (d_read_buffer_is_mine)
1236 if (d_uses_fill_value) {
1240 dmrpp_easy_handle *handle = DmrppRequestHandler::curl_handle_pool->get_easy_handle(
this);
1242 throw BESInternalError(prolog +
"No more libcurl handles.", __FILE__, __LINE__);
1246 DmrppRequestHandler::curl_handle_pool->release_handle(handle);
1255 DmrppRequestHandler::curl_handle_pool->release_handle(handle);
1263 oss <<
"Wrong number of bytes read for chunk; read: " <<
get_bytes_read() <<
", expected: " <<
get_size();
1271void Chunk::read_chunk_dio() {
1279 if (d_read_buffer_is_mine)
1282 dmrpp_easy_handle *handle = DmrppRequestHandler::curl_handle_pool->get_easy_handle(
this);
1284 throw BESInternalError(prolog +
"No more libcurl handles.", __FILE__, __LINE__);
1288 DmrppRequestHandler::curl_handle_pool->release_handle(handle);
1297 DmrppRequestHandler::curl_handle_pool->release_handle(handle);
1305 oss <<
"Wrong number of bytes read for chunk; read: " <<
get_bytes_read() <<
", expected: " <<
get_size();
1306 throw BESInternalError(oss.str(), __FILE__, __LINE__);
1325 oss <<
"[ptr='" << (
void *)
this <<
"']";
1326 oss <<
"[data_url='" << d_data_url->str() <<
"']";
1327 oss <<
"[offset=" << d_offset <<
"]";
1328 oss <<
"[size=" << d_size <<
"]";
1329 oss <<
"[chunk_position_in_array=(";
1330 for (
unsigned long long i = 0; i < d_chunk_position_in_array.size(); i++) {
1332 oss << d_chunk_position_in_array[i];
1335 oss <<
"[is_read=" << d_is_read <<
"]";
1336 oss <<
"[is_inflated=" << d_is_inflated <<
"]";
1339string Chunk::to_string()
const {
1340 std::ostringstream oss;
1360 if (d_data_url ==
nullptr)
1363 BESDEBUG(MODULE, prolog <<
"Using data_url: " << effective_url->str() << endl);
1365#if ENABLE_TRACKING_QUERY_PARAMETER
1368 if (!d_query_marker.empty()) {
1369 string url_str = effective_url->str();
1370 if(url_str.find(
'?') != string::npos){
1371 url_str.append(
"&");
1374 url_str.append(
"?");
1376 url_str += d_query_marker;
1377 shared_ptr<http::url> query_marker_url(
new http::url(url_str));
1378 return query_marker_url;
1382 return effective_url;
Base exception class for the BES with basic string message.
exception thrown if internal error encountered
Regular expression matching.
int match(const char *s, int len, int pos=0) const
Does the pattern match.
static std::vector< std::string > split(const std::string &s, char delim='/', bool skip_empty=true)
Splits the string s into the return vector of tokens using the delimiter delim and skipping empty val...
static EffectiveUrlCache * TheCache()
Get the singleton EffectiveUrlCache instance.
virtual void set_bytes_read(unsigned long long bytes_read)
Set the size of this Chunk's data block.
virtual void dump(std::ostream &strm) const
virtual char * get_rbuf()
virtual void read_chunk()
void add_tracking_query_param()
Modify this chunk's data URL so that it includes tracking info.
virtual std::string get_curl_range_arg_string()
Returns a curl range argument. The libcurl requires a string argument for range-ge activitys,...
virtual std::shared_ptr< http::url > get_data_url() const
Get the data URL for this chunk.
virtual void set_rbuf_to_size()
Allocates the internal read buffer to be d_size bytes.
virtual unsigned long long get_bytes_read() const
void set_position_in_array(const std::string &pia)
parse the chunk position string
virtual unsigned long long get_rbuf_size() const
virtual unsigned long long get_size() const
void set_read_buffer(char *buf, unsigned long long buf_size, unsigned long long bytes_read=0, bool assume_ownership=true)
Set the target read buffer for this chunk.
virtual void filter_chunk(const std::string &filters, unsigned long long chunk_size, unsigned long long elem_width)
filter data in the chunk
virtual void load_fill_values()
Load the chunk with fill values - temporary implementation.
void set_response_content_type(const std::string &ct)
Set the response type of the last response.
Bundle a libcurl easy handle with other information.
void read_data()
This is the read_data() method for all transfers.
std::shared_ptr< EffectiveUrl > get_effective_url(std::shared_ptr< url > source_url)
Parse a URL into the protocol, host, path and query parts.