Compare commits
1 Commits
inactive/p
...
inactive/h
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
378717659a |
198
src/H5Dchunk.c
198
src/H5Dchunk.c
@@ -186,6 +186,9 @@ static herr_t H5D_chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *typ
|
||||
H5D_chunk_map_t *fm);
|
||||
static herr_t H5D_chunk_flush(H5D_t *dset, hid_t dxpl_id);
|
||||
static herr_t H5D_chunk_io_term(const H5D_chunk_map_t *fm);
|
||||
static htri_t H5D_chunk_compare(const H5F_t *f1, const H5F_t *f2,
|
||||
const H5O_layout_t *layout1, const H5O_layout_t *layout2, hid_t dxpl1_id,
|
||||
hid_t dxpl2_id, H5D_cmp_ud_t *udata);
|
||||
|
||||
/* "Nonexistent" layout operation callback */
|
||||
static ssize_t
|
||||
@@ -237,7 +240,8 @@ const H5D_layout_ops_t H5D_LOPS_CHUNK[1] = {{
|
||||
NULL,
|
||||
NULL,
|
||||
H5D_chunk_flush,
|
||||
H5D_chunk_io_term
|
||||
H5D_chunk_io_term,
|
||||
H5D_chunk_compare
|
||||
}};
|
||||
|
||||
|
||||
@@ -260,6 +264,7 @@ const H5D_layout_ops_t H5D_LOPS_NONEXISTENT[1] = {{
|
||||
H5D_nonexistent_readvv,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
}};
|
||||
|
||||
@@ -5045,3 +5050,194 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* H5D_nonexistent_readvv() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5D_chunk_compare
|
||||
*
|
||||
* Purpose: fnord
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Neil Fortner
|
||||
* Friday, December 3, 2010
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static htri_t
|
||||
H5D_chunk_compare(const H5F_t *f1, const H5F_t *f2,
|
||||
const H5O_layout_t *layout1, const H5O_layout_t *layout2, hid_t dxpl1_id,
|
||||
hid_t dxpl2_id, H5D_cmp_ud_t *udata)
|
||||
{
|
||||
void *buf1 = NULL;
|
||||
void *buf2 = NULL;
|
||||
size_t buf_size = 0;
|
||||
H5D_chk_idx_info_t idx_info1; /* Chunked index info */
|
||||
H5D_chk_idx_info_t idx_info2; /* Chunked index info */
|
||||
hbool_t idx_info1_init = FALSE;
|
||||
hbool_t idx_info2_init = FALSE;
|
||||
H5D_chunk_ud_t chk_udata1;
|
||||
H5D_chunk_ud_t chk_udata2;
|
||||
int space_ndims; /* Dataset's space rank */
|
||||
hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Current dataspace dimensions */
|
||||
hsize_t chunk_offset[H5O_LAYOUT_NDIMS]; /* Offset of current chunk */
|
||||
hbool_t carry = FALSE; /* Flag to indicate that chunk increment carries to higher dimension (sorta) */
|
||||
int i;
|
||||
htri_t ret_value = FALSE; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(H5D_chunk_compare, FAIL)
|
||||
|
||||
/* Sanity check */
|
||||
HDassert(f1);
|
||||
HDassert(f2);
|
||||
HDassert(layout1);
|
||||
HDassert(layout2);
|
||||
HDassert(udata);
|
||||
|
||||
if(H5F_addr_defined(layout1->storage.u.chunk.idx_addr)) {
|
||||
if(H5F_addr_defined(layout2->storage.u.chunk.idx_addr)) {
|
||||
/* Both have space allocated. Read both datasets into memory and
|
||||
* compare, chunk by chunk. */
|
||||
/* Go get the rank & dimensions */
|
||||
if((space_ndims = H5S_get_simple_extent_dims(udata->space,
|
||||
space_dim, NULL)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
|
||||
|
||||
/* Create index info structs */
|
||||
idx_info1.f = f1;
|
||||
idx_info1.dxpl_id = dxpl1_id;
|
||||
idx_info1.pline = udata->pline1;
|
||||
idx_info1.layout = &layout1->u.chunk;
|
||||
idx_info1.storage = &layout1->storage.u.chunk;
|
||||
if((layout1->storage.u.chunk.ops->init)(&idx_info1, udata->space,
|
||||
udata->addr1) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't init index info")
|
||||
idx_info1_init = TRUE;
|
||||
|
||||
idx_info2.f = f2;
|
||||
idx_info2.dxpl_id = dxpl2_id;
|
||||
idx_info2.pline = udata->pline2;
|
||||
idx_info2.layout = &layout2->u.chunk;
|
||||
idx_info2.storage = &(layout2->storage.u.chunk);
|
||||
if((layout2->storage.u.chunk.ops->init)(&idx_info2, udata->space,
|
||||
udata->addr2) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't init index info")
|
||||
idx_info2_init = TRUE;
|
||||
|
||||
/* Initialize chunk udatas */
|
||||
chk_udata1.common.layout = &(layout1->u.chunk);
|
||||
chk_udata1.common.storage = &(layout1->storage.u.chunk);
|
||||
chk_udata1.common.offset = chunk_offset;
|
||||
chk_udata1.common.rdcc = NULL;
|
||||
chk_udata1.idx_hint = UINT_MAX;
|
||||
|
||||
chk_udata2.common.layout = &(layout2->u.chunk);
|
||||
chk_udata2.common.storage = &(layout2->storage.u.chunk);
|
||||
chk_udata2.common.offset = chunk_offset;
|
||||
chk_udata2.common.rdcc = NULL;
|
||||
chk_udata2.idx_hint = UINT_MAX;
|
||||
|
||||
/* Loop over all chunks logically according to offset */
|
||||
HDmemset(chunk_offset, 0, sizeof(chunk_offset));
|
||||
while(!carry) {
|
||||
/* Lookup chunk 1 */
|
||||
chk_udata1.nbytes = 0;
|
||||
chk_udata1.filter_mask = 0;
|
||||
chk_udata1.addr = HADDR_UNDEF;
|
||||
if((layout1->storage.u.chunk.ops->get_addr)(&idx_info1,
|
||||
&chk_udata1) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query chunk address")
|
||||
|
||||
/* Lookup chunk 2 */
|
||||
chk_udata2.nbytes = 0;
|
||||
chk_udata2.filter_mask = 0;
|
||||
chk_udata2.addr = HADDR_UNDEF;
|
||||
if((layout2->storage.u.chunk.ops->get_addr)(&idx_info2,
|
||||
&chk_udata2) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't query chunk address")
|
||||
|
||||
if(H5F_addr_defined(chk_udata1.addr)) {
|
||||
if(H5F_addr_defined(chk_udata2.addr)) {
|
||||
/* Both chunks exist, read from disk and compare */
|
||||
/* Check that the sizes are identical */
|
||||
if(chk_udata1.nbytes != chk_udata2.nbytes)
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
/* Allocate new buffer, if necessary */
|
||||
if(chk_udata1.nbytes > buf_size) {
|
||||
buf_size = chk_udata1.nbytes;
|
||||
if(NULL == (buf1 = H5MM_realloc(buf1, buf_size)))
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate memory")
|
||||
if(NULL == (buf2 = H5MM_realloc(buf2, buf_size)))
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate memory")
|
||||
} /* end if */
|
||||
|
||||
/* Read chunks */
|
||||
if(H5F_block_read(f1, H5FD_MEM_DRAW, chk_udata1.addr,
|
||||
chk_udata1.nbytes, dxpl1_id, buf1) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
|
||||
if(H5F_block_read(f2, H5FD_MEM_DRAW, chk_udata2.addr,
|
||||
chk_udata1.nbytes, dxpl2_id, buf2) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
|
||||
|
||||
/* Compare */
|
||||
if(HDmemcmp(buf1, buf2, chk_udata1.nbytes))
|
||||
HGOTO_DONE(TRUE)
|
||||
} /* end if */
|
||||
else
|
||||
/* One chunk exists and the other doesn't. Assume they
|
||||
* are different. Eventually should check data in 1
|
||||
* against fill value in 2. */
|
||||
HGOTO_DONE(TRUE)
|
||||
} /* end if */
|
||||
else
|
||||
if(H5F_addr_defined(chk_udata2.addr))
|
||||
/* One chunk exists and the other doesn't. Assume they
|
||||
* are different. Eventually should check data in 2
|
||||
* against fill value in 1. */
|
||||
HGOTO_DONE(TRUE)
|
||||
else
|
||||
/* Neither chunk exists. If their fill values are not
|
||||
* identical, they are different. */
|
||||
if(!udata->fill_identical)
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
/* Increment indices */
|
||||
carry = TRUE;
|
||||
for(i = space_ndims - 1; i >= 0; --i) {
|
||||
chunk_offset[i] += layout1->u.chunk.dim[i];
|
||||
if(chunk_offset[i] >= space_dim[i])
|
||||
chunk_offset[i] = 0;
|
||||
else {
|
||||
carry = FALSE;
|
||||
break;
|
||||
} /* end else */
|
||||
} /* end for */
|
||||
} /* end while */
|
||||
} /* end if */
|
||||
else
|
||||
/* One has space allocated and the other doesn't. Assume they are
|
||||
* different. Eventually should check data in 1 against fill value
|
||||
* in 2. */
|
||||
HGOTO_DONE(TRUE)
|
||||
} /* end if */
|
||||
else
|
||||
if(H5F_addr_defined(layout2->storage.u.chunk.idx_addr))
|
||||
/* One has space allocated and the other doesn't. Assume they are
|
||||
* different. Eventually should check data in 2 against fill value
|
||||
* in 1. */
|
||||
HGOTO_DONE(TRUE)
|
||||
else
|
||||
/* Neither has space allocated. If their fill values are not
|
||||
* identical, they are different. */
|
||||
if(!udata->fill_identical)
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
done:
|
||||
if(idx_info1_init && (layout1->storage.u.chunk.ops->dest)(&idx_info1) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't destroy index info")
|
||||
if(idx_info2_init && (layout2->storage.u.chunk.ops->dest)(&idx_info2) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't destroy index info")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5D_chunk_compare() */
|
||||
|
||||
|
||||
@@ -70,6 +70,9 @@ static ssize_t H5D_compact_writevv(const H5D_io_info_t *io_info,
|
||||
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_size_arr[], hsize_t dset_offset_arr[],
|
||||
size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_size_arr[], hsize_t mem_offset_arr[]);
|
||||
static herr_t H5D_compact_flush(H5D_t *dset, hid_t dxpl_id);
|
||||
static htri_t H5D_compact_compare(const H5F_t *f1, const H5F_t *f2,
|
||||
const H5O_layout_t *layout1, const H5O_layout_t *layout2, hid_t dxpl1_id,
|
||||
hid_t dxpl2_id, H5D_cmp_ud_t *udata);
|
||||
|
||||
|
||||
/*********************/
|
||||
@@ -91,7 +94,8 @@ const H5D_layout_ops_t H5D_LOPS_COMPACT[1] = {{
|
||||
H5D_compact_readvv,
|
||||
H5D_compact_writevv,
|
||||
H5D_compact_flush,
|
||||
NULL
|
||||
NULL,
|
||||
H5D_compact_compare
|
||||
}};
|
||||
|
||||
|
||||
@@ -576,3 +580,44 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5D_compact_copy() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5D_compact_compare
|
||||
*
|
||||
* Purpose: fnord
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Neil Fortner
|
||||
* Tuesday, November 30, 2010
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static htri_t
|
||||
H5D_compact_compare(const H5F_t UNUSED *f1, const H5F_t UNUSED *f2,
|
||||
const H5O_layout_t *layout1, const H5O_layout_t *layout2,
|
||||
hid_t UNUSED dxpl1_id, hid_t UNUSED dxpl2_id, H5D_cmp_ud_t UNUSED *udata)
|
||||
{
|
||||
htri_t ret_value = FALSE; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI_NOFUNC(H5D_compact_compare)
|
||||
|
||||
/* Sanity check */
|
||||
HDassert(f1);
|
||||
HDassert(f2);
|
||||
HDassert(layout1);
|
||||
HDassert(layout2);
|
||||
HDassert(layout1->storage.u.compact.buf);
|
||||
HDassert(layout2->storage.u.compact.buf);
|
||||
HDassert(layout1->storage.u.compact.size
|
||||
== layout2->storage.u.compact.size);
|
||||
|
||||
/* Compare the two datasets */
|
||||
if(HDmemcmp(layout1->storage.u.compact.buf, layout2->storage.u.compact.buf,
|
||||
layout1->storage.u.compact.size))
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5D_compact_compare() */
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "H5FLprivate.h" /* Free Lists */
|
||||
#include "H5Iprivate.h" /* IDs */
|
||||
#include "H5MFprivate.h" /* File memory management */
|
||||
#include "H5MMprivate.h" /* Memory management */
|
||||
#include "H5Oprivate.h" /* Object headers */
|
||||
#include "H5Pprivate.h" /* Property lists */
|
||||
#include "H5Vprivate.h" /* Vector and array functions */
|
||||
@@ -106,6 +107,9 @@ static ssize_t H5D_contig_writevv(const H5D_io_info_t *io_info,
|
||||
size_t dset_max_nseq, size_t *dset_curr_seq, size_t dset_len_arr[], hsize_t dset_offset_arr[],
|
||||
size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
|
||||
static herr_t H5D_contig_flush(H5D_t *dset, hid_t dxpl_id);
|
||||
static htri_t H5D_contig_compare(const H5F_t *f1, const H5F_t *f2,
|
||||
const H5O_layout_t *layout1, const H5O_layout_t *layout2, hid_t dxpl1_id,
|
||||
hid_t dxpl2_id, H5D_cmp_ud_t *udata);
|
||||
|
||||
/* Helper routines */
|
||||
static herr_t H5D_contig_write_one(H5D_io_info_t *io_info, hsize_t offset,
|
||||
@@ -131,7 +135,8 @@ const H5D_layout_ops_t H5D_LOPS_CONTIG[1] = {{
|
||||
H5D_contig_readvv,
|
||||
H5D_contig_writevv,
|
||||
H5D_contig_flush,
|
||||
NULL
|
||||
NULL,
|
||||
H5D_contig_compare
|
||||
}};
|
||||
|
||||
|
||||
@@ -1525,3 +1530,81 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5D_contig_copy() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5D_contig_compare
|
||||
*
|
||||
* Purpose: fnord
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Neil Fortner
|
||||
* Tuesday, November 30, 2010
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static htri_t
|
||||
H5D_contig_compare(const H5F_t *f1, const H5F_t *f2,
|
||||
const H5O_layout_t *layout1, const H5O_layout_t *layout2, hid_t dxpl1_id,
|
||||
hid_t dxpl2_id, H5D_cmp_ud_t *udata)
|
||||
{
|
||||
void *buf1 = NULL;
|
||||
void *buf2 = NULL;
|
||||
htri_t ret_value = FALSE; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(H5D_contig_compare, FAIL)
|
||||
|
||||
/* Sanity check */
|
||||
HDassert(f1);
|
||||
HDassert(f2);
|
||||
HDassert(layout1);
|
||||
HDassert(layout2);
|
||||
HDassert(udata);
|
||||
|
||||
if(H5F_addr_defined(layout1->storage.u.contig.addr)) {
|
||||
if(H5F_addr_defined(layout2->storage.u.contig.addr)) {
|
||||
/* Both have space allocated. Read both datasets into memory and
|
||||
* compare. Will eventually want to use a buffer with a
|
||||
* user-configurable size so we don't alloc something too big. */
|
||||
HDassert(layout1->storage.u.contig.size
|
||||
== layout2->storage.u.contig.size);
|
||||
if(NULL == (buf1 = H5MM_malloc(layout1->storage.u.contig.size)))
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate memory")
|
||||
if(NULL == (buf2 = H5MM_malloc(layout1->storage.u.contig.size)))
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate memory")
|
||||
|
||||
if(H5F_block_read(f1, H5FD_MEM_DRAW, layout1->storage.u.contig.addr,
|
||||
layout1->storage.u.contig.size, dxpl1_id, buf1) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
|
||||
if(H5F_block_read(f2, H5FD_MEM_DRAW, layout2->storage.u.contig.addr,
|
||||
layout1->storage.u.contig.size, dxpl2_id, buf2) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "block read failed")
|
||||
|
||||
if(HDmemcmp(buf1, buf2, layout1->storage.u.contig.size))
|
||||
HGOTO_DONE(TRUE)
|
||||
} /* end if */
|
||||
else
|
||||
/* One has space allocated and the other doesn't. Assume they are
|
||||
* different. Eventually should check data in 1 against fill value
|
||||
* in 2. */
|
||||
HGOTO_DONE(TRUE)
|
||||
} /* end if */
|
||||
else
|
||||
if(H5F_addr_defined(layout2->storage.u.contig.addr))
|
||||
/* One has space allocated and the other doesn't. Assume they are
|
||||
* different. Eventually should check data in 2 against fill value
|
||||
* in 1. */
|
||||
HGOTO_DONE(TRUE)
|
||||
else
|
||||
/* Neither has space allocated. If their fill values are not
|
||||
* identical, they are different. */
|
||||
if(!udata->fill_identical)
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
done:
|
||||
buf1 = H5MM_xfree(buf1);
|
||||
buf2 = H5MM_xfree(buf2);
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5D_contig_compare() */
|
||||
|
||||
|
||||
303
src/H5Doh.c
303
src/H5Doh.c
@@ -55,6 +55,9 @@ static void *H5O_dset_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc,
|
||||
static H5O_loc_t *H5O_dset_get_oloc(hid_t obj_id);
|
||||
static herr_t H5O_dset_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
|
||||
H5_ih_info_t *bh_info);
|
||||
static htri_t H5O_dset_compare(const H5F_t *f1, const H5F_t *f2,
|
||||
const H5O_t *oh1, const H5O_t *oh2, haddr_t addr1, haddr_t addr2,
|
||||
hid_t dxpl1_id, hid_t dxpl2_id, H5O_cmp_t *cmp_info);
|
||||
|
||||
|
||||
/*********************/
|
||||
@@ -81,7 +84,8 @@ const H5O_obj_class_t H5O_OBJ_DATASET[1] = {{
|
||||
H5O_dset_open, /* open an object of this class */
|
||||
H5O_dset_create, /* create an object of this class */
|
||||
H5O_dset_get_oloc, /* get an object header location for an object */
|
||||
H5O_dset_bh_info /* get the index & heap info for an object */
|
||||
H5O_dset_bh_info, /* get the index & heap info for an object */
|
||||
H5O_dset_compare /* compare two datasets */
|
||||
}};
|
||||
|
||||
/* Declare a free list to manage the H5D_copy_file_ud_t struct */
|
||||
@@ -431,3 +435,300 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_dset_bh_info() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_dset_compare
|
||||
*
|
||||
* Purpose: fnord
|
||||
*
|
||||
* Return: Success: 0 (equal) or 1 (not equal)
|
||||
* Failure: negative
|
||||
*
|
||||
* Programmer: Neil Fortner
|
||||
* October 27, 2010
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static htri_t
|
||||
H5O_dset_compare(const H5F_t *f1, const H5F_t *f2, const H5O_t *oh1,
|
||||
const H5O_t *oh2, haddr_t addr1, haddr_t addr2, hid_t dxpl1_id,
|
||||
hid_t dxpl2_id, H5O_cmp_t UNUSED *cmp_info)
|
||||
{
|
||||
H5S_t *space1; /* Dataspace message */
|
||||
H5S_t *space2; /* Dataspace message */
|
||||
H5O_layout_t layout1; /* Data storage layout message */
|
||||
H5O_layout_t layout2; /* Data storage layout message */
|
||||
H5O_pline_t pline1 = H5O_CRT_PIPELINE_DEF; /* I/O pipeline message */
|
||||
H5O_pline_t pline2 = H5O_CRT_PIPELINE_DEF; /* I/O pipeline message */
|
||||
H5T_t *dtype1; /* Datatype message */
|
||||
H5T_t *dtype2; /* Datatype message */
|
||||
H5O_fill_t fill1; /* Fill value message */
|
||||
H5O_fill_t fill2; /* Fill value message */
|
||||
hbool_t space_read = FALSE; /* Whether the dataspace messages were read */
|
||||
hbool_t layout_read = FALSE; /* Whether the layout messages were read */
|
||||
hbool_t pline_read = FALSE; /* Whether the I/O pipeline messages were read */
|
||||
hbool_t dtype_read = FALSE; /* Whether the datatype messages were read */
|
||||
hbool_t fill1_read = FALSE; /* Whether the fill value message was read */
|
||||
hbool_t fill2_read = FALSE; /* Whether the fill value message was read */
|
||||
int ndims1;
|
||||
int ndims2;
|
||||
hsize_t dims1[H5O_LAYOUT_NDIMS];
|
||||
hsize_t dims2[H5O_LAYOUT_NDIMS];
|
||||
H5D_cmp_ud_t udata;
|
||||
htri_t tri_ret; /* htri_t return value */
|
||||
unsigned i;
|
||||
htri_t ret_value; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(H5O_dset_compare, FAIL)
|
||||
|
||||
/* Sanity check */
|
||||
HDassert(f1);
|
||||
HDassert(f2);
|
||||
HDassert(oh1);
|
||||
HDassert(oh2);
|
||||
|
||||
/* Save the dset oh addresses in udata */
|
||||
udata.addr1 = addr1;
|
||||
udata.addr2 = addr2;
|
||||
|
||||
/* Get the dataspace messages */
|
||||
if(NULL == (space1 = H5S_read_oh(f1, oh1, dxpl1_id)))
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't read dataspace message")
|
||||
if(NULL == (space2 = H5S_read_oh(f2, oh2, dxpl2_id))) {
|
||||
if(H5S_close(space1) < 0)
|
||||
HERROR(H5E_DATASET, H5E_CANTFREE, "can't close dataspace");
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't read dataspace message")
|
||||
} /* end if */
|
||||
space_read = TRUE;
|
||||
|
||||
/* Check if the dataspace extents are identical */
|
||||
if((ndims1 = H5S_get_simple_extent_dims(space1, dims1, NULL)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataspace dimensions")
|
||||
if((ndims2 = H5S_get_simple_extent_dims(space2, dims2, NULL)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataspace dimensions")
|
||||
if(ndims1 != ndims2 || HDmemcmp(dims1, dims2, (size_t)ndims1 * sizeof(dims1[0])))
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
/* Save the dataspace in udata */
|
||||
udata.space = space1;
|
||||
|
||||
/* Get the layout messages */
|
||||
if(NULL == H5O_msg_read_oh(f1, dxpl1_id, oh1, H5O_LAYOUT_ID, &layout1))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't find layout message")
|
||||
if(NULL == H5O_msg_read_oh(f2, dxpl2_id, oh2, H5O_LAYOUT_ID, &layout2)) {
|
||||
if(H5O_msg_reset(H5O_LAYOUT_ID, &layout1) < 0)
|
||||
HERROR(H5E_DATASET, H5E_CANTRESET, "unable to reset data storage layout message");
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't find layout message")
|
||||
} /* end if */
|
||||
layout_read = TRUE;
|
||||
|
||||
/* Check if the layout messages are identical */
|
||||
/* Will eventually want to check if they are compatible, even if not
|
||||
* identical -NAF */
|
||||
/*FIXME fnord Note we do not handle external datasets! */
|
||||
if(layout1.type != layout2.type)
|
||||
HGOTO_DONE(TRUE)
|
||||
else if(layout1.type == H5D_CHUNKED) {
|
||||
if(layout1.u.chunk.ndims != layout2.u.chunk.ndims ||
|
||||
HDmemcmp(layout1.u.chunk.dim, layout2.u.chunk.dim,
|
||||
layout1.u.chunk.ndims * sizeof(layout1.u.chunk.dim[0])))
|
||||
HGOTO_DONE(TRUE)
|
||||
HDassert(layout1.u.chunk.size == layout2.u.chunk.size);
|
||||
HDassert(layout1.u.chunk.nchunks == layout2.u.chunk.nchunks);
|
||||
HDassert(!HDmemcmp(layout1.u.chunk.chunks, layout2.u.chunk.chunks,
|
||||
layout1.u.chunk.ndims * sizeof(layout1.u.chunk.dim[0])));
|
||||
HDassert(!HDmemcmp(layout1.u.chunk.down_chunks,
|
||||
layout2.u.chunk.down_chunks, layout1.u.chunk.ndims
|
||||
* sizeof(layout1.u.chunk.dim[0])));
|
||||
} /* end if */
|
||||
|
||||
/* Get the pipeline messages */
|
||||
if((tri_ret = H5O_msg_exists_oh(oh1, H5O_PLINE_ID)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
|
||||
if(tri_ret) {
|
||||
/* Make sure both objects have a pipeline - mix/match not supported yet
|
||||
*/
|
||||
if((tri_ret = H5O_msg_exists_oh(oh2 , H5O_PLINE_ID)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
|
||||
if(!tri_ret)
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
if(NULL == H5O_msg_read_oh(f1, dxpl1_id, oh1, H5O_PLINE_ID, &pline1))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't find pipeline message")
|
||||
if(NULL == H5O_msg_read_oh(f2, dxpl2_id, oh2, H5O_PLINE_ID, &pline2)) {
|
||||
if(H5O_msg_reset(H5O_PLINE_ID, &pline1) < 0)
|
||||
HERROR(H5E_DATASET, H5E_CANTRESET, "unable to reset pipeline message");
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't find pipeline message")
|
||||
} /* end if */
|
||||
pline_read = TRUE;
|
||||
|
||||
/* Check if the pipeline messages are identical */
|
||||
/* Will eventually want to handle different pipelines */
|
||||
if(pline1.nused != pline2.nused)
|
||||
HGOTO_DONE(TRUE)
|
||||
else
|
||||
for(i=0; i<pline1.nused; i++)
|
||||
if(pline1.filter[i].id != pline2.filter[i].id
|
||||
|| pline1.filter[i].cd_nelmts != pline2.filter[i].cd_nelmts
|
||||
|| HDmemcmp(pline1.filter[i].cd_values,
|
||||
pline2.filter[i].cd_values, pline1.filter[i].cd_nelmts
|
||||
* sizeof(pline1.filter[i].cd_values[0])))
|
||||
HGOTO_DONE(TRUE)
|
||||
} /* end if */
|
||||
else {
|
||||
/* Make sure object 2 doesn't have a pipeline */
|
||||
if((tri_ret = H5O_msg_exists_oh(oh2 , H5O_PLINE_ID)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
|
||||
if(tri_ret)
|
||||
HGOTO_DONE(TRUE)
|
||||
} /* end else */
|
||||
|
||||
/* Save the plines in udata */
|
||||
udata.pline1 = &pline1;
|
||||
udata.pline2 = &pline2;
|
||||
|
||||
/* Get the datatype messages */
|
||||
if(NULL == (dtype1 = (H5T_t *)H5O_msg_read_oh(f1, dxpl1_id, oh1,
|
||||
H5O_DTYPE_ID, NULL)))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't find datatype message")
|
||||
if(NULL == (dtype2 = (H5T_t *)H5O_msg_read_oh(f2, dxpl2_id, oh2,
|
||||
H5O_DTYPE_ID, NULL)))
|
||||
{
|
||||
(void)H5O_msg_free(H5O_DTYPE_ID, dtype1);
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't find datatype message")
|
||||
} /* end if */
|
||||
dtype_read = TRUE;
|
||||
|
||||
/* Check if the datatypes are identical */
|
||||
if(H5T_cmp(dtype1, dtype2, FALSE))
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
/* Check for vlen or reference types - not supported currently */
|
||||
if(H5T_detect_class(dtype1, H5T_VLEN, FALSE))
|
||||
HGOTO_DONE(TRUE)
|
||||
if(H5T_detect_class(dtype1, H5T_REFERENCE, FALSE))
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
/* Get the fill value messages */
|
||||
if((tri_ret = H5O_msg_exists_oh(oh1, H5O_FILL_NEW_ID)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
|
||||
if(tri_ret) {
|
||||
if(NULL == H5O_msg_read_oh(f1, dxpl1_id, oh1, H5O_FILL_NEW_ID, &fill1))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read fill message")
|
||||
fill1_read = TRUE;
|
||||
} /* end if */
|
||||
else {
|
||||
if((tri_ret = H5O_msg_exists_oh(oh1, H5O_FILL_ID)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
|
||||
if(tri_ret) {
|
||||
if(NULL == H5O_msg_read_oh(f1, dxpl1_id, oh1, H5O_FILL_ID, &fill1))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read fill message")
|
||||
fill1_read = TRUE;
|
||||
} else {
|
||||
fill1.fill_time = H5D_FILL_TIME_NEVER;
|
||||
fill1.fill_defined = FALSE;
|
||||
} /* end else */
|
||||
} /* end else */
|
||||
if((tri_ret = H5O_msg_exists_oh(oh2, H5O_FILL_NEW_ID)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
|
||||
if(tri_ret) {
|
||||
if(NULL == H5O_msg_read_oh(f2, dxpl2_id, oh2, H5O_FILL_NEW_ID, &fill2))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read fill message")
|
||||
fill2_read = TRUE;
|
||||
} /* end if */
|
||||
else {
|
||||
if((tri_ret = H5O_msg_exists_oh(oh2, H5O_FILL_ID)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
|
||||
if(tri_ret) {
|
||||
if(NULL == H5O_msg_read_oh(f2, dxpl2_id, oh2, H5O_FILL_ID, &fill2))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't read fill message")
|
||||
fill2_read = TRUE;
|
||||
} else {
|
||||
fill2.fill_time = H5D_FILL_TIME_NEVER;
|
||||
fill2.fill_defined = FALSE;
|
||||
} /* end else */
|
||||
} /* end else */
|
||||
|
||||
/* Check if fill values are identical */
|
||||
if(fill1.fill_defined && (fill1.fill_time == H5D_FILL_TIME_IFSET
|
||||
|| fill1.fill_time == H5D_FILL_TIME_ALLOC)) {
|
||||
if(fill2.fill_defined && (fill2.fill_time == H5D_FILL_TIME_IFSET
|
||||
|| fill2.fill_time == H5D_FILL_TIME_ALLOC)) {
|
||||
/* Both fill values are defined */
|
||||
HDassert(fill1.size == fill2.size);
|
||||
if(HDmemcmp(fill1.buf, fill2.buf, (size_t)fill1.size))
|
||||
udata.fill_identical = FALSE;
|
||||
else
|
||||
udata.fill_identical = TRUE;
|
||||
} /* end if */
|
||||
else {
|
||||
/* fill1 is defined but fill2 isn't */
|
||||
/* Check for a non-zero character in fill1 (is there an ISO C
|
||||
* function that does this?) */
|
||||
udata.fill_identical = TRUE;
|
||||
for(i=0; i<fill1.size; i++)
|
||||
if(((uint8_t *)fill1.buf)[i] != (uint8_t)0) {
|
||||
udata.fill_identical = FALSE;
|
||||
break;
|
||||
} /* end if */
|
||||
} /* end else */
|
||||
} /* end if */
|
||||
else {
|
||||
if(fill2.fill_defined && (fill2.fill_time == H5D_FILL_TIME_IFSET
|
||||
|| fill2.fill_time == H5D_FILL_TIME_ALLOC)) {
|
||||
/* fill2 is defined but fill1 isn't */
|
||||
/* Check for a non-zero character in fill2 (is there an ISO C
|
||||
* function that does this?) */
|
||||
udata.fill_identical = TRUE;
|
||||
for(i=0; i<fill2.size; i++)
|
||||
if(((uint8_t *)fill2.buf)[i] != (uint8_t)0) {
|
||||
udata.fill_identical = FALSE;
|
||||
break;
|
||||
} /* end if */
|
||||
} /* end if */
|
||||
else
|
||||
/* Both fill1 and fill2 are undefined */
|
||||
udata.fill_identical = TRUE;
|
||||
} /* end else */
|
||||
|
||||
/* Perform the comparison */
|
||||
HDassert(layout1.ops->compare);
|
||||
if((ret_value = layout1.ops->compare(f1, f2, &layout1, &layout2, dxpl1_id,
|
||||
dxpl2_id, &udata)) < 0)
|
||||
HGOTO_ERROR(H5E_DATASET, H5E_CANTCOMPARE, FAIL, "unable to compare datasets")
|
||||
|
||||
done:
|
||||
/* Free messages, if they've been read in */
|
||||
if(space_read) {
|
||||
if(H5S_close(space1) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't close dataspace")
|
||||
if(H5S_close(space2) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "can't close dataspace")
|
||||
} /* end if */
|
||||
if(layout_read) {
|
||||
if(H5O_msg_reset(H5O_LAYOUT_ID, &layout1) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset data storage layout message")
|
||||
if(H5O_msg_reset(H5O_LAYOUT_ID, &layout2) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset data storage layout message")
|
||||
} /* end if */
|
||||
if(pline_read) {
|
||||
if(H5O_msg_reset(H5O_PLINE_ID, &pline1) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset I/O pipeline message")
|
||||
if(H5O_msg_reset(H5O_PLINE_ID, &pline2) < 0)
|
||||
HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset I/O pipeline message")
|
||||
} /* end if */
|
||||
if(dtype_read) {
|
||||
(void)H5O_msg_free(H5O_DTYPE_ID, dtype1);
|
||||
(void)H5O_msg_free(H5O_DTYPE_ID, dtype2);
|
||||
} /* end if */
|
||||
/* Note that we take advantage of the fact that both versions of the fill
|
||||
* message use the same reset routine. If this changes, we will have to
|
||||
* change this to pass the correct message ID. */
|
||||
if(fill1_read)
|
||||
(void)H5O_msg_reset(H5O_FILL_NEW_ID, &fill1);
|
||||
if(fill2_read)
|
||||
(void)H5O_msg_reset(H5O_FILL_NEW_ID, &fill2);
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_dset_compare() */
|
||||
|
||||
|
||||
14
src/H5Dpkg.h
14
src/H5Dpkg.h
@@ -94,6 +94,16 @@ typedef struct H5D_type_info_t {
|
||||
hbool_t bkg_buf_allocated; /* Whether the background buffer was allocated */
|
||||
} H5D_type_info_t;
|
||||
|
||||
/* Typedef for udata struct shared between functions when comparing datasets */
|
||||
typedef struct H5D_cmp_ud_t {
|
||||
hbool_t fill_identical; /* Whether the fill values are identical */
|
||||
const H5O_pline_t *pline1; /* Pipeline for dataset "1" */
|
||||
const H5O_pline_t *pline2; /* Pipeline for dataset "2" */
|
||||
H5S_t *space; /* Dataspace (must be the same for datasets 1 and 2) */
|
||||
haddr_t addr1; /* Address for dataset 1 */
|
||||
haddr_t addr2; /* Address for dataset 2 */
|
||||
} H5D_cmp_ud_t;
|
||||
|
||||
/* Forward declaration of structs used below */
|
||||
struct H5D_io_info_t;
|
||||
struct H5D_chunk_map_t;
|
||||
@@ -121,6 +131,9 @@ typedef ssize_t (*H5D_layout_writevv_func_t)(const struct H5D_io_info_t *io_info
|
||||
size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]);
|
||||
typedef herr_t (*H5D_layout_flush_func_t)(H5D_t *dataset, hid_t dxpl_id);
|
||||
typedef herr_t (*H5D_layout_io_term_func_t)(const struct H5D_chunk_map_t *cm);
|
||||
typedef htri_t (*H5D_layout_compare_func_t)(const H5F_t *f1, const H5F_t *f2,
|
||||
const H5O_layout_t *layout1, const H5O_layout_t *layout2,
|
||||
hid_t dxpl1_id, hid_t dxpl2_id, H5D_cmp_ud_t *udata);
|
||||
|
||||
/* Typedef for grouping layout I/O routines */
|
||||
typedef struct H5D_layout_ops_t {
|
||||
@@ -138,6 +151,7 @@ typedef struct H5D_layout_ops_t {
|
||||
H5D_layout_writevv_func_t writevv; /* Low-level I/O routine for writing data */
|
||||
H5D_layout_flush_func_t flush; /* Low-level I/O routine for flushing raw data */
|
||||
H5D_layout_io_term_func_t io_term; /* I/O shutdown routine */
|
||||
H5D_layout_compare_func_t compare; /* Data comparison routine */
|
||||
} H5D_layout_ops_t;
|
||||
|
||||
/* Function pointers for either multiple or single block I/O access */
|
||||
|
||||
749
src/H5Ocompare.c
Normal file
749
src/H5Ocompare.c
Normal file
@@ -0,0 +1,749 @@
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Copyright by The HDF Group. *
|
||||
* Copyright by the Board of Trustees of the University of Illinois. *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This file is part of HDF5. The full HDF5 copyright notice, including *
|
||||
* terms governing use, modification, and redistribution, is contained in *
|
||||
* the files COPYING and Copyright.html. COPYING can be found at the root *
|
||||
* of the source code distribution tree; Copyright.html can be found at the *
|
||||
* root level of an installed copy of the electronic HDF5 document set and *
|
||||
* is linked from the top-level documents page. It can also be found at *
|
||||
* http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
|
||||
* access to either file, you may request a copy from help@hdfgroup.org. *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* Created: H5Ocompare.c
|
||||
* Oct 12 2010
|
||||
* Neil Fortner <nfortne2@hdfgroup.org>
|
||||
*
|
||||
* Purpose: Object comparison routines.
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/****************/
|
||||
/* Module Setup */
|
||||
/****************/
|
||||
|
||||
#define H5O_PACKAGE /*suppress error about including H5Opkg */
|
||||
|
||||
/***********/
|
||||
/* Headers */
|
||||
/***********/
|
||||
#include "H5private.h" /* Generic Functions */
|
||||
#include "H5Eprivate.h" /* Error handling */
|
||||
#include "H5Iprivate.h" /* IDs */
|
||||
#include "H5MMprivate.h" /* Memory management */
|
||||
#include "H5Opkg.h" /* Object headers */
|
||||
#include "H5Pprivate.h" /* Property lists */
|
||||
|
||||
|
||||
/****************/
|
||||
/* Local Macros */
|
||||
/****************/
|
||||
|
||||
|
||||
/******************/
|
||||
/* Local Typedefs */
|
||||
/******************/
|
||||
|
||||
|
||||
/********************/
|
||||
/* Package Typedefs */
|
||||
/********************/
|
||||
|
||||
|
||||
/********************/
|
||||
/* Local Prototypes */
|
||||
/********************/
|
||||
|
||||
static herr_t H5O_compare_obj(const H5O_loc_t *oloc1, const H5O_loc_t *oloc2,
|
||||
hid_t ocmppl_id);
|
||||
|
||||
/*********************/
|
||||
/* Package Variables */
|
||||
/*********************/
|
||||
|
||||
|
||||
/*****************************/
|
||||
/* Library Private Variables */
|
||||
/*****************************/
|
||||
|
||||
|
||||
/*******************/
|
||||
/* Local Variables */
|
||||
/*******************/
|
||||
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5Ocompare
|
||||
*
|
||||
* Purpose: fnord
|
||||
*
|
||||
* Usage: fnord
|
||||
*
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Neil Fortner
|
||||
* October 12, 2010
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
htri_t
|
||||
H5Ocompare(hid_t loc1_id, const char *name1, hid_t loc2_id, const char *name2,
|
||||
hid_t ocmppl_id)
|
||||
{
|
||||
H5G_loc_t base_loc1; /* Base location for object 1 */
|
||||
H5G_loc_t base_loc2; /* Base location for object 2 */
|
||||
H5G_loc_t loc1; /* Object location for object 1 */
|
||||
H5G_loc_t loc2; /* Object location for object 2 */
|
||||
|
||||
/* for opening the objects */
|
||||
H5G_name_t path1; /* Opened object 1 hier. path */
|
||||
H5G_name_t path2; /* Opened object 2 hier. path */
|
||||
H5O_loc_t oloc1; /* Opened object 1 object location */
|
||||
H5O_loc_t oloc2; /* Opened object 2 object location */
|
||||
hbool_t loc1_found = FALSE; /* Location at 'name1' found */
|
||||
hbool_t loc2_found = FALSE; /* Location at 'name2' found */
|
||||
hbool_t obj1_open = FALSE; /* Entry at 'name1' found */
|
||||
hbool_t obj2_open = FALSE; /* Entry at 'name2' found */
|
||||
|
||||
htri_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_API(H5Ocompare, FAIL)
|
||||
|
||||
/* Check arguments */
|
||||
if(H5G_loc(loc1_id, &base_loc1) < 0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "loc1_id not a location")
|
||||
if(H5G_loc(loc2_id, &base_loc2) < 0)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "loc2_id not a location")
|
||||
if(!name1 || !*name2)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified for object 1")
|
||||
if(!name2 || !*name2)
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified for object 2")
|
||||
|
||||
/* Set up opened group locations to fill in */
|
||||
loc1.oloc = &oloc1;
|
||||
loc1.path = &path1;
|
||||
H5G_loc_reset(&loc1);
|
||||
loc2.oloc = &oloc2;
|
||||
loc2.path = &path2;
|
||||
H5G_loc_reset(&loc2);
|
||||
|
||||
/* Find the objects to compare */
|
||||
if(H5G_loc_find(&base_loc1, name1, &loc1/*out*/, H5P_DEFAULT, H5AC_dxpl_id) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object 1 not found")
|
||||
loc1_found = TRUE;
|
||||
if(H5G_loc_find(&base_loc2, name2, &loc2/*out*/, H5P_DEFAULT, H5AC_dxpl_id) < 0)
|
||||
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "object 2 not found")
|
||||
loc2_found = TRUE;
|
||||
|
||||
/* Open the objects' object headers */
|
||||
if(H5O_open(&oloc1) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object 1")
|
||||
obj1_open = TRUE;
|
||||
if(H5O_open(&oloc2) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTOPENOBJ, FAIL, "unable to open object 2")
|
||||
obj2_open = TRUE;
|
||||
#if 0
|
||||
/* Get correct property lists */
|
||||
if(H5P_DEFAULT == lcpl_id) {
|
||||
if((lcpl_id = H5L_get_default_lcpl()) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to get default lcpl")
|
||||
} /* end if */
|
||||
else
|
||||
if(TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list")
|
||||
|
||||
/* Get object copy property list */
|
||||
if(H5P_DEFAULT == ocpypl_id)
|
||||
ocpypl_id = H5P_OBJECT_COPY_DEFAULT;
|
||||
else
|
||||
if(TRUE != H5P_isa_class(ocpypl_id, H5P_OBJECT_COPY))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not object copy property list")
|
||||
#endif
|
||||
/* Do the actual copying of the object */
|
||||
if((ret_value = H5O_compare_obj(&oloc1, &oloc2, ocmppl_id)) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOMPARE, FAIL, "unable to compare object")
|
||||
|
||||
done:
|
||||
if(loc1_found && H5G_loc_free(&loc1) < 0)
|
||||
HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location 1")
|
||||
if(loc2_found && H5G_loc_free(&loc2) < 0)
|
||||
HDONE_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't free location 2")
|
||||
if(obj1_open)
|
||||
H5O_close(&oloc1);
|
||||
if(obj2_open)
|
||||
H5O_close(&oloc2);
|
||||
|
||||
FUNC_LEAVE_API(ret_value)
|
||||
} /* end H5Ocompare() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_compare_obj
|
||||
*
|
||||
* Purpose: fnord
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Neil Fortner
|
||||
* Novermeber 23, 2010
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static htri_t
|
||||
H5O_compare_obj(const H5O_loc_t *oloc1, const H5O_loc_t *oloc2, hid_t ocmppl_id)
|
||||
{
|
||||
H5O_t *oh1 = NULL; /* Object header for object 1 */
|
||||
H5O_t *oh2 = NULL; /* Object header for object 2 */
|
||||
const H5O_obj_class_t *obj1_class = NULL; /* Type of object 1 */
|
||||
const H5O_obj_class_t *obj2_class = NULL; /* Type of object 2 */
|
||||
hid_t dxpl1_id = H5AC_dxpl_id;
|
||||
hid_t dxpl2_id = -1;
|
||||
H5P_genplist_t *dxpl = NULL;
|
||||
haddr_t prev_tag1 = HADDR_UNDEF;
|
||||
haddr_t prev_tag2 = HADDR_UNDEF;
|
||||
htri_t ret_value = SUCCEED;
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_compare_obj)
|
||||
|
||||
HDassert(oloc1);
|
||||
HDassert(oloc1->file);
|
||||
HDassert(H5F_addr_defined(oloc1->addr));
|
||||
HDassert(oloc2);
|
||||
HDassert(oloc2->file);
|
||||
HDassert(H5F_addr_defined(oloc2->addr));
|
||||
|
||||
/* Copy dxpl1 to dxpl2 */
|
||||
if(NULL == (dxpl = (H5P_genplist_t *)H5I_object_verify(dxpl1_id, H5I_GENPROP_LST)))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
|
||||
if((dxpl2_id = H5P_copy_plist((H5P_genplist_t *)dxpl, FALSE)) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTCOPY, FAIL, "can't copy property list");
|
||||
|
||||
/* Set up metadata tagging */
|
||||
if(H5AC_tag(dxpl1_id, oloc1->addr, &prev_tag1) < 0)
|
||||
HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "unable to apply metadata tag")
|
||||
if(H5AC_tag(dxpl2_id, oloc2->addr, &prev_tag2) < 0)
|
||||
HGOTO_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "unable to apply metadata tag")
|
||||
|
||||
/* Get object headers */
|
||||
/*FIXME fnord Set up tagging here? */
|
||||
if(NULL == (oh1 = H5O_protect(oloc1, dxpl1_id, H5AC_READ)))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
|
||||
if(NULL == (oh2 = H5O_protect(oloc2, dxpl2_id, H5AC_READ)))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
|
||||
|
||||
/* Get pointer to object class for objects */
|
||||
if(NULL == (obj1_class = H5O_obj_class_real(oh1)))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
|
||||
if(NULL == (obj2_class = H5O_obj_class_real(oh1)))
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to determine object type")
|
||||
if(obj1_class->type != obj2_class->type)
|
||||
HGOTO_DONE(TRUE)
|
||||
|
||||
/* Do the comparison */
|
||||
HDassert(obj1_class->compare);
|
||||
if((ret_value = obj1_class->compare(oloc1->file, oloc2->file, oh1, oh2,
|
||||
oloc1->addr, oloc2->addr, dxpl1_id, dxpl2_id, NULL)) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOMPARE, FAIL, "unable to compare objects")
|
||||
|
||||
done:
|
||||
/* Release pointer to object headers and their derived objects */
|
||||
if(oh1 && H5O_unprotect(oloc1, dxpl1_id, oh1, H5AC__NO_FLAGS_SET) < 0)
|
||||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
|
||||
if(oh2 && H5O_unprotect(oloc2, dxpl2_id, oh2, H5AC__NO_FLAGS_SET) < 0)
|
||||
HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
|
||||
|
||||
if(H5AC_tag(dxpl1_id, prev_tag1, NULL) < 0)
|
||||
HDONE_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "unable to apply metadata tag")
|
||||
if(H5AC_tag(dxpl2_id, prev_tag2, NULL) < 0)
|
||||
HDONE_ERROR(H5E_CACHE, H5E_CANTTAG, FAIL, "unable to apply metadata tag")
|
||||
|
||||
if(dxpl2_id >= 0 && H5I_dec_ref(dxpl2_id) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "can't decrement ID ref count")
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_compare_obj() */
|
||||
|
||||
#if 0
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_copy_header_map
|
||||
*
|
||||
* Purpose: Copy header object from one location to another, detecting
|
||||
* already mapped objects, etc.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Quincey Koziol
|
||||
* November 1, 2005
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_copy_header_map(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
|
||||
hid_t dxpl_id, H5O_copy_t *cpy_info, hbool_t inc_depth,
|
||||
H5O_type_t *obj_type, void **udata)
|
||||
{
|
||||
H5O_addr_map_t *addr_map = NULL; /* Address mapping of object copied */
|
||||
H5_obj_t src_obj_pos; /* Position of source object */
|
||||
hbool_t inc_link; /* Whether to increment the link count for the object */
|
||||
herr_t ret_value = SUCCEED;
|
||||
|
||||
FUNC_ENTER_NOAPI(H5O_copy_header_map, FAIL)
|
||||
|
||||
/* Sanity check */
|
||||
HDassert(oloc_src);
|
||||
HDassert(oloc_src->file);
|
||||
HDassert(oloc_dst);
|
||||
HDassert(oloc_dst->file);
|
||||
HDassert(cpy_info);
|
||||
|
||||
/* Create object "position" struct */
|
||||
H5F_GET_FILENO(oloc_src->file, src_obj_pos.fileno);
|
||||
src_obj_pos.addr = oloc_src->addr;
|
||||
|
||||
/* Search for the object in the skip list of copied objects */
|
||||
addr_map = (H5O_addr_map_t *)H5SL_search(cpy_info->map_list,
|
||||
&src_obj_pos);
|
||||
|
||||
/* Check if address is already in list of objects copied */
|
||||
if(addr_map == NULL) {
|
||||
/* Copy object for the first time */
|
||||
|
||||
/* Check for incrementing the depth of copy */
|
||||
/* (Can't do this for all copies, since committed datatypes should always be copied) */
|
||||
if(inc_depth)
|
||||
cpy_info->curr_depth++;
|
||||
|
||||
/* Copy object referred to */
|
||||
if(H5O_copy_header_real(oloc_src, oloc_dst, dxpl_id, cpy_info, obj_type,
|
||||
udata) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
|
||||
|
||||
/* Check for incrementing the depth of copy */
|
||||
if(inc_depth)
|
||||
cpy_info->curr_depth--;
|
||||
|
||||
/* When an object is copied for the first time, increment it's link */
|
||||
inc_link = TRUE;
|
||||
|
||||
/* indicate that a new object is created */
|
||||
ret_value++;
|
||||
} /* end if */
|
||||
else {
|
||||
/* Object has already been copied, set its address in destination file */
|
||||
oloc_dst->addr = addr_map->dst_addr;
|
||||
|
||||
/* Return saved obj_type and udata, if requested */
|
||||
if(obj_type) {
|
||||
HDassert(udata);
|
||||
*obj_type = addr_map->obj_class->type;
|
||||
*udata = addr_map->udata;
|
||||
} /* end if */
|
||||
|
||||
/* If the object is locked currently (because we are copying a group
|
||||
* hierarchy and this is a link to a group higher in the hierarchy),
|
||||
* increment it's deferred reference count instead of incrementing the
|
||||
* reference count now.
|
||||
*/
|
||||
if(addr_map->is_locked) {
|
||||
addr_map->inc_ref_count++;
|
||||
inc_link = FALSE;
|
||||
} /* end if */
|
||||
else
|
||||
inc_link = TRUE;
|
||||
} /* end else */
|
||||
|
||||
/* Increment destination object's link count, if allowed */
|
||||
if(inc_link)
|
||||
if(H5O_link(oloc_dst, 1, dxpl_id) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to increment object link count")
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_copy_header_map() */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
NAME
|
||||
H5O_copy_free_addrmap_cb
|
||||
PURPOSE
|
||||
Internal routine to free address maps from the skip list for copying objects
|
||||
USAGE
|
||||
herr_t H5O_copy_free_addrmap_cb(item, key, op_data)
|
||||
void *item; IN/OUT: Pointer to addr
|
||||
void *key; IN/OUT: (unused)
|
||||
void *op_data; IN: (unused)
|
||||
RETURNS
|
||||
Returns zero on success, negative on failure.
|
||||
DESCRIPTION
|
||||
Releases the memory for the address.
|
||||
GLOBAL VARIABLES
|
||||
COMMENTS, BUGS, ASSUMPTIONS
|
||||
EXAMPLES
|
||||
REVISION LOG
|
||||
--------------------------------------------------------------------------*/
|
||||
static herr_t
|
||||
H5O_copy_free_addrmap_cb(void *_item, void UNUSED *key, void UNUSED *op_data)
|
||||
{
|
||||
H5O_addr_map_t *item = (H5O_addr_map_t *)_item;
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_copy_free_addrmap_cb)
|
||||
|
||||
HDassert(item);
|
||||
|
||||
/* Release user data for particular type of object */
|
||||
if(item->udata) {
|
||||
HDassert(item->obj_class);
|
||||
HDassert(item->obj_class->free_copy_file_udata);
|
||||
(item->obj_class->free_copy_file_udata)(item->udata);
|
||||
} /* end if */
|
||||
|
||||
/* Release the item */
|
||||
item = H5FL_FREE(H5O_addr_map_t, item);
|
||||
|
||||
FUNC_LEAVE_NOAPI(0)
|
||||
} /* H5O_copy_free_addrmap_cb() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_copy_header
|
||||
*
|
||||
* Purpose: copy header object from one location to another.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Peter Cao
|
||||
* May 30, 2005
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
|
||||
hid_t dxpl_id, unsigned cpy_option)
|
||||
{
|
||||
H5O_copy_t cpy_info; /* Information for copying object */
|
||||
herr_t ret_value = SUCCEED;
|
||||
|
||||
FUNC_ENTER_NOAPI_NOINIT(H5O_copy_header)
|
||||
|
||||
HDassert(oloc_src);
|
||||
HDassert(oloc_src->file);
|
||||
HDassert(H5F_addr_defined(oloc_src->addr));
|
||||
HDassert(oloc_dst->file);
|
||||
|
||||
/* Convert copy flags into copy struct */
|
||||
HDmemset(&cpy_info, 0, sizeof(H5O_copy_t));
|
||||
if((cpy_option & H5O_COPY_SHALLOW_HIERARCHY_FLAG) > 0) {
|
||||
cpy_info.copy_shallow = TRUE;
|
||||
cpy_info.max_depth = 1;
|
||||
} /* end if */
|
||||
else
|
||||
cpy_info.max_depth = -1; /* Current default is for full, recursive hier. copy */
|
||||
cpy_info.curr_depth = 0;
|
||||
if((cpy_option & H5O_COPY_EXPAND_SOFT_LINK_FLAG) > 0)
|
||||
cpy_info.expand_soft_link = TRUE;
|
||||
if((cpy_option & H5O_COPY_EXPAND_EXT_LINK_FLAG) > 0)
|
||||
cpy_info.expand_ext_link = TRUE;
|
||||
if((cpy_option & H5O_COPY_EXPAND_REFERENCE_FLAG) > 0)
|
||||
cpy_info.expand_ref = TRUE;
|
||||
if((cpy_option & H5O_COPY_WITHOUT_ATTR_FLAG) > 0)
|
||||
cpy_info.copy_without_attr = TRUE;
|
||||
if((cpy_option & H5O_COPY_PRESERVE_NULL_FLAG) > 0)
|
||||
cpy_info.preserve_null = TRUE;
|
||||
|
||||
/* Create a skip list to keep track of which objects are copied */
|
||||
if((cpy_info.map_list = H5SL_create(H5SL_TYPE_OBJ)) == NULL)
|
||||
HGOTO_ERROR(H5E_SLIST, H5E_CANTCREATE, FAIL, "cannot make skip list")
|
||||
|
||||
/* copy the object from the source file to the destination file */
|
||||
if(H5O_copy_header_real(oloc_src, oloc_dst, dxpl_id, &cpy_info, NULL, NULL)
|
||||
< 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
|
||||
|
||||
done:
|
||||
if(cpy_info.map_list)
|
||||
H5SL_destroy(cpy_info.map_list, H5O_copy_free_addrmap_cb, NULL);
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_copy_header() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_copy_obj
|
||||
*
|
||||
* Purpose: Copy an object to destination location
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Peter Cao
|
||||
* June 4, 2005
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_copy_obj(H5G_loc_t *src_loc, H5G_loc_t *dst_loc, const char *dst_name,
|
||||
hid_t ocpypl_id, hid_t lcpl_id)
|
||||
{
|
||||
H5P_genplist_t *ocpy_plist=NULL; /* Object copy property list created */
|
||||
hid_t dxpl_id=H5AC_dxpl_id;
|
||||
H5G_name_t new_path; /* Copied object group hier. path */
|
||||
H5O_loc_t new_oloc; /* Copied object object location */
|
||||
H5G_loc_t new_loc; /* Group location of object copied */
|
||||
H5F_t *cached_dst_file; /* Cached destination file */
|
||||
hbool_t entry_inserted=FALSE; /* Flag to indicate that the new entry was inserted into a group */
|
||||
unsigned cpy_option = 0; /* Copy options */
|
||||
herr_t ret_value = SUCCEED; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(H5O_copy_obj, FAIL)
|
||||
|
||||
HDassert(src_loc);
|
||||
HDassert(src_loc->oloc->file);
|
||||
HDassert(dst_loc);
|
||||
HDassert(dst_loc->oloc->file);
|
||||
HDassert(dst_name);
|
||||
|
||||
/* Get the copy property list */
|
||||
if(NULL == (ocpy_plist = (H5P_genplist_t *)H5I_object(ocpypl_id)))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
|
||||
|
||||
/* Retrieve the copy parameters */
|
||||
if(H5P_get(ocpy_plist, H5O_CPY_OPTION_NAME, &cpy_option) < 0)
|
||||
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get object copy flag")
|
||||
|
||||
/* Set up copied object location to fill in */
|
||||
new_loc.oloc = &new_oloc;
|
||||
new_loc.path = &new_path;
|
||||
H5G_loc_reset(&new_loc);
|
||||
new_oloc.file = dst_loc->oloc->file;
|
||||
|
||||
/* Make a copy of the destination file, in case the original is changed by
|
||||
* H5O_copy_header. If and when oloc's point to the shared file struct,
|
||||
* this will no longer be necessary, so this code can be removed. */
|
||||
cached_dst_file = dst_loc->oloc->file;
|
||||
|
||||
/* Copy the object from the source file to the destination file */
|
||||
if(H5O_copy_header(src_loc->oloc, &new_oloc, dxpl_id, cpy_option) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
|
||||
|
||||
/* Patch dst_loc. Again, this can be removed once oloc's point to shared
|
||||
* file structs. */
|
||||
dst_loc->oloc->file = cached_dst_file;
|
||||
|
||||
/* Insert the new object in the destination file's group */
|
||||
if(H5L_link(dst_loc, dst_name, &new_loc, lcpl_id, H5P_DEFAULT, dxpl_id) < 0)
|
||||
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert link")
|
||||
entry_inserted = TRUE;
|
||||
|
||||
done:
|
||||
/* Free the ID to name buffers */
|
||||
if(entry_inserted)
|
||||
H5G_loc_free(&new_loc);
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_copy_obj() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_copy_obj_by_ref
|
||||
*
|
||||
* Purpose: Copy the object pointed by _src_ref.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Peter Cao
|
||||
* Aug 7 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
static herr_t
|
||||
H5O_copy_obj_by_ref(H5O_loc_t *src_oloc, hid_t dxpl_id, H5O_loc_t *dst_oloc,
|
||||
H5G_loc_t *dst_root_loc, H5O_copy_t *cpy_info)
|
||||
{
|
||||
herr_t ret_value = SUCCEED;
|
||||
|
||||
FUNC_ENTER_NOAPI(H5O_copy_obj_by_ref, FAIL)
|
||||
|
||||
HDassert(src_oloc);
|
||||
HDassert(dst_oloc);
|
||||
|
||||
/* Perform the copy, or look up existing copy */
|
||||
if((ret_value = H5O_copy_header_map(src_oloc, dst_oloc, dxpl_id, cpy_info,
|
||||
FALSE, NULL, NULL)) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
|
||||
|
||||
/* Check if a new valid object is copied to the destination */
|
||||
if(H5F_addr_defined(dst_oloc->addr) && (ret_value > SUCCEED)) {
|
||||
char tmp_obj_name[80];
|
||||
H5G_name_t new_path;
|
||||
H5O_loc_t new_oloc;
|
||||
H5G_loc_t new_loc;
|
||||
|
||||
/* Set up group location for new object */
|
||||
new_loc.oloc = &new_oloc;
|
||||
new_loc.path = &new_path;
|
||||
H5G_loc_reset(&new_loc);
|
||||
new_oloc.file = dst_oloc->file;
|
||||
new_oloc.addr = dst_oloc->addr;
|
||||
|
||||
/* Pick a default name for the new object */
|
||||
sprintf(tmp_obj_name, "~obj_pointed_by_%llu", (unsigned long long)dst_oloc->addr);
|
||||
|
||||
/* Create a link to the newly copied object */
|
||||
/* Note: since H5O_copy_header_map actually copied the target object, it
|
||||
* must exist either in cache or on disk, therefore it is is safe to not
|
||||
* pass the obj_type and udata fields returned by H5O_copy_header_map.
|
||||
* This could be changed in the future to slightly improve performance
|
||||
* --NAF */
|
||||
if(H5L_link(dst_root_loc, tmp_obj_name, &new_loc, H5P_DEFAULT, H5P_DEFAULT, dxpl_id) < 0)
|
||||
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert link")
|
||||
|
||||
H5G_loc_free(&new_loc);
|
||||
} /* if (H5F_addr_defined(dst_oloc.addr)) */
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_copy_obj_by_ref() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5O_copy_expand_ref
|
||||
*
|
||||
* Purpose: Copy the object pointed by _src_ref.
|
||||
*
|
||||
* Return: Non-negative on success/Negative on failure
|
||||
*
|
||||
* Programmer: Peter Cao
|
||||
* Aug 7 2006
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
herr_t
|
||||
H5O_copy_expand_ref(H5F_t *file_src, void *_src_ref, hid_t dxpl_id,
|
||||
H5F_t *file_dst, void *_dst_ref, size_t ref_count, H5R_type_t ref_type,
|
||||
H5O_copy_t *cpy_info)
|
||||
{
|
||||
H5O_loc_t dst_oloc; /* Copied object object location */
|
||||
H5O_loc_t src_oloc; /* Temporary object location for source object */
|
||||
H5G_loc_t dst_root_loc; /* The location of root group of the destination file */
|
||||
uint8_t *p; /* Pointer to OID to store */
|
||||
size_t i; /* Local index variable */
|
||||
herr_t ret_value = SUCCEED;
|
||||
|
||||
FUNC_ENTER_NOAPI(H5O_copy_expand_ref, FAIL)
|
||||
|
||||
/* Sanity checks */
|
||||
HDassert(file_src);
|
||||
HDassert(_src_ref);
|
||||
HDassert(file_dst);
|
||||
HDassert(_dst_ref);
|
||||
HDassert(ref_count);
|
||||
HDassert(cpy_info);
|
||||
|
||||
/* Initialize object locations */
|
||||
H5O_loc_reset(&src_oloc);
|
||||
H5O_loc_reset(&dst_oloc);
|
||||
src_oloc.file = file_src;
|
||||
dst_oloc.file = file_dst;
|
||||
|
||||
/* Set up the root group in the destination file */
|
||||
if(NULL == (dst_root_loc.oloc = H5G_oloc(H5G_rootof(file_dst))))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get object location for root group")
|
||||
if(NULL == (dst_root_loc.path = H5G_nameof(H5G_rootof(file_dst))))
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unable to get path for root group")
|
||||
|
||||
/* Copy object references */
|
||||
if(H5R_OBJECT == ref_type) {
|
||||
hobj_ref_t *src_ref = (hobj_ref_t *)_src_ref;
|
||||
hobj_ref_t *dst_ref = (hobj_ref_t *)_dst_ref;
|
||||
|
||||
/* Making equivalent references in the destination file */
|
||||
for(i = 0; i < ref_count; i++) {
|
||||
/* Set up for the object copy for the reference */
|
||||
p = (uint8_t *)(&src_ref[i]);
|
||||
H5F_addr_decode(src_oloc.file, (const uint8_t **)&p, &(src_oloc.addr));
|
||||
dst_oloc.addr = HADDR_UNDEF;
|
||||
|
||||
/* Attempt to copy object from source to destination file */
|
||||
if(src_oloc.addr != (haddr_t)0) {
|
||||
if(H5O_copy_obj_by_ref(&src_oloc, dxpl_id, &dst_oloc, &dst_root_loc, cpy_info) < 0)
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
|
||||
} /* end if */
|
||||
else
|
||||
/* Set parameters so the reference is written as all 0's */
|
||||
HDmemset(&dst_oloc.addr, 0, sizeof(dst_oloc.addr));
|
||||
|
||||
/* Set the object reference info for the destination file */
|
||||
p = (uint8_t *)(&dst_ref[i]);
|
||||
H5F_addr_encode(dst_oloc.file, &p, dst_oloc.addr);
|
||||
} /* end for */
|
||||
} /* end if */
|
||||
/* Copy region references */
|
||||
else if(H5R_DATASET_REGION == ref_type) {
|
||||
hdset_reg_ref_t *src_ref = (hdset_reg_ref_t *)_src_ref;
|
||||
hdset_reg_ref_t *dst_ref = (hdset_reg_ref_t *)_dst_ref;
|
||||
uint8_t *buf = NULL; /* Buffer to store serialized selection in */
|
||||
H5HG_t hobjid; /* Heap object ID */
|
||||
size_t buf_size; /* Length of object in heap */
|
||||
|
||||
/* Making equivalent references in the destination file */
|
||||
for(i = 0; i < ref_count; i++) {
|
||||
/* Get the heap ID for the dataset region */
|
||||
p = (uint8_t *)(&src_ref[i]);
|
||||
H5F_addr_decode(src_oloc.file, (const uint8_t **)&p, &(hobjid.addr));
|
||||
INT32DECODE(p, hobjid.idx);
|
||||
|
||||
if(hobjid.addr != (haddr_t)0) {
|
||||
/* Get the dataset region from the heap (allocate inside routine) */
|
||||
if((buf = (uint8_t *)H5HG_read(src_oloc.file, dxpl_id, &hobjid, NULL, &buf_size)) == NULL)
|
||||
HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, FAIL, "Unable to read dataset region information")
|
||||
|
||||
/* Get the object oid for the dataset */
|
||||
p = (uint8_t *)buf;
|
||||
H5F_addr_decode(src_oloc.file, (const uint8_t **)&p, &(src_oloc.addr));
|
||||
dst_oloc.addr = HADDR_UNDEF;
|
||||
|
||||
/* copy the object pointed by the ref to the destination */
|
||||
if(H5O_copy_obj_by_ref(&src_oloc, dxpl_id, &dst_oloc, &dst_root_loc, cpy_info) < 0) {
|
||||
H5MM_xfree(buf);
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object")
|
||||
} /* end if */
|
||||
|
||||
/* Serialize object ID */
|
||||
p = (uint8_t *)buf;
|
||||
H5F_addr_encode(dst_oloc.file, &p, dst_oloc.addr);
|
||||
|
||||
/* Save the serialized buffer to the destination */
|
||||
if(H5HG_insert(dst_oloc.file, dxpl_id, buf_size, buf, &hobjid) < 0) {
|
||||
H5MM_xfree(buf);
|
||||
HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "Unable to write dataset region information")
|
||||
} /* end if */
|
||||
} /* end if */
|
||||
else
|
||||
/* Set parameters so the reference is written as all 0's */
|
||||
HDmemset(&hobjid, 0, sizeof(hobjid));
|
||||
|
||||
/* Set the dataset region reference info for the destination file */
|
||||
p = (uint8_t *)(&dst_ref[i]);
|
||||
H5F_addr_encode(dst_oloc.file, &p, hobjid.addr);
|
||||
INT32ENCODE(p, hobjid.idx);
|
||||
|
||||
/* Free the buffer allocated in H5HG_read() */
|
||||
H5MM_xfree(buf);
|
||||
} /* end for */
|
||||
} /* end if */
|
||||
else
|
||||
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid reference type")
|
||||
|
||||
done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5O_copy_expand_ref() */
|
||||
#endif
|
||||
|
||||
@@ -325,6 +325,9 @@ typedef struct H5O_obj_class_t {
|
||||
void *(*create)(H5F_t *, void *, H5G_loc_t *, hid_t ); /*create an object of this class */
|
||||
H5O_loc_t *(*get_oloc)(hid_t ); /*get the object header location for an object */
|
||||
herr_t (*bh_info)(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info); /*get the index & heap info for an object */
|
||||
htri_t (*compare)(const H5F_t *f1, const H5F_t *f2, const H5O_t *oh1,
|
||||
const H5O_t *oh2, haddr_t addr1, haddr_t addr2, hid_t dxpl1_id,
|
||||
hid_t dxpl2_id, H5O_cmp_t *cmp_info); /*compare two objects of this class */
|
||||
} H5O_obj_class_t;
|
||||
|
||||
/* Node in skip list to map addresses from one file to another during object header copy */
|
||||
|
||||
@@ -145,6 +145,10 @@ typedef struct H5O_copy_t {
|
||||
H5O_t *oh_dst; /* The destination object header */
|
||||
} H5O_copy_t;
|
||||
|
||||
/* Settings/flags for comparing objects */
|
||||
/* Empty for now */
|
||||
typedef void H5O_cmp_t;
|
||||
|
||||
/* Header message IDs */
|
||||
#define H5O_NULL_ID 0x0000 /* Null Message. */
|
||||
#define H5O_SDSPACE_ID 0x0001 /* Dataspace Message. */
|
||||
|
||||
@@ -172,6 +172,8 @@ H5_DLL herr_t H5Ovisit(hid_t obj_id, H5_index_t idx_type, H5_iter_order_t order,
|
||||
H5_DLL herr_t H5Ovisit_by_name(hid_t loc_id, const char *obj_name,
|
||||
H5_index_t idx_type, H5_iter_order_t order, H5O_iterate_t op,
|
||||
void *op_data, hid_t lapl_id);
|
||||
H5_DLL htri_t H5Ocompare(hid_t loc1_id, const char *name1, hid_t loc2_id,
|
||||
const char *name2, hid_t ocmppl_id);
|
||||
H5_DLL herr_t H5Oclose(hid_t object_id);
|
||||
|
||||
/* Symbols defined for compatibility with previous versions of the HDF5 API.
|
||||
|
||||
48
src/H5S.c
48
src/H5S.c
@@ -1062,6 +1062,54 @@ done:
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5S_read() */
|
||||
|
||||
|
||||
/*-------------------------------------------------------------------------
|
||||
* Function: H5S_read_oh
|
||||
*
|
||||
* Purpose: Reads the dataspace from an object header.
|
||||
*
|
||||
* Return: Success: Pointer to a new dataspace.
|
||||
*
|
||||
* Failure: NULL
|
||||
*
|
||||
* Programmer: Robb Matzke
|
||||
* Tuesday, December 9, 1997
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
H5S_t *
|
||||
H5S_read_oh(const H5F_t *f, const H5O_t *oh, hid_t dxpl_id)
|
||||
{
|
||||
H5S_t *ds = NULL; /* Dataspace to return */
|
||||
H5S_t *ret_value; /* Return value */
|
||||
|
||||
FUNC_ENTER_NOAPI(H5S_read_oh, NULL)
|
||||
|
||||
/* check args */
|
||||
HDassert(oh);
|
||||
|
||||
if(NULL == (ds = H5FL_CALLOC(H5S_t)))
|
||||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
|
||||
|
||||
if(H5O_msg_read_oh(f, dxpl_id, oh, H5O_SDSPACE_ID, &(ds->extent)) == NULL)
|
||||
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to load dataspace info from dataset header")
|
||||
|
||||
/* Default to entire dataspace being selected */
|
||||
if(H5S_select_all(ds, FALSE) < 0)
|
||||
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
|
||||
|
||||
/* Set the value for successful return */
|
||||
ret_value = ds;
|
||||
|
||||
done:
|
||||
if(ret_value == NULL) {
|
||||
if(ds != NULL)
|
||||
ds = H5FL_FREE(H5S_t, ds);
|
||||
} /* end if */
|
||||
|
||||
FUNC_LEAVE_NOAPI(ret_value)
|
||||
} /* end H5S_read_oh() */
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
NAME
|
||||
|
||||
@@ -188,6 +188,7 @@ H5_DLL herr_t H5S_write(H5F_t *f, hid_t dxpl_id, H5O_t *oh, unsigned update_flag
|
||||
H5S_t *ds);
|
||||
H5_DLL herr_t H5S_append(H5F_t *f, hid_t dxpl_id, struct H5O_t *oh, H5S_t *ds);
|
||||
H5_DLL H5S_t *H5S_read(const struct H5O_loc_t *loc, hid_t dxpl_id);
|
||||
H5_DLL H5S_t *H5S_read_oh(const H5F_t *f, const H5O_t *oh, hid_t dxpl_id);
|
||||
H5_DLL htri_t H5S_set_extent(H5S_t *space, const hsize_t *size);
|
||||
H5_DLL herr_t H5S_set_extent_real(H5S_t *space, const hsize_t *size);
|
||||
H5_DLL H5S_t *H5S_create(H5S_class_t type);
|
||||
|
||||
@@ -77,8 +77,8 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
|
||||
H5MM.c H5MP.c H5MPtest.c \
|
||||
H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
|
||||
H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c H5Ochunk.c \
|
||||
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
|
||||
H5Ofill.c H5Ofsinfo.c H5Oginfo.c \
|
||||
H5Ocompare.c H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c \
|
||||
H5Oefl.c H5Ofill.c H5Ofsinfo.c H5Oginfo.c \
|
||||
H5Olayout.c \
|
||||
H5Olinfo.c H5Olink.c H5Omessage.c H5Omtime.c \
|
||||
H5Oname.c H5Onull.c H5Opline.c H5Orefcount.c \
|
||||
|
||||
@@ -126,7 +126,7 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
|
||||
H5L.lo H5Lexternal.lo H5lib_settings.lo H5MF.lo H5MFaggr.lo \
|
||||
H5MFdbg.lo H5MFsection.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \
|
||||
H5Oainfo.lo H5Oalloc.lo H5Oattr.lo H5Oattribute.lo H5Obogus.lo \
|
||||
H5Obtreek.lo H5Ocache.lo H5Ochunk.lo H5Ocont.lo H5Ocopy.lo \
|
||||
H5Obtreek.lo H5Ocache.lo H5Ochunk.lo H5Ocompare.lo H5Ocont.lo H5Ocopy.lo \
|
||||
H5Odbg.lo H5Odrvinfo.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo \
|
||||
H5Ofsinfo.lo H5Oginfo.lo H5Olayout.lo H5Olinfo.lo H5Olink.lo \
|
||||
H5Omessage.lo H5Omtime.lo H5Oname.lo H5Onull.lo H5Opline.lo \
|
||||
@@ -510,7 +510,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
|
||||
H5MM.c H5MP.c H5MPtest.c \
|
||||
H5O.c H5Oainfo.c H5Oalloc.c H5Oattr.c \
|
||||
H5Oattribute.c H5Obogus.c H5Obtreek.c H5Ocache.c H5Ochunk.c \
|
||||
H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
|
||||
H5Ocompare.c H5Ocont.c H5Ocopy.c H5Odbg.c H5Odrvinfo.c H5Odtype.c H5Oefl.c \
|
||||
H5Ofill.c H5Ofsinfo.c H5Oginfo.c \
|
||||
H5Olayout.c \
|
||||
H5Olinfo.c H5Olink.c H5Omessage.c H5Omtime.c \
|
||||
@@ -835,6 +835,7 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Obtreek.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ocache.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ochunk.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ocompare.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ocont.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Ocopy.Plo@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Odbg.Plo@am__quote@
|
||||
|
||||
@@ -44,7 +44,16 @@ hsize_t diff_dataset( hid_t file1_id,
|
||||
hid_t dcpl1 = -1;
|
||||
hid_t dcpl2 = -1;
|
||||
hsize_t nfound = 0;
|
||||
htri_t tri_ret;
|
||||
|
||||
/* Do the comparison */
|
||||
if((tri_ret = H5Ocompare(file1_id, obj1_name, file2_id, obj2_name, H5P_DEFAULT)) < 0)
|
||||
goto error;
|
||||
|
||||
if(tri_ret)
|
||||
nfound = 1;
|
||||
|
||||
#if 0
|
||||
/*-------------------------------------------------------------------------
|
||||
* open the handles
|
||||
*-------------------------------------------------------------------------
|
||||
@@ -102,12 +111,14 @@ hsize_t diff_dataset( hid_t file1_id,
|
||||
H5Dclose(did2);
|
||||
/* enable error reporting */
|
||||
} H5E_END_TRY;
|
||||
#endif
|
||||
|
||||
|
||||
return nfound;
|
||||
|
||||
error:
|
||||
options->err_stat=1;
|
||||
#if 0
|
||||
/* disable error reporting */
|
||||
H5E_BEGIN_TRY {
|
||||
H5Pclose(dcpl1);
|
||||
@@ -116,6 +127,7 @@ error:
|
||||
H5Dclose(did2);
|
||||
/* enable error reporting */
|
||||
} H5E_END_TRY;
|
||||
#endif
|
||||
|
||||
return nfound;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user