Re: [netcdfgroup] NetCDF-3 file format changes


Hi Ed,

Ed Hartnett wrote:
Mario Emmenlauer <mario@xxxxxxxxxxxxx> writes:
Hi,
Roy Mendelssohn wrote:
See http://www.unidata.ucar.edu/software/netcdf/docs/faq.html#Large%20File%20Support0. It has been possible since netcdf3.6
with severe bugs, as posted by me to this mailing list on 09/12/2007
(i.e. [netcdfgroup] possible bug in 3.6.2 with variables > 4GB).
For variable types NC_BYTE, NC_CHAR and NC_SHORT it crashes badly.

I have actually never received an answer to my bug report, don't know
why nobody cared :-/

We care very much!

But apparently your email passed us by without action, which is not
good. Sorry about that. :-(

I did not mean to sound so harsh, I was just very much concerned
back then that nobody ever recognized such a severe bug. I mean,
writing files > 4GB did never actually work for datatypes < 32bit,
did it?

For your bug, what are you trying to do, write the extra large last
variable?

We have a library that interfaces blitz++ with netcdf, and that
provides simple save_array and load_array functions. The save_array
call for 3D datasets has (without the debug output messages) the
following form:

template< class DataType, int Rank>
void
BlitzNCFile::save_array( const blitz::Array<DataType,Rank> &arr,
                         const char *varName)
{
  /*---------------------------------------------------------------------
   *  Check if variable already exists and has correct dimensions
   *---------------------------------------------------------------------*/
  NcError errorHandling( NcError::silent_nonfatal);
  NcVar *outVar = get_var( varName);
  if( outVar != 0)
  {
    if( outVar->num_dims() != 3
        || outVar->type() != get_NcType( DataType() )
        || outVar->get_dim(0)->size() != arr.extent(0)
        || outVar->get_dim(1)->size() != arr.extent(1)
        || outVar->get_dim(2)->size() != (arr.extent(2)
                                          * numberComponents<DataType>()))
    {
      BlitzNCSaveError err;
      err << "Can't save data: variable `" << varName
          << "' already exists with different dimensions or type\n"
          << "voxelblock has type " << get_NcTypeName( DataType() )
          << " and dims (" << arr.extent(0) << "," << arr.extent(1)
          << "," << arr.extent(2) << ")\n";
      throw( err);
    }
  }
  else
  {
    /*-------------------------------------------------------------------
     *  Create new variable (3D)
     *  check if dimensions exist or create new
     *-------------------------------------------------------------------*/
    std::vector<std::string> defaultDimNames;

    const std::vector<std::string> *dimNames
    char tmp[256];
    sprintf( tmp, "level_%d", arr.extent(0));
    defaultDimNames.push_back( tmp);
    sprintf( tmp, "row_%d", arr.extent(1));
    defaultDimNames.push_back( tmp);
    sprintf( tmp, "col_%d", arr.extent(2));
    defaultDimNames.push_back( std::string(tmp)
                               + colDimNameExtension_nc<DataType>());
    dimNames = &defaultDimNames;


    // add the three dimensions, all with error checking
    NcDim* levelDim = get_dim( (*dimNames)[0].c_str());
    if( levelDim == 0)
    {
      levelDim = add_dim( (*dimNames)[0].c_str(), arr.extent(0));
      if( levelDim == 0)
      {
        BlitzNCSaveError err;
        err << fileName() << ": " << nc_strerror( errorHandling.get_err());
        throw( err);
      }
    }
    else
    {
      if( levelDim->size() != arr.extent(0))
      {
        BlitzNCSaveError err;
        err << "Can't save data: Variable `" << varName
            << "' has " << levelDim->size()
            << " levels and voxelblock has "
            << arr.extent(0) << " levels!\n";
        throw( err);
      }
    }

    NcDim* rowDim = get_dim( (*dimNames)[1].c_str());
    if( rowDim == 0)
    {
      rowDim = add_dim( (*dimNames)[1].c_str(), arr.extent(1));
      if( rowDim == 0)
      {
        BlitzNCSaveError err;
        err << fileName() << ": " << nc_strerror( errorHandling.get_err());
        throw( err);
      }
    }
    else
    {
      if( rowDim->size() != arr.extent(1))
      {
        BlitzNCSaveError err;
        err << "Can't save data: Variable `" << varName
            << "' has " << rowDim->size() << " rows and voxelblock has "
            << arr.extent(1) << " rows!\n";
        throw( err);
      }
    }

    NcDim* colDim = get_dim( (*dimNames)[2].c_str());
    if( colDim == 0)
    {
      colDim = add_dim( (*dimNames)[2].c_str(),
                        arr.extent(2) * numberComponents<DataType>());
      if( colDim == 0)
      {
        BlitzNCSaveError err;
        err << fileName() << ": " << nc_strerror( errorHandling.get_err());
        throw( err);
      }
    }
    else
    {
      if( colDim->size() != arr.extent(2) * numberComponents<DataType>())
      {
        BlitzNCSaveError err;
        err << "Can't save data: Variable `" << varName
            << "' has " << colDim->size() << " cols and voxelblock has "
            << arr.extent(2) * numberComponents<DataType>()
            << " cols!\n";
        throw( err);
      }
    }


    // finally, we can add the varibale
    outVar = add_var( varName, get_NcType( DataType()),
                      levelDim, rowDim, colDim);
    if( outVar == 0)
    {
      BlitzNCSaveError err;
      err << fileName() << ": " << nc_strerror( errorHandling.get_err());
      throw( err);
    }
  }

  /*---------------------------------------------------------------------
   *  Write data to variable
   *---------------------------------------------------------------------*/
  // Note: we use this on x86_64 linux hosts, where long is 64 bit
  //       (however correctly this should all be ssize_t)
  int nlevels  = arr.extent(0);
  long nrows   = arr.extent(1);
  long ncols   = arr.extent(2) * numberComponents<DataType>();
  const DataType *data = arr.data();
  long picsize = nrows*arr.extent(2);


  for( int i = 0; i < nlevels; i++)
  {
    outVar->set_cur(i,0,0);
    outVar->put( ncCast( data), 1, nrows, ncols);
    data += picsize;
  }
}

I do not know which part actually triggers the assertion, and I'm out
of office until next week. Do you want me to test with valgrind when
I'm back?

Cheers,

   Mario


  • 2008 messages navigation, sorted by:
    1. Thread
    2. Subject
    3. Author
    4. Date
    5. ↑ Table Of Contents
  • Search the netcdfgroup archives: