[svn-r18818] Bug fix:

Fixed a bug in the H5DSdetach_scale function when 0 bytes
     were allocated after the last reference to a dim. scale
     was removed from the list of references in a VL element of the
     DIMENSION_LIST attribute; modified the function to comply
     with the Spec: DIMENSION_LIST attribute is deleted now when no
     dimension scales left attached.

Platforms tested: jam with electric fence, amani amd linew
This commit is contained in:
Elena Pourmal 2010-05-14 23:10:53 -05:00
parent a6698e571c
commit d7a89d6c7b
5 changed files with 251 additions and 114 deletions

View File

@ -620,9 +620,11 @@ out:
*
* Date: December 20, 2004
*
* Comments:
* Comments:
*
* Modifications:
* Modifications: Function didn't delete DIMENSION_LIST attribute, when
* all dimension scales were detached from a dataset; added.
* 2010/05/13 EIP
*
*-------------------------------------------------------------------------
*/
@ -642,14 +644,15 @@ herr_t H5DSdetach_scale(hid_t did,
hid_t aid = -1; /* attribute ID */
int rank; /* rank of dataset */
ds_list_t *dsbuf = NULL; /* array of attribute data in the DS pointing to the dataset */
ds_list_t *dsbufn = NULL; /* array of attribute data in the DS pointing to the dataset */
hsize_t *dims = NULL; /* dimension of the "REFERENCE_LIST" array */
hsize_t dims[1]; /* dimension of the "REFERENCE_LIST" array */
hobj_ref_t ref; /* reference to the DS */
hvl_t *buf = NULL; /* VL buffer to store in the attribute */
unsigned i, j, jj;
H5O_info_t oi1, oi2, oi3, oi4;
int i;
size_t j;
hssize_t ii;
H5O_info_t did_oi, dsid_oi, tmp_oi;
int found_dset = 0, found_ds = 0;
H5I_type_t it1, it2;
int have_ds = 0;
htri_t is_scale;
/*-------------------------------------------------------------------------
@ -657,32 +660,28 @@ herr_t H5DSdetach_scale(hid_t did,
*-------------------------------------------------------------------------
*/
if ((is_scale = H5DSis_scale(did)) < 0)
/* check for valid types of identifiers */
if(H5I_DATASET!=H5Iget_type(did) || H5I_DATASET!=H5Iget_type(dsid))
return FAIL;
if((is_scale = H5DSis_scale(did)) < 0)
return FAIL;
/* the dataset cannot be a DS dataset */
if ( is_scale == 1)
if( is_scale == 1)
return FAIL;
/* get info for the dataset in the parameter list */
if(H5Oget_info(did, &oi1) < 0)
if(H5Oget_info(did, &did_oi) < 0)
return FAIL;
/* get info for the scale in the parameter list */
if(H5Oget_info(dsid, &oi2) < 0)
if(H5Oget_info(dsid, &dsid_oi) < 0)
return FAIL;
/* same object, not valid */
if(oi1.fileno == oi2.fileno && oi1.addr == oi2.addr)
return FAIL;
/* get ID type */
if ((it1 = H5Iget_type(did)) < 0)
return FAIL;
if ((it2 = H5Iget_type(dsid)) < 0)
return FAIL;
if (H5I_DATASET!=it1 || H5I_DATASET!=it2)
if(did_oi.fileno == dsid_oi.fileno && did_oi.addr == dsid_oi.addr)
return FAIL;
@ -761,46 +760,62 @@ herr_t H5DSdetach_scale(hid_t did,
if ((dsid_j = H5Rdereference(did,H5R_OBJECT,&ref)) < 0)
goto out;
/* get info for DS in the parameter list */
if(H5Oget_info(dsid, &oi1) < 0)
/* get info for this DS */
if(H5Oget_info(dsid_j, &tmp_oi) < 0)
goto out;
/* get info for this DS */
if(H5Oget_info(dsid_j, &oi2) < 0)
/* Close the dereferenced dataset */
if (H5Dclose(dsid_j) < 0)
goto out;
/* same object, reset */
if(oi1.fileno == oi2.fileno && oi1.addr == oi2.addr)
if(dsid_oi.fileno == tmp_oi.fileno && dsid_oi.addr == tmp_oi.addr)
{
size_t len;
/* If there are more than one reference in the VL element
and the reference we found is not the last one,
copy the last one to replace the found one since the order
of the references doesn't matter according to the spec;
reduce the size of the VL element by 1;
if the length of the element becomes 0, free the pointer
and reset to NULL */
for(jj=j; jj<buf[idx].len-1; jj++)
{
((hobj_ref_t *)buf[idx].p)[jj] = ((hobj_ref_t *)buf[idx].p)[jj+1];
size_t len = buf[idx].len;
if(j<len-1)
((hobj_ref_t *)buf[idx].p)[j] = ((hobj_ref_t *)buf[idx].p)[len-1];
len = --buf[idx].len;
if(len == 0) {
free(buf[idx].p);
buf[idx].p = NULL;
}
buf[idx].len--;
len = buf[idx].len;
buf[idx].p = realloc( buf[idx].p, len * sizeof(hobj_ref_t));
/* Since a reference to a dim. scale can be inserted only once,
we do not need to continue the search if it is found */
found_ds = 1;
/* close the dereferenced dataset and break */
if (H5Dclose(dsid_j) < 0)
goto out;
break;
}
/* close the dereferenced dataset */
if (H5Dclose(dsid_j) < 0)
goto out;
} /* j */
} /* if */
/* write the attribute */
if (H5Awrite(aid,tid,buf) < 0)
/* the scale must be present to continue */
if(found_ds == 0)
goto out;
/* Write the attribute, but check first, if we have any scales left,
because if not, we should delete the attribute according to the spec */
for(i=0; i < rank; i++) {
if(buf[i].len > 0) {
have_ds = 1;
break;
}
}
if(have_ds) {
if(H5Awrite(aid,tid,buf) < 0)
goto out;
}
else {
if(H5Adelete(did,DIMENSION_LIST) < 0)
goto out;
}
/* close */
if (H5Dvlen_reclaim(tid,sid,H5P_DEFAULT,buf) < 0)
goto out;
@ -817,9 +832,6 @@ herr_t H5DSdetach_scale(hid_t did,
buf = NULL;
}
/* the scale must be present */
if(found_ds == 0)
goto out;
/*-------------------------------------------------------------------------
* the "REFERENCE_LIST" array exists, update
@ -849,41 +861,36 @@ herr_t H5DSdetach_scale(hid_t did,
if (H5Aread(aid,ntid,dsbuf) < 0)
goto out;
for(i=0; i<nelmts; i++)
{
/* get the reference to the dataset */
ref = dsbuf[i].ref;
for(ii=0; ii<nelmts; ii++) {
/* First check if we have the same dimension index */
if((int)idx == dsbuf[ii].dim_idx) {
/* get the reference to the dataset */
ref = dsbuf[ii].ref;
/* get the dataset id */
if ((did_i = H5Rdereference(did,H5R_OBJECT,&ref)) < 0)
goto out;
/* get info for dataset in the parameter list */
if(H5Oget_info(did, &oi3) < 0)
goto out;
/* get info for this dataset */
if(H5Oget_info(did_i, &oi4) < 0)
goto out;
/* same object, reset. we want to detach only for this DIM */
if(oi3.fileno == oi4.fileno && oi3.addr == oi4.addr && (int)idx == dsbuf[i].dim_idx) {
for(jj=i; jj<nelmts-1; jj++)
dsbuf[jj] = dsbuf[jj+1];
nelmts--;
found_dset=1;
/* close the dereferenced dataset and break */
if (H5Dclose(did_i) < 0)
/* get the dataset id */
if ((did_i = H5Rdereference(did,H5R_OBJECT,&ref)) < 0)
goto out;
break;
} /* if */
/* close the dereferenced dataset */
if (H5Dclose(did_i) < 0)
goto out;
/* get info for this dataset */
if(H5Oget_info(did_i, &tmp_oi) < 0)
goto out;
} /* i */
/* close the dereferenced dataset */
if(H5Dclose(did_i) < 0)
goto out;
/* same object, reset. we want to detach only for this DIM */
if(did_oi.fileno == tmp_oi.fileno && did_oi.addr == tmp_oi.addr) {
/* if we found not the last one, copy the last one to replace
the one which is found */
if(i < nelmts-1)
dsbuf[ii] = dsbuf[nelmts-1];
nelmts--;
found_dset=1;
break;
} /* if */
} /* if we have the same dimension index */
} /* ii */
/* close space and attribute */
if (H5Sclose(sid) < 0)
@ -915,19 +922,8 @@ herr_t H5DSdetach_scale(hid_t did,
if(nelmts)
{
/* create a new data space for the new references array */
dims = (hsize_t*)malloc((size_t)nelmts * sizeof (hsize_t));
if(dims == NULL)
goto out;
dims[0] = nelmts;
dsbufn = (ds_list_t*) malloc((size_t)nelmts * sizeof(ds_list_t));
if(dsbufn == NULL)
goto out;
/* store the new information */
for(i = 0; i < nelmts; i++)
dsbufn[i] = dsbuf[i];
if((sid = H5Screate_simple(1, dims, NULL)) < 0)
goto out;
@ -936,7 +932,7 @@ herr_t H5DSdetach_scale(hid_t did,
goto out;
/* write the new attribute with the new references */
if(H5Awrite(aid, tid, dsbufn) < 0)
if(H5Awrite(aid, tid, dsbuf) < 0)
goto out;
/* close space and attribute */
@ -955,16 +951,6 @@ herr_t H5DSdetach_scale(hid_t did,
free(dsbuf);
dsbuf=NULL;
}
if (dsbufn)
{
free(dsbufn);
dsbufn=NULL;
}
if (dims)
{
free(dims);
dims=NULL;
}
return SUCCEED;
@ -982,18 +968,14 @@ out:
free(dsbuf);
dsbuf=NULL;
}
if (dsbufn)
{
free(dsbufn);
dsbufn=NULL;
}
if (dims)
{
free(dims);
dims=NULL;
}
if (buf)
{
/* Failure occured before H5Dvlen_reclaim was called;
free the pointers allocated when we read data in */
for(i=0; i<rank; i++) {
if(buf[i].p)
free(buf[i].p);
}
free(buf);
buf=NULL;
}
@ -1218,7 +1200,7 @@ htri_t H5DSis_attached(hid_t did,
if (dsbuf == NULL)
goto out;
if (H5Aread(aid,ntid,dsbuf) < 0)
if (H5Aread(aid,ntid,dsbuf) < 0)
goto out;
/*-------------------------------------------------------------------------

View File

@ -46,6 +46,6 @@ endif
# Temporary files. These files are the ones created by running `make test'.
CHECK_CLEANFILES+=combine_tables[1-2].h5 test_ds[1-9].h5 test_image[1-3].h5 \
test_lite[1-2].h5 test_table.h5 test_packet_table.h5 \
test_packet_compress.h5
test_packet_compress.h5 test_detach.h5
include $(top_srcdir)/config/conclude.am

View File

@ -383,7 +383,8 @@ TRACE = perl $(top_srcdir)/bin/trace
# Temporary files. These files are the ones created by running `make test'.
CHECK_CLEANFILES = *.chkexe *.chklog *.clog combine_tables[1-2].h5 \
test_ds[1-9].h5 test_image[1-3].h5 test_lite[1-2].h5 \
test_table.h5 test_packet_table.h5 test_packet_compress.h5
test_table.h5 test_packet_table.h5 test_packet_compress.h5 \
test_detach.h5
# The tests depend on the hdf5, hdf5 test, and hdf5_hl libraries
LDADD = $(LIBH5_HL) $(LIBH5TEST) $(LIBHDF5)

View File

@ -71,6 +71,7 @@ static int test_long_scalenames(const char *fileext);
static int test_samelong_scalenames(const char *fileext);
static int test_float_scalenames(const char *fileext);
static int test_foreign_scaleattached(const char *fileforeign);
static int test_detachscales(void);
static int test_simple(void);
static int test_errors(void);
@ -136,6 +137,9 @@ static int read_data( const char* fname, int ndims, hsize_t *dims, float **buf )
#define FILE6 "test_ds8.h5"
#define FILE7 "test_ds9.h5"
#define DIMENSION_LIST "DIMENSION_LIST"
#define REFERENCE_LIST "REFERENCE_LIST"
/*-------------------------------------------------------------------------
* the main program
*-------------------------------------------------------------------------
@ -169,6 +173,7 @@ int main(void)
nerrors += test_samelong_scalenames("2") < 0 ? 1 : 0;
nerrors += test_foreign_scaleattached(FOREIGN_FILE1) < 0 ? 1 : 0;
nerrors += test_foreign_scaleattached(FOREIGN_FILE2) < 0 ? 1 : 0;
nerrors += test_detachscales() < 0 ? 1 : 0;
/* the following tests have not been rewritten to match those above */
nerrors += test_simple() < 0 ?1:0;
@ -1144,6 +1149,148 @@ herr_t test_cmp_scalename(hid_t fid, hid_t did, const char *name, const char *sc
return ret_value;
}
static int test_detachscales(void)
{
hid_t fid = -1;
hid_t did = -1;
hid_t dsid = -1;
int rank1 = 1;
int rank3 = 3;
hsize_t dims[] = {1,2,3}; /*some bogus numbers, not important for the test*/
int *buf = NULL;
char dname[10];
int i;
/* This tests creates two three dimensional datasets; then it creates
four integer datasets that are used as dim. scales; we will attach
and detach them to check that at the end there is no attributes
REFERENCE_LIST on a dimension scale and DIMENSION_LIST on a dataset */
TESTING2("test_detachscales");
if((fid = H5Fcreate("test_detach.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT)) < 0)
goto out;
/* make datasets; they are three dimensional*/
for (i=0; i < 2; i++) {
sprintf(dname,"D%d", i);
if(H5LTmake_dataset_int(fid, dname, rank3, dims, buf) < 0)
goto out;
}
/* create datasets and make them dim. scales */
for (i=0; i < 4; i++) {
sprintf(dname, "DS%d", i);
if(H5LTmake_dataset_int(fid, dname, rank1, dims, buf) < 0)
goto out;
}
/* attach scales to the first dataset; first dimension will have
two scales attached */
if((did = H5Dopen2(fid, "D0", H5P_DEFAULT)) >= 0) {
for (i=0; i<4; i++) {
sprintf(dname, "DS%d", i);
if((dsid = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0)
goto out;
if(H5DSattach_scale(did, dsid, (unsigned int) i%3) < 0)
goto out;
if(H5Dclose(dsid) < 0)
goto out;
}
if(H5Dclose(did) < 0)
goto out;
}
else
goto out;
/* attach scales to the second dataset */
if((did = H5Dopen2(fid, "D1", H5P_DEFAULT)) >= 0) {
for (i=0; i<3; i++) {
sprintf(dname, "DS%d", i);
if((dsid = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0)
goto out;
if(H5DSattach_scale(did, dsid, (unsigned int) i) < 0)
goto out;
if(H5Dclose(dsid) < 0)
goto out;
}
if(H5Dclose(did) < 0)
goto out;
}
else
goto out;
/* detach DS0 from first dimension of D0 and D1; then check
that DS0 doesn't have attribute REFERENCE _LIST */
if((dsid = H5Dopen2(fid, "DS0", H5P_DEFAULT)) < 0)
goto out;
for (i=0; i<2; i++) {
sprintf(dname, "D%d", i);
if((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0)
goto out;
if(H5DSdetach_scale(did, dsid, (unsigned int)0) < 0)
goto out;
if(H5Dclose(did) < 0)
goto out;
}
/* Check that attribute "REFERENCE_LIST" doesn't exist anymore */
if(H5Aexists(dsid, REFERENCE_LIST)!= 0)
goto out;
if(H5Dclose(dsid) < 0)
goto out;
/* Check that DS3 is the only dim. scale attached to the first
dimension of D0 */
if((did = H5Dopen2(fid, "D0", H5P_DEFAULT)) < 0)
goto out;
if((dsid = H5Dopen2(fid, "DS3", H5P_DEFAULT)) < 0)
goto out;
if(H5DSis_attached(did, dsid, (unsigned int) 0) <= 0)
goto out;
if(H5Dclose(did) < 0)
goto out;
if(H5Dclose(dsid) < 0)
goto out;
/* Detach the rest of the scales DS3, DS1, DS2 from D0 and make
sure that attribute "DIMENSION_LIST" doesn't exist anymore */
if((did = H5Dopen2(fid, "D0", H5P_DEFAULT)) >= 0) {
for (i=1; i<4; i++) {
sprintf(dname, "DS%d", i);
if((dsid = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0)
goto out;
if(H5DSdetach_scale(did, dsid, (unsigned int) i%3) < 0)
goto out;
if(H5Dclose(dsid) < 0)
goto out;
}
/* Check that attribute "REFERENCE_LIST" doesn't exist anymore */
if(H5Aexists(did, DIMENSION_LIST)!= 0)
goto out;
if(H5Dclose(did) < 0)
goto out;
}
else
goto out;
PASSED();
H5Fclose(fid);
return SUCCEED;
out:
H5E_BEGIN_TRY {
H5Dclose(did);
H5Dclose(dsid);
H5Fclose(fid);
} H5E_END_TRY;
H5_FAILED();
return FAIL;
}
static int test_char_attachscales(const char *fileext)
{
hid_t fid = -1;

View File

@ -469,6 +469,13 @@ Bug Fixes since HDF5-1.8.0 release
High-Level APIs:
------
- Fixed a bug in the H5DSdetach_scale function when 0 bytes
were allocated after the last reference to a dim. scale
was removed from the list of references in a VL element of the
DIMENSION_LIST attribute; modified the function to comply
with the Spec: DIMENSION_LIST attribute is deleted now when no
dimension scales left attached.
(EIP - 2010/05/14 -1822)
- Fixed a bug where the H5TB API would forget the order of fields when
added out of offset order. (NAF - 2009/10/27 - 1582)
- H5DSis_attached failed to account for different platform types. Added a