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