Esempio n. 1
0
File: nccr.c Progetto: U-238/gempak
int
NCCR_close(int ncid)
{
    NC_GRP_INFO_T *grp;
    NC_HDF5_FILE_INFO_T *h5;
    NCCR* nccr = NULL;
    int ncstat = NC_NOERR;
    NC* nc;

    LOG((1, "nc_close: ncid 0x%x", ncid));

    /* Avoid repeated close  */
    ncstat = NC_check_id(ncid, (NC**)&nccr); 
    if(ncstat != NC_NOERR) return THROW(ncstat);

    /* Find our metadata for this file. */
    ncstat = nc4_find_nc_grp_h5(ncid, (NC_FILE_INFO_T**)&nccr, &grp, &h5);
    if(ncstat != NC_NOERR) return THROW(ncstat);

    /* This must be the root group. */
    if (grp->parent) ncstat = NC_EBADGRPID;

    freeNCCDMR(nccr->cdmr);

    /* Destroy/close the NC_FILE_INFO_T state */
    NC4_abort(ncid);

    return THROW(ncstat);
}
Esempio n. 2
0
/**
 * @internal
 * Write an attribute to a netCDF-4/HDF5 file, converting
 * data type if necessary.
 * Wrapper around nc4_put_att
 *
 * @param ncid File and group ID.
 * @param varid Variable ID.
 * @param name Name of attribute.
 * @param file_type Type of the attribute data in file.
 * @param len Number of elements in attribute array.
 * @param data Attribute data.
 * @param mem_type Type of data in memory.
 *
 * @return ::NC_NOERR No error.
 * @return ::NC_EINVAL Invalid parameters.
 * @return ::NC_EBADID Bad ncid.
 * @return ::NC_ENOTVAR Variable not found.
 * @return ::NC_EBADNAME Name contains illegal characters.
 * @return ::NC_ENAMEINUSE Name already in use.
 * @author Ed Hartnett, Dennis Heimbigner
 */
