28#include <unordered_set> 
   37#include <libdap/Str.h> 
   38#include <libdap/Structure.h> 
   39#include <libdap/util.h> 
   40#include <libdap/D4Attributes.h> 
   42#include <BESNotFoundError.h> 
   43#include <BESInternalError.h> 
   44#include <BESInternalFatalError.h> 
   46#include <TheBESKeys.h> 
   47#include <BESContextManager.h> 
   50#include "DmrppTypeFactory.h" 
   51#include "DmrppD4Group.h" 
   52#include "DmrppArray.h" 
   54#include "D4ParserSax2.h" 
   58#define ERROR(x) do { cerr << "ERROR: " << x << " " << __FILE__ << ":" << __LINE__ << endl; } while(false) 
   63using SD_mapping_info_t = 
struct {
 
   77namespace build_dmrpp_util_h4 {
 
   81#define VERBOSE(x) do { if (verbose) (x); } while(false) 
   82#define prolog std::string("build_dmrpp_h4::").append(__func__).append("() - ") 
   84constexpr auto INVOCATION_CONTEXT = 
"invocation";
 
   88int SDfree_mapping_info(SD_mapping_info_t  *map_info)
 
   90    intn  ret_value = SUCCEED;
 
   93    if (map_info == 
nullptr)
 
   96    map_info->nblocks = 0;
 
   98    if (map_info->offsets != 
nullptr) {
 
   99        HDfree(map_info->offsets);
 
  100        map_info->offsets = 
nullptr;
 
  103    if (map_info->lengths) {
 
  104        HDfree(map_info->lengths);
 
  105        map_info->lengths = 
nullptr;
 
  111void close_hdf4_file_ids(int32 sd_id, int32 file_id) {
 
  118size_t combine_linked_blocks(
const SD_mapping_info_t &map_info, vector<int> & merged_lengths, vector<int> &merged_offsets) {
 
  120    int num_eles = map_info.nblocks;
 
  123    for (
int i = 0; i<offset.size(); i++) {
 
  124       cout<<
"offset["<<i<<
"]= "<<offset[i] <<endl;
 
  125       cout<<
"length["<<i<<
"]= "<<length[i] <<endl;
 
  130    merged_offsets.push_back(map_info.offsets[0]);
 
  132    int temp_length = map_info.lengths[0];
 
  134    for (
int i = 0; i <(num_eles-1); i++) {
 
  139        if (map_info.offsets[i+1] !=(map_info.offsets[i] + map_info.lengths[i])) {
 
  140            merged_lengths.push_back(temp_length);
 
  141            merged_offsets.push_back(map_info.offsets[i+1]);
 
  142            temp_length = map_info.lengths[i+1];
 
  145            temp_length +=map_info.lengths[i+1];
 
  151    merged_lengths.push_back(temp_length);
 
  153    return merged_lengths.size();
 
  165vector<unsigned long long>
 
  166write_chunk_position_in_array(
int rank, 
const unsigned long long *lengths, 
const int32_t *strides)
 
  168    vector<unsigned long long> chunk_pos;
 
  170    for(
int i = 0; i < rank; i++){
 
  171        unsigned long long index = lengths[i] * (
unsigned long long)strides[i];
 
  172        chunk_pos.push_back(index);
 
  192int read_chunk(
int sdsid, SD_mapping_info_t *map_info, 
int *origin)
 
  194    intn  ret_value = SUCCEED;
 
  198    SDfree_mapping_info(map_info);
 
  207    intn info_count = SDgetdatainfo(sdsid, origin, 0, 0, 
nullptr, 
nullptr);
 
  208    if (info_count == FAIL) {
 
  209        ERROR(
"SDgetedatainfo() failed in read_chunk().\n");
 
  214    if (info_count > 0) {
 
  215        map_info->nblocks = (int32) info_count;
 
  216        map_info->offsets = (int32 *)HDmalloc(
sizeof(int32)*map_info->nblocks);
 
  217        if (map_info->offsets == 
nullptr) {
 
  218            ERROR(
"HDmalloc() failed: Out of Memory");
 
  221        map_info->lengths = (int32 *)HDmalloc(
sizeof(int32)*map_info->nblocks);
 
  222        if (map_info->lengths == 
nullptr) {
 
  223            HDfree(map_info->offsets);
 
  224            ERROR(
"HDmalloc() failed: Out of Memory");
 
  228        ret_value = SDgetdatainfo(sdsid, origin, 0, info_count, map_info->offsets, map_info->lengths);
 
  236string get_sds_fill_value_str(int32 sdsid, int32 datatype) {
 
  240    if (SDcheckempty(sdsid,&emptySDS) == FAIL) {
 
  242        throw BESInternalError(
"SDcheckempty fails. ",__FILE__,__LINE__);
 
  251            if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
 
  252                ret_value = to_string(fvalue);
 
  254            else if(emptySDS == 1)
 
  255                ret_value = to_string(255);
 
  261            if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
 
  262                ret_value = to_string(fvalue);
 
  263            else if(emptySDS == 1)
 
  264                ret_value = to_string(FILL_BYTE);
 
  270            if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
 
  271                ret_value = to_string(fvalue);
 
  272            else if(emptySDS == 1)
 
  273                ret_value = to_string(FILL_SHORT);
 
  279            if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
 
  280                ret_value = to_string(fvalue);
 
  281             else if(emptySDS == 1)
 
  282                ret_value = to_string(65535);
 
  288            if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
 
  289                ret_value = to_string(fvalue);
 
  290            else if(emptySDS == 1)
 
  291                ret_value = to_string(FILL_LONG);
 
  297            if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
 
  298                ret_value = to_string(fvalue);
 
  299            else if(emptySDS == 1)
 
  300                ret_value = to_string(4294967295);
 
  306            if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
 
  307                ret_value = to_string(fvalue);
 
  308            else if(emptySDS == 1)
 
  309                ret_value = to_string(FILL_FLOAT);
 
  315            if (SDgetfillvalue(sdsid, &fvalue) == SUCCEED)
 
  316                ret_value = to_string(fvalue);
 
  317            else if(emptySDS == 1)
 
  318                ret_value = to_string(FILL_DOUBLE);
 
  328bool SD_set_fill_value(int32 sdsid, int32 datatype, BaseType *btp) {
 
  330    string fill_value = get_sds_fill_value_str(sdsid,datatype);
 
  331    if (!fill_value.empty()) {
 
  332         auto dc = 
dynamic_cast<DmrppCommon *
>(btp);
 
  334             ERROR(
"Expected to find a DmrppCommon instance but did not.");
 
  337        dc->set_uses_fill_value(
true);
 
  338        dc->set_fill_value_string(fill_value);
 
  342bool  ingest_sds_info_to_chunk(
int file, int32 obj_ref, BaseType *btp) {
 
  344    int32 sds_index = SDreftoindex(file, obj_ref);
 
  345    if (sds_index == FAIL) {
 
  346        ERROR(
"SDreftoindex() failed");
 
  350    int sdsid = SDselect(file, sds_index);
 
  352        ERROR(
"SDselect() failed");
 
  356    VERBOSE(cerr << 
"Name: " << btp->name() << endl);
 
  357    VERBOSE(cerr << 
"DMR FQN: " << btp->FQN() << endl);
 
  358    VERBOSE(cerr << 
"sdsid: " << sdsid << endl);
 
  360    char obj_name[H4_MAX_NC_NAME]; 
 
  362    int32 dimsizes[H4_MAX_VAR_DIMS]; 
 
  363    int32 data_type = -1;            
 
  364    int32 num_attrs = -1;            
 
  366    int status = SDgetinfo(sdsid, obj_name, &rank, dimsizes, &data_type, &num_attrs);
 
  367    if (status == FAIL) {
 
  368        ERROR(
"SDgetinfo() failed.");
 
  374    int32 chunk_flag = -1;        
 
  376    status = SDgetchunkinfo(sdsid, &cdef, &chunk_flag);
 
  377    if (status == FAIL) {
 
  378        ERROR(
"SDgetchunkinfo() failed.");
 
  383    switch (chunk_flag) {
 
  385            VERBOSE(cerr << 
"No chunking.\n");
 
  390                ERROR(
"Invalid rank.");
 
  394            VERBOSE(cerr << 
"HDF_CHUNK or HDF_COMP.\n");
 
  398            ERROR(
"NBit Compression chunking not supported.");
 
  402            ERROR(
"Unknown chunking flag.");
 
  409    int result = Hgetntinfo(data_type, &info);
 
  410    if (result == FAIL) {
 
  411        ERROR(
"Hgetntinfo() failed.");
 
  416        if (strncmp(info.byte_order, 
"bigEndian", 9) == 0)
 
  418        else if (strncmp(info.byte_order, 
"littleEndian", 12) == 0)
 
  421            endian_name = 
"UNKNOWN";
 
  424    auto dc = 
dynamic_cast<DmrppCommon *
>(btp);
 
  426       ERROR(
"Expected to find a DmrppCommon instance but did not.");
 
  434    comp_coder_t        comp_coder_type = COMP_CODE_NONE;
 
  437    if (SDgetcompinfo(sdsid, &comp_coder_type, &c_info) == FAIL) {
 
  438        ERROR(
"SDgetcompinfo() failed.");
 
  444    if (chunk_flag == HDF_CHUNK || chunk_flag == HDF_COMP ) {
 
  445        vector<unsigned long long> chunk_dimension_sizes(rank, 0);
 
  446        for (
int i = 0; i < rank; i++) {
 
  447            if (chunk_flag == HDF_CHUNK) {
 
  448                chunk_dimension_sizes[i] = cdef.chunk_lengths[i];
 
  451                chunk_dimension_sizes[i] = cdef.comp.chunk_lengths[i];
 
  454        if (chunk_flag == HDF_COMP) {
 
  456            if (comp_coder_type == COMP_CODE_DEFLATE) {
 
  457                dc->ingest_compression_type(
"deflate");
 
  458                vector<unsigned int> deflate_levels;
 
  459                deflate_levels.push_back(c_info.deflate.level);
 
  460                dc->set_deflate_levels(deflate_levels);
 
  463                ERROR(
"Encounter unsupported compression method. Currently only support deflate compression.");
 
  468        dc->set_chunk_dimension_sizes(chunk_dimension_sizes);
 
  472        SD_mapping_info_t map_info;
 
  473        map_info.is_empty = 0;
 
  474        map_info.nblocks = 0;
 
  475        map_info.offsets = 
nullptr;
 
  476        map_info.lengths = 
nullptr;
 
  477        map_info.data_type = data_type;
 
  481        vector<unsigned long long> position_in_array(rank, 0);
 
  484        vector<int> steps(rank, 0);
 
  485        vector<int32_t> strides(rank, 0);
 
  486        int number_of_chunks = 1;
 
  487        for (
int i = 0; i < rank; i++) {
 
  489            steps[i] =  1 + ((dimsizes[i] - 1) / chunk_dimension_sizes[i]);
 
  490            number_of_chunks = number_of_chunks * steps[i];
 
  494        VERBOSE(cerr << 
"number_of_chunks: " << number_of_chunks << endl);
 
  495        VERBOSE(cerr << 
"rank: " << rank << endl);
 
  496        VERBOSE(cerr << 
"chunk dimension sizes: ");
 
  497        VERBOSE(copy(chunk_dimension_sizes.begin(), chunk_dimension_sizes.end(),
 
  498                     ostream_iterator<int32>(cerr, 
" ")));
 
  502        vector<uint32> info_count(number_of_chunks);
 
  503        intn max_num_blocks = SDgetallchunkdatainfo(sdsid,number_of_chunks,rank,steps.data(),0,info_count.data(),
 
  505        if (max_num_blocks == FAIL) {
 
  506            ERROR(
"SDgetallchunkdatainfo failed.");
 
  511        vector<int32>offsetarray(max_num_blocks*number_of_chunks);
 
  512        vector<int32>lengtharray(max_num_blocks*number_of_chunks);
 
  514        max_num_blocks = SDgetallchunkdatainfo(sdsid,number_of_chunks,rank,steps.data(),max_num_blocks,info_count.data(),
 
  515                                               offsetarray.data(),lengtharray.data());
 
  516        if (max_num_blocks == FAIL) {
 
  517            ERROR(
"SDgetallchunkdatainfo failed.");
 
  521        bool LBChunk = (max_num_blocks>1);
 
  524        for (
int k = 0; k < number_of_chunks; ++k) {
 
  526            auto pia = write_chunk_position_in_array(rank, chunk_dimension_sizes.data(), strides.data());
 
  529            if (info_count[k] >1) {
 
  531                VERBOSE(cerr << 
"number of blocks in a chunk is: " << info_count[k]<< endl);
 
  532                for (
unsigned int i = 0; i < info_count[k]; i++) {
 
  533                    VERBOSE(cerr << 
"offsets[" << k << 
", " << i << 
"]: " << offsetarray[ol_counter] << endl);
 
  534                    VERBOSE(cerr << 
"lengths[" << k << 
", " << i << 
"]: " << lengtharray[ol_counter] << endl);
 
  536                    dc->add_chunk(endian_name, lengtharray[ol_counter], offsetarray[ol_counter], pia,
true,i);
 
  539                ol_counter +=max_num_blocks-info_count[k];
 
  543            else if (info_count[k] == 1) {
 
  545                dc->add_chunk(endian_name, lengtharray[ol_counter], offsetarray[ol_counter], pia);
 
  546                ol_counter +=max_num_blocks;
 
  548            else if (info_count[k] == 0) 
 
  549                ol_counter +=max_num_blocks;
 
  553            for(
int i = rank-1; i >= 0 ; i--) {
 
  554                if ((k+1) % scale == 0) {
 
  555                    strides[i] = ++strides[i] % steps[i];
 
  557                scale = scale * steps[i];
 
  561            dc->set_multi_linked_blocks_chunk(LBChunk);
 
  567    if (chunk_flag == HDF_CHUNK || chunk_flag == HDF_COMP ) {
 
  568        vector<unsigned long long> chunk_dimension_sizes(rank, 0);
 
  569        for (
int i = 0; i < rank; i++) {
 
  570            if (chunk_flag == HDF_CHUNK) {
 
  571                chunk_dimension_sizes[i] = cdef.chunk_lengths[i];
 
  574                chunk_dimension_sizes[i] = cdef.comp.chunk_lengths[i];
 
  577        if (chunk_flag == HDF_COMP) {
 
  579            if (comp_coder_type == COMP_CODE_DEFLATE) {
 
  580                dc->ingest_compression_type(
"deflate");
 
  581                vector<unsigned int> deflate_levels;
 
  582                deflate_levels.push_back(c_info.deflate.level);
 
  583                dc->set_deflate_levels(deflate_levels);
 
  586                ERROR(
"Encounter unsupported compression method. Currently only support deflate compression.");
 
  591        dc->set_chunk_dimension_sizes(chunk_dimension_sizes);
 
  593        SD_mapping_info_t map_info;
 
  594        map_info.is_empty = 0;
 
  595        map_info.nblocks = 0;
 
  596        map_info.offsets = 
nullptr;
 
  597        map_info.lengths = 
nullptr;
 
  598        map_info.data_type = data_type;
 
  600        vector<unsigned long long> position_in_array(rank, 0);
 
  603        vector<int> steps(rank, 0);
 
  604        vector<int32_t> strides(rank, 0);
 
  605        int number_of_chunks = 1;
 
  606        for(
int i = 0; i < rank; i++) {
 
  607            steps[i] =  1 + ((dimsizes[i] - 1) / chunk_dimension_sizes[i]);
 
  608            number_of_chunks = number_of_chunks * steps[i];
 
  612        VERBOSE(cerr << 
"number_of_chunks: " << number_of_chunks << endl);
 
  613        VERBOSE(cerr << 
"rank: " << rank << endl);
 
  614        VERBOSE(cerr << 
"chunk dimension sizes: ");
 
  615        VERBOSE(copy(chunk_dimension_sizes.begin(), chunk_dimension_sizes.end(),
 
  616                     ostream_iterator<int32>(cerr, 
" ")));
 
  619        bool LBChunk = 
false;
 
  621        for (
int k = 0; k < number_of_chunks; ++k) {
 
  622            auto info_count = read_chunk(sdsid, &map_info, strides.data());
 
  623            if (info_count == FAIL) {
 
  624                ERROR(
"read_chunk() failed.");
 
  629            auto pia = write_chunk_position_in_array(rank, chunk_dimension_sizes.data(), strides.data());
 
  632            if (map_info.nblocks >1) {
 
  636                VERBOSE(cerr << 
"number of blocks in a chunk is: " << map_info.nblocks << endl);
 
  637                for (
unsigned int i = 0; i < map_info.nblocks; i++) {
 
  638                    VERBOSE(cerr << 
"offsets[" << k << 
", " << i << 
"]: " << map_info.offsets[i] << endl);
 
  639                    VERBOSE(cerr << 
"lengths[" << k << 
", " << i << 
"]: " << map_info.lengths[i] << endl);
 
  641                    dc->add_chunk(endian_name, map_info.lengths[i], map_info.offsets[i], pia,
true,i);
 
  646            else if (map_info.nblocks == 1) {
 
  647                    dc->add_chunk(endian_name, map_info.lengths[0], map_info.offsets[0], pia);
 
  652            for(
int i = rank-1; i >= 0 ; i--) {
 
  653                if ((k+1) % scale == 0) {
 
  654                    strides[i] = ++strides[i] % steps[i];
 
  656                scale = scale * steps[i];
 
  658            SDfree_mapping_info(&map_info);
 
  661            dc->set_multi_linked_blocks_chunk(LBChunk);
 
  664    else if (chunk_flag == HDF_NONE) {
 
  665        SD_mapping_info_t map_info;
 
  666        map_info.is_empty = 0;
 
  667        map_info.nblocks = 0;
 
  668        map_info.offsets = 
nullptr;
 
  669        map_info.lengths = 
nullptr;
 
  670        map_info.data_type = data_type;
 
  673        if (comp_coder_type != COMP_CODE_NONE) {
 
  674            if (comp_coder_type == COMP_CODE_DEFLATE) {
 
  675                dc->ingest_compression_type(
"deflate");
 
  676                vector<unsigned int> deflate_levels;
 
  677                deflate_levels.push_back(c_info.deflate.level);
 
  678                dc->set_deflate_levels(deflate_levels);
 
  681                ERROR(
"Encounter unsupported compression method. Currently only support deflate compression.");
 
  687        vector<int> origin(rank, 0);
 
  688        auto info_count = read_chunk(sdsid, &map_info, origin.data());
 
  689        if (info_count == FAIL) {
 
  690            ERROR(
"read_chunk() failed in the middle of ingest_sds_info_to_chunk().");
 
  695        vector<unsigned long long> position_in_array(rank, 0);
 
  696        if (map_info.nblocks ==1) {
 
  697              dc->add_chunk(endian_name, map_info.lengths[0], map_info.offsets[0], position_in_array);
 
  699        else if (map_info.nblocks>1) {
 
  703            vector<int> merged_lengths;
 
  704            vector<int> merged_offsets;
 
  705            size_t merged_number_blocks = combine_linked_blocks(map_info, merged_lengths, merged_offsets);
 
  706            for (
unsigned i = 0; i < merged_number_blocks; i++) {
 
  707                VERBOSE(cerr << 
"offsets[" << i << 
"]: " << map_info.offsets[i] << endl);
 
  708                VERBOSE(cerr << 
"lengths[" << i << 
"]: " << map_info.lengths[i] << endl);
 
  711                dc->add_chunk(endian_name, merged_lengths[i], merged_offsets[i], 
true,i);
 
  715        SDfree_mapping_info(&map_info);
 
  719        ERROR(
"Unknown chunking type.");
 
  725    if (
false == SD_set_fill_value(sdsid,data_type, btp)) {
 
  726        ERROR(
"SD_set_fill_value failed");
 
  736size_t combine_linked_blocks_vdata( 
const vector<int>& lengths, 
const vector<int>& offsets, vector<int> & merged_lengths, vector<int> &merged_offsets) {
 
  738    size_t num_eles = lengths.size();
 
  741    for (
int i = 0; i<offset.size(); i++) {
 
  742       cout<<
"offset["<<i<<
"]= "<<offset[i] <<endl;
 
  743       cout<<
"length["<<i<<
"]= "<<length[i] <<endl;
 
  748    merged_offsets.push_back(offsets[0]);
 
  749    int temp_length = lengths[0];
 
  751    for (
size_t i = 0; i <(num_eles-1); i++) {
 
  756        if (offsets[i+1] !=(offsets[i] + lengths[i])) {
 
  757            merged_lengths.push_back(temp_length);
 
  758            merged_offsets.push_back(offsets[i+1]);
 
  759            temp_length = lengths[i+1];
 
  762            temp_length +=lengths[i+1];
 
  768    merged_lengths.push_back(temp_length);
 
  771for (
int i = 0; i <merged_lengths.size(); i++) {
 
  772cout <<
"merged_lengths["<<i<<
"]= "<<merged_lengths[i]<<endl;
 
  773cout <<
"merged_offsets["<<i<<
"]= "<<merged_offsets[i]<<endl;
 
  777    return merged_lengths.size();
 
  782bool  ingest_vdata_info_to_chunk(int32 file_id, int32 obj_ref, BaseType *btp) {
 
  784    int32 vdata_id = VSattach(file_id, obj_ref, 
"r");
 
  785    if (vdata_id == FAIL){
 
  786        ERROR(
"VSattach() failed.");
 
  791    int32 field_datatype = VFfieldtype(vdata_id,0);
 
  792    if (field_datatype == FAIL){
 
  793        ERROR(
"VFfieldtype() failed.");
 
  800    int result = Hgetntinfo(field_datatype, &info);
 
  801    if (result == FAIL) {
 
  802        ERROR(
"Hgetntinfo() failed in ingest_vdata_info_to_chunk.");
 
  807        if (strncmp(info.byte_order, 
"bigEndian", 9) == 0)
 
  809        else if (strncmp(info.byte_order, 
"littleEndian", 12) == 0)
 
  812            endian_name = 
"UNKNOWN";
 
  815    int32 num_linked_blocks = VSgetdatainfo(vdata_id,0,0,
nullptr,
nullptr);
 
  817    if (num_linked_blocks == FAIL){
 
  818        ERROR(
"VSgetdatainfo() failed in ingest_vdata_info_to_chunk.");
 
  822    if (num_linked_blocks == 1) {
 
  826        if (VSgetdatainfo(vdata_id,0,1,&offset,&length) == FAIL){
 
  827            ERROR(
"VSgetdatainfo() failed, cannot obtain offset and length info.");
 
  832        auto dc = 
dynamic_cast<DmrppCommon *
>(btp);
 
  834            ERROR(
"Expected to find a DmrppCommon instance but did not in ingested_vdata_info_to_chunk");
 
  838        auto da = 
dynamic_cast<DmrppArray *
>(btp);
 
  840            ERROR(
"Expected to find a DmrppArray instance but did not in ingested_vdata_info_to_chunk");
 
  845        if (da->width_ll() != (int64_t)length) {
 
  846            ERROR(
"The retrieved vdata size is no equal to the original size.");
 
  850        dc->add_chunk(endian_name, (
unsigned long long)length, (
unsigned long long)offset,
"");
 
  853        int32 total_num_fields = VFnfields(vdata_id);
 
  854        if (total_num_fields == 1) {
 
  857            VSgetdatainfo(vdata_id,0,1,&offset,&length);           
 
  858cout <<
"offset is: "<<offset <<endl;
 
  859cout <<
"length is: "<<length <<endl;
 
  865    else if (num_linked_blocks >1) {
 
  870        lengths.resize(num_linked_blocks);
 
  871        offsets.resize(num_linked_blocks);
 
  872        if (VSgetdatainfo(vdata_id, 0, num_linked_blocks, offsets.data(), lengths.data()) == FAIL) {
 
  873            ERROR(
"VSgetdatainfo() failed, cannot obtain offset and length info when the num_linked_blocks is >1.");
 
  877        vector<int>merged_lengths;
 
  878        vector<int>merged_offsets;
 
  879        size_t merged_number_blocks = combine_linked_blocks_vdata(lengths,offsets,merged_lengths,merged_offsets);
 
  880        auto dc = 
dynamic_cast<DmrppCommon *
>(btp);
 
  882            ERROR(
"Expected to find a DmrppArray instance but did not when num_linked_blocks is >1.");
 
  887        for (
unsigned i = 0; i < merged_number_blocks; i++)
 
  888            dc->add_chunk(endian_name, merged_lengths[i], merged_offsets[i],
true,i);
 
  898bool obtain_compress_encode_data(
string &encoded_str, 
const Bytef*source_data,
size_t source_data_size, 
string &err_msg) {
 
  900    uLong ssize = (uLong)source_data_size;
 
  901    uLongf csize = (uLongf)ssize*2;
 
  902    vector<Bytef> compressed_src;
 
  903    compressed_src.resize(source_data_size*2);
 
  905    int retval = compress(compressed_src.data(), &csize, source_data, ssize);
 
  907        err_msg = 
"Fail to compress the data";
 
  911    encoded_str = base64::Base64::encode(compressed_src.data(),(
int)csize);
 
  918bool add_missing_cf_grid(
const string &filename,BaseType *btp, 
const D4Attribute *eos_cf_attr, 
string &err_msg) {
 
  920    VERBOSE(cerr<<
"Coming to add_missing_cf_grid"<<endl);
 
  922    string eos_cf_attr_value = eos_cf_attr->value(0);
 
  924    VERBOSE(cerr<<
"eos_cf_attr_value: "<<eos_cf_attr_value <<endl);
 
  926    size_t space_pos = eos_cf_attr_value.find_last_of(
' ');
 
  927    if (space_pos ==string::npos) { 
 
  928        err_msg = 
"Attribute eos_latlon must have space inside";
 
  932    string grid_name = eos_cf_attr_value.substr(0,space_pos);
 
  933    string cf_name = eos_cf_attr_value.substr(space_pos+1);
 
  935    VERBOSE(cerr<<
"grid_name: "<<grid_name <<endl);
 
  936    VERBOSE(cerr<<
"cf_name: "<<cf_name<<endl);
 
  938    if (cf_name ==
"YDim")
 
  941    int32 gridfd = GDopen(
const_cast < char *
>(filename.c_str()), DFACC_READ);
 
  943        err_msg = 
"HDF-EOS: GDopen failed";
 
  946    int32 gridid = GDattach(gridfd, 
const_cast<char *
>(grid_name.c_str()));
 
  948        err_msg = 
"HDF-EOS: GDattach failed to attach " + grid_name;
 
  960    if (GDgridinfo(gridid, &xdim, &ydim, upleft,
 
  964        err_msg = 
"GDgridinfo failed for grid name: " + grid_name;
 
  968    auto dc = 
dynamic_cast<DmrppCommon *
>(btp);
 
  972        err_msg = 
"Expected to find a DmrppCommon instance but did not in add_missing_cf_grid";
 
  975    auto da = 
dynamic_cast<DmrppArray *
>(btp);
 
  979        err_msg = 
"Expected to find a DmrppArray instance but did not in add_missing_cf_grid";
 
  983    da->set_missing_data(
true);
 
  985    int total_num = is_xdim?xdim:ydim;
 
  986    vector<double>val(total_num);    
 
  992        evalue = lowright[0];
 
  996        evalue = lowright[1];
 
  999    double step_v = (evalue - svalue)/total_num;
 
 1002    for(
int i = 1;i<total_num; i++)
 
 1003        val[i] = val[i-1] + step_v;
 
 1005    da->set_value(val.data(),total_num);
 
 1006    da->set_read_p(
true);
 
 1016bool add_missing_eos_latlon(
const string &filename,BaseType *btp, 
const D4Attribute *eos_ll_attr, 
string &err_msg) {
 
 1018    VERBOSE(cerr<<
"Coming to add_missing_eos_latlon"<<endl);
 
 1020    string eos_ll_attr_value = eos_ll_attr->value(0);
 
 1022    VERBOSE(cerr<<
"eos_ll_attr_value: "<<eos_ll_attr_value <<endl);
 
 1024    size_t space_pos = eos_ll_attr_value.find_last_of(
' ');
 
 1025    if (space_pos ==string::npos) { 
 
 1026        err_msg = 
"Attribute eos_latlon must have space inside";
 
 1030    string grid_name = eos_ll_attr_value.substr(0,space_pos);
 
 1031    string ll_name = eos_ll_attr_value.substr(space_pos+1);
 
 1033    VERBOSE(cerr<<
"grid_name: "<<grid_name <<endl);
 
 1034    VERBOSE(cerr<<
"ll_name: "<<ll_name<<endl);
 
 1036    if (ll_name ==
"lon")
 
 1039    int32 gridfd = GDopen(
const_cast < char *
>(filename.c_str()), DFACC_READ);
 
 1041        err_msg = 
"HDF-EOS: GDopen failed";
 
 1044    int32 gridid = GDattach(gridfd, 
const_cast<char *
>(grid_name.c_str()));
 
 1046        err_msg = 
"HDF-EOS: GDattach failed to attach " + grid_name;
 
 1053    int32 projcode = -1; 
 
 1062    float64 lowright[2];
 
 1064    if (GDprojinfo (gridid, &projcode, &zone, &sphere, params) <0) {
 
 1067        err_msg = 
"GDprojinfo failed for grid name: " + grid_name;
 
 1072    if (GDgridinfo(gridid, &xdim, &ydim, upleft,
 
 1076        err_msg = 
"GDgridinfo failed for grid name: " + grid_name;
 
 1083    intn r = GDpixreginfo (gridid, &pixreg);
 
 1087        err_msg = 
"GDpixreginfo failed for grid name: " + grid_name;
 
 1093    r = GDorigininfo (gridid, &origin);
 
 1097        err_msg = 
"GDoriginfo failed for grid name: " + grid_name;
 
 1105    rows.resize(xdim*ydim);
 
 1106    cols.resize(xdim*ydim);
 
 1107    lon.resize(xdim*ydim);
 
 1108    lat.resize(xdim*ydim);
 
 1123    for (k = j = 0; j < ydim; ++j) {
 
 1124        for (i = 0; i < xdim; ++i) {
 
 1132    r = GDij2ll (projcode, zone, params, sphere, xdim, ydim, upleft, lowright,
 
 1133                 xdim * ydim, rows.data(), cols.data(), lon.data(), lat.data(), pixreg, origin);
 
 1138        err_msg = 
"cannot calculate grid latitude and longitude for grid name: " + grid_name;
 
 1142    VERBOSE(cerr<<
"The first value of longtitude: "<<lon[0]<<endl);
 
 1143    VERBOSE(cerr<<
"The first value of latitude: "<<lat[0]<<endl);
 
 1145    auto dc = 
dynamic_cast<DmrppCommon *
>(btp);
 
 1149        err_msg = 
"Expected to find a DmrppCommon instance but did not in add_missing_eos_latlon";
 
 1152    auto da = 
dynamic_cast<DmrppArray *
>(btp);
 
 1156        err_msg = 
"Expected to find a DmrppArray instance but did not in add_missing_eos_latlon";
 
 1160    da->set_missing_data(
true);
 
 1164        if (projcode == GCTP_CEA || projcode == GCTP_GEO) {
 
 1165            vector<float64>out_lat;
 
 1166            out_lat.resize(ydim);
 
 1168            for (i =0; i<xdim*ydim;i = i+xdim){
 
 1169                out_lat[j] = lat[i];
 
 1172            da->set_value(out_lat.data(),ydim);
 
 1176            da->set_value(lat.data(),xdim*ydim);
 
 1179        if (projcode == GCTP_CEA || projcode == GCTP_GEO) {
 
 1180            vector<float64>out_lon;
 
 1181            out_lon.resize(xdim);
 
 1182            for (i =0; i<xdim;i++)
 
 1183                out_lon[i] = lon[i];
 
 1184            da->set_value(out_lon.data(),xdim);
 
 1188            da->set_value(lon.data(),xdim*ydim);
 
 1191    da->set_read_p(
true);
 
 1194    size_t orig_buf_size = tmp_data.size()*
sizeof(double);
 
 1195    uLong ssize = (uLong)orig_buf_size;
 
 1196    uLongf csize = (uLongf)ssize*2;
 
 1197    vector<Bytef> compressed_src;
 
 1198    compressed_src.resize(orig_buf_size*2);
 
 1200    int retval = compress(compressed_src.data(), &csize, (
const Bytef*)tmp_data.data(), ssize);
 
 1202        cout<<
"Fail to compress the data"<<endl;
 
 1206    string encoded = base64::Base64::encode(compressed_src.data(),(
int)csize);
 
 1217bool add_missing_sp_latlon(BaseType *btp, 
const D4Attribute *sp_ll_attr, 
string &err_msg) {
 
 1219    VERBOSE(cerr<<
"Coming to add_missing_sp_latlon"<<endl);
 
 1221    string sp_ll_attr_value = sp_ll_attr->value(0);
 
 1223    VERBOSE(cerr<<
"sp_ll_attr_value: "<<sp_ll_attr_value <<endl);
 
 1224    size_t space_pos = sp_ll_attr_value.find(
' ');
 
 1225    if (space_pos ==string::npos) { 
 
 1226        err_msg = 
"Attribute sp_h4_ll must have space inside";
 
 1229    string ll_name = sp_ll_attr_value.substr(0,space_pos);
 
 1230    VERBOSE(cerr<<
"ll_name: "<<ll_name<<endl);
 
 1232    size_t sec_space_pos = sp_ll_attr_value.find(
' ',space_pos+1);
 
 1233    if (sec_space_pos ==string::npos) { 
 
 1234        err_msg = 
"Attribute sp_h4_ll must have two spaces inside";
 
 1237    string ll_start_str = sp_ll_attr_value.substr(space_pos+1,sec_space_pos-space_pos-1);
 
 1238    VERBOSE(cerr<<
"ll_start: "<<ll_start_str<<endl);
 
 1240    string ll_res_str = sp_ll_attr_value.substr(sec_space_pos);
 
 1241    VERBOSE(cerr<<
"ll_res: "<<ll_res_str<<endl);
 
 1243    float ll_start = stof(ll_start_str);
 
 1244    float ll_res   = stof(ll_res_str);
 
 1246    auto dc = 
dynamic_cast<DmrppCommon *
>(btp);
 
 1248        err_msg = 
"Expected to find a DmrppCommon instance but did not in add_missing_sp_latlon";
 
 1251    auto da = 
dynamic_cast<DmrppArray *
>(btp);
 
 1253        err_msg = 
"Expected to find a DmrppArray instance but did not in add_missing_sp_latlon";
 
 1257    if (da->dimensions() !=1){
 
 1258        err_msg = 
"The number of dimensions of the array should be 1.";
 
 1262    da->set_missing_data(
true);
 
 1264    vector<float32> ll_value;
 
 1265    ll_value.resize((
size_t)(da->length()));
 
 1266    for (int64_t i = 0; i <da->length(); i++) {
 
 1267        ll_value[i] = ll_start+ll_res/2+i*ll_res;
 
 1270    da->set_value(ll_value.data(),da->length());
 
 1280bool get_chunks_for_an_array(
const string& filename, int32 sd_id, int32 file_id, BaseType *btp, 
bool disable_missing_data) {
 
 1282    VERBOSE(cerr<<
"var name: "<<btp->name() <<endl);
 
 1284    D4Attributes *d4_attrs = btp->attributes();
 
 1286        close_hdf4_file_ids(sd_id,file_id);
 
 1287        throw BESInternalError(
"Expected to find an DAP4 attribute list for " + btp->name() + 
" but did not.",
 
 1288                               __FILE__, __LINE__);
 
 1294    D4Attribute *attr = d4_attrs->find(
"dmr_sds_ref");
 
 1296    bool is_sds = 
false;
 
 1300        attr = d4_attrs->find(
"dmr_vdata_ref");
 
 1303        obj_ref = stoi(attr->value(0));
 
 1305            if (
false == ingest_sds_info_to_chunk(sd_id, obj_ref,btp)) {
 
 1306                close_hdf4_file_ids(sd_id,file_id);
 
 1307                throw BESInternalError(
"Cannot retrieve SDS information correctly for  " + btp->name() ,
 
 1308                                   __FILE__, __LINE__);
 
 1313            if (
false == ingest_vdata_info_to_chunk(file_id, obj_ref,btp)) {
 
 1314                close_hdf4_file_ids(sd_id,file_id);
 
 1315                throw BESInternalError(
"Cannot retrieve vdata information correctly for  " + btp->name() ,
 
 1316                                   __FILE__, __LINE__);
 
 1320    else if (disable_missing_data == 
false){
 
 1322        VERBOSE(cerr<<
"coming to eos_latlon block"<<endl);
 
 1324        attr = d4_attrs->find(
"eos_latlon");
 
 1327            bool ret_value = add_missing_eos_latlon(filename, btp, attr,err_msg);
 
 1328            if (ret_value == 
false) {
 
 1329                close_hdf4_file_ids(sd_id,file_id);
 
 1330                throw BESInternalError(err_msg,__FILE__,__LINE__);
 
 1335            attr = d4_attrs->find(
"sp_h4_ll");
 
 1338                bool ret_value = add_missing_sp_latlon(btp, attr,err_msg);
 
 1339                if (ret_value == 
false) {
 
 1340                    close_hdf4_file_ids(sd_id,file_id);
 
 1341                    throw BESInternalError(err_msg,__FILE__,__LINE__);
 
 1345                attr = d4_attrs->find(
"eos_cf_grid");
 
 1348                    bool ret_value = add_missing_cf_grid(filename, btp, attr,err_msg);
 
 1349                    if (ret_value == 
false) {
 
 1350                        close_hdf4_file_ids(sd_id,file_id);
 
 1351                        throw BESInternalError(err_msg,__FILE__,__LINE__);
 
 1356                    close_hdf4_file_ids(sd_id,file_id);
 
 1357                    string error_msg = 
"Expected to find an attribute that stores either HDF4 SDS reference or HDF4 Vdata reference or eos lat/lon or special HDF4 lat/lon or special cf grid for ";
 
 1358                    throw BESInternalError(error_msg + btp->name() + 
" but did not.",__FILE__,__LINE__);
 
 1369bool handle_chunks_for_none_array(BaseType *btp, 
bool disable_missing_data, 
string &err_msg) {
 
 1371    bool ret_value = 
false;
 
 1373    VERBOSE(cerr<<
"For none_array: var name: "<<btp->name() <<endl);
 
 1375    D4Attributes *d4_attrs = btp->attributes();
 
 1376    if (d4_attrs->empty() == 
false && btp->type() == dods_byte_c) {
 
 1378        auto attr = d4_attrs->find(
"eos_cf_grid_mapping");
 
 1380        if (disable_missing_data == 
false) {
 
 1385                auto dc = 
dynamic_cast<DmrppCommon *
>(btp);
 
 1387                    err_msg = 
"Expected to find a DmrppCommon instance but did not in handle_chunks_for_none_array";
 
 1390                auto db = 
dynamic_cast<DmrppByte *
>(btp);
 
 1392                    err_msg = 
"Expected to find a DmrppByte instance but did not in handle_chunks_for_none_array";
 
 1396                VERBOSE(cerr<<
"For none_array cf dummy grid variable: var name: "<<btp->name() <<endl);
 
 1399                db->set_missing_data(
true);
 
 1400                db->set_value((dods_byte)buf);
 
 1401                db->set_read_p(
true);
 
 1412bool get_chunks_for_a_variable(
const string& filename,int32 sd_id, int32 file_id, BaseType *btp, 
bool disable_missing_data) {
 
 1414    switch (btp->type()) {
 
 1415        case dods_structure_c: {
 
 1421            auto sp = 
dynamic_cast<Structure *
>(btp);
 
 1424            close_hdf4_file_ids(sd_id,file_id);
 
 1425            throw BESInternalError(
"Structure scalar is not supported by DAP4 for HDF4 at this time.\n", __FILE__, __LINE__);
 
 1427        case dods_sequence_c:
 
 1428            VERBOSE(cerr << btp->FQN() << 
": Sequence is not supported by DMR++ for HDF4 at this time.\n");
 
 1431            close_hdf4_file_ids(sd_id,file_id);
 
 1432            throw BESInternalError(
"Grids are not supported by DAP4.", __FILE__, __LINE__);
 
 1435            return get_chunks_for_an_array(filename,sd_id,file_id, btp,disable_missing_data);
 
 1438            bool ret_value = handle_chunks_for_none_array(btp,disable_missing_data,err_msg);
 
 1439            if (ret_value == 
false) {
 
 1440                if (err_msg.empty() == 
false) { 
 
 1441                    close_hdf4_file_ids(sd_id,file_id);
 
 1442                    throw BESInternalError(err_msg, __FILE__, __LINE__);
 
 1445                    VERBOSE(cerr << btp->FQN() << 
": " << btp->type_name() << 
" is not supported by DMR++ for HDF4 at this time.\n");
 
 1459void get_chunks_for_all_variables(
const string& filename, int32 sd_id, int32 file_id, D4Group *group, 
bool disable_missing_data) {
 
 1462    for(
auto btp : group->variables()) {
 
 1463        if (btp->type() != dods_group_c) {
 
 1466            if (!get_chunks_for_a_variable(filename,sd_id,file_id, btp, disable_missing_data)) {
 
 1467                ERROR(
"Could not include DMR++ metadata for variable " << btp->FQN());
 
 1472            auto g = 
dynamic_cast<D4Group*
>(btp);
 
 1474                throw BESInternalError(
"Expected "  + btp->name() + 
" to be a D4Group but it is not.", __FILE__, __LINE__);
 
 1475            get_chunks_for_all_variables(filename,sd_id,file_id, g, disable_missing_data);
 
 1479    for (
auto g = group->grp_begin(), ge = group->grp_end(); g != ge; ++g) {
 
 1480        get_chunks_for_all_variables(filename,sd_id,file_id, *g, disable_missing_data);
 
 1490void add_chunk_information(
const string &h4_file_name, DMRpp *dmrpp, 
bool disable_missing_data)
 
 1493    int32 sd_id = SDstart(h4_file_name.c_str(), DFACC_READ);
 
 1496        msg << 
"Error: HDF4 file '" << h4_file_name << 
"' cannot be opened." << endl;
 
 1497        throw BESNotFoundError(msg.str(), __FILE__, __LINE__);
 
 1500    int32 file_id = Hopen(h4_file_name.c_str(),DFACC_READ,0);
 
 1503        msg << 
"Error: HDF4 file '" << h4_file_name << 
"' Hopen failed." << endl;
 
 1504        throw BESNotFoundError(msg.str(), __FILE__, __LINE__);
 
 1507    if (Vstart(file_id)<0) { 
 
 1509        msg << 
"Error: HDF4 file '" << h4_file_name << 
"' Vstart failed." << endl;
 
 1510        throw BESNotFoundError(msg.str(), __FILE__, __LINE__);
 
 1515    get_chunks_for_all_variables(h4_file_name, sd_id,file_id, dmrpp->root(),disable_missing_data);
 
 1517    close_hdf4_file_ids(sd_id,file_id);
 
 1535void qc_input_file(
const string &file_fqn)
 
 1540    if (file_fqn.empty()) {
 
 1542        msg << 
"HDF4 input file name must be provided (-f <input>) and be a fully qualified path name." << endl;
 
 1543        throw BESInternalFatalError(msg.str(), __FILE__, __LINE__);
 
 1546    std::ifstream file(file_fqn, ios::binary);
 
 1547    auto errnum = errno;
 
 1551        msg << 
"Encountered a Read/writing error when attempting to open the file: " << file_fqn << endl;
 
 1552        msg << 
"*  strerror(errno): " << strerror(errnum) << endl;
 
 1553        msg << 
"*          failbit: " << (((file.rdstate() & std::ifstream::failbit) != 0) ? 
"true" : 
"false") << endl;
 
 1554        msg << 
"*           badbit: " << (((file.rdstate() & std::ifstream::badbit) != 0) ? 
"true" : 
"false") << endl;
 
 1555        msg << 
"Things to check:" << endl;
 
 1556        msg << 
"* Does the file exist at expected location?" << endl;
 
 1557        msg << 
"* Does your user have permission to read the file?" << endl;
 
 1558        throw BESInternalFatalError(msg.str(), __FILE__, __LINE__);
 
 1562    int status = Hishdf(file_fqn.c_str());
 
 1567        msg << 
"The provided file: " << file_fqn << 
" - ";
 
 1568        msg << 
"is not an HDF4 file" << endl;
 
 1569        throw BESInternalFatalError(msg.str(), __FILE__, __LINE__);
 
 1581static string recreate_cmdln_from_args(
int argc, 
char *argv[])
 
 1584    for(
int i=0; i<argc; i++) {
 
 1597std::string what_time_is_it(){
 
 1599    auto now = std::chrono::system_clock::now();
 
 1602    auto time_t_now = std::chrono::system_clock::to_time_t(now);
 
 1606    const std::tm* gmt_time = gmtime_r(&time_t_now, &tbuf);
 
 1609    std::stringstream ss;
 
 1610    ss << std::put_time(gmt_time, 
"%Y-%m-%dT%H:%M:%SZ");
 
 1624void inject_version_and_configuration_worker( DMRpp *dmrpp, 
const string &bes_conf_doc, 
const string &invocation)
 
 1626    dmrpp->set_version(CVER);
 
 1629    auto version_unique = make_unique<D4Attribute>(
"build_dmrpp_metadata", StringToD4AttributeType(
"container"));
 
 1630    auto version = version_unique.get();
 
 1632    auto creation_date_unique = make_unique<D4Attribute>(
"created", StringToD4AttributeType(
"string")); 
 
 1633    auto creation_date = creation_date_unique.get();
 
 1634    creation_date->add_value(what_time_is_it()); 
 
 1635    version->attributes()->add_attribute_nocopy(creation_date_unique.release()); 
 
 1637    auto build_dmrpp_version_unique = make_unique<D4Attribute>(
"build_dmrpp", StringToD4AttributeType(
"string"));
 
 1638    auto build_dmrpp_version = build_dmrpp_version_unique.get();
 
 1639    build_dmrpp_version->add_value(CVER);
 
 1640    version->attributes()->add_attribute_nocopy(build_dmrpp_version_unique.release());
 
 1642    auto bes_version_unique = make_unique<D4Attribute>(
"bes", StringToD4AttributeType(
"string"));
 
 1643    auto bes_version = bes_version_unique.get();
 
 1644    bes_version->add_value(CVER);
 
 1645    version->attributes()->add_attribute_nocopy(bes_version_unique.release());
 
 1648    ldv << libdap_name() << 
"-" << libdap_version();
 
 1649    auto libdap4_version_unique =  make_unique<D4Attribute>(
"libdap", StringToD4AttributeType(
"string"));
 
 1650    auto libdap4_version = libdap4_version_unique.get();
 
 1651    libdap4_version->add_value(ldv.str());
 
 1652    version->attributes()->add_attribute_nocopy(libdap4_version_unique.release());
 
 1654    if(!bes_conf_doc.empty()) {
 
 1656        auto config_unique = make_unique<D4Attribute>(
"configuration", StringToD4AttributeType(
"string"));
 
 1657        auto config = config_unique.get();
 
 1658        config->add_value(bes_conf_doc);
 
 1659        version->attributes()->add_attribute_nocopy(config_unique.release());
 
 1662    if(!invocation.empty()) {
 
 1664        auto invoke_unique = make_unique<D4Attribute>(
"invocation", StringToD4AttributeType(
"string"));
 
 1665        auto invoke = invoke_unique.get();
 
 1666        invoke->add_value(invocation);
 
 1667        version->attributes()->add_attribute_nocopy(invoke_unique.release());
 
 1670    dmrpp->root()->attributes()->add_attribute_nocopy(version_unique.release());
 
 1687 void inject_version_and_configuration(
int argc, 
char **argv, 
const string &bes_conf_file_used_to_create_dmr, DMRpp *dmrpp)
 
 1689    string bes_configuration;
 
 1691    if(!bes_conf_file_used_to_create_dmr.empty()) {
 
 1697    invocation = recreate_cmdln_from_args(argc, argv);
 
 1699    inject_version_and_configuration_worker(dmrpp, bes_configuration, invocation);
 
 1713void inject_version_and_configuration(DMRpp *dmrpp)
 
 1717    string bes_configuration;
 
 1725    invocation = BESContextManager::TheManager()->
get_context(INVOCATION_CONTEXT, found);
 
 1728    inject_version_and_configuration_worker(dmrpp, bes_configuration, invocation);
 
 1743void build_dmrpp_from_dmr_file(
const string &dmrpp_href_value, 
const string &dmr_filename, 
const string &h4_file_fqn,
 
 1744        bool add_production_metadata, 
bool disable_missing_data, 
const string &bes_conf_file_used_to_create_dmr, 
int argc, 
char *argv[])
 
 1748    DmrppTypeFactory dtf;
 
 1749    dmrpp.set_factory(&dtf);
 
 1751    ifstream in(dmr_filename.c_str());
 
 1752    D4ParserSax2 parser;
 
 1753    parser.intern(in, &dmrpp, 
false);
 
 1755    add_chunk_information(h4_file_fqn, &dmrpp,disable_missing_data);
 
 1757    if (add_production_metadata) {
 
 1758        inject_version_and_configuration(argc,argv,bes_conf_file_used_to_create_dmr,&dmrpp);
 
 1763    cout << writer.get_doc();
 
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
std::string get_as_config() const
static TheBESKeys * TheKeys()
Access to the singleton.
static std::string ConfigFile
virtual void print_dmrpp(libdap::XMLWriter &xml, const std::string &href="", bool constrained=false, bool print_chunks=true)
Print the DMR++ response.