From 2917a6a1235717e8f221234bc64dc052c44bf4e0 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Mon, 1 Dec 2014 08:52:53 -0600 Subject: [PATCH] Interim checkpoint of working code. --- include/nc4internal.h | 1 + libsrc4/nc4attr.c | 5 +++++ libsrc4/nc4hdf.c | 46 ++++++++++++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/include/nc4internal.h b/include/nc4internal.h index 56c2257a2..88c64ff1a 100644 --- a/include/nc4internal.h +++ b/include/nc4internal.h @@ -151,6 +151,7 @@ typedef struct NC_VAR_INFO nc_bool_t is_new_var; /* True if variable is newly created */ nc_bool_t was_coord_var; /* True if variable was a coordinate var, but either the dim or var has been renamed */ nc_bool_t became_coord_var; /* True if variable _became_ a coordinate var, because either the dim or var has been renamed */ + nc_bool_t fill_val_changed; /* True if variable's fill value changes after it has been created */ nc_bool_t attr_dirty; /* True if variable's attributes are dirty and should be rewritten */ nc_bool_t created; /* Variable has already been created (_not_ that it was just created) */ nc_bool_t written_to; /* True if variable has data written to it */ diff --git a/libsrc4/nc4attr.c b/libsrc4/nc4attr.c index 37d750770..452b47ff9 100644 --- a/libsrc4/nc4attr.c +++ b/libsrc4/nc4attr.c @@ -410,6 +410,11 @@ nc4_put_att(int ncid, NC *nc, int varid, const char *name, } else memcpy(var->fill_value, data, type_size); + + /* Indicate that the fill value was changed, if the variable has already + * been created in the file, so the dataset gets deleted and re-created. */ + if (var->created) + var->fill_val_changed = NC_TRUE; } /* Copy the attribute data, if there is any. VLENs and string diff --git a/libsrc4/nc4hdf.c b/libsrc4/nc4hdf.c index 864c872c5..f33cbf173 100644 --- a/libsrc4/nc4hdf.c +++ b/libsrc4/nc4hdf.c @@ -2115,16 +2115,16 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, nc_bool_t write_dimid) LOG((4, "%s: writing var %s", __func__, var->name)); - /* If this is a coordinate var, and a dataset has already - * been created for it, then delete that dataset and recreate - * it (because its type may be wrong anyway.) But then we - * have to reattach dimension scales for all vars! Oh well, - * this all only happens when the user defines a var, writes - * metadata, reenters define mode, and adds a coordinate - * var. Presumably this will happen rarely. */ + /* If the variable has already been created & the fill value changed, + * indicate that the existing variable should be replaced. */ + if (var->created && var->fill_val_changed) + { + replace_existing_var = NC_TRUE; + var->fill_val_changed = NC_FALSE; + } /* Is this a coordinate var that has already been created in - * the HDF5 as a dimscale dataset? Check for dims with the + * the HDF5 file as a dimscale dataset? Check for dims with the * same name in this group. If there is one, check to see if * this object exists in the HDF group. */ if (var->became_coord_var) @@ -2140,10 +2140,34 @@ write_var(NC_VAR_INFO_T *var, NC_GRP_INFO_T *grp, nc_bool_t write_dimid) return retval; if (exists) { - hid_t dim_datasetid; /* Dataset ID for dimension */ + /* Indicate that the variable already exists, and should be replaced */ + replace_existing_var = NC_TRUE; + break; + } + } + } - /* Indicate that the variable already exists */ - replace_existing_var = NC_TRUE; + /* Check dims if the variable will be replaced, so that the dimensions + * will be de-attached and re-attached correctly. */ + /* (Note: There's a temptation to merge this loop over the dimensions with + * the prior loop over dimensions, but that blurs the line over the + * purpose of them, so they are currently separate. If performance + * becomes an issue here, it would be possible to merge them. -QAK) + */ + if (replace_existing_var) + { + NC_DIM_INFO_T *d1; + + for (d1 = grp->dim; d1; d1 = d1->l.next) + if (!strcmp(d1->name, var->name)) + { + nc_bool_t exists; + + if ((retval = var_exists(grp->hdf_grpid, var->name, &exists))) + return retval; + if (exists) + { + hid_t dim_datasetid; /* Dataset ID for dimension */ /* Find dataset ID for dimension */ if (d1->coord_var)