int
NC4_put_att(int ncid, int varid, const char *name, nc_type file_type,
            size_t len, const void *data, nc_type mem_type)
{
   int ret = NC_NOERR;
   NC *nc;
   NC_FILE_INFO_T *h5;
   NC_GRP_INFO_T *grp;
    
   /* Find info for this file, group, and h5 info. */
   if ((ret = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return ret;
   assert(nc && grp && h5);

   return nc4_put_att(grp,varid,name,file_type,len,data,mem_type,0);
}
Esempio n. 3
0
/* Given dim name, find its id. */
int
NC4_inq_dimid(int ncid, const char *name, int *idp)
{
   NC_FILE_INFO_T *nc;
   NC_GRP_INFO_T *grp, *g;
   NC_HDF5_FILE_INFO_T *h5;
   NC_DIM_INFO_T *dim;
   char norm_name[NC_MAX_NAME + 1];
   int finished = 0;
   int retval;

   LOG((2, "nc_inq_dimid: ncid 0x%x name %s", ncid, name));

   /* Find metadata for this file. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;

#ifdef USE_PNETCDF
   /* Take care of files created/opened with parallel-netcdf library. */
   if (nc->pnetcdf_file)
      return ncmpi_inq_dimid(nc->int_ncid, name, idp);
#endif /* USE_PNETCDF */

   /* Handle netcdf-3 files. */
   assert(h5);

   assert(nc && grp);

   /* Normalize name. */
   if ((retval = nc4_normalize_name(name, norm_name)))
      return retval;

   /* Go through each dim and check for a name match. */
   for (g = grp; g && !finished; g = g->parent)
      for (dim = g->dim; dim; dim = dim->next)
	 if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
	 {
	    if (idp)
	       *idp = dim->dimid;
	    finished++;
	    return NC_NOERR;
	 }

   return NC_EBADDIM;
}
Esempio n. 4
0
/* Note that this code is inconsistent with nc_inq */
int 
NC4_inq_unlimdim(int ncid, int *unlimdimidp)
{
   NC_FILE_INFO_T *nc;
   NC_GRP_INFO_T *grp, *g;
   NC_HDF5_FILE_INFO_T *h5;
   NC_DIM_INFO_T *dim;
   int found = 0;
   int retval;
 
   LOG((2, "called nc_inq_unlimdim"));

   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;

#ifdef USE_PNETCDF
   /* Take care of files created/opened with parallel-netcdf library. */
   if (nc->pnetcdf_file)
      return ncmpi_inq_unlimdim(nc->int_ncid, unlimdimidp);
#endif /* USE_PNETCDF */

   /* Take care of netcdf-3 files. */
   assert(h5);

   /* According to netcdf-3 manual, return -1 if there is no unlimited
      dimension. */
   *unlimdimidp = -1;
   for (g = grp; g && !found; g = g->parent)
   {
      for (dim = g->dim; dim; dim = dim->next)
      {
	 if (dim->unlimited)
	 {
	    *unlimdimidp = dim->dimid;
	    found++;
	    break;
	 }
      }
   }

   return NC_NOERR;
}
Esempio n. 5
0
/**
 * @internal Netcdf-4 files might have more than one unlimited
 * dimension, but return the first one anyway.
 *
 * @note that this code is inconsistent with nc_inq
 *
 * @param ncid File and group ID.
 * @param unlimdimidp Pointer that gets ID of first unlimited
 * dimension, or -1.
 *
 * @return ::NC_NOERR No error.
 * @return ::NC_EBADID Bad ncid.
 * @author Ed Hartnett
 */
int
NC4_inq_unlimdim(int ncid, int *unlimdimidp)
{
   NC *nc;
   NC_GRP_INFO_T *grp, *g;
   NC_FILE_INFO_T *h5;
   NC_DIM_INFO_T *dim;
   int found = 0;
   int retval;
   int i;

   LOG((2, "%s: called", __func__));

   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;
   assert(h5 && nc && grp);

   if (unlimdimidp)
   {
      /* According to netcdf-3 manual, return -1 if there is no unlimited
         dimension. */
      *unlimdimidp = -1;
      for (g = grp; g && !found; g = g->parent)
      {
         for(i=0;i<ncindexsize(grp->dim);i++)
         {
            dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
            if(dim == NULL) continue;
            if (dim->unlimited)
            {
               *unlimdimidp = dim->hdr.id;
               found++;
               break;
            }
         }
      }
   }

   return NC_NOERR;
}
Esempio n. 6
0
/**
 * @internal Returns an array of unlimited dimension ids.The user can
 * get the number of unlimited dimensions by first calling this with
 * NULL for the second pointer.
 *
 * @param ncid File and group ID.
 * @param nunlimdimsp Pointer that gets the number of unlimited
 * dimensions. Ignored if NULL.
 * @param unlimdimidsp Pointer that gets arrray of unlimited dimension
 * ID. Ignored if NULL.
 *
 * @return ::NC_NOERR No error.
 * @return ::NC_EBADID Bad ncid.
 * @author Ed Hartnett, Dennis Heimbigner
 */
int
NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp)
{
   NC_DIM_INFO_T *dim;
   NC_GRP_INFO_T *grp;
   NC *nc;
   NC_FILE_INFO_T *h5;
   int num_unlim = 0;
   int retval;
   int i;

   LOG((2, "%s: ncid 0x%x", __func__, ncid));

   /* Find info for this file and group, and set pointer to each. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;
   assert(h5 && nc && grp);

   /* Get our dim info. */
   assert(h5);
   {
      for(i=0;i<ncindexsize(grp->dim);i++)
      {
         dim = (NC_DIM_INFO_T*)ncindexith(grp->dim,i);
         if(dim == NULL) continue;
         if (dim->unlimited)
         {
            if (unlimdimidsp)
               unlimdimidsp[num_unlim] = dim->hdr.id;
            num_unlim++;
         }
      }
   }

   /* Give the number if the user wants it. */
   if (nunlimdimsp)
      *nunlimdimsp = num_unlim;

   return NC_NOERR;
}
Esempio n. 7
0
/**
 * @internal Given dim name, find its id.
 *
 * @param ncid File and group ID.
 * @param name Name of the dimension to find.
 * @param idp Pointer that gets dimension ID.
 *
 * @return ::NC_NOERR No error.
 * @return ::NC_EBADID Bad ncid.
 * @return ::NC_EBADDIM Dimension not found.
 * @return ::NC_EINVAL Invalid input. Name must be provided.
 * @author Ed Hartnett
 */
int
NC4_inq_dimid(int ncid, const char *name, int *idp)
{
   NC *nc;
   NC_GRP_INFO_T *grp, *g;
   NC_FILE_INFO_T *h5;
   NC_DIM_INFO_T *dim;
   char norm_name[NC_MAX_NAME + 1];
   int retval;
   int found;

   LOG((2, "%s: ncid 0x%x name %s", __func__, ncid, name));

   /* Check input. */
   if (!name)
      return NC_EINVAL;

   /* Find metadata for this file. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;
   assert(h5 && nc && grp);

   /* Normalize name. */
   if ((retval = nc4_normalize_name(name, norm_name)))
      return retval;

   /* check for a name match in this group and its parents */
   found = 0;
   for (g = grp; g ; g = g->parent) {
      dim = (NC_DIM_INFO_T*)ncindexlookup(g->dim,norm_name);
      if(dim != NULL) {found = 1; break;}
   }
   if(!found)
      return NC_EBADDIM;
   assert(dim != NULL);
   if (idp)
      *idp = dim->hdr.id;
   return NC_NOERR;
}
Esempio n. 8
0
/* Returns an array of unlimited dimension ids.The user can get the
   number of unlimited dimensions by first calling this with NULL for
   the second pointer.
*/
int 
NC4_inq_unlimdims(int ncid, int *nunlimdimsp, int *unlimdimidsp) 
{
  NC_DIM_INFO_T *dim;
  NC_GRP_INFO_T *grp;
  NC_FILE_INFO_T *nc;
  NC_HDF5_FILE_INFO_T *h5;
  int num_unlim = 0;
  int retval;

  LOG((2, "nc_inq_unlimdims: ncid 0x%x", ncid));

   /* Find info for this file and group, and set pointer to each. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;

   /* Get our dim info. */
   assert(h5);
   {
      for (dim=grp->dim; dim; dim=dim->next)
      {
	 if (dim->unlimited)
	 {
	    if (unlimdimidsp)
	       unlimdimidsp[num_unlim] = dim->dimid;
	    num_unlim++;
	 }
      }
   }

   /* Give the number if the user wants it. */
   if (nunlimdimsp)
      *nunlimdimsp = num_unlim;

   return NC_NOERR;
}
Esempio n. 9
0
/* Dimensions are defined in attributes attached to the appropriate
   group in the data file. */
int
NC4_def_dim(int ncid, const char *name, size_t len, int *idp)
{
   NC_FILE_INFO_T *nc;
   NC_GRP_INFO_T *grp;
   NC_HDF5_FILE_INFO_T *h5;
   NC_DIM_INFO_T *dim;
   char norm_name[NC_MAX_NAME + 1];
   int retval = NC_NOERR;

   LOG((2, "nc_def_dim: ncid 0x%x name %s len %d", ncid, name, 
	(int)len));

   /* Find our global metadata structure. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;
   
#ifdef USE_PNETCDF
   /* Take care of files created/opened with parallel-netcdf library. */
   if (nc->pnetcdf_file)
      return ncmpi_def_dim(nc->int_ncid, name, len, idp);
#endif /* USE_PNETCDF */

   /* Take care of netcdf-3 files. */
   assert(h5);

   assert(h5 && nc && grp);

   /* If the file is read-only, return an error. */
   if (h5->no_write)
     return NC_EPERM;

   /* Check some stuff if strict nc3 rules are in effect. */
   if (h5->cmode & NC_CLASSIC_MODEL)
   {
      /* Only one limited dimenson for strict nc3. */
      if (len == NC_UNLIMITED)
	 for (dim = grp->dim; dim; dim = dim->next)
	    if (dim->unlimited)
	       return NC_EUNLIMIT;

      /* Must be in define mode for stict nc3. */
      if (!(h5->flags & NC_INDEF))
	 return NC_ENOTINDEFINE;
   }   

   /* If it's not in define mode, enter define mode. */
   if (!(h5->flags & NC_INDEF))
      if ((retval = nc_redef(ncid)))
	 return retval;

   /* Make sure this is a valid netcdf name. */
   if ((retval = nc4_check_name(name, norm_name)))
      return retval;

   /* For classic model, stick with the classic format restriction:
    * dim length has to fit in a 32-bit signed int. For 64-bit offset,
    * it has to fit in a 32-bit unsigned int. */
   if (h5->cmode & NC_CLASSIC_MODEL)
      if((unsigned long) len > X_INT_MAX) /* Backward compat */
	 return NC_EDIMSIZE;

   /* Make sure the name is not already in use. */
   for (dim = grp->dim; dim; dim = dim->next)
      if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
	 return NC_ENAMEINUSE;

   /* Add a dimension to the list. The ID must come from the file
    * information, since dimids are visible in more than one group. */
   nc4_dim_list_add(&grp->dim);
   grp->dim->dimid = grp->file->nc4_info->next_dimid++;

   /* Initialize the metadata for this dimension. */
   if (!(grp->dim->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
      return NC_ENOMEM;
   strcpy(grp->dim->name, norm_name);
   grp->dim->len = len;
   grp->dim->dirty++;
   if (len == NC_UNLIMITED)
      grp->dim->unlimited++;

   /* Pass back the dimid. */
   if (idp)
      *idp = grp->dim->dimid;

   return retval;
}
Esempio n. 10
0
/* Rename a dimension, for those who like to prevaricate. */
int
NC4_rename_dim(int ncid, int dimid, const char *name)
{
   NC_FILE_INFO_T *nc;
   NC_GRP_INFO_T *grp;
   NC_HDF5_FILE_INFO_T *h5;
   NC_DIM_INFO_T *dim;
   char norm_name[NC_MAX_NAME + 1];
   int retval;

   if (!name)
      return NC_EINVAL;

   LOG((2, "nc_rename_dim: ncid 0x%x dimid %d name %s", ncid, 
	dimid, name));

   /* Find info for this file and group, and set pointer to each. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))      
      return retval;
   assert(nc);
   
#ifdef USE_PNETCDF
   /* Take care of files created/opened with parallel-netcdf library. */
   if (nc->pnetcdf_file)
      return ncmpi_rename_dim(nc->int_ncid, dimid, name);
#endif /* USE_PNETCDF */

   /* Handle netcdf-3 cases. */
   assert(h5);
   assert(h5 && grp);

   /* Trying to write to a read-only file? No way, Jose! */
   if (h5->no_write)
      return NC_EPERM;

   /* Make sure this is a valid netcdf name. */
   if ((retval = nc4_check_name(name, norm_name)))
      return retval;

   /* Make sure the new name is not already in use in this group. */
   for (dim = grp->dim; dim; dim = dim->next)
      if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
	 return NC_ENAMEINUSE;

   /* Find the dim. */
   for (dim = grp->dim; dim; dim = dim->next)
      if (dim->dimid == dimid)
	 break;
   if (!dim)
      return NC_EBADDIM;

   /* If not in define mode, switch to it, unless the new name is
    * shorter. (This is in accordance with the v3 interface.) */
/*    if (!(h5->flags & NC_INDEF) && strlen(name) > strlen(dim->name)) */
/*    { */
/*       if (h5->cmode & NC_CLASSIC_MODEL) */
/* 	 return NC_ENOTINDEFINE; */
/*       if ((retval = nc_redef(ncid))) */
/* 	 return retval; */
/*    } */

   /* Save the old name, we'll need it to rename this object when we
    * sync to HDF5 file. But if there already is an old_name saved,
    * just stick with what we've got, since the user might be renaming
    * the crap out of this thing, without ever syncing with the
    * file. When the sync does take place, we only need the original
    * name of the dim, not any of the intermediate ones. If the user
    * could just make up his mind, we could all get on to writing some
    * data... */
   if (!dim->old_name)
   {
      if (!(dim->old_name = malloc((strlen(dim->name) + 1) * sizeof(char))))
	 return NC_ENOMEM;
      strcpy(dim->old_name, dim->name);
   }

   /* Give the dimension its new name in metadata. UTF8 normalization
    * has been done. */
   free(dim->name);
   if (!(dim->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
      return NC_ENOMEM;
   strcpy(dim->name, norm_name);

   return NC_NOERR;
}
Esempio n. 11
0
/* Find out name and len of a dim. For an unlimited dimension, the
   length is the largest lenght so far written. If the name of lenp
   pointers are NULL, they will be ignored. */
int
NC4_inq_dim(int ncid, int dimid, char *name, size_t *lenp)
{
   NC_FILE_INFO_T *nc;
   NC_HDF5_FILE_INFO_T *h5;
   NC_GRP_INFO_T *grp, *dim_grp;
   NC_DIM_INFO_T *dim;
   int ret = NC_NOERR;

   LOG((2, "nc_inq_dim: ncid 0x%x dimid %d", ncid, dimid));

   /* Find our global metadata structure. */
   if ((ret = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return ret;
   
#ifdef USE_PNETCDF
   /* Take care of files created/opened with parallel-netcdf library. */
   if (nc->pnetcdf_file)
   {
      MPI_Offset mpi_len;
      if ((ret = ncmpi_inq_dim(nc->int_ncid, dimid, name, &mpi_len)))
	 return ret;
      if (lenp)
	 *lenp = mpi_len;
   }
#endif /* USE_PNETCDF */

   /* Take care of netcdf-3 files. */
   assert(h5);
   
   assert(nc && grp);

   /* Find the dimension and its home group. */
   if ((ret = nc4_find_dim(grp, dimid, &dim, &dim_grp)))
      return ret;
   assert(dim);

   /* Return the dimension name, if the caller wants it. */
   if (name && dim->name) 
      strcpy(name, dim->name);	    
   
   /* Return the dimension length, if the caller wants it. */
   if (lenp)
   {
      if (dim->unlimited)
      {
	 /* Since this is an unlimited dimension, go to the file
	    and see how many records there are. Take the max number
	    of records from all the vars that share this
	    dimension. */
	 *lenp = 0;
	 if ((ret = nc4_find_dim_len(dim_grp, dimid, &lenp)))
	    return ret;
      }
      else
      {
	 if (dim->too_long)
	 {
	    ret = NC_EDIMSIZE;
	    *lenp = NC_MAX_UINT;
	 }
	 else
	    *lenp = dim->len;
      }
   }

   return ret;
}
Esempio n. 12
0
/* Rename a dimension, for those who like to prevaricate. */
int
NC4_rename_dim(int ncid, int dimid, const char *name)
{
   NC *nc;
   NC_GRP_INFO_T *grp;
   NC_HDF5_FILE_INFO_T *h5;
   NC_DIM_INFO_T *dim, *tmp_dim;
   char norm_name[NC_MAX_NAME + 1];
   int retval;

   if (!name)
      return NC_EINVAL;

   LOG((2, "%s: ncid 0x%x dimid %d name %s", __func__, ncid, 
	dimid, name));

   /* Find info for this file and group, and set pointer to each. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))      
      return retval;

   assert(nc);
   assert(h5 && grp);
   
   /* Trying to write to a read-only file? No way, Jose! */
   if (h5->no_write)
      return NC_EPERM;

#if 0 /*def USE_PNETCDF*/
   /* Take care of files created/opened with parallel-netcdf library. */
   if (h5->pnetcdf_file)
      return ncmpi_rename_dim(nc->int_ncid, dimid, name);
#endif /* USE_PNETCDF */

   /* Make sure this is a valid netcdf name. */
   if ((retval = nc4_check_name(name, norm_name)))
      return retval;

   /* Check if name is in use, and retain a pointer to the correct dim */
   tmp_dim = NULL;
   for (dim = grp->dim; dim; dim = dim->l.next)
   {
      if (!strncmp(dim->name, norm_name, NC_MAX_NAME))
	 return NC_ENAMEINUSE;
      if (dim->dimid == dimid)
	 tmp_dim = dim;
   }
   if (!tmp_dim)
      return NC_EBADDIM;
   dim = tmp_dim;

   /* Check for renaming dimension w/o variable */
   if (dim->hdf_dimscaleid)
   {
      /* Sanity check */
      assert(!dim->coord_var);

      /* Close the HDF5 dataset */
      if (H5Dclose(dim->hdf_dimscaleid) < 0) 
         return NC_EHDFERR;
      dim->hdf_dimscaleid = 0;
            
      /* Now delete the dataset (it will be recreated later, if necessary) */
      if (H5Gunlink(grp->hdf_grpid, dim->name) < 0)
         return NC_EDIMMETA;
   }

   /* Give the dimension its new name in metadata. UTF8 normalization
    * has been done. */
   if(dim->name)
      free(dim->name);
   if (!(dim->name = malloc((strlen(norm_name) + 1) * sizeof(char))))
      return NC_ENOMEM;
   strcpy(dim->name, norm_name);

   /* Check if dimension was a coordinate variable, but names are different now */
   if (dim->coord_var && strcmp(dim->name, dim->coord_var->name))
   {
      /* Break up the coordinate variable */
      if ((retval = nc4_break_coord_var(grp, dim->coord_var, dim)))
         return retval;
   }

   /* Check if dimension should become a coordinate variable */
   if (!dim->coord_var)
   {
      NC_VAR_INFO_T *var;

      /* Attempt to find a variable with the same name as the dimension in
       * the current group. */
      if ((retval = nc4_find_var(grp, dim->name, &var)))
         return retval;

      /* Check if we found a variable and the variable has the dimension in
       * index 0. */
      if (var && var->dim[0] == dim)
      {
          /* Sanity check */
          assert(var->dimids[0] == dim->dimid);

          /* Reform the coordinate variable */
          if ((retval = nc4_reform_coord_var(grp, var, dim)))
             return retval;
      }
   }

   return NC_NOERR;
}
Esempio n. 13
0
File: nccr.c Progetto: U-238/gempak
/* See ncd4dispatch.c for other version */
int
NCCR_open(const char * path, int mode,
               int basepe, size_t *chunksizehintp,
 	       int useparallel, void* mpidata,
               NC_Dispatch* dispatch, NC** ncpp)
{
    NCerror ncstat = NC_NOERR;
    NC_URL* tmpurl;
    NCCR* nccr = NULL; /* reuse the ncdap3 structure*/
    NCCDMR* cdmr = NULL;
    NC_HDF5_FILE_INFO_T* h5 = NULL;
    NC_GRP_INFO_T *grp = NULL;
    int ncid = -1;
    int fd;
    char* tmpname = NULL;
    NClist* shows;
    bytes_t buf;
    long filetime;
    ast_runtime* rt = NULL;
    ast_err aststat = AST_NOERR;
    Header* hdr = NULL;

    LOG((1, "nc_open_file: path %s mode %d", path, mode));

    if(nc_urlparse(path,&tmpurl) != NC_NOERR) PANIC("libcdmr: non-url path");
    nc_urlfree(tmpurl); /* no longer needed */

    /* Check for legal mode flags */
    if((mode & NC_WRITE) != 0) ncstat = NC_EINVAL;
    else if(mode & (NC_WRITE|NC_CLOBBER)) ncstat = NC_EPERM;
    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}

    mode = (mode & ~(NC_MPIIO | NC_MPIPOSIX));
    /* Despite the above check, we want the file to be initially writable */
    mode |= (NC_WRITE|NC_CLOBBER);

    /* Use NCCR code to establish a pseudo file */
    tmpname = nulldup(PSEUDOFILE);
    fd = mkstemp(tmpname);
    if(fd < 0) {THROWCHK(errno); goto done;}
    /* Now, use the file to create the hdf5 file */
    ncstat = NC4_create(tmpname,NC_NETCDF4|NC_CLOBBER,
			0,0,NULL,0,NULL,dispatch,(NC**)&nccr);
    ncid = nccr->info.ext_ncid;
    /* unlink the temp file so it will automatically be reclaimed */
    unlink(tmpname);
    free(tmpname);
    /* Avoid fill */
    dispatch->set_fill(ncid,NC_NOFILL,NULL);
    if(ncstat)
	{THROWCHK(ncstat); goto done;}
    /* Find our metadata for this file. */
    ncstat = nc4_find_nc_grp_h5(ncid, (NC_FILE_INFO_T**)&nccr, &grp, &h5);
    if(ncstat)
	{THROWCHK(ncstat); goto done;}

    /* Setup tentative NCCR state*/
    nccr->info.dispatch = dispatch;
    cdmr = (NCCDMR*)calloc(1,sizeof(NCCDMR));
    if(cdmr == NULL) {ncstat = NC_ENOMEM; goto done;}
    nccr->cdmr = cdmr;
    nccr->cdmr->controller = (NC*)nccr;
    nccr->cdmr->urltext = nulldup(path);
    nc_urlparse(nccr->cdmr->urltext,&nccr->cdmr->url);

    /* Create the curl connection (does not make the server connection)*/
    ncstat = nccr_curlopen(&nccr->cdmr->curl.curl);
    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}

    shows = nc_urllookup(nccr->cdmr->url,"show");
    if(nc_urllookupvalue(shows,"fetch"))
	nccr->cdmr->controls |= SHOWFETCH;

    /* Parse the projection */
    


    /* fetch meta data */
    buf = bytes_t_null;
    NCbytes* completeurl = ncbytesnew();
    ncbytescat(completeurl,nccr->cdmr->url->url);
    ncbytescat(completeurl,"?req=header");
    ncstat = nccr_fetchurl(nccr->cdmr->curl.curl,ncbytescontents(completeurl),
			   &buf,&filetime);
    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}

    /* Parse the meta data */
    ncstat = nccr_decodeheader(&buf,&hdr);
    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}

    if(buf.bytes != NULL) free(buf.bytes);

    /* Compute various things about the Header tree */

    /* Collect all nodes and fill in the CRnode part*/
    cdmr->nodeset = nclistnew();
    ncstat = nccr_walk_Header(hdr,cdmr->nodeset);
    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}

    /* Compute the pathnames */
    ncstat = nccr_compute_pathnames(cdmr->nodeset);
    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}

    /* Map dimension references to matching declaration */
    ncstat = nccr_map_dimensions(cdmr->nodeset);
    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}

    /* Replace dimension references with matching declaration */
    nccr_deref_dimensions(cdmr->nodeset);

    /* Elide any variables not in the url projection */
    ncstat = nccr_elide_vars(cdmr);
    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}

    /* build the meta data */
    ncstat = nccr_buildnc(nccr,hdr);
    if(ncstat != NC_NOERR) {THROWCHK(ncstat); goto done;}

    /* Mark as no longer indef and no longer writable*/
    h5->flags &= ~(NC_INDEF);
    h5->no_write = 1;

