39#include <libdap/Array.h> 
   40#include <libdap/AttrTable.h> 
   41#include <libdap/D4Attributes.h> 
   43#include <BESInternalError.h> 
   47#include "FONcRequestHandler.h"  
   53#include "FONcAttributes.h" 
   59#define CLEAR_LOCAL_DATA 1 
   60#define STRING_ARRAY_OPT 1 
   64const int MAX_CHUNK_SIZE = 1024;
 
   67const int GENERAL_MAX_CHUNK_SIZES = 1048576; 
 
   70const int NORMAL_1D_MAX_CHUNK_SIZES = 65536;
 
   81    d_a = 
dynamic_cast<Array *
>(b);
 
   83        string s = 
"File out netcdf, FONcArray was passed a variable that is not a DAP Array";
 
   87    for (
unsigned int i = 0; i < d_a->dimensions(); i++)
 
   88        use_d4_dim_ids.push_back(
false);
 
   93    d_a = 
dynamic_cast<Array *
>(b);
 
   95        string s = 
"File out netcdf, FONcArray was passed a variable that is not a DAP Array";
 
   99        BESDEBUG(
"fonc", 
"FONcArray() - constructor is dap4 " << endl);
 
  100        d4_dim_ids = fd4_dim_ids;
 
  101        use_d4_dim_ids = fuse_d4_dim_ids;
 
  103        d4_rds_nums = rds_nums;
 
  118    for (
auto &dim: d_dims) {
 
  122    for (
auto &
map: d_grid_maps) {
 
 
  142    FONcBaseType::convert(embed, _dap4, is_dap4_group);
 
  146    BESDEBUG(
"fonc", 
"FONcArray::convert() - converting array " << d_varname << endl);
 
  150    if(d_array_type == NC_NAT) {
 
  152        string err = 
"fileout_netcdf: The datatype of this variable '" + d_varname;
 
  153        err += 
"' is not supported. It is very possible that you try to obtain ";
 
  154        err += 
"a netCDF file that follows the netCDF classic model. ";
 
  155        err += 
"The unsigned 32-bit integer and signed/unsigned 64-bit integer ";
 
  156        err += 
"are not supported by the netCDF classic model. Downloading this file as the netCDF-4 file that ";
 
  157        err += 
"follows the netCDF enhanced model should solve the problem.";
 
  163    if (d4_dim_ids.size() > 0) {
 
  164        BESDEBUG(
"fonc", 
"FONcArray::convert() - d4_dim_ids size is " << d4_dim_ids.size() << endl);
 
  168    d_ndims = d_a->dimensions();
 
  169    d_actual_ndims = d_ndims; 
 
  170    if (d_array_type == NC_CHAR) {
 
  179    d_dim_ids.resize(d_ndims);
 
  180    d_dim_sizes.resize(d_ndims);
 
  183    Array::Dim_iter di = d_a->dim_begin();
 
  184    Array::Dim_iter de = d_a->dim_end();
 
  186    for (; di != de; di++) {
 
  187        int64_t size = d_a->dimension_size_ll(di, 
true);
 
  188        d_dim_sizes[dimnum] = size;
 
  196        if (d_a->dimensions() == 1) {
 
  197            if (size < NORMAL_1D_MAX_CHUNK_SIZES)
 
  198                d_chunksizes.push_back(size <= MAX_CHUNK_SIZE ? size : MAX_CHUNK_SIZE);
 
  199            else if ( size >= NORMAL_1D_MAX_CHUNK_SIZES && size <=GENERAL_MAX_CHUNK_SIZES*16)
 
  200                d_chunksizes.push_back(NORMAL_1D_MAX_CHUNK_SIZES);
 
  202                d_chunksizes.push_back(GENERAL_MAX_CHUNK_SIZES);
 
  206        else if (d_a->dimensions() ==2) 
 
  207            d_chunksizes.push_back(size <= MAX_CHUNK_SIZE ? size : MAX_CHUNK_SIZE);
 
  213        BESDEBUG(
"fonc", 
"FONcArray::convert() - dim num: " << dimnum << 
", dim size: " << size << endl);
 
  214        BESDEBUG(
"fonc", 
"FONcArray::convert() - dim name: " << d_a->dimension_name(di) << endl);
 
  217        if (
true == d4_def_dim && use_d4_dim_ids[dimnum] == 
true) {
 
  218            d_dim_ids[dimnum] = d4_dim_ids[dimnum];
 
  219            BESDEBUG(
"fonc", 
"FONcArray::convert() - has dap4 group" << endl);
 
  226            int ds_num = FONcDim::DimNameNum + 1;
 
  227            while (find(d4_rds_nums.begin(), d4_rds_nums.end(), ds_num) != d4_rds_nums.end()) {
 
  238            FONcDim::DimNameNum = ds_num - 1;
 
  240            FONcDim *use_dim = find_dim(embed, d_a->dimension_name(di), size);
 
  241            d_dims.push_back(use_dim);
 
  279    if (d_a->dimensions() >2) {
 
  282        size_t two_fastest_chunk_dim_sizes=1;
 
  283        auto d_chunksize_it = d_chunksizes.begin();
 
  285        for (
size_t i = d_a->dimensions();i>d_a->dimensions()-2; i--) {
 
  287            size_t size = d_dim_sizes[i-1];
 
  288            BESDEBUG(
"fonc", 
"FONcArray::CHUNK - dim size backward: " << size << endl);
 
  289            d_chunksize_it = d_chunksizes.insert(d_chunksize_it, size <= MAX_CHUNK_SIZE ? size : MAX_CHUNK_SIZE);
 
  290            two_fastest_chunk_dim_sizes *=d_chunksizes[0];
 
  292        BESDEBUG(
"fonc", 
"FONcArray::CHUNK - two fastest dimchunk_sizes " << two_fastest_chunk_dim_sizes << endl);
 
  298        size_t rest_dim_stop_index = d_a->dimensions()-2;
 
  300        if (two_fastest_chunk_dim_sizes <= GENERAL_MAX_CHUNK_SIZES) {
 
  302            size_t total_chunk_size_so_far = two_fastest_chunk_dim_sizes;
 
  304            for (
int i = d_a->dimensions()-2;i>0; i--) {
 
  306                size_t size = d_dim_sizes[i-1];
 
  307                size_t chunk_size_candidate =((size<=MAX_CHUNK_SIZE)?size:MAX_CHUNK_SIZE); 
 
  309                if (total_chunk_size_so_far * chunk_size_candidate <= GENERAL_MAX_CHUNK_SIZES) {
 
  310                    total_chunk_size_so_far *=chunk_size_candidate;
 
  311                    d_chunksize_it = d_chunksizes.insert(d_chunksize_it,chunk_size_candidate);
 
  314                        rest_dim_stop_index = 0;
 
  317                    rest_dim_stop_index = i;
 
  321            BESDEBUG(
"fonc", 
"FONcArray::CHUNK - total_chunk_size_so_far: " << total_chunk_size_so_far << endl);
 
  323        BESDEBUG(
"fonc", 
"FONcArray::CHUNK - rest_dim_stop_index: " << rest_dim_stop_index << endl);
 
  329        size_t higher_dimension_size = 1;
 
  330        size_t total_higher_dim_chunk_size = 1;
 
  331        int max_num_higher_chunks = 512;
 
  333        for (
size_t i = 0; i<rest_dim_stop_index; i++) 
 
  334            higher_dimension_size *= d_dim_sizes[i];
 
  336        if (higher_dimension_size > (
size_t)max_num_higher_chunks)
 
  337            total_higher_dim_chunk_size = higher_dimension_size/max_num_higher_chunks;
 
  339        size_t left_higher_dim_chunk_size = total_higher_dim_chunk_size;
 
  342        for (
size_t i = rest_dim_stop_index;i>0; i--) {
 
  344            size_t size = d_dim_sizes[i-1];
 
  346            BESDEBUG(
"fonc", 
"FONcArray::CHUNK - left_higher_dim_chunk_size " << left_higher_dim_chunk_size << endl);
 
  347            if (size < left_higher_dim_chunk_size) {
 
  348                d_chunksize_it = d_chunksizes.insert(d_chunksize_it,size);
 
  351                    left_higher_dim_chunk_size = left_higher_dim_chunk_size/size;
 
  354                d_chunksize_it = d_chunksizes.insert(d_chunksize_it,left_higher_dim_chunk_size);
 
  356                left_higher_dim_chunk_size = 1;
 
  362    for( 
const auto &chunk_size:d_chunksizes) 
 
  363        BESDEBUG(
"fonc", 
"FONcArray::CHUNK - chunk_size final: " <<chunk_size << endl);
 
  367    if (d_array_type == NC_CHAR) {
 
  384        if (d_is_dap4 || get_eval() == 
nullptr || get_dds() == 
nullptr)
 
  387            d_a->intern_data(*get_eval(), *get_dds());
 
  390        int array_length = d_a->length();
 
  392        d_str_data.reserve(array_length);
 
  393        d_a->value(d_str_data);
 
  396        size_t max_length = 0;
 
  397        for (
int i = 0; i < array_length; i++) {
 
  398            if (d_str_data[i].size() > max_length) {
 
  399                max_length = d_str_data[i].size();
 
  404        size_t max_length = 0;
 
  405        for (
int i = 0; i < array_length; i++) {
 
  406            if (d_a->get_str()[i].size() > max_length) {
 
  407                max_length = d_a->get_str()[i].size();
 
  414        if (is_dap4_group == 
true) {
 
  419            dim_suffix_strm << 
"_len" << FONcDim::DimNameNum + 1;
 
  420            FONcDim::DimNameNum++;
 
  421            lendim_name = d_varname + dim_suffix_strm.str();
 
  425            lendim_name = d_varname + 
"_len";
 
  428        FONcDim *use_dim = find_dim(empty_embed, lendim_name, max_length, 
true);
 
  430        if (use_dim->size() < 
static_cast<int>(max_length)) {
 
  431            use_dim->update_size(max_length);
 
  434        d_dim_sizes[d_ndims - 1] = use_dim->size();
 
  435        d_dim_ids[d_ndims - 1] = use_dim->dimid();
 
  438        use_d4_dim_ids.push_back(
false);
 
  439        d_dims.push_back(use_dim);
 
  448        d_chunksizes.push_back(max_length <= MAX_CHUNK_SIZE ? max_length : MAX_CHUNK_SIZE);
 
  457    if(d_is_dap4 == 
false) {
 
  458        if (!
FONcGrid::InGrid && d_actual_ndims == 1 && d_a->name() == d_a->dimension_name(d_a->dim_begin())) {
 
  463               auto new_map = 
new FONcMap(
this);
 
  464                d_grid_maps.push_back(new_map);        
 
  468                d_dont_use_it = 
true;
 
  473    BESDEBUG(
"fonc", 
"FONcArray::convert() - done converting array " << d_varname << endl);
 
 
  490FONcArray::find_dim(
const vector<string> &embed, 
const string &name, int64_t size, 
bool ignore_size) {
 
  496    for (; i != e && !ret_dim; i++) {
 
  497        if (!((*i)->name().empty()) && ((*i)->name() == 
name)) {
 
  501            else if ((*i)->size() == size) {
 
  505                if (embed.size() > 0) {
 
  507                    return find_dim(tmp, ename, size);
 
  509                string err = 
"fileout_netcdf: dimension found with the same name, but different size";
 
  510                throw BESInternalError(err, __FILE__, __LINE__);
 
  516        ret_dim = 
new FONcDim(
name, size);
 
  517        FONcArray::Dimensions.push_back(ret_dim);
 
  541    BESDEBUG(
"fonc", 
"FONcArray::define() - defining array '" << d_varname << 
"'" << endl);
 
  543    if (!d_defined && !d_dont_use_it) {
 
  545        BESDEBUG(
"fonc", 
"FONcArray::define() - defining array ' defined already: " << d_varname << 
"'" << endl);
 
  550        if(d4_dim_ids.size() >0) {
 
  551           if(d_array_type == NC_CHAR) {
 
  552               if(d_dims.size() == 1) {
 
  553                   FONcDim *fd = *(d_dims.begin());
 
  555                   d_dim_ids[d_ndims-1] = fd->dimid();
 
  566        if (
false == d4_def_dim) {
 
  570            for (; i != e; i++) {
 
  573                d_dim_ids[dimnum] = fd->dimid();
 
  574                BESDEBUG(
"fonc", 
"FONcArray::define() - dim_id: " << fd->dimid() << 
" size:" << fd->size() << endl);
 
  580            for (
unsigned int i = 0; i < use_d4_dim_ids.size(); i++) {
 
  581                if (use_d4_dim_ids[i] == 
false) {
 
  584                    d_dim_ids[i] = fd->dimid();
 
  590        int stax = nc_def_var(ncid, d_varname.c_str(), d_array_type, d_ndims, d_dim_ids.data(), &d_varid);
 
  591        if (stax != NC_NOERR) {
 
  592            string err = (
string) 
"fileout.netcdf - Failed to define variable " + d_varname;
 
  596        stax = nc_def_var_fill(ncid, d_varid, NC_NOFILL, NULL );
 
  597        if (stax != NC_NOERR) {
 
  598            string err = (
string) 
"fileout.netcdf - " + 
"Failed to clear fill value for " + d_varname;
 
  604            BESDEBUG(
"fonc",
"variable name is "<<d_varname << endl);
 
  605            BESDEBUG(
"fonc",
"FONC direct io flag is true before calling the intern_data()"<<endl);
 
  608            BESDEBUG(
"fonc",
"variable name is "<<d_varname << endl);
 
  609            BESDEBUG(
"fonc",
"FONC direct io flag is false before calling the intern_data()"<<endl);
 
  612        bool d_io_flag_phase_2 = d_a->get_dio_flag();
 
  613        if (d_io_flag_phase_2) {
 
  614            BESDEBUG(
"fonc",
"variable name is "<<d_varname << endl);
 
  615            BESDEBUG(
"fonc",
"direct io flag is true before calling the intern_data()"<<endl);
 
  616            Array::var_storage_info dmrpp_vs_info = d_a->get_var_storage_info();
 
  618            BESDEBUG(
"fonc", 
"filters: "<<dmrpp_vs_info.filter<<endl);
 
  619            for (
const auto& def_lev:dmrpp_vs_info.deflate_levels) 
 
  620                BESDEBUG(
"fonc", 
"deflate level: "<<def_lev<<endl);
 
  622            for (
unsigned int i = 0; i < dmrpp_vs_info.chunk_dims.size(); i++) 
 
  623                BESDEBUG(
"fonc", 
"chunk_dim["<<i<<
"]: "<<dmrpp_vs_info.chunk_dims[i]<<endl);
 
  625            BESDEBUG(
"fonc",
"End of checking the chunk info. for the define mode.  "<<d_varname << endl);
 
  636        if (d_array_type != NC_CHAR && fdio_flag == 
true) {
 
  640                d_a->intern_data(*get_eval(), *get_dds());
 
  645        bool d_io_flag = d_a->get_dio_flag();
 
  648        BESDEBUG(
"fonc", 
"d_io_flag after intern_data(): "<<d_io_flag<<endl);
 
  652            Array::var_storage_info dmrpp_vs_info = d_a->get_var_storage_info();
 
  654            BESDEBUG(
"fonc", 
"filters: "<<dmrpp_vs_info.filter<<endl);
 
  655            for (
const auto& def_lev:dmrpp_vs_info.deflate_levels) 
 
  656                BESDEBUG(
"fonc", 
"deflate level: "<<def_lev<<endl);
 
  658            for (
unsigned int i = 0; i < dmrpp_vs_info.chunk_dims.size(); i++) 
 
  659                BESDEBUG(
"fonc", 
"chunk_dim["<<i<<
"]: "<<dmrpp_vs_info.chunk_dims[i]<<endl);
 
  661            for (
unsigned int i = 0; i<dmrpp_vs_info.var_chunk_info.size(); i++) {
 
  662                BESDEBUG(
"fonc", 
"chunk index: "<<i<<
" filter mask "<<dmrpp_vs_info.var_chunk_info[i].filter_mask<<endl);
 
  663                BESDEBUG(
"fonc", 
"chunk index: "<<i<<
" chunk_direct_io_offset "<<dmrpp_vs_info.var_chunk_info[i].chunk_direct_io_offset<<endl);
 
  664                BESDEBUG(
"fonc", 
"chunk index: "<<i<<
" chunk_buffer_size "<<dmrpp_vs_info.var_chunk_info[i].chunk_buffer_size<<endl);
 
  666                BESDEBUG(
"fonc", 
"chunk index: "<<i<<
" coordinates are  "<<endl);
 
  667                for (
unsigned int j = 0; j<dmrpp_vs_info.var_chunk_info[i].chunk_coords.size(); j++)
 
  668                    BESDEBUG(
"fonc", 
"coordinate index: "<<j<<
" value "<<dmrpp_vs_info.var_chunk_info[i].chunk_coords[j]<<endl);
 
  672        BESDEBUG(
"fonc", 
"FONcArray::define() netcdf-4 version is " << d_ncVersion << endl);
 
  677            BESDEBUG(
"fonc", 
"FONcArray::define() Working netcdf-4 branch " << endl);
 
  681                define_dio_filters(ncid, d_varid);     
 
  684                if (FONcRequestHandler::chunk_size == 0)
 
  686                    stax = nc_def_var_chunking(ncid, d_varid, NC_CONTIGUOUS, d_chunksizes.data());
 
  688                    stax = nc_def_var_chunking(ncid, d_varid, NC_CHUNKED, d_chunksizes.data());
 
  690                if (stax != NC_NOERR) {
 
  691                    string err = 
"fileout.netcdf - Failed to define chunking for variable " + d_varname;
 
  698                if (FONcRequestHandler::use_compression) {
 
  703                    if (NC_SHORT == d_array_type || NC_USHORT == d_array_type || NC_INT == d_array_type ||
 
  704                        NC_UINT == d_array_type || NC_INT64 == d_array_type || NC_UINT64 == d_array_type ||
 
  705                        FONcRequestHandler::use_shuffle)                
 
  709                    int deflate_level = 4;
 
  710                    stax = nc_def_var_deflate(ncid, d_varid, shuffle, deflate, deflate_level);
 
  712                    if (stax != NC_NOERR) {
 
  713                        string err = (
string) 
"fileout.netcdf - Failed to define compression (deflate) level for variable " 
  723            D4Attributes *d4_attrs = d_a->attributes();
 
  724            updateD4AttrType(d4_attrs, d_array_type);
 
  727            AttrTable &attrs = d_a->get_attr_table();
 
  728            updateAttrType(attrs, d_array_type);
 
  731        BESDEBUG(
"fonc", 
"FONcArray::define() - Adding attributes " << endl);
 
  738            BESDEBUG(
"fonc", 
"FONcArray::define() - variable " << d_varname << 
" is already defined" << endl);
 
  741            BESDEBUG(
"fonc", 
"FONcArray::define() - variable " << d_varname << 
" is not being used" << endl);
 
  745    BESDEBUG(
"fonc", 
"FONcArray::define() - done defining array '" << d_varname << 
"'" << endl);
 
 
  753void FONcArray::write_nc_variable(
int ncid, nc_type var_type) {
 
  757    if (d_is_dap4 || get_eval() == 
nullptr || get_dds() == 
nullptr)
 
  760        d_a->intern_data(*get_eval(), *get_dds());
 
  763    bool d_io_flag = d_a->get_dio_flag();
 
  767        write_direct_io_data(ncid,d_varid);
 
  769        d_a->clear_local_data();
 
  777            stax = nc_put_var_uchar(ncid, d_varid, 
reinterpret_cast<unsigned char *
>(d_a->get_buf()));
 
  780            stax = nc_put_var_schar(ncid, d_varid, 
reinterpret_cast<signed char *
>(d_a->get_buf()));
 
  783            stax = nc_put_var_short(ncid, d_varid, 
reinterpret_cast<short *
>(d_a->get_buf()));
 
  786            stax = nc_put_var_int(ncid, d_varid, 
reinterpret_cast<int *
>(d_a->get_buf()));
 
  789            stax = nc_put_var_longlong(ncid, d_varid, 
reinterpret_cast<long long *
>(d_a->get_buf()));
 
  792            stax = nc_put_var_float(ncid, d_varid, 
reinterpret_cast<float *
>(d_a->get_buf()));
 
  795            stax = nc_put_var_double(ncid, d_varid, 
reinterpret_cast<double *
>(d_a->get_buf()));
 
  798            stax = nc_put_var_ushort(ncid, d_varid, 
reinterpret_cast<unsigned short *
>(d_a->get_buf()));
 
  801            stax = nc_put_var_uint(ncid, d_varid, 
reinterpret_cast<unsigned int *
>(d_a->get_buf()));
 
  804            stax = nc_put_var_ulonglong(ncid, d_varid, 
reinterpret_cast<unsigned long long *
>(d_a->get_buf()));
 
  808            throw BESInternalError(
"Failed to transform array of unknown type in file out netcdf (1)",
 
  812    if (stax != NC_NOERR) {
 
  813        string err = 
"fileout.netcdf - Failed to create array of " + d_a->var()->type_name() + 
" for " + d_varname;
 
  819    if (!FONcGrid::InMaps(d_a))
 
  820        d_a->clear_local_data();
 
  837    if (the_strings.empty()==
true)
 
  840        size_t length = the_strings[0].size();
 
  841        if ( std::all_of(the_strings.begin()+1, the_strings.end(),
 
  842                         [length](
string &s){return s.size() == length;}) )
 
  860    BESDEBUG(
"fonc", 
"FONcArray::write() BEGIN  var: " << d_varname << 
"[" << d_nelements << 
"]" << endl);
 
  861    BESDEBUG(
"fonc", 
"FONcArray::write() BEGIN  var type: " << d_array_type << 
" " << endl);
 
  864        BESDEBUG(
"fonc", 
"FONcTransform::write not using variable " << d_varname << endl);
 
  874    if (d_array_type == NC_CHAR) {
 
  888        if (equal_length(d_a->get_str())) {
 
  890            write_equal_length_string_array(ncid);
 
  892            write_string_array(ncid);
 
  896            write_string_array(ncid);
 
  899    else if (isNetCDF4_ENHANCED()) {
 
  902        write_for_nc4_types(ncid);
 
  905        write_for_nc3_types(ncid);
 
  908    BESDEBUG(
"fonc", 
"FONcArray::write() END  var: " << d_varname << 
"[" << d_nelements << 
"]" << endl);
 
 
  911void FONcArray::write_for_nc3_types(
int ncid) {
 
  912    Type element_type = d_a->var()->type();
 
  914    switch (d_array_type) {
 
  918            write_nc_variable(ncid, d_array_type);
 
  926            if (element_type == dods_byte_c || element_type == dods_uint8_c) {
 
  933                    d_a->intern_data(*get_eval(), *get_dds());
 
  938                for (
size_t d_i = 0; d_i < d_nelements; d_i++) 
 
  939                    data[d_i] = *(
reinterpret_cast<unsigned char *
>(d_a->get_buf()) + d_i);
 
  941                int stax = nc_put_var_short(ncid, d_varid, data.data());
 
  942                if (stax != NC_NOERR) {
 
  943                    string err = (string) 
"fileout.netcdf - Failed to create array of shorts for " + d_varname;
 
  950                if (!FONcGrid::InMaps(d_a))
 
  951                    d_a->clear_local_data();
 
  954                write_nc_variable(ncid, NC_SHORT);
 
  961            if (element_type == dods_int64_c || element_type == dods_uint64_c) {
 
  966                if (FONcRequestHandler::classic_model == 
false) {
 
  967                    msg = 
"You asked for one or more 64-bit integer values returned using a netCDF3 file. " 
  968                          "Try asking for netCDF4 enhanced and/or contact the server administrator.";
 
  971                    msg = 
"You asked for one or more 64-bit integer values, but either returned using a netCDF3 file or " 
  972                          "from a server that is configured to use the 'classic' netCDF data model with netCDF4. " 
  973                          "Try netCDF4 and/or contact the server administrator.";
 
  975                throw BESInternalError(msg, __FILE__, __LINE__);
 
  978            if (element_type == dods_uint16_c) {
 
  986                    d_a->intern_data(*get_eval(), *get_dds());
 
  988                vector<int> data(d_nelements);
 
  989                for (
size_t d_i = 0; d_i < d_nelements; d_i++)
 
  990                    data[d_i] = *(
reinterpret_cast<unsigned short *
>(d_a->get_buf()) + d_i);
 
  992                int stax = nc_put_var_int(ncid, d_varid, data.data());
 
  993                if (stax != NC_NOERR) {
 
  994                    string err = (string) 
"fileout.netcdf - Failed to create array of ints for " + d_varname;
 
  998                if (!FONcGrid::InMaps(d_a))
 
  999                    d_a->clear_local_data();
 
 1002                write_nc_variable(ncid, NC_INT);
 
 1007            throw BESInternalError(
"Failed to transform array of unknown type in file out netcdf (2)",
 
 1008                                   __FILE__, __LINE__);
 
 1016void FONcArray::write_string_array(
int ncid) {
 
 1017    vector<size_t> var_count(d_ndims);
 
 1018    vector<size_t> var_start(d_ndims);
 
 1020    for (dim = 0; dim < d_ndims; dim++) {
 
 1032    auto const &d_a_str = d_a->get_str();
 
 1033    for (
size_t element = 0; element < d_nelements; element++) {
 
 1034        var_count[d_ndims - 1] = d_a_str[element].size() + 1;
 
 1035        var_start[d_ndims - 1] = 0;
 
 1038        int stax = nc_put_vara_text(ncid, d_varid, var_start.data(), var_count.data(),
 
 1039                                    d_a_str[element].c_str());
 
 1041        if (stax != NC_NOERR) {
 
 1042            string err = (string) 
"fileout.netcdf - Failed to create array of strings for " + d_varname;
 
 1047        if (element + 1 < d_nelements) {
 
 1051                var_start[dim] = var_start[dim] + 1;
 
 1052                if (var_start[dim] == d_dim_sizes[dim]) {
 
 1065    d_a->get_str().clear();
 
 1075void FONcArray::write_equal_length_string_array(
int ncid) {
 
 1076    vector<size_t> var_count(d_ndims);
 
 1077    vector<size_t> var_start(d_ndims);
 
 1079    auto const &d_a_str = d_a->get_str();
 
 1081    vector<char> text_data;
 
 1082    text_data.reserve(d_a_str.size() * (d_a_str[0].size() + 1));
 
 1083    for (
auto &str: d_a_str) {
 
 1085            text_data.emplace_back(c);
 
 1086        text_data.emplace_back(
'\0');
 
 1089    for (
int dim = 0; dim < d_ndims; dim++) {
 
 1092    for (
int dim = 0; dim < d_ndims; dim++) {
 
 1093        var_count[dim] = d_dim_sizes[dim];
 
 1095    var_count[d_ndims - 1] = d_a_str[0].size() + 1;
 
 1097    int stax = nc_put_vara_text(ncid, d_varid, var_start.data(), var_count.data(), text_data.data());
 
 1099    if (stax != NC_NOERR) {
 
 1100        string err = (string) 
"fileout.netcdf - Failed to create array of strings for " + d_varname;
 
 1104    d_a->get_str().clear();
 
 1125    strm << BESIndent::LMarg << 
"FONcArray::dump - (" << (
void *) 
this << 
")" << endl;
 
 1126    BESIndent::Indent();
 
 1127    strm << BESIndent::LMarg << 
"name = " << d_varname << endl;
 
 1128    strm << BESIndent::LMarg << 
"ndims = " << d_ndims << endl;
 
 1129    strm << BESIndent::LMarg << 
"actual ndims = " << d_actual_ndims << endl;
 
 1130    strm << BESIndent::LMarg << 
"nelements = " << d_nelements << endl;
 
 1131    if (d_dims.size()) {
 
 1132        strm << BESIndent::LMarg << 
"dimensions:" << endl;
 
 1133        BESIndent::Indent();
 
 1136        for (; i != e; i++) {
 
 1139        BESIndent::UnIndent();
 
 1142        strm << BESIndent::LMarg << 
"dimensions: none" << endl;
 
 1144    BESIndent::UnIndent();
 
 
 1156void FONcArray::write_for_nc4_types(
int ncid) {
 
 1165    switch (d_array_type) {
 
 1176            write_nc_variable(ncid, d_array_type);
 
 1180            string err = (string) 
"Failed to transform array of unknown type in file out netcdf";
 
 1186void FONcArray::define_dio_filters(
int ncid, 
int d_varid) {
 
 1188    Array::var_storage_info dmrpp_vs_info = d_a->get_var_storage_info();
 
 1190    BESDEBUG(
"fonc", 
"filters: "<<dmrpp_vs_info.filter<<endl);
 
 1192    string filters_string = dmrpp_vs_info.filter;
 
 1194    bool has_fletcher_first = 
false;
 
 1195    bool has_fletcher_last = 
false;
 
 1196    bool has_shuffle = 
false;
 
 1197    bool has_2deflates = 
false;
 
 1198    bool has_1deflate = 
false;
 
 1201    obtain_dio_filters_order(filters_string, has_fletcher_first, has_fletcher_last, has_shuffle, has_2deflates, has_1deflate);
 
 1204    stax = nc_def_var_chunking_direct_write(ncid, d_varid, NC_CHUNKED, dmrpp_vs_info.chunk_dims.data());
 
 1205    if (stax != NC_NOERR) {
 
 1206                string err = 
"fileout.netcdf - Failed to define direct_io chunking for variable " + d_varname;
 
 1211    allocate_dio_nc4_def_filters(ncid, d_varid, has_fletcher_first, has_fletcher_last, has_shuffle, has_2deflates, has_1deflate, dmrpp_vs_info.deflate_levels);
 
 1217void FONcArray::obtain_dio_filters_order(
const string & filters, 
bool &has_fle_first, 
bool &has_fle_last, 
bool &has_shuffle, 
bool &has_2defs, 
bool &has_1def)
 const {
 
 1222    for (
unsigned int i = 0; i <filter_array.size(); i++) {
 
 1223        if (filter_array[i] == 
"shuffle") 
 
 1225        else if (filter_array[i] == 
"deflate") 
 
 1227        else if (filter_array[i] == 
"fletcher32") {
 
 1229                has_fle_first = 
true;
 
 1231                has_fle_last = 
true;
 
 1237    else if (num_defs == 2)
 
 1239    else if (num_defs >2)
 
 1240        throw BESInternalError(
"Currently we don't support more than 2 deflate filters.", __FILE__, __LINE__);
 
 1245void FONcArray::allocate_dio_nc4_def_filters(
int ncid, 
int d_varid, 
bool has_fle_first, 
bool has_fle_last, 
bool has_shuffle, 
 
 1246                                         bool has_2defs, 
bool has_1def, 
const vector<unsigned int>& def_levs)
 const {
 
 1250    if (has_1def && def_levs.size() !=1)
 
 1251        throw BESInternalError(
"The size of def_levs should be 1 for one deflate filter", __FILE__, __LINE__);
 
 1253    if (has_2defs && def_levs.size() !=2)
 
 1254        throw BESInternalError(
"The size of def_levs should be 2 for two deflate filters", __FILE__, __LINE__);
 
 1256    if (has_fle_first) {
 
 1258        stax = nc_def_var_fletcher32(ncid, d_varid, 1);
 
 1259        if (stax != NC_NOERR) {
 
 1260                string err = 
"fileout.netcdf - Failed to define the fletcher32 filter for variable " + d_varname;
 
 1267            stax = nc_def_var_deflate(ncid, d_varid, 1, 1, def_levs[0]);
 
 1268            if (stax != NC_NOERR) {
 
 1269                string err = 
"fileout.netcdf - Failed to define the deflate and the shuffle filters for variable " + d_varname;
 
 1273        else if (has_2defs) {
 
 1274            stax = nc_def_var_two_deflates(ncid, d_varid, 1, 1, def_levs[0], def_levs[1]);
 
 1275            if (stax != NC_NOERR) {
 
 1276                string err = 
"fileout.netcdf - Failed to define the two deflate filters and the shuffle filter for variable " + d_varname;
 
 1283            stax = nc_def_var_deflate(ncid, d_varid, 0, 1, def_levs[0]);
 
 1284            if (stax != NC_NOERR) {
 
 1285                string err = 
"fileout.netcdf - Failed to define the deflate filter for variable " + d_varname;
 
 1289        else if (has_2defs) {
 
 1290            stax = nc_def_var_two_deflates(ncid, d_varid, 0, 1, def_levs[0], def_levs[1]);
 
 1291            if (stax != NC_NOERR) {
 
 1292                string err = 
"fileout.netcdf - Failed to define the two deflate filters for variable " + d_varname;
 
 1299        stax = nc_def_var_fletcher32(ncid, d_varid,1);   
 
 1300        if (stax != NC_NOERR) {
 
 1301            string err = 
"fileout.netcdf - Failed to define the filter fletcher32 for variable " + d_varname;
 
 1309void FONcArray::write_direct_io_data(
int ncid, 
int d_varid) {
 
 1311    char dummy_buffer[1];
 
 1313    BESDEBUG(
"fonc", 
"FONcArray() - direct IO write " << endl);
 
 1315    int stax = nc_put_var(ncid, d_varid, dummy_buffer);
 
 1316    if (stax != NC_NOERR) {
 
 1317        string err = 
"fileout.netcdf - the direct IO version of nc_put_var error for variable " + d_varname;
 
 1321    Array::var_storage_info dmrpp_vs_info = d_a->get_var_storage_info();
 
 1323    for (
const auto & var_chunk_info:dmrpp_vs_info.var_chunk_info) {
 
 1325        Array::var_chunk_info_t vci = var_chunk_info;
 
 1327        auto chunk_buf = 
new char[vci.chunk_buffer_size];
 
 1328        memcpy (chunk_buf,d_a->get_buf()+vci.chunk_direct_io_offset,vci.chunk_buffer_size);
 
 1330        stax = nc4_write_chunk(ncid, d_varid, vci.filter_mask, vci.chunk_coords.size(), (
const size_t *)(vci.chunk_coords.data()),vci.chunk_buffer_size, chunk_buf);
 
 1331        if (stax != NC_NOERR) {
 
 1332            string err = 
"fileout.netcdf - nc4_write_chunk error for variable " + d_varname;
 
exception thrown if internal error encountered
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...
virtual void dump(std::ostream &strm) const override
dumps information about this object for debugging purposes
virtual void define(int ncid) override
define the DAP Array in the netcdf file
~FONcArray() override
Destructor that cleans up the array.
virtual void convert(std::vector< std::string > embed, bool _dap4=false, bool is_dap4_group=false) override
Converts the DAP Array to a FONcArray.
virtual void write(int ncid) override
Write the array out to the netcdf file.
std::string name() override
returns the name of the DAP Array
static void add_original_name(int ncid, int varid, const string &var_name, const string &orig)
Adds an attribute for the variable if the variable name had to be modified in any way.
static void add_variable_attributes(int ncid, int varid, BaseType *b, bool is_netCDF_enhanced, bool is_dap4)
Add the attributes for an OPeNDAP variable to the netcdf file.
A DAP BaseType with file out netcdf information included.
virtual bool isNetCDF4()
Returns true if NetCDF4 features will be required.
A class that represents the dimension of an array.
virtual void define(int ncid)
define the DAP dimension in the netcdf file
static vector< FONcMap * > Maps
global list of maps that could be shared amongst the different grids
static bool InGrid
tells whether we are converting or defining a grid.
A map of a DAP Grid with file out netcdf information included.
static void handle_error(int stax, const string &err, const string &file, int line)
handle any netcdf errors
static nc_type get_nc_type(libdap::BaseType *element, bool isNC4_ENHANCED)
translate the OPeNDAP data type to a netcdf data type
static string gen_name(const vector< string > &embed, const string &name, string &original)
generate a new name for the embedded variable