done:
    if(aststat != AST_NOERR) {ncstat = nccr_cvtasterr(aststat);}
    if(ncstat) {
        if(nccr != NULL) {
	    int ncid = nccr->info.ext_ncid;
            NCCR_abort(ncid);
        }
    } else {
        if(ncpp) *ncpp = (NC*)nccr;
    }
    return THROW(ncstat);
}
Esempio n. 14
0
/**
 * @internal I think all atts should be named the exact same thing, to
 * avoid confusion!
 *
 * @param ncid File and group ID.
 * @param varid Variable ID.
 * @param name Name of attribute.
 * @param newname New name for attribute.
 *
 * @return ::NC_NOERR No error.
 * @return ::NC_EBADID Bad ncid.
 * @return ::NC_EMAXNAME New name too long.
 * @return ::NC_EPERM File is read-only.
 * @return ::NC_ENAMEINUSE New name already in use.
 * @return ::NC_ENOTINDEFINE Classic model file not in define mode.
 * @return ::NC_EHDFERR HDF error.
 * @return ::NC_ENOMEM Out of memory.
 * @return ::NC_EINTERNAL Could not rebuild list.
 * @author Ed Hartnett
 */
int
NC4_rename_att(int ncid, int varid, const char *name, const char *newname)
{
   NC *nc;
   NC_GRP_INFO_T *grp;
   NC_FILE_INFO_T *h5;
   NC_VAR_INFO_T *var = NULL;
   NC_ATT_INFO_T *att;
   NCindex *list;
   char norm_newname[NC_MAX_NAME + 1], norm_name[NC_MAX_NAME + 1];
   hid_t datasetid = 0;
   int retval = NC_NOERR;

   if (!name || !newname)
      return NC_EINVAL;

   LOG((2, "nc_rename_att: ncid 0x%x varid %d name %s newname %s",
        ncid, varid, name, newname));

   /* If the new name is too long, that's an error. */
   if (strlen(newname) > NC_MAX_NAME)
      return NC_EMAXNAME;

   /* Find info for this file, group, and h5 info. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;
   assert(h5 && grp && h5);

   /* If the file is read-only, return an error. */
   if (h5->no_write)
      return NC_EPERM;

   /* Check and normalize the name. */
   if ((retval = nc4_check_name(newname, norm_newname)))
      return retval;

   /* Get the list of attributes. */
   if ((retval = getattlist(grp, varid, &var, &list)))
      return retval;

   /* Is new name in use? */
   att = (NC_ATT_INFO_T*)ncindexlookup(list,norm_newname);
   if(att != NULL)
      return NC_ENAMEINUSE;

   /* Normalize name and find the attribute. */
   if ((retval = nc4_normalize_name(name, norm_name)))
      return retval;

   att = (NC_ATT_INFO_T*)ncindexlookup(list,norm_name);
   if (!att)
      return NC_ENOTATT;

   /* If we're not in define mode, new name must be of equal or
      less size, if complying with strict NC3 rules. */
   if (!(h5->flags & NC_INDEF) && strlen(norm_newname) > strlen(att->hdr.name) &&
       (h5->cmode & NC_CLASSIC_MODEL))
      return NC_ENOTINDEFINE;

   /* Delete the original attribute, if it exists in the HDF5 file. */
   if (att->created)
   {
      if (varid == NC_GLOBAL)
      {
         if (H5Adelete(((NC_HDF5_GRP_INFO_T *)(grp->format_grp_info))->hdf_grpid,
                       att->hdr.name) < 0)
            return NC_EHDFERR;
      }
      else
      {
         if ((retval = nc4_open_var_grp2(grp, varid, &datasetid)))
            return retval;
         if (H5Adelete(datasetid, att->hdr.name) < 0)
            return NC_EHDFERR;
      }
      att->created = NC_FALSE;
   }

   /* Copy the new name into our metadata. */
   if(att->hdr.name) free(att->hdr.name);
   if (!(att->hdr.name = strdup(norm_newname)))
      return NC_ENOMEM;
   att->hdr.hashkey = NC_hashmapkey(att->hdr.name,strlen(att->hdr.name)); /* Fix hash key */

   att->dirty = NC_TRUE;

   /* Rehash the attribute list so that the new name is used */
   if(!ncindexrebuild(list))
      return NC_EINTERNAL;

   /* Mark attributes on variable dirty, so they get written */
   if(var)
      var->attr_dirty = NC_TRUE;

   return retval;
}
Esempio n. 15
0
/* Delete an att. Rub it out. Push the button on it. Liquidate
   it. Bump it off. Take it for a one-way ride. Terminate it. Drop the
   bomb on it. You get the idea.
   Ed Hartnett, 10/1/3
*/
int
NC4_del_att(int ncid, int varid, const char *name)
{
   NC *nc;
   NC_GRP_INFO_T *grp;
   NC_HDF5_FILE_INFO_T *h5;
   NC_ATT_INFO_T *att, *natt;
   NC_VAR_INFO_T *var;
   NC_ATT_INFO_T **attlist = NULL;
   hid_t locid = 0, datasetid = 0;
   int retval = NC_NOERR;

   if (!name)
      return NC_EINVAL;

   LOG((2, "nc_del_att: ncid 0x%x varid %d name %s",
	ncid, varid, name));

   /* Find metadata for this file. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;

   assert(h5 && grp);

   /* If the file is read-only, return an error. */
   if (h5->no_write)
      return NC_EPERM;

#if 0 /*def USE_PNETCDF*/
   /* Take care of files created/opened with parallel-netcdf library. */
   if (h5->pnetcdf_file)
      return ncmpi_del_att(nc->int_ncid, varid, name);
#endif /* USE_PNETCDF */

   /* If it's not in define mode, forget it. */
   if (!(h5->flags & NC_INDEF))
   {
      if (h5->cmode & NC_CLASSIC_MODEL)
	 return NC_ENOTINDEFINE;
      if ((retval = NC4_redef(ncid)))
	 BAIL(retval);
   }

   /* Get either the global or a variable attribute list. Also figure
      out the HDF5 location it's attached to. */
   if (varid == NC_GLOBAL)
   {
      attlist = &grp->att;
      locid = grp->hdf_grpid;
   }
   else
   {
      for(var = grp->var; var; var = var->l.next)
      {
	 if (var->varid == varid)
	 {
	    attlist = &var->att;
	    break;
	 }
      }
      if (!var)
	 return NC_ENOTVAR;
      if (var->created)
	 locid = var->hdf_datasetid;
   }

   /* Now find the attribute by name or number. */
   for (att = *attlist; att; att = att->l.next)
      if (!strcmp(att->name, name))
	 break;

   /* If att is NULL, we couldn't find the attribute. */
   if (!att)
      BAIL_QUIET(NC_ENOTATT);

   /* Delete it from the HDF5 file, if it's been created. */
   if (att->created)
   {
      assert(locid);

      if(H5Adelete(locid, att->name) < 0)
	 BAIL(NC_EATTMETA);
   }

   /* Renumber all following attributes. */
   for (natt = att->l.next; natt; natt = natt->l.next)
      natt->attnum--;

   /* Delete this attribute from this list. */
   if ((retval = nc4_att_list_del(attlist, att)))
      BAIL(retval);

 exit:
   if (datasetid > 0) H5Dclose(datasetid);
   return retval;
}
Esempio n. 16
0
/* I think all atts should be named the exact same thing, to avoid
   confusion! */
int
NC4_rename_att(int ncid, int varid, const char *name,
	      const char *newname)
{
   NC *nc;
   NC_GRP_INFO_T *grp;
   NC_HDF5_FILE_INFO_T *h5;
   NC_VAR_INFO_T *var;
   NC_ATT_INFO_T *att, *list;
   char norm_newname[NC_MAX_NAME + 1], norm_name[NC_MAX_NAME + 1];
   hid_t datasetid = 0;
   int retval = NC_NOERR;

   if (!name || !newname)
      return NC_EINVAL;

   LOG((2, "nc_rename_att: ncid 0x%x varid %d name %s newname %s",
	ncid, varid, name, newname));

   /* If the new name is too long, that's an error. */
   if (strlen(newname) > NC_MAX_NAME)
      return NC_EMAXNAME;

   /* Find metadata for this file. */
   if ((retval = nc4_find_nc_grp_h5(ncid, &nc, &grp, &h5)))
      return retval;

   assert(h5 && grp);

   /* If the file is read-only, return an error. */
   if (h5->no_write)
     return NC_EPERM;

#if 0 /*def USE_PNETCDF*/
   /* Take care of files created/opened with parallel-netcdf library. */
   if (h5->pnetcdf_file)
      return ncmpi_rename_att(nc->int_ncid, varid, name, newname);
#endif /* USE_PNETCDF */

   /* Check and normalize the name. */
   if ((retval = nc4_check_name(newname, norm_newname)))
      return retval;

   /* Is norm_newname in use? */
   if (varid == NC_GLOBAL)
   {
      list = grp->att;
   }
   else
   {
      for (var = grp->var; var; var = var->l.next)
	 if (var->varid == varid)
	 {
	    list = var->att;
	    break;
	 }
      if (!var)
	 return NC_ENOTVAR;
   }
   for (att = list; att; att = att->l.next)
      if (!strncmp(att->name, norm_newname, NC_MAX_NAME))
	 return NC_ENAMEINUSE;

   /* Normalize name and find the attribute. */
   if ((retval = nc4_normalize_name(name, norm_name)))
      return retval;
   for (att = list; att; att = att->l.next)
      if (!strncmp(att->name, norm_name, NC_MAX_NAME))
	 break;
   if (!att)
      return NC_ENOTATT;

   /* If we're not in define mode, new name must be of equal or
      less size, if complying with strict NC3 rules. */
   if (!(h5->flags & NC_INDEF) && strlen(norm_newname) > strlen(att->name) &&
       (h5->cmode & NC_CLASSIC_MODEL))
      return NC_ENOTINDEFINE;

   /* Delete the original attribute, if it exists in the HDF5 file. */
   if (att->created)
   {
      if (varid == NC_GLOBAL)
      {
         if (H5Adelete(grp->hdf_grpid, att->name) < 0)
	    return NC_EHDFERR;
      }
      else
      {
	 if ((retval = nc4_open_var_grp2(grp, varid, &datasetid)))
	    return retval;
         if (H5Adelete(datasetid, att->name) < 0)
	    return NC_EHDFERR;
      }
      att->created = NC_FALSE;
   }

   /* Copy the new name into our metadata. */
   free(att->name);
   if (!(att->name = malloc((strlen(norm_newname) + 1) * sizeof(char))))
      return NC_ENOMEM;
   strcpy(att->name, norm_newname);
   att->dirty = NC_TRUE;

   return retval;
}