From 08910385629d5cbfde5aa43cef0bcba17f7995b1 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Sun, 6 Nov 2005 22:13:53 -0500 Subject: [svn-r11686] Purpose: New feature Description: Add in baseline "object copy" code from Peter [in the form of a new API routine: H5Gcopy()]. There's still some work to do (like handling variable- length datatypes and possibly support for references) and it hasn't been tested on mounted files yet, but the core functionality is there and working correctly. I've also got a set of patches to update the 1.6 branch with tweaks to keep the branches mostly in sync, but Elena will kill me if I import them before the 1.6.5 release is out... :-) Platforms tested: FreeBSD 4.11 (sleipnir) h5committested --- MANIFEST | 2 + release_docs/RELEASE.txt | 3 + src/H5Apkg.h | 7 + src/H5B.c | 444 +----- src/H5B2.c | 31 +- src/H5B2private.h | 4 + src/H5BPcache.c | 4 +- src/H5Bcache.c | 417 ++++++ src/H5Bpkg.h | 23 +- src/H5Bprivate.h | 42 +- src/H5D.c | 4 + src/H5Distore.c | 619 +++++---- src/H5Dpkg.h | 2 + src/H5Dpublic.h | 24 +- src/H5G.c | 110 +- src/H5Gnode.c | 136 +- src/H5Gpkg.h | 18 +- src/H5Gpublic.h | 6 +- src/H5Gstab.c | 47 + src/H5O.c | 531 +++++++- src/H5Oattr.c | 101 +- src/H5Obogus.c | 4 +- src/H5Ocont.c | 54 +- src/H5Odtype.c | 4 +- src/H5Oefl.c | 87 +- src/H5Ofill.c | 8 +- src/H5Olayout.c | 127 +- src/H5Omtime.c | 8 +- src/H5Oname.c | 4 +- src/H5Onull.c | 4 +- src/H5Opkg.h | 9 +- src/H5Opline.c | 4 +- src/H5Oprivate.h | 20 +- src/H5Osdspace.c | 4 +- src/H5Oshared.c | 63 +- src/H5Ostab.c | 99 +- src/H5S.c | 101 ++ src/H5Shyper.c | 18 +- src/H5Spublic.h | 1 + src/H5T.c | 3 +- src/Makefile.am | 3 +- src/Makefile.in | 12 +- test/Makefile.am | 5 +- test/Makefile.in | 38 +- test/objcopy.c | 3350 ++++++++++++++++++++++++++++++++++++++++++++++ test/th5s.c | 518 +++++++ 46 files changed, 6253 insertions(+), 870 deletions(-) create mode 100644 src/H5Bcache.c create mode 100755 test/objcopy.c diff --git a/MANIFEST b/MANIFEST index 1e17278..93bfecd 100644 --- a/MANIFEST +++ b/MANIFEST @@ -398,6 +398,7 @@ ./src/H5ACprivate.h ./src/H5ACpublic.h ./src/H5B.c +./src/H5Bcache.c ./src/H5Bpkg.h ./src/H5Bprivate.h ./src/H5Bpublic.h @@ -662,6 +663,7 @@ ./test/noencoder.h5 ./test/ntypes.c ./test/ohdr.c +./test/objcopy.c ./test/reserved.c ./test/space_overflow.c _DO_NOT_DISTRIBUTE_ ./test/gen_deflate.c _DO_NOT_DISTRIBUTE_ diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index ca65c7c..9a8d092 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -130,6 +130,9 @@ New Features Library: -------- + - Added H5Gcopy() routine to copy objects between while keeping + data in compressed form. QAK - 2005/11/06 + - Added H5Sextent_equal() routine. QAK - 2005/11/06 - Added HSYS_ERROR which retrieves the system error message and pushes it to the error stack. This gives more information of the failed system call. AKC - 2005/08/04 diff --git a/src/H5Apkg.h b/src/H5Apkg.h index 976340d..753ad64 100644 --- a/src/H5Apkg.h +++ b/src/H5Apkg.h @@ -38,6 +38,7 @@ #include "H5Aprivate.h" /* Other private headers needed by this file */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5Sprivate.h" /* Dataspace */ #include "H5Tprivate.h" /* Datatype functions */ @@ -54,6 +55,12 @@ struct H5A_t { size_t data_size; /* Size of data on disk */ }; +/* Declare extern the free list for H5A_t's */ +H5FL_EXTERN(H5A_t); + +/* Declare extern a free list to manage blocks of type conversion data */ +H5FL_BLK_EXTERN(attr_buf); + /* Function prototypes for H5A package scope */ H5_DLL H5A_t *H5A_copy(H5A_t *new_attr, const H5A_t *old_attr, unsigned update_flags); H5_DLL herr_t H5A_free(H5A_t *attr); diff --git a/src/H5B.c b/src/H5B.c index c5775d8..700ae48 100644 --- a/src/H5B.c +++ b/src/H5B.c @@ -14,7 +14,7 @@ /*------------------------------------------------------------------------- * - * Created: hdf5btree.c + * Created: H5B.c * Jul 10 1997 * Robb Matzke * @@ -89,41 +89,47 @@ * that type of B-tree. * * - * Modifications: - * - * Robb Matzke, 4 Aug 1997 - * Added calls to H5E. - * *------------------------------------------------------------------------- */ +/****************/ +/* Module Setup */ +/****************/ + #define H5B_PACKAGE /*suppress error about including H5Bpkg */ #define H5F_PACKAGE /*suppress error about including H5Fpkg */ -/* private headers */ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ #include "H5ACprivate.h" /* Metadata cache */ #include "H5Bpkg.h" /* B-link trees */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ #include "H5Fpkg.h" /* File access */ -#include "H5FLprivate.h" /* Free Lists */ #include "H5Iprivate.h" /* IDs */ #include "H5MFprivate.h" /* File memory management */ #include "H5MMprivate.h" /* Memory management */ #include "H5Pprivate.h" /* Property lists */ -/* Local macros */ +/****************/ +/* Local Macros */ +/****************/ #define H5B_SIZEOF_HDR(F) \ (H5B_SIZEOF_MAGIC + /*magic number */ \ 4 + /*type, level, num entries */ \ 2*H5F_SIZEOF_ADDR(F)) /*left and right sibling addresses */ #define H5B_NKEY(b,shared,idx) ((b)->native+(shared)->nkey[(idx)]) -/* Local typedefs */ +/******************/ +/* Local Typedefs */ +/******************/ -/* PRIVATE PROTOTYPES */ +/********************/ +/* Local Prototypes */ +/********************/ static H5B_ins_t H5B_insert_helper(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type, uint8_t *lt_key, @@ -139,40 +145,34 @@ static herr_t H5B_split(H5F_t *f, hid_t dxpl_id, H5B_t *old_bt, unsigned *old_bt_flags, haddr_t old_addr, unsigned idx, void *udata, haddr_t *new_addr/*out*/); static H5B_t * H5B_copy(const H5B_t *old_bt); -static herr_t H5B_serialize(const H5F_t *f, const H5B_t *bt); #ifdef H5B_DEBUG static herr_t H5B_assert(H5F_t *f, hid_t dxpl_id, haddr_t addr, const H5B_class_t *type, void *udata); #endif -/* Metadata cache callbacks */ -static H5B_t *H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata); -static herr_t H5B_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *b); -static herr_t H5B_dest(H5F_t *f, H5B_t *b); -static herr_t H5B_clear(H5F_t *f, H5B_t *b, hbool_t destroy); -static herr_t H5B_compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_ptr); - -/* H5B inherits cache-like properties from H5AC */ -static const H5AC_class_t H5AC_BT[1] = {{ - H5AC_BT_ID, - (H5AC_load_func_t)H5B_load, - (H5AC_flush_func_t)H5B_flush, - (H5AC_dest_func_t)H5B_dest, - (H5AC_clear_func_t)H5B_clear, - (H5AC_size_func_t)H5B_compute_size, -}}; +/*********************/ +/* Package Variables */ +/*********************/ + +/* Declare a free list to manage the haddr_t sequence information */ +H5FL_SEQ_DEFINE(haddr_t); /* Declare a PQ free list to manage the native block information */ -H5FL_BLK_DEFINE_STATIC(native_block); +H5FL_BLK_DEFINE(native_block); -/* Declare a free list to manage the haddr_t sequence information */ -H5FL_SEQ_DEFINE_STATIC(haddr_t); +/* Declare a free list to manage the H5B_t struct */ +H5FL_DEFINE(H5B_t); + +/*****************************/ +/* Library Private Variables */ +/*****************************/ /* Declare a free list to manage the H5B_shared_t struct */ H5FL_DEFINE(H5B_shared_t); -/* Declare a free list to manage the H5B_t struct */ -H5FL_DEFINE_STATIC(H5B_t); +/*******************/ +/* Local Variables */ +/*******************/ /*------------------------------------------------------------------------- @@ -263,377 +263,7 @@ done: } FUNC_LEAVE_NOAPI(ret_value) -} /*lint !e818 Can't make udata a pointer to const */ - - -/*------------------------------------------------------------------------- - * Function: H5B_load - * - * Purpose: Loads a B-tree node from the disk. - * - * Return: Success: Pointer to a new B-tree node. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 23 1997 - * - * Modifications: - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - *------------------------------------------------------------------------- - */ -static H5B_t * -H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata) -{ - const H5B_class_t *type = (const H5B_class_t *) _type; - H5B_t *bt = NULL; - H5B_shared_t *shared; /* Pointer to shared B-tree info */ - uint8_t *p; /* Pointer into raw data buffer */ - uint8_t *native; /* Pointer to native keys */ - unsigned u; /* Local index variable */ - H5B_t *ret_value; - - FUNC_ENTER_NOAPI(H5B_load, NULL) - - /* Check arguments */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(type); - assert(type->get_shared); - - if (NULL==(bt = H5FL_MALLOC(H5B_t))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - HDmemset(&bt->cache_info,0,sizeof(H5AC_info_t)); - if((bt->rc_shared=(type->get_shared)(f, udata))==NULL) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "can't retrieve B-tree node buffer") - shared=H5RC_GET_OBJ(bt->rc_shared); - HDassert(shared); - if (NULL==(bt->native=H5FL_BLK_MALLOC(native_block,shared->sizeof_keys)) || - NULL==(bt->child=H5FL_SEQ_MALLOC(haddr_t,(size_t)shared->two_k))) - HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") - - if (H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->sizeof_rnode, dxpl_id, shared->page)<0) - HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree node") - - p = shared->page; - - /* magic number */ - if (HDmemcmp(p, H5B_MAGIC, (size_t)H5B_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree signature") - p += 4; - - /* node type and level */ - if (*p++ != (uint8_t)type->id) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree node type") - bt->level = *p++; - - /* entries used */ - UINT16DECODE(p, bt->nchildren); - - /* sibling pointers */ - H5F_addr_decode(f, (const uint8_t **) &p, &(bt->left)); - H5F_addr_decode(f, (const uint8_t **) &p, &(bt->right)); - - /* the child/key pairs */ - native=bt->native; - for (u = 0; u < bt->nchildren; u++) { - /* Decode native key value */ - if ((type->decode) (f, bt, p, native) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode key") - p += shared->sizeof_rkey; - native += type->sizeof_nkey; - - /* Decode address value */ - H5F_addr_decode(f, (const uint8_t **) &p, bt->child + u); - } - - /* Decode final key */ - if(bt->nchildren>0) { - /* Decode native key value */ - if ((type->decode) (f, bt, p, native) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode key") - } /* end if */ - - /* Set return value */ - ret_value = bt; - -done: - if (!ret_value && bt) - (void)H5B_dest(f,bt); - FUNC_LEAVE_NOAPI(ret_value) -} /*lint !e818 Can't make udata a pointer to const */ - - -/*------------------------------------------------------------------------- - * Function: H5B_serialize - * - * Purpose: Serialize the data structure for writing to disk or - * storing on the SAP (for FPHDF5). - * - * Return: Success: SUCCEED - * Failure: FAIL - * - * Programmer: Bill Wendling - * wendling@ncsa.uiuc.edu - * Sept. 15, 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B_serialize(const H5F_t *f, const H5B_t *bt) -{ - H5B_shared_t *shared=NULL; /* Pointer to shared B-tree info */ - unsigned u; - uint8_t *p; /* Pointer into raw data buffer */ - uint8_t *native; /* Pointer to native keys */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5B_serialize, FAIL) - - /* check arguments */ - assert(f); - assert(bt); - assert(bt->rc_shared); - shared=H5RC_GET_OBJ(bt->rc_shared); - HDassert(shared); - - p = shared->page; - - /* magic number */ - HDmemcpy(p, H5B_MAGIC, (size_t)H5B_SIZEOF_MAGIC); - p += 4; - - /* node type and level */ - *p++ = (uint8_t)shared->type->id; - H5_CHECK_OVERFLOW(bt->level, unsigned, uint8_t); - *p++ = (uint8_t)bt->level; - - /* entries used */ - UINT16ENCODE(p, bt->nchildren); - - /* sibling pointers */ - H5F_addr_encode(f, &p, bt->left); - H5F_addr_encode(f, &p, bt->right); - - /* child keys and pointers */ - native=bt->native; - for (u = 0; u < bt->nchildren; ++u) { - /* encode the key */ - if (shared->type->encode(f, bt, p, native) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key") - p += shared->sizeof_rkey; - native += shared->type->sizeof_nkey; - - /* encode the child address */ - H5F_addr_encode(f, &p, bt->child[u]); - } /* end for */ - if(bt->nchildren>0) { - /* Encode the final key */ - if (shared->type->encode(f, bt, p, native) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key") - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5B_flush - * - * Purpose: Flushes a dirty B-tree node to disk. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 23 1997 - * - * Modifications: - * rky 980828 - * Only p0 writes metadata to disk. - * - * Robb Matzke, 1999-07-28 - * The ADDR argument is passed by value. - * - * Quincey Koziol, 2002-7-180 - * Added dxpl parameter to allow more control over I/O from metadata - * cache. - * - * Bill Wendling, 2003-09-15 - * Separated out the bit of code that serializes the B-Tree - * structure. - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *bt) -{ - H5B_shared_t *shared; /* Pointer to shared B-tree info */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5B_flush, FAIL) - - /* check arguments */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(bt); - shared=H5RC_GET_OBJ(bt->rc_shared); - HDassert(shared); - assert(shared->type); - assert(shared->type->encode); - - if (bt->cache_info.is_dirty) { - if (H5B_serialize(f, bt) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTSERIALIZE, FAIL, "unable to serialize B-tree") - - /* - * Write the disk page. We always write the header, but we don't - * bother writing data for the child entries that don't exist or - * for the final unchanged children. - */ - if (H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->sizeof_rnode, dxpl_id, shared->page) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree node to disk") - - bt->cache_info.is_dirty = FALSE; - } /* end if */ - - if (destroy) - if (H5B_dest(f,bt) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} - - -/*------------------------------------------------------------------------- - * Function: H5B_dest - * - * Purpose: Destroys a B-tree node in memory. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jan 15 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -/* ARGSUSED */ -static herr_t -H5B_dest(H5F_t UNUSED *f, H5B_t *bt) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B_dest) - - /* - * Check arguments. - */ - assert(bt); - assert(bt->rc_shared); - - H5FL_SEQ_FREE(haddr_t,bt->child); - H5FL_BLK_FREE(native_block,bt->native); - H5RC_DEC(bt->rc_shared); - H5FL_FREE(H5B_t,bt); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5B_dest() */ - - -/*------------------------------------------------------------------------- - * Function: H5B_clear - * - * Purpose: Mark a B-tree node in memory as non-dirty. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 20 2003 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B_clear(H5F_t *f, H5B_t *bt, hbool_t destroy) -{ - herr_t ret_value = SUCCEED; - - FUNC_ENTER_NOAPI_NOINIT(H5B_clear) - - /* - * Check arguments. - */ - assert(bt); - - /* Reset the dirty flag. */ - bt->cache_info.is_dirty = FALSE; - - if (destroy) - if (H5B_dest(f, bt) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5B_clear() */ - - -/*------------------------------------------------------------------------- - * Function: H5B_compute_size - * - * Purpose: Compute the size in bytes of the specified instance of - * H5B_t on disk, and return it in *len_ptr. On failure, - * the value of *len_ptr is undefined. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: John Mainzer - * 5/13/04 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5B_compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_ptr) -{ - H5B_shared_t *shared; /* Pointer to shared B-tree info */ - size_t size; - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5B_compute_size) - - /* check arguments */ - HDassert(f); - HDassert(bt); - HDassert(bt->rc_shared); - shared=H5RC_GET_OBJ(bt->rc_shared); - HDassert(shared); - HDassert(shared->type); - HDassert(size_ptr); - - /* Check node's size */ - if ((size = H5B_nodesize(f, shared, NULL)) == 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, "H5B_nodesize() failed") - - /* Set size value */ - *size_ptr = size; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5B_H5B_compute_size() */ +} /* end H5B_create() */ /*lint !e818 Can't make udata a pointer to const */ /*------------------------------------------------------------------------- @@ -749,7 +379,7 @@ done: HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release node") FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5B_find() */ /*------------------------------------------------------------------------- @@ -934,7 +564,7 @@ done: HDONE_ERROR(H5E_BTREE, H5E_PROTECT, FAIL, "unable to release B-tree node") FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5B_split() */ /*------------------------------------------------------------------------- @@ -1106,7 +736,7 @@ H5B_insert(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr, done: FUNC_LEAVE_NOAPI(ret_value) -} +} /* end H5B_insert() */ /*------------------------------------------------------------------------- diff --git a/src/H5B2.c b/src/H5B2.c index b7cbb5d..194cdb6 100644 --- a/src/H5B2.c +++ b/src/H5B2.c @@ -28,15 +28,23 @@ *------------------------------------------------------------------------- */ +/****************/ +/* Module Setup */ +/****************/ + #define H5B2_PACKAGE /*suppress error about including H5B2pkg */ -/* Private headers */ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ #include "H5B2pkg.h" /* v2 B-trees */ #include "H5Eprivate.h" /* Error handling */ #include "H5MFprivate.h" /* File memory management */ -/* Local macros */ +/****************/ +/* Local Macros */ +/****************/ /* Format overhead for each node (on disk) */ #define H5B2_OVERHEAD_SIZE (H5B2_SIZEOF_MAGIC+1) /* Signature + version # */ @@ -51,9 +59,13 @@ /* #define H5B2_DEBUG */ -/* Local typedefs */ +/******************/ +/* Local Typedefs */ +/******************/ -/* Local prototypes */ +/********************/ +/* Local Prototypes */ +/********************/ /* Helper functions */ static herr_t H5B2_create_leaf(H5F_t *f, hid_t dxpl_id, H5RC_t *bt2_shared, @@ -113,7 +125,9 @@ static herr_t H5B2_assert_internal2(hsize_t parent_all_nrec, H5B2_shared_t *shar #endif /* H5B2_DEBUG */ -/* Package variables */ +/*********************/ +/* Package Variables */ +/*********************/ /* Declare a free list to manage the H5B2_t struct */ H5FL_DEFINE(H5B2_t); @@ -124,8 +138,13 @@ H5FL_DEFINE(H5B2_internal_t); /* Declare a free list to manage the H5B2_leaf_t struct */ H5FL_DEFINE(H5B2_leaf_t); +/*****************************/ +/* Library Private Variables */ +/*****************************/ -/* Static variables */ +/*******************/ +/* Local Variables */ +/*******************/ /* Declare a free list to manage B-tree node pages to/from disk */ H5FL_BLK_DEFINE_STATIC(node_page); diff --git a/src/H5B2private.h b/src/H5B2private.h index 3be4413..850eb50 100644 --- a/src/H5B2private.h +++ b/src/H5B2private.h @@ -96,6 +96,10 @@ typedef struct H5B2_class_t { } H5B2_class_t; +/*****************************/ +/* Library-private Variables */ +/*****************************/ + /***************************************/ /* Library-private Function Prototypes */ /***************************************/ diff --git a/src/H5BPcache.c b/src/H5BPcache.c index 57e1677..4580c38 100644 --- a/src/H5BPcache.c +++ b/src/H5BPcache.c @@ -551,7 +551,7 @@ H5BP_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5 /* Encode the record */ if((shared->type->encode)(f, leaf->rec_ptr[u], p, &rec_len) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, NULL, "can't encode B+ tree record") + HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "can't encode B+ tree record") assert(rec_len > 0); p += rec_len; @@ -561,7 +561,7 @@ H5BP_cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5 } /* end if */ else { HDfprintf(stderr,"%s: attempting to decode fixed-size records from leaf node\n",FUNC); -HGOTO_ERROR(H5E_BTREE, H5E_UNSUPPORTED, NULL, "Can't decode records yet!") +HGOTO_ERROR(H5E_BTREE, H5E_UNSUPPORTED, FAIL, "Can't decode records yet!") } /* end else */ #ifdef LATER diff --git a/src/H5Bcache.c b/src/H5Bcache.c new file mode 100644 index 0000000..443b482 --- /dev/null +++ b/src/H5Bcache.c @@ -0,0 +1,417 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Bcache.c + * Oct 31 2005 + * Quincey Koziol + * + * Purpose: Implement B-tree metadata cache methods. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5B_PACKAGE /*suppress error about including H5Bpkg */ + + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Bpkg.h" /* B-link trees */ +#include "H5Eprivate.h" /* Error handling */ + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +/* General routines */ +static herr_t H5B_serialize(const H5F_t *f, const H5B_t *bt); + +/* Metadata cache callbacks */ +static H5B_t *H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata); +static herr_t H5B_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *b); +static herr_t H5B_clear(H5F_t *f, H5B_t *b, hbool_t destroy); +static herr_t H5B_compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_ptr); + +/*********************/ +/* Package Variables */ +/*********************/ + +/* H5B inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_BT[1] = {{ + H5AC_BT_ID, + (H5AC_load_func_t)H5B_load, + (H5AC_flush_func_t)H5B_flush, + (H5AC_dest_func_t)H5B_dest, + (H5AC_clear_func_t)H5B_clear, + (H5AC_size_func_t)H5B_compute_size, +}}; + +/*******************/ +/* Local Variables */ +/*******************/ + + +/*------------------------------------------------------------------------- + * Function: H5B_serialize + * + * Purpose: Serialize the data structure for writing to disk or + * storing on the SAP (for FPHDF5). + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Bill Wendling + * wendling@ncsa.uiuc.edu + * Sept. 15, 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B_serialize(const H5F_t *f, const H5B_t *bt) +{ + H5B_shared_t *shared=NULL; /* Pointer to shared B-tree info */ + unsigned u; + uint8_t *p; /* Pointer into raw data buffer */ + uint8_t *native; /* Pointer to native keys */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5B_serialize, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(bt); + HDassert(bt->rc_shared); + shared=H5RC_GET_OBJ(bt->rc_shared); + HDassert(shared); + + p = shared->page; + + /* magic number */ + HDmemcpy(p, H5B_MAGIC, (size_t)H5B_SIZEOF_MAGIC); + p += 4; + + /* node type and level */ + *p++ = (uint8_t)shared->type->id; + H5_CHECK_OVERFLOW(bt->level, unsigned, uint8_t); + *p++ = (uint8_t)bt->level; + + /* entries used */ + UINT16ENCODE(p, bt->nchildren); + + /* sibling pointers */ + H5F_addr_encode(f, &p, bt->left); + H5F_addr_encode(f, &p, bt->right); + + /* child keys and pointers */ + native=bt->native; + for (u = 0; u < bt->nchildren; ++u) { + /* encode the key */ + if (shared->type->encode(f, bt, p, native) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key") + p += shared->sizeof_rkey; + native += shared->type->sizeof_nkey; + + /* encode the child address */ + H5F_addr_encode(f, &p, bt->child[u]); + } /* end for */ + if(bt->nchildren>0) { + /* Encode the final key */ + if (shared->type->encode(f, bt, p, native) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B_serialize() */ + + +/*------------------------------------------------------------------------- + * Function: H5B_load + * + * Purpose: Loads a B-tree node from the disk. + * + * Return: Success: Pointer to a new B-tree node. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 23 1997 + * + *------------------------------------------------------------------------- + */ +static H5B_t * +H5B_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_type, void *udata) +{ + const H5B_class_t *type = (const H5B_class_t *) _type; + H5B_t *bt = NULL; + H5B_shared_t *shared; /* Pointer to shared B-tree info */ + uint8_t *p; /* Pointer into raw data buffer */ + uint8_t *native; /* Pointer to native keys */ + unsigned u; /* Local index variable */ + H5B_t *ret_value; + + FUNC_ENTER_NOAPI(H5B_load, NULL) + + /* Check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(type); + HDassert(type->get_shared); + + if (NULL==(bt = H5FL_MALLOC(H5B_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HDmemset(&bt->cache_info,0,sizeof(H5AC_info_t)); + if((bt->rc_shared=(type->get_shared)(f, udata))==NULL) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "can't retrieve B-tree node buffer") + shared=H5RC_GET_OBJ(bt->rc_shared); + HDassert(shared); + if (NULL==(bt->native=H5FL_BLK_MALLOC(native_block,shared->sizeof_keys)) || + NULL==(bt->child=H5FL_SEQ_MALLOC(haddr_t,(size_t)shared->two_k))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + if (H5F_block_read(f, H5FD_MEM_BTREE, addr, shared->sizeof_rnode, dxpl_id, shared->page)<0) + HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree node") + + p = shared->page; + + /* magic number */ + if (HDmemcmp(p, H5B_MAGIC, (size_t)H5B_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree signature") + p += 4; + + /* node type and level */ + if (*p++ != (uint8_t)type->id) + HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree node type") + bt->level = *p++; + + /* entries used */ + UINT16DECODE(p, bt->nchildren); + + /* sibling pointers */ + H5F_addr_decode(f, (const uint8_t **) &p, &(bt->left)); + H5F_addr_decode(f, (const uint8_t **) &p, &(bt->right)); + + /* the child/key pairs */ + native=bt->native; + for (u = 0; u < bt->nchildren; u++) { + /* Decode native key value */ + if ((type->decode) (f, bt, p, native) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode key") + p += shared->sizeof_rkey; + native += type->sizeof_nkey; + + /* Decode address value */ + H5F_addr_decode(f, (const uint8_t **) &p, bt->child + u); + } + + /* Decode final key */ + if(bt->nchildren>0) { + /* Decode native key value */ + if ((type->decode) (f, bt, p, native) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode key") + } /* end if */ + + /* Set return value */ + ret_value = bt; + +done: + if (!ret_value && bt) + (void)H5B_dest(f,bt); + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B_load() */ /*lint !e818 Can't make udata a pointer to const */ + + +/*------------------------------------------------------------------------- + * Function: H5B_flush + * + * Purpose: Flushes a dirty B-tree node to disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jun 23 1997 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *bt) +{ + H5B_shared_t *shared; /* Pointer to shared B-tree info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5B_flush, FAIL) + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(bt); + shared=H5RC_GET_OBJ(bt->rc_shared); + HDassert(shared); + HDassert(shared->type); + HDassert(shared->type->encode); + + if (bt->cache_info.is_dirty) { + if (H5B_serialize(f, bt) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTSERIALIZE, FAIL, "unable to serialize B-tree") + + /* + * Write the disk page. We always write the header, but we don't + * bother writing data for the child entries that don't exist or + * for the final unchanged children. + */ + if (H5F_block_write(f, H5FD_MEM_BTREE, addr, shared->sizeof_rnode, dxpl_id, shared->page) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree node to disk") + + bt->cache_info.is_dirty = FALSE; + } /* end if */ + + if (destroy) + if (H5B_dest(f,bt) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5B_dest + * + * Purpose: Destroys a B-tree node in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Jan 15 2003 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +herr_t +H5B_dest(H5F_t UNUSED *f, H5B_t *bt) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5B_dest) + + /* + * Check arguments. + */ + HDassert(bt); + HDassert(bt->rc_shared); + + H5FL_SEQ_FREE(haddr_t,bt->child); + H5FL_BLK_FREE(native_block,bt->native); + H5RC_DEC(bt->rc_shared); + H5FL_FREE(H5B_t,bt); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5B_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5B_clear + * + * Purpose: Mark a B-tree node in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 20 2003 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B_clear(H5F_t *f, H5B_t *bt, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5B_clear) + + /* + * Check arguments. + */ + HDassert(bt); + + /* Reset the dirty flag. */ + bt->cache_info.is_dirty = FALSE; + + if (destroy) + if (H5B_dest(f, bt) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5B_compute_size + * + * Purpose: Compute the size in bytes of the specified instance of + * H5B_t on disk, and return it in *len_ptr. On failure, + * the value of *len_ptr is undefined. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: John Mainzer + * 5/13/04 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B_compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_ptr) +{ + H5B_shared_t *shared; /* Pointer to shared B-tree info */ + size_t size; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5B_compute_size) + + /* check arguments */ + HDassert(f); + HDassert(bt); + HDassert(bt->rc_shared); + shared=H5RC_GET_OBJ(bt->rc_shared); + HDassert(shared); + HDassert(shared->type); + HDassert(size_ptr); + + /* Check node's size */ + if ((size = H5B_nodesize(f, shared, NULL)) == 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGETSIZE, FAIL, "H5B_nodesize() failed") + + /* Set size value */ + *size_ptr = size; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5B_compute_size() */ diff --git a/src/H5Bpkg.h b/src/H5Bpkg.h index 74fa393..e96161d 100644 --- a/src/H5Bpkg.h +++ b/src/H5Bpkg.h @@ -31,7 +31,7 @@ #include "H5Bprivate.h" /* Other private headers needed by this file */ -#include "H5RCprivate.h" /* Reference counted object functions */ +#include "H5RCprivate.h" /* Reference counted objects */ /**************************/ /* Package Private Macros */ @@ -41,9 +41,7 @@ /* Package Private Typedefs */ /****************************/ -/* - * The B-tree node as stored in memory... - */ +/* The B-tree node as stored in memory... */ struct H5B_t { H5AC_info_t cache_info; /* Information for H5AC cache functions, _must_ be */ /* first field in structure */ @@ -56,8 +54,25 @@ struct H5B_t { haddr_t *child; /*2k child pointers */ }; +/*****************************/ +/* Package Private Variables */ +/*****************************/ + +/* H5B header inherits cache-like properties from H5AC */ +H5_DLLVAR const H5AC_class_t H5AC_BT[1]; + +/* Declare a free list to manage the haddr_t sequence information */ +H5FL_SEQ_EXTERN(haddr_t); + +/* Declare a PQ free list to manage the native block information */ +H5FL_BLK_EXTERN(native_block); + +/* Declare a free list to manage the H5B_t struct */ +H5FL_EXTERN(H5B_t); + /******************************/ /* Package Private Prototypes */ /******************************/ +herr_t H5B_dest(H5F_t *f, H5B_t *b); #endif /*_H5Bpkg_H*/ diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index 28494f7..246d0c5 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -34,8 +34,13 @@ #include "H5private.h" /* Generic Functions */ #include "H5ACprivate.h" /* Metadata cache */ #include "H5Fprivate.h" /* File access */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5RCprivate.h" /* Reference counted object functions */ +/**************************/ +/* Library Private Macros */ +/**************************/ + /* * Feature: Define this constant if you want to check B-tree consistency * after each B-tree operation. Note that this slows down the @@ -48,6 +53,19 @@ #define H5B_MAGIC "TREE" /*tree node magic number */ #define H5B_SIZEOF_MAGIC 4 /*size of magic number */ +/* Define return values from operator callback function for H5B_iterate */ +/* (Actually, any postive value will cause the iterator to stop and pass back + * that positive value to the function that called the iterator) + */ +#define H5B_ITER_ERROR (-1) +#define H5B_ITER_CONT (0) +#define H5B_ITER_STOP (1) + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* Define return values from B-tree insertion callbacks */ typedef enum H5B_ins_t { H5B_INS_ERROR = -1, /*error return value */ H5B_INS_NOOP = 0, /*insert made no changes */ @@ -58,14 +76,6 @@ typedef enum H5B_ins_t { H5B_INS_REMOVE = 5 /*remove current node */ } H5B_ins_t; -/* Define return values from operator callback function for H5B_iterate */ -/* (Actually, any postive value will cause the iterator to stop and pass back - * that positive value to the function that called the iterator) - */ -#define H5B_ITER_ERROR (-1) -#define H5B_ITER_CONT (0) -#define H5B_ITER_STOP (1) - /* Define the operator callback function pointer for H5B_iterate() */ typedef int (*H5B_operator_t)(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, const void *_rt_key, void *_udata); @@ -97,7 +107,6 @@ typedef struct H5B_shared_t { typedef struct H5B_class_t { H5B_subid_t id; /*id as found in file*/ size_t sizeof_nkey; /*size of native (memory) key*/ - size_t (*get_sizeof_rkey)(const H5F_t*, const void*); /*raw key size */ H5RC_t * (*get_shared)(const H5F_t*, const void*); /*shared info for node */ herr_t (*new_node)(H5F_t*, hid_t, H5B_ins_t, void*, void*, void*, haddr_t*); int (*cmp2)(H5F_t*, hid_t, void*, void*, void*); /*compare 2 keys */ @@ -120,12 +129,19 @@ typedef struct H5B_class_t { herr_t (*decode)(const H5F_t*, const struct H5B_t*, const uint8_t*, void*); herr_t (*encode)(const H5F_t*, const struct H5B_t*, uint8_t*, void*); herr_t (*debug_key)(FILE*, H5F_t*, hid_t, int, int, const void*, const void*); - } H5B_class_t; -/* - * Library prototypes. - */ +/*****************************/ +/* Library-private Variables */ +/*****************************/ + +/* Declare a free list to manage the H5B_shared_t struct */ +H5FL_EXTERN(H5B_shared_t); + + +/***************************************/ +/* Library-private Function Prototypes */ +/***************************************/ H5_DLL size_t H5B_nodesize(const H5F_t *f, const H5B_shared_t *shared, size_t *total_nkey_size); H5_DLL herr_t H5B_create (H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, void *udata, diff --git a/src/H5D.c b/src/H5D.c index 8f73149..156b70d 100644 --- a/src/H5D.c +++ b/src/H5D.c @@ -87,6 +87,10 @@ static herr_t H5D_xfer_xform_close(const char* name, size_t size, void* value); /* Define a "default" dataset transfer property list cache structure to use for default DXPLs */ H5D_dxpl_cache_t H5D_def_dxpl_cache; +/*****************************/ +/* Library Private Variables */ +/*****************************/ + /*******************/ /* Local Variables */ /*******************/ diff --git a/src/H5Distore.c b/src/H5Distore.c index bf0c92e..b0d60d6 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -144,14 +144,57 @@ typedef struct H5D_istore_key_t { unsigned filter_mask; /*excluded filters */ } H5D_istore_key_t; -typedef struct H5D_istore_ud1_t { +/* + * Common data exchange structure for indexed storage nodes. This structure is + * passed through the B-link tree layer to the methods for the objects + * to which the B-link tree points. + */ +typedef struct H5D_istore_bt_ud_common_t { + /* downward */ H5D_istore_key_t key; /*key values */ - haddr_t addr; /*file address of chunk */ const H5O_layout_t *mesg; /*layout message */ +} H5D_istore_bt_ud_common_t; + +/* + * Data exchange structure for indexed storage nodes. This structure is + * passed through the B-link tree layer to the methods for the objects + * to which the B-link tree points for operations which require no + * additional information. + * + * (Just an alias for the "common" info). + */ +typedef H5D_istore_bt_ud_common_t H5D_istore_ud0_t; + +typedef struct H5D_istore_ud1_t { + H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */ + haddr_t addr; /*file address of chunk */ +} H5D_istore_ud1_t; + +/* B-tree callback info for iteration to total allocated space */ +typedef struct H5D_istore_it_ud1_t { + H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */ hsize_t total_storage; /*output from iterator */ +} H5D_istore_it_ud1_t; + +/* B-tree callback info for iteration to dump node's info */ +typedef struct H5D_istore_it_ud2_t { + H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */ FILE *stream; /*debug output stream */ + hbool_t header_displayed; /* Node's header is displayed? */ +} H5D_istore_it_ud2_t; + +/* B-tree callback info for iteration to prune chunks */ +typedef struct H5D_istore_it_ud3_t { + H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */ hsize_t *dims; /*dataset dimensions */ -} H5D_istore_ud1_t; +} H5D_istore_it_ud3_t; + +/* B-tree callback info for iteration to copy data */ +typedef struct H5D_istore_it_ud4_t { + H5D_istore_bt_ud_common_t common; /* Common info for B-tree user data (must be first) */ + H5F_t *file_dst; /* Destination file for copy */ + haddr_t addr_dst; /* Address of dest. B-tree */ +} H5D_istore_it_ud4_t; /********************/ /* Local Prototypes */ @@ -169,9 +212,10 @@ static int H5D_istore_iter_dump(H5F_t *f, hid_t dxpl_id, const void *left_key, h const void *right_key, void *_udata); static int H5D_istore_prune_extent(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, const void *_rt_key, void *_udata); +static int H5D_istore_iter_copy(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, + const void *_rt_key, void *_udata); /* B-tree callbacks */ -static size_t H5D_istore_sizeof_rkey(const H5F_t *f, const void *_udata); static H5RC_t *H5D_istore_get_shared(const H5F_t *f, const void *_udata); static herr_t H5D_istore_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t, void *_lt_key, void *_udata, void *_rt_key, @@ -202,7 +246,6 @@ static herr_t H5D_istore_debug_key(FILE *stream, H5F_t *f, hid_t dxpl_id, H5B_class_t H5B_ISTORE[1] = {{ H5B_ISTORE_ID, /*id */ sizeof(H5D_istore_key_t), /*sizeof_nkey */ - H5D_istore_sizeof_rkey, /*get_sizeof_rkey */ H5D_istore_get_shared, /*get_shared */ H5D_istore_new_node, /*new */ H5D_istore_cmp2, /*cmp2 */ @@ -221,13 +264,14 @@ H5B_class_t H5B_ISTORE[1] = {{ /* Package Variables */ /*********************/ +/*****************************/ +/* Library Private Variables */ +/*****************************/ + /*******************/ /* Local Variables */ /*******************/ -/* Declare a free list to manage the H5B_shared_t struct */ -H5FL_EXTERN(H5B_shared_t); - /* Declare a free list to manage H5F_rdcc_ent_t objects */ H5FL_DEFINE_STATIC(H5D_rdcc_ent_t); @@ -245,43 +289,6 @@ H5FL_BLK_DEFINE_STATIC(chunk_page); /*------------------------------------------------------------------------- - * Function: H5D_istore_sizeof_rkey - * - * Purpose: Returns the size of a raw key for the specified UDATA. The - * size of the key is dependent on the number of dimensions for - * the object to which this B-tree points. The dimensionality - * of the UDATA is the only portion that's referenced here. - * - * Return: Success: Size of raw key in bytes. - * - * Failure: abort() - * - * Programmer: Robb Matzke - * Wednesday, October 8, 1997 - * - *------------------------------------------------------------------------- - */ -/* ARGSUSED */ -static size_t -H5D_istore_sizeof_rkey(const H5F_t UNUSED *f, const void *_udata) -{ - const H5D_istore_ud1_t *udata = (const H5D_istore_ud1_t *) _udata; - size_t nbytes; - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_sizeof_rkey) - - assert(udata); - assert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS); - - nbytes = 4 + /*storage size */ - 4 + /*filter mask */ - udata->mesg->u.chunk.ndims*8; /*dimension indices */ - - FUNC_LEAVE_NOAPI(nbytes) -} /* end H5D_istore_sizeof_rkey() */ - - -/*------------------------------------------------------------------------- * Function: H5D_istore_get_shared * * Purpose: Returns the shared B-tree info for the specified UDATA. @@ -299,13 +306,13 @@ H5D_istore_sizeof_rkey(const H5F_t UNUSED *f, const void *_udata) static H5RC_t * H5D_istore_get_shared(const H5F_t UNUSED *f, const void *_udata) { - const H5D_istore_ud1_t *udata = (const H5D_istore_ud1_t *) _udata; + const H5D_istore_ud0_t *udata = (const H5D_istore_ud0_t *) _udata; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_get_shared) - assert(udata); - assert(udata->mesg); - assert(udata->mesg->u.chunk.btree_shared); + HDassert(udata); + HDassert(udata->mesg); + HDassert(udata->mesg->u.chunk.btree_shared); /* Increment reference count on B-tree info */ H5RC_INC(udata->mesg->u.chunk.btree_shared); @@ -413,26 +420,23 @@ H5D_istore_encode_key(const H5F_t UNUSED *f, const H5B_t *bt, uint8_t *raw, void */ /* ARGSUSED */ static herr_t -H5D_istore_debug_key (FILE *stream, H5F_t UNUSED *f, hid_t UNUSED dxpl_id, int indent, int fwidth, +H5D_istore_debug_key(FILE *stream, H5F_t UNUSED *f, hid_t UNUSED dxpl_id, int indent, int fwidth, const void *_key, const void *_udata) { const H5D_istore_key_t *key = (const H5D_istore_key_t *)_key; - const H5D_istore_ud1_t *udata = (const H5D_istore_ud1_t *)_udata; + const H5D_istore_ud0_t *udata = (const H5D_istore_ud0_t *)_udata; unsigned u; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_debug_key) - assert (key); + HDassert(key); - HDfprintf(stream, "%*s%-*s %Zd bytes\n", indent, "", fwidth, - "Chunk size:", key->nbytes); - HDfprintf(stream, "%*s%-*s 0x%08x\n", indent, "", fwidth, - "Filter mask:", key->filter_mask); - HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, - "Logical offset:"); - for (u=0; umesg->u.chunk.ndims; u++) - HDfprintf (stream, "%s%Hd", u?", ":"", key->offset[u]); - HDfputs ("}\n", stream); + HDfprintf(stream, "%*s%-*s %Zd bytes\n", indent, "", fwidth, "Chunk size:", key->nbytes); + HDfprintf(stream, "%*s%-*s 0x%08x\n", indent, "", fwidth, "Filter mask:", key->filter_mask); + HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Logical offset:"); + for(u = 0; u < udata->mesg->u.chunk.ndims; u++) + HDfprintf(stream, "%s%Hd", u?", ":"", key->offset[u]); + HDfputs("}\n", stream); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5D_istore_debug_key() */ @@ -464,15 +468,15 @@ H5D_istore_cmp2(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_uda { H5D_istore_key_t *lt_key = (H5D_istore_key_t *) _lt_key; H5D_istore_key_t *rt_key = (H5D_istore_key_t *) _rt_key; - H5D_istore_ud1_t *udata = (H5D_istore_ud1_t *) _udata; + H5D_istore_ud0_t *udata = (H5D_istore_ud0_t *) _udata; int ret_value; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_cmp2) - assert(lt_key); - assert(rt_key); - assert(udata); - assert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS); + HDassert(lt_key); + HDassert(rt_key); + HDassert(udata); + HDassert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS); /* Compare the offsets but ignore the other fields */ ret_value = H5V_vector_cmp_u(udata->mesg->u.chunk.ndims, lt_key->offset, rt_key->offset); @@ -515,15 +519,15 @@ H5D_istore_cmp3(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, void *_lt_key, void *_uda { H5D_istore_key_t *lt_key = (H5D_istore_key_t *) _lt_key; H5D_istore_key_t *rt_key = (H5D_istore_key_t *) _rt_key; - H5D_istore_ud1_t *udata = (H5D_istore_ud1_t *) _udata; + H5D_istore_ud0_t *udata = (H5D_istore_ud0_t *) _udata; int ret_value = 0; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_cmp3) - assert(lt_key); - assert(rt_key); - assert(udata); - assert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS); + HDassert(lt_key); + HDassert(rt_key); + HDassert(udata); + HDassert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims <= H5O_LAYOUT_NDIMS); /* Special case for faster checks on 1-D chunks */ /* (Checking for ndims==2 because last dimension is the datatype size) */ @@ -580,22 +584,22 @@ H5D_istore_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t op, H5D_istore_key_t *rt_key = (H5D_istore_key_t *) _rt_key; H5D_istore_ud1_t *udata = (H5D_istore_ud1_t *) _udata; unsigned u; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5D_istore_new_node) /* check args */ - assert(f); - assert(lt_key); - assert(rt_key); - assert(udata); - assert(udata->mesg->u.chunk.ndims > 0 && udata->mesg->u.chunk.ndims < H5O_LAYOUT_NDIMS); - assert(addr_p); + HDassert(f); + HDassert(lt_key); + HDassert(rt_key); + HDassert(udata); + HDassert(udata->common.mesg->u.chunk.ndims > 0 && udata->common.mesg->u.chunk.ndims < H5O_LAYOUT_NDIMS); + HDassert(addr_p); /* Allocate new storage */ - assert (udata->key.nbytes > 0); - H5_CHECK_OVERFLOW( udata->key.nbytes ,size_t, hsize_t); - if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->key.nbytes))) + HDassert(udata->common.key.nbytes > 0); + H5_CHECK_OVERFLOW(udata->common.key.nbytes ,size_t, hsize_t); + if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->common.key.nbytes))) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "couldn't allocate new file storage") udata->addr = *addr_p; @@ -603,10 +607,10 @@ H5D_istore_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t op, * The left key describes the storage of the UDATA chunk being * inserted into the tree. */ - lt_key->nbytes = udata->key.nbytes; - lt_key->filter_mask = udata->key.filter_mask; - for (u=0; umesg->u.chunk.ndims; u++) - lt_key->offset[u] = udata->key.offset[u]; + lt_key->nbytes = udata->common.key.nbytes; + lt_key->filter_mask = udata->common.key.filter_mask; + for (u=0; ucommon.mesg->u.chunk.ndims; u++) + lt_key->offset[u] = udata->common.key.offset[u]; /* * The right key might already be present. If not, then add a zero-width @@ -615,10 +619,10 @@ H5D_istore_new_node(H5F_t *f, hid_t dxpl_id, H5B_ins_t op, if (H5B_INS_LEFT != op) { rt_key->nbytes = 0; rt_key->filter_mask = 0; - for (u=0; umesg->u.chunk.ndims; u++) { - assert (udata->key.offset[u]+udata->mesg->u.chunk.dim[u] > - udata->key.offset[u]); - rt_key->offset[u] = udata->key.offset[u] + udata->mesg->u.chunk.dim[u]; + for (u=0; ucommon.mesg->u.chunk.ndims; u++) { + HDassert(udata->common.key.offset[u]+udata->common.mesg->u.chunk.dim[u] > + udata->common.key.offset[u]); + rt_key->offset[u] = udata->common.key.offset[u] + udata->common.mesg->u.chunk.dim[u]; } } @@ -659,28 +663,28 @@ H5D_istore_found(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, haddr_t addr, const void H5D_istore_ud1_t *udata = (H5D_istore_ud1_t *) _udata; const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *) _lt_key; unsigned u; - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_found) /* Check arguments */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(udata); - assert(lt_key); + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(udata); + HDassert(lt_key); /* Is this *really* the requested chunk? */ - for (u=0; umesg->u.chunk.ndims; u++) - if (udata->key.offset[u] >= lt_key->offset[u]+udata->mesg->u.chunk.dim[u]) + for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) + if(udata->common.key.offset[u] >= lt_key->offset[u] + udata->common.mesg->u.chunk.dim[u]) HGOTO_DONE(FAIL) /* Initialize return values */ udata->addr = addr; - udata->key.nbytes = lt_key->nbytes; - udata->key.filter_mask = lt_key->filter_mask; - assert (lt_key->nbytes>0); - for (u = 0; u < udata->mesg->u.chunk.ndims; u++) - udata->key.offset[u] = lt_key->offset[u]; + udata->common.key.nbytes = lt_key->nbytes; + udata->common.key.filter_mask = lt_key->filter_mask; + HDassert(lt_key->nbytes>0); + for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) + udata->common.key.offset[u] = lt_key->offset[u]; done: FUNC_LEAVE_NOAPI(ret_value) @@ -734,30 +738,30 @@ H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, FUNC_ENTER_NOAPI_NOINIT(H5D_istore_insert) /* check args */ - assert(f); - assert(H5F_addr_defined(addr)); - assert(lt_key); - assert(lt_key_changed); - assert(md_key); - assert(udata); - assert(rt_key); - assert(new_node_p); + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(lt_key); + HDassert(lt_key_changed); + HDassert(md_key); + HDassert(udata); + HDassert(rt_key); + HDassert(new_node_p); cmp = H5D_istore_cmp3(f, dxpl_id, lt_key, udata, rt_key); - assert(cmp <= 0); + HDassert(cmp <= 0); if (cmp < 0) { /* Negative indices not supported yet */ HGOTO_ERROR(H5E_STORAGE, H5E_UNSUPPORTED, H5B_INS_ERROR, "internal error") - } else if (H5V_vector_eq_u (udata->mesg->u.chunk.ndims, - udata->key.offset, lt_key->offset) && + } else if (H5V_vector_eq_u (udata->common.mesg->u.chunk.ndims, + udata->common.key.offset, lt_key->offset) && lt_key->nbytes>0) { /* * Already exists. If the new size is not the same as the old size * then we should reallocate storage. */ - if (lt_key->nbytes != udata->key.nbytes) { + if (lt_key->nbytes != udata->common.key.nbytes) { /* Currently, the old chunk data is "thrown away" after the space is reallocated, * so avoid data copy in H5MF_realloc() call by just free'ing the space and * allocating new space. @@ -768,19 +772,19 @@ H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, * QAK - 11/19/2002 */ #ifdef OLD_WAY - if (HADDR_UNDEF==(*new_node_p=H5MF_realloc(f, H5FD_MEM_DRAW, addr, - (hsize_t)lt_key->nbytes, (hsize_t)udata->key.nbytes))) - HGOTO_ERROR (H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk storage") + if(HADDR_UNDEF == (*new_node_p = H5MF_realloc(f, H5FD_MEM_DRAW, addr, + (hsize_t)lt_key->nbytes, (hsize_t)udata->common.key.nbytes))) + HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk storage") #else /* OLD_WAY */ H5_CHECK_OVERFLOW( lt_key->nbytes ,size_t, hsize_t); - if (H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes)<0) + if(H5MF_xfree(f, H5FD_MEM_DRAW, dxpl_id, addr, (hsize_t)lt_key->nbytes)<0) HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, H5B_INS_ERROR, "unable to free chunk") - H5_CHECK_OVERFLOW( udata->key.nbytes ,size_t, hsize_t); - if (HADDR_UNDEF==(*new_node_p=H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->key.nbytes))) + H5_CHECK_OVERFLOW(udata->common.key.nbytes ,size_t, hsize_t); + if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->common.key.nbytes))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "unable to reallocate chunk") #endif /* OLD_WAY */ - lt_key->nbytes = udata->key.nbytes; - lt_key->filter_mask = udata->key.filter_mask; + lt_key->nbytes = udata->common.key.nbytes; + lt_key->filter_mask = udata->common.key.filter_mask; *lt_key_changed = TRUE; udata->addr = *new_node_p; ret_value = H5B_INS_CHANGE; @@ -789,28 +793,28 @@ H5D_istore_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_lt_key, ret_value = H5B_INS_NOOP; } - } else if (H5V_hyper_disjointp(udata->mesg->u.chunk.ndims, - lt_key->offset, udata->mesg->u.chunk.dim, - udata->key.offset, udata->mesg->u.chunk.dim)) { - assert(H5V_hyper_disjointp(udata->mesg->u.chunk.ndims, - rt_key->offset, udata->mesg->u.chunk.dim, - udata->key.offset, udata->mesg->u.chunk.dim)); + } else if (H5V_hyper_disjointp(udata->common.mesg->u.chunk.ndims, + lt_key->offset, udata->common.mesg->u.chunk.dim, + udata->common.key.offset, udata->common.mesg->u.chunk.dim)) { + HDassert(H5V_hyper_disjointp(udata->common.mesg->u.chunk.ndims, + rt_key->offset, udata->common.mesg->u.chunk.dim, + udata->common.key.offset, udata->common.mesg->u.chunk.dim)); /* * Split this node, inserting the new new node to the right of the * current node. The MD_KEY is where the split occurs. */ - md_key->nbytes = udata->key.nbytes; - md_key->filter_mask = udata->key.filter_mask; - for (u=0; umesg->u.chunk.ndims; u++) { - assert(0 == udata->key.offset[u] % udata->mesg->u.chunk.dim[u]); - md_key->offset[u] = udata->key.offset[u]; + md_key->nbytes = udata->common.key.nbytes; + md_key->filter_mask = udata->common.key.filter_mask; + for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) { + HDassert(0 == udata->common.key.offset[u] % udata->common.mesg->u.chunk.dim[u]); + md_key->offset[u] = udata->common.key.offset[u]; } /* * Allocate storage for the new chunk */ - H5_CHECK_OVERFLOW( udata->key.nbytes ,size_t, hsize_t); - if (HADDR_UNDEF==(*new_node_p=H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->key.nbytes))) + H5_CHECK_OVERFLOW(udata->common.key.nbytes ,size_t, hsize_t); + if(HADDR_UNDEF == (*new_node_p = H5MF_alloc(f, H5FD_MEM_DRAW, dxpl_id, (hsize_t)udata->common.key.nbytes))) HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, H5B_INS_ERROR, "file allocation failed") udata->addr = *new_node_p; ret_value = H5B_INS_RIGHT; @@ -843,12 +847,12 @@ static int H5D_istore_iter_allocated (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_lt_key, haddr_t UNUSED addr, const void UNUSED *_rt_key, void *_udata) { - H5D_istore_ud1_t *bt_udata = (H5D_istore_ud1_t *)_udata; + H5D_istore_it_ud1_t *udata = (H5D_istore_it_ud1_t *)_udata; const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *)_lt_key; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_iter_allocated) - bt_udata->total_storage += lt_key->nbytes; + udata->total_storage += lt_key->nbytes; FUNC_LEAVE_NOAPI(H5B_ITER_CONT) } /* H5D_istore_iter_allocated() */ @@ -874,35 +878,86 @@ static int H5D_istore_iter_dump (H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_lt_key, haddr_t UNUSED addr, const void UNUSED *_rt_key, void *_udata) { - H5D_istore_ud1_t *bt_udata = (H5D_istore_ud1_t *)_udata; + H5D_istore_it_ud2_t *udata = (H5D_istore_it_ud2_t *)_udata; const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *)_lt_key; unsigned u; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_iter_dump) - if (bt_udata->stream) { - if (0==bt_udata->total_storage) { - fprintf(bt_udata->stream, - " Flags Bytes Address Logical Offset\n"); - fprintf(bt_udata->stream, - " ========== ======== ========== " - "==============================\n"); - } - HDfprintf(bt_udata->stream, " 0x%08x %8Zu %10a [", - lt_key->filter_mask, lt_key->nbytes, addr); - for (u=0; umesg->u.chunk.ndims; u++) - HDfprintf(bt_udata->stream, "%s%Hd", u?", ":"", lt_key->offset[u]); - HDfputs("]\n", bt_udata->stream); - - /* Use "total storage" information as flag for printing headers */ - bt_udata->total_storage++; - } + if(udata->stream) { + if(!udata->header_displayed) { + HDfprintf(udata->stream, " Flags Bytes Address Logical Offset\n"); + HDfprintf(udata->stream, " ========== ======== ========== ==============================\n"); + + /* Set flag that the headers has been printed */ + udata->header_displayed = TRUE; + } /* end if */ + HDfprintf(udata->stream, " 0x%08x %8Zu %10a [", lt_key->filter_mask, lt_key->nbytes, addr); + for(u = 0; u < udata->common.mesg->u.chunk.ndims; u++) + HDfprintf(udata->stream, "%s%Hd", (u ? ", " : ""), lt_key->offset[u]); + HDfputs("]\n", udata->stream); + } /* end if */ FUNC_LEAVE_NOAPI(H5B_ITER_CONT) } /* H5D_istore_iter_dump() */ /*------------------------------------------------------------------------- + * Function: H5D_istore_iter_copy + * + * Purpose: copy chunked raw data from source file and insert to the + * B-tree node in the destination file + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Peter Cao + * August 20, 2005 + * + *------------------------------------------------------------------------- + */ +static int +H5D_istore_iter_copy(H5F_t *f_src, hid_t dxpl_id, const void *_lt_key, haddr_t addr_src, + const void UNUSED *_rt_key, void *_udata) +{ + H5D_istore_it_ud4_t *udata = (H5D_istore_it_ud4_t *)_udata; + const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *)_lt_key; + void *chunk = NULL; /*the chunk data */ + H5D_istore_ud1_t udata_dst; + int ret_value = H5B_ITER_CONT; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5D_istore_iter_copy) + + /* Allocate memory for copying the chunk */ + if(NULL == (chunk = H5MM_malloc(lt_key->nbytes))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5B_ITER_ERROR, "memory allocation failed for raw data chunk") + + /* read chunk data from the source file */ + if(H5F_block_read(f_src, H5FD_MEM_DRAW, addr_src, lt_key->nbytes, dxpl_id, chunk) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, H5B_ITER_ERROR, "unable to read raw data chunk") + + /* Copy source chunk callback information for insertion */ + HDmemset(&udata_dst, 0, sizeof(udata_dst)); + HDmemcpy(&(udata_dst.common.key), lt_key, sizeof(H5D_istore_key_t)); + udata_dst.common.mesg = udata->common.mesg; /* Share this pointer for a short while */ + + /* Insert chunk into the destination Btree */ + if(H5B_insert(udata->file_dst, dxpl_id, H5B_ISTORE, udata->addr_dst, &udata_dst) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, H5B_ITER_ERROR, "unable to allocate chunk") + + /* Write chunk data to destination file */ + HDassert(H5F_addr_defined(udata_dst.addr)); + if(H5F_block_write(udata->file_dst, H5FD_MEM_DRAW, udata_dst.addr, udata_dst.common.key.nbytes, dxpl_id, chunk) < 0) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, H5B_ITER_ERROR, "unable to write raw data to file") + +done: + if(chunk) + H5MM_xfree(chunk); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_istore_iter_copy() */ + + +/*------------------------------------------------------------------------- * Function: H5D_istore_init * * Purpose: Initialize the raw data chunk cache for a dataset. This is @@ -974,12 +1029,12 @@ H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_ if (ent->dirty) { H5D_istore_ud1_t udata; /*pass through B-tree */ - udata.mesg = &io_info->dset->shared->layout; - udata.key.filter_mask = 0; + udata.common.mesg = &io_info->dset->shared->layout; + udata.common.key.filter_mask = 0; udata.addr = HADDR_UNDEF; - udata.key.nbytes = ent->chunk_size; + udata.common.key.nbytes = ent->chunk_size; for (u=0; udset->shared->layout.u.chunk.ndims; u++) - udata.key.offset[u] = ent->offset[u]; + udata.common.key.offset[u] = ent->offset[u]; alloc = ent->alloc_size; /* Should the chunk be filtered before writing it to disk? */ @@ -1005,8 +1060,8 @@ H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_ point_of_no_return = TRUE; ent->chunk = NULL; } - if (H5Z_pipeline(&(io_info->dset->shared->dcpl_cache.pline), 0, &(udata.key.filter_mask), io_info->dxpl_cache->err_detect, - io_info->dxpl_cache->filter_cb, &(udata.key.nbytes), &alloc, &buf)<0) + if (H5Z_pipeline(&(io_info->dset->shared->dcpl_cache.pline), 0, &(udata.common.key.filter_mask), io_info->dxpl_cache->err_detect, + io_info->dxpl_cache->filter_cb, &(udata.common.key.nbytes), &alloc, &buf)<0) HGOTO_ERROR(H5E_PLINE, H5E_WRITEERROR, FAIL, "output pipeline failed") } @@ -1016,7 +1071,7 @@ H5D_istore_flush_entry(const H5D_io_info_t *io_info, H5D_rdcc_ent_t *ent, hbool_ */ if (H5B_insert(io_info->dset->ent.file, io_info->dxpl_id, H5B_ISTORE, io_info->dset->shared->layout.u.chunk.addr, &udata)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to allocate chunk") - if (H5F_block_write(io_info->dset->ent.file, H5FD_MEM_DRAW, udata.addr, udata.key.nbytes, io_info->dxpl_id, buf)<0) + if (H5F_block_write(io_info->dset->ent.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, io_info->dxpl_id, buf)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") /* Mark cache entry as clean */ @@ -1251,16 +1306,12 @@ done: static herr_t H5D_istore_shared_create (const H5F_t *f, H5O_layout_t *layout) { - H5D_istore_ud1_t udata; H5B_shared_t *shared; /* Shared B-tree node info */ size_t u; /* Local index variable */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5D_istore_shared_create) - /* Initialize "user" data for B-tree callbacks, etc. */ - udata.mesg = layout; - /* Allocate space for the shared structure */ if(NULL==(shared=H5FL_MALLOC(H5B_shared_t))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for shared B-tree info") @@ -1268,7 +1319,9 @@ H5D_istore_shared_create (const H5F_t *f, H5O_layout_t *layout) /* Set up the "global" information for this file's groups */ shared->type= H5B_ISTORE; shared->two_k=2*H5F_KVALUE(f,H5B_ISTORE); - shared->sizeof_rkey = H5D_istore_sizeof_rkey(f, &udata); + shared->sizeof_rkey = 4 + /*storage size */ + 4 + /*filter mask */ + layout->u.chunk.ndims*8; /*dimension indices */ assert(shared->sizeof_rkey); shared->sizeof_rnode = H5B_nodesize(f, shared, &shared->sizeof_keys); assert(shared->sizeof_rnode); @@ -1539,10 +1592,10 @@ H5D_istore_lock(const H5D_io_info_t *io_info, haddr_t chunk_addr; /* Address of chunk on disk */ if(udata!=NULL) - chunk_addr=udata->addr; + chunk_addr = udata->addr; else { /* Point at temporary storage for B-tree pass through */ - udata=&tmp_udata; + udata = &tmp_udata; /* * Not in the cache. Read it from the file and count this as a miss @@ -1552,22 +1605,22 @@ H5D_istore_lock(const H5D_io_info_t *io_info, } /* end else */ if (H5F_addr_defined(chunk_addr)) { - size_t chunk_alloc=0; /*allocated chunk size */ + size_t chunk_alloc = 0; /*allocated chunk size */ /* * The chunk exists on disk. */ /* Chunk size on disk isn't [likely] the same size as the final chunk * size in memory, so allocate memory big enough. */ - chunk_alloc = udata->key.nbytes; + chunk_alloc = udata->common.key.nbytes; if (NULL==(chunk = H5D_istore_chunk_alloc (chunk_alloc,pline))) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk") - if (H5F_block_read(dset->ent.file, H5FD_MEM_DRAW, chunk_addr, udata->key.nbytes, io_info->dxpl_id, chunk)<0) + if (H5F_block_read(dset->ent.file, H5FD_MEM_DRAW, chunk_addr, udata->common.key.nbytes, io_info->dxpl_id, chunk)<0) HGOTO_ERROR (H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk") if (pline->nused) - if (H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->key.filter_mask), io_info->dxpl_cache->err_detect, - io_info->dxpl_cache->filter_cb, &(udata->key.nbytes), &chunk_alloc, &chunk)<0) { + if (H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->common.key.filter_mask), io_info->dxpl_cache->err_detect, + io_info->dxpl_cache->filter_cb, &(udata->common.key.nbytes), &chunk_alloc, &chunk)<0) { HGOTO_ERROR(H5E_PLINE, H5E_READERROR, NULL, "data pipeline read failed") } #ifdef H5D_ISTORE_DEBUG @@ -1831,16 +1884,16 @@ H5D_istore_readvv(const H5D_io_info_t *io_info, FUNC_ENTER_NOAPI(H5D_istore_readvv, FAIL) /* Check args */ - assert(io_info); - assert(dset && H5D_CHUNKED==dset->shared->layout.type); - assert(dset->shared->layout.u.chunk.ndims>0 && dset->shared->layout.u.chunk.ndims<=H5O_LAYOUT_NDIMS); - assert(io_info->dxpl_cache); - assert(io_info->store); - assert(chunk_len_arr); - assert(chunk_offset_arr); - assert(mem_len_arr); - assert(mem_offset_arr); - assert(buf); + HDassert(io_info); + HDassert(dset && H5D_CHUNKED==dset->shared->layout.type); + HDassert(dset->shared->layout.u.chunk.ndims>0 && dset->shared->layout.u.chunk.ndims<=H5O_LAYOUT_NDIMS); + HDassert(io_info->dxpl_cache); + HDassert(io_info->store); + HDassert(chunk_len_arr); + HDassert(chunk_offset_arr); + HDassert(mem_len_arr); + HDassert(mem_offset_arr); + HDassert(buf); /* Get the address of this chunk on disk */ #ifdef QAK @@ -1848,7 +1901,7 @@ HDfprintf(stderr,"%s: io_info->store->chunk.offset={",FUNC); for(u=0; ushared->layout.u.chunk.ndims; u++) HDfprintf(stderr,"%Hd%s",io_info->store->chunk.offset[u],(u<(dset->shared->layout.u.chunk.ndims-1) ? ", " : "}\n")); #endif /* QAK */ - chunk_addr=H5D_istore_get_addr(io_info, &udata); + chunk_addr = H5D_istore_get_addr(io_info, &udata); #ifdef QAK HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Zu\n",FUNC,chunk_addr,dset->shared->layout.u.chunk.size); HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]); @@ -2013,7 +2066,7 @@ H5D_istore_writevv(const 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[], const void *buf) { - H5D_t *dset=io_info->dset; /* Local pointer to the dataset info */ + H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */ H5D_istore_ud1_t udata; /*B-tree pass-through */ haddr_t chunk_addr; /* Chunk address on disk */ size_t u; /* Local index variables */ @@ -2022,16 +2075,16 @@ H5D_istore_writevv(const H5D_io_info_t *io_info, FUNC_ENTER_NOAPI(H5D_istore_writevv, FAIL) /* Check args */ - assert(io_info); - assert(dset && H5D_CHUNKED==dset->shared->layout.type); - assert(dset->shared->layout.u.chunk.ndims>0 && dset->shared->layout.u.chunk.ndims<=H5O_LAYOUT_NDIMS); - assert(io_info->dxpl_cache); - assert(io_info->store); - assert(chunk_len_arr); - assert(chunk_offset_arr); - assert(mem_len_arr); - assert(mem_offset_arr); - assert(buf); + HDassert(io_info); + HDassert(dset && H5D_CHUNKED==dset->shared->layout.type); + HDassert(dset->shared->layout.u.chunk.ndims>0 && dset->shared->layout.u.chunk.ndims<=H5O_LAYOUT_NDIMS); + HDassert(io_info->dxpl_cache); + HDassert(io_info->store); + HDassert(chunk_len_arr); + HDassert(chunk_offset_arr); + HDassert(mem_len_arr); + HDassert(mem_offset_arr); + HDassert(buf); /* Get the address of this chunk on disk */ #ifdef QAK @@ -2039,7 +2092,7 @@ HDfprintf(stderr,"%s: io_info->store->chunk.offset={",FUNC); for(u=0; ushared->layout.u.chunk.ndims; u++) HDfprintf(stderr,"%Hd%s",io_info->store->chunk.offset[u],(u<(dset->shared->layout.u.chunk.ndims-1) ? ", " : "}\n")); #endif /* QAK */ - chunk_addr=H5D_istore_get_addr(io_info, &udata); + chunk_addr = H5D_istore_get_addr(io_info, &udata); #ifdef QAK HDfprintf(stderr,"%s: chunk_addr=%a, chunk_size=%Zu\n",FUNC,chunk_addr,dset->shared->layout.u.chunk.size); HDfprintf(stderr,"%s: chunk_len_arr[%Zu]=%Zu\n",FUNC,*chunk_curr_seq,chunk_len_arr[*chunk_curr_seq]); @@ -2161,29 +2214,29 @@ done: *------------------------------------------------------------------------- */ herr_t -H5D_istore_create(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout /*out */ ) +H5D_istore_create(H5F_t *f, hid_t dxpl_id, H5O_layout_t *layout /*out */) { - H5D_istore_ud1_t udata; + H5D_istore_ud0_t udata; #ifndef NDEBUG unsigned u; #endif - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5D_istore_create, FAIL) /* Check args */ - assert(f); - assert(layout && H5D_CHUNKED == layout->type); - assert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS); + HDassert(f); + HDassert(layout && H5D_CHUNKED == layout->type); + HDassert(layout->u.chunk.ndims > 0 && layout->u.chunk.ndims <= H5O_LAYOUT_NDIMS); #ifndef NDEBUG - for (u = 0; u < layout->u.chunk.ndims; u++) - assert(layout->u.chunk.dim[u] > 0); + for(u = 0; u < layout->u.chunk.ndims; u++) + HDassert(layout->u.chunk.dim[u] > 0); #endif /* Initialize "user" data for B-tree callbacks, etc. */ udata.mesg = layout; - if (H5B_create(f, dxpl_id, H5B_ISTORE, &udata, &(layout->u.chunk.addr)/*out*/) < 0) + if(H5B_create(f, dxpl_id, H5B_ISTORE, &udata, &(layout->u.chunk.addr)/*out*/) < 0) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "can't create B-tree") done: @@ -2215,12 +2268,12 @@ H5D_istore_allocated(H5D_t *dset, hid_t dxpl_id) H5D_rdcc_ent_t *ent; /*cache entry */ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */ - H5D_istore_ud1_t udata; + H5D_istore_it_ud1_t udata; hsize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI(H5D_istore_allocated, 0) - assert(dset); + HDassert(dset); /* Fill the DXPL cache values for later use */ if (H5D_get_dxpl_cache(dxpl_id,&dxpl_cache)<0) @@ -2237,12 +2290,12 @@ H5D_istore_allocated(H5D_t *dset, hid_t dxpl_id) } /* end for */ HDmemset(&udata, 0, sizeof udata); - udata.mesg = &dset->shared->layout; + udata.common.mesg = &dset->shared->layout; if (H5B_iterate(dset->ent.file, dxpl_id, H5B_ISTORE, H5D_istore_iter_allocated, dset->shared->layout.u.chunk.addr, &udata)<0) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, 0, "unable to iterate over chunk B-tree") /* Set return value */ - ret_value=udata.total_storage; + ret_value = udata.total_storage; done: FUNC_LEAVE_NOAPI(ret_value) @@ -2273,18 +2326,18 @@ H5D_istore_get_addr(const H5D_io_info_t *io_info, H5D_istore_ud1_t *_udata) FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5D_istore_get_addr) - assert(io_info); - assert(io_info->dset); - assert(io_info->dset->shared->layout.u.chunk.ndims > 0); - assert(io_info->store->chunk.offset); + HDassert(io_info); + HDassert(io_info->dset); + HDassert(io_info->dset->shared->layout.u.chunk.ndims > 0); + HDassert(io_info->store->chunk.offset); /* Check for udata struct to return */ - udata = (_udata!=NULL ? _udata : &tmp_udata); + udata = (_udata != NULL ? _udata : &tmp_udata); /* Initialize the information about the chunk we are looking for */ - for (u=0; udset->shared->layout.u.chunk.ndims; u++) - udata->key.offset[u] = io_info->store->chunk.offset[u]; - udata->mesg = &(io_info->dset->shared->layout); + for(u = 0; u < io_info->dset->shared->layout.u.chunk.ndims; u++) + udata->common.key.offset[u] = io_info->store->chunk.offset[u]; + udata->common.mesg = &(io_info->dset->shared->layout); udata->addr = HADDR_UNDEF; /* Go get the chunk information */ @@ -2328,6 +2381,7 @@ static void * H5D_istore_chunk_alloc(size_t size, const H5O_pline_t *pline) { void *ret_value=NULL; /* Return value */ + FUNC_ENTER_NOAPI_NOINIT(H5D_istore_chunk_alloc) assert(size); @@ -2411,7 +2465,6 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) H5D_fill_time_t fill_time; /* When to write fill values */ H5D_fill_value_t fill_status; /* The fill value status */ unsigned should_fill=0; /* Whether fill values should be written */ - H5D_istore_ud1_t udata; /* B-tree pass-through for creating chunk */ void *chunk=NULL; /* Chunk buffer for writing fill values */ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */ H5D_dxpl_cache_t *dxpl_cache=&_dxpl_cache; /* Data transfer property cache */ @@ -2562,14 +2615,16 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) } /* end if */ if(!chunk_exists) { + H5D_istore_ud1_t udata; /* B-tree pass-through for creating chunk */ + /* Initialize the chunk information */ - udata.mesg = &dset->shared->layout; - udata.key.filter_mask = filter_mask; + udata.common.mesg = &dset->shared->layout; + udata.common.key.filter_mask = filter_mask; udata.addr = HADDR_UNDEF; H5_CHECK_OVERFLOW(chunk_size,hsize_t,size_t); - udata.key.nbytes = (size_t)chunk_size; - for (u=0; ushared->layout.u.chunk.ndims; u++) - udata.key.offset[u] = chunk_offset[u]; + udata.common.key.nbytes = (size_t)chunk_size; + for(u = 0; u < dset->shared->layout.u.chunk.ndims; u++) + udata.common.key.offset[u] = chunk_offset[u]; /* Allocate the chunk with all processes */ if (H5B_insert(dset->ent.file, dxpl_id, H5B_ISTORE, dset->shared->layout.u.chunk.addr, &udata)<0) @@ -2583,7 +2638,7 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) /* Write the chunks out from only one process */ /* !! Use the internal "independent" DXPL!! -QAK */ if(H5_PAR_META_WRITE==mpi_rank) { - if (H5F_block_write(dset->ent.file, H5FD_MEM_DRAW, udata.addr, udata.key.nbytes, H5AC_ind_dxpl_id, chunk)<0) + if (H5F_block_write(dset->ent.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, H5AC_ind_dxpl_id, chunk)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") } /* end if */ @@ -2592,7 +2647,7 @@ H5D_istore_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite) } /* end if */ else { #endif /* H5_HAVE_PARALLEL */ - if (H5F_block_write(dset->ent.file, H5FD_MEM_DRAW, udata.addr, udata.key.nbytes, dxpl_id, chunk)<0) + if (H5F_block_write(dset->ent.file, H5FD_MEM_DRAW, udata.addr, udata.common.key.nbytes, dxpl_id, chunk)<0) HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file") #ifdef H5_HAVE_PARALLEL } /* end else */ @@ -2735,14 +2790,14 @@ done: herr_t H5D_istore_prune_by_extent(const H5D_io_info_t *io_info) { - H5D_t *dset=io_info->dset; /* Local pointer to the dataset info */ + H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */ const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */ H5D_rdcc_ent_t *ent = NULL, *next = NULL; /*cache entry */ unsigned u; /*counters */ int found; /*remove this entry */ - H5D_istore_ud1_t udata; /*B-tree pass-through */ + H5D_istore_it_ud3_t udata; /*B-tree pass-through */ hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /*current dataspace dimensions */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5D_istore_prune_by_extent, FAIL) @@ -2794,8 +2849,7 @@ H5D_istore_prune_by_extent(const H5D_io_info_t *io_info) */ HDmemset(&udata, 0, sizeof udata); - udata.stream = stdout; - udata.mesg = &dset->shared->layout; + udata.common.mesg = &dset->shared->layout; udata.dims = curr_dims; if(H5B_iterate(dset->ent.file, io_info->dxpl_id, H5B_ISTORE, H5D_istore_prune_extent, dset->shared->layout.u.chunk.addr, &udata) < 0) @@ -2826,11 +2880,10 @@ static int H5D_istore_prune_extent(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t UNUSED addr, const void UNUSED *_rt_key, void *_udata) { - H5D_istore_ud1_t *bt_udata = (H5D_istore_ud1_t *)_udata; + H5D_istore_it_ud3_t *udata = (H5D_istore_it_ud3_t *)_udata; const H5D_istore_key_t *lt_key = (const H5D_istore_key_t *)_lt_key; unsigned u; - H5D_istore_ud1_t udata; - int ret_value=H5B_ITER_CONT; /* Return value */ + int ret_value = H5B_ITER_CONT; /* Return value */ /* The LT_KEY is the left key (the one that describes the chunk). It points to a chunk of * storage that contains the beginning of the logical address space represented by UDATA. @@ -2839,21 +2892,16 @@ H5D_istore_prune_extent(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t UN FUNC_ENTER_NOAPI_NOINIT(H5D_istore_prune_extent) /* Figure out what chunks are no longer in use for the specified extent and release them */ - for(u = 0; u < bt_udata->mesg->u.chunk.ndims - 1; u++) - if((hsize_t)lt_key->offset[u] > bt_udata->dims[u]) { -#ifdef H5D_ISTORE_DEBUG - HDfputs("b-tree:remove:[", bt_udata->stream); - for(u = 0; u < bt_udata->mesg->u.chunk.ndims - 1; u++) - HDfprintf(bt_udata->stream, "%s%Hd", u ? ", " : "", lt_key->offset[u]); - HDfputs("]\n", bt_udata->stream); -#endif + for(u = 0; u < udata->common.mesg->u.chunk.ndims - 1; u++) + if((hsize_t)lt_key->offset[u] > udata->dims[u]) { + H5D_istore_ud0_t bt_udata; - HDmemset(&udata, 0, sizeof udata); - udata.key = *lt_key; - udata.mesg = bt_udata->mesg; + HDmemset(&bt_udata, 0, sizeof bt_udata); + bt_udata.key = *lt_key; + bt_udata.mesg = udata->common.mesg; /* Remove */ - if(H5B_remove(f, dxpl_id, H5B_ISTORE, bt_udata->mesg->u.chunk.addr, &udata) < 0) + if(H5B_remove(f, dxpl_id, H5B_ISTORE, udata->common.mesg->u.chunk.addr, &bt_udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_ITER_ERROR, "unable to remove entry") break; } /* end if */ @@ -3128,7 +3176,7 @@ H5D_istore_delete(H5F_t *f, hid_t dxpl_id, const H5O_layout_t *layout) /* Check if the B-tree has been created in the file */ if(H5F_addr_defined(layout->u.chunk.addr)) { H5O_layout_t tmp_layout=*layout;/* Local copy of layout info */ - H5D_istore_ud1_t udata; /* User data for B-tree iterator call */ + H5D_istore_ud0_t udata; /* User data for B-tree iterator call */ /* Set up user data for B-tree deletion */ HDmemset(&udata, 0, sizeof udata); @@ -3253,6 +3301,67 @@ done: /*------------------------------------------------------------------------- + * Function: H5D_istore_copy + * + * Purpose: copy an indexed storage B-tree from SRC file to DST file. + * + * Return: Non-negative on success (with the ISTORE argument initialized + * and ready to write to an object header). Negative on failure. + * + * Programmer: Peter Cao + * August 20, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D_istore_copy(H5F_t *f_src, H5O_layout_t *layout_src, + H5F_t *f_dst, H5O_layout_t *layout_dst, hid_t dxpl_id) +{ + H5D_istore_it_ud4_t udata; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5D_istore_copy, FAIL) + + /* Check args */ + HDassert(f_src); + HDassert(f_dst); + HDassert(layout_src && H5D_CHUNKED == layout_src->type); + HDassert(layout_dst && H5D_CHUNKED == layout_dst->type); + + /* Create shared B-tree info for each file */ + if(H5D_istore_shared_create(f_src, layout_src) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info") + if(H5D_istore_shared_create(f_dst, layout_dst) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info") + + /* Check if we need to create the B-tree in the dest. file */ + if(layout_dst->u.chunk.addr == HADDR_UNDEF) { + /* Create the root of the B-tree that describes chunked storage */ + if(H5D_istore_create(f_dst, dxpl_id, layout_dst) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to initialize chunked storage") + } /* end if */ + + /* Initialize the callback structure for the source */ + HDmemset(&udata, 0, sizeof udata); + udata.common.mesg = layout_src; + udata.file_dst = f_dst; + udata.addr_dst = layout_dst->u.chunk.addr; + + /* copy the chunked data by iteration */ + if(H5B_iterate(f_src, dxpl_id, H5B_ISTORE, H5D_istore_iter_copy, layout_src->u.chunk.addr, &udata) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "unable to iterate over chunk B-tree") + +done: + if(H5RC_DEC(layout_src->u.chunk.btree_shared) < 0) + HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page") + if(H5RC_DEC(layout_dst->u.chunk.btree_shared) < 0) + HDONE_ERROR(H5E_IO, H5E_CANTFREE, FAIL, "unable to decrement ref-counted page") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D_istore_copy() */ + + +/*------------------------------------------------------------------------- * Function: H5D_istore_dump_btree * * Purpose: Prints information about the storage B-tree to the specified @@ -3271,17 +3380,17 @@ herr_t H5D_istore_dump_btree(H5F_t *f, hid_t dxpl_id, FILE *stream, unsigned ndims, haddr_t addr) { H5O_layout_t layout; - H5D_istore_ud1_t udata; + H5D_istore_it_ud2_t udata; herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5D_istore_dump_btree, FAIL) HDmemset(&udata, 0, sizeof udata); layout.u.chunk.ndims = ndims; - udata.mesg = &layout; + udata.common.mesg = &layout; udata.stream = stream; if(stream) - HDfprintf(stream, " Address: %a\n",addr); + HDfprintf(stream, " Address: %a\n", addr); if(H5B_iterate(f, dxpl_id, H5B_ISTORE, H5D_istore_iter_dump, addr, &udata)<0) HGOTO_ERROR(H5E_IO, H5E_CANTINIT, 0, "unable to iterate over chunk B-tree") @@ -3371,20 +3480,22 @@ H5D_istore_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int inden int fwidth, unsigned ndims) { H5O_layout_t layout; - H5D_istore_ud1_t udata; - herr_t ret_value=SUCCEED; /* Return value */ + H5D_istore_ud0_t udata; /* B-tree user data */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5D_istore_debug,FAIL) layout.u.chunk.ndims = ndims; - HDmemset (&udata, 0, sizeof udata); - udata.mesg = &layout; /* Allocate the shared structure */ if(H5D_istore_shared_create(f, &layout)<0) HGOTO_ERROR (H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't create wrapper for shared B-tree info") - (void)H5B_debug (f, dxpl_id, addr, stream, indent, fwidth, H5B_ISTORE, &udata); + /* Set up B-tree user data */ + HDmemset(&udata, 0, sizeof udata); + udata.mesg = &layout; + + (void)H5B_debug(f, dxpl_id, addr, stream, indent, fwidth, H5B_ISTORE, &udata); /* Free the raw B-tree node buffer */ if(layout.u.chunk.btree_shared==NULL) diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index 04fce35..651f2b8 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -271,6 +271,8 @@ H5_DLL ssize_t H5D_istore_writevv(const H5D_io_info_t *io_info, const void *buf); H5_DLL haddr_t H5D_istore_get_addr(const H5D_io_info_t *io_info, struct H5D_istore_ud1_t *_udata); +H5_DLL herr_t H5D_istore_copy(H5F_t *f_src, H5O_layout_t *layout_src, + H5F_t *f_dst, H5O_layout_t *layout_dst, hid_t dxpl_id); /* Functions that operate on external file list (efl) storage */ H5_DLL ssize_t H5D_efl_readvv(const H5D_io_info_t *io_info, diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h index 83074f2..0edabb3 100644 --- a/src/H5Dpublic.h +++ b/src/H5Dpublic.h @@ -88,29 +88,28 @@ extern "C" { typedef herr_t (*H5D_operator_t)(void *elem, hid_t type_id, unsigned ndim, const hsize_t *point, void *operator_data); -H5_DLL hid_t H5Dcreate (hid_t file_id, const char *name, hid_t type_id, +H5_DLL hid_t H5Dcreate(hid_t file_id, const char *name, hid_t type_id, hid_t space_id, hid_t plist_id); -H5_DLL hid_t H5Dopen (hid_t file_id, const char *name); -H5_DLL herr_t H5Dclose (hid_t dset_id); -H5_DLL hid_t H5Dget_space (hid_t dset_id); -H5_DLL herr_t H5Dget_space_status(hid_t dset_id, - H5D_space_status_t *allocation); -H5_DLL hid_t H5Dget_type (hid_t dset_id); -H5_DLL hid_t H5Dget_create_plist (hid_t dset_id); +H5_DLL hid_t H5Dopen(hid_t file_id, const char *name); +H5_DLL herr_t H5Dclose(hid_t dset_id); +H5_DLL hid_t H5Dget_space(hid_t dset_id); +H5_DLL herr_t H5Dget_space_status(hid_t dset_id, H5D_space_status_t *allocation); +H5_DLL hid_t H5Dget_type(hid_t dset_id); +H5_DLL hid_t H5Dget_create_plist(hid_t dset_id); H5_DLL hsize_t H5Dget_storage_size(hid_t dset_id); H5_DLL haddr_t H5Dget_offset(hid_t dset_id); -H5_DLL herr_t H5Dread (hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, +H5_DLL herr_t H5Dread(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, void *buf/*out*/); -H5_DLL herr_t H5Dwrite (hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, +H5_DLL herr_t H5Dwrite(hid_t dset_id, hid_t mem_type_id, hid_t mem_space_id, hid_t file_space_id, hid_t plist_id, const void *buf); -H5_DLL herr_t H5Dextend (hid_t dset_id, const hsize_t *size); +H5_DLL herr_t H5Dextend(hid_t dset_id, const hsize_t *size); H5_DLL herr_t H5Diterate(void *buf, hid_t type_id, hid_t space_id, H5D_operator_t op, void *operator_data); H5_DLL herr_t H5Dvlen_reclaim(hid_t type_id, hid_t space_id, hid_t plist_id, void *buf); H5_DLL herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *size); H5_DLL herr_t H5Dfill(const void *fill, hid_t fill_type, void *buf, hid_t buf_type, hid_t space); -H5_DLL herr_t H5Dset_extent (hid_t dset_id, const hsize_t *size); +H5_DLL herr_t H5Dset_extent(hid_t dset_id, const hsize_t *size); H5_DLL herr_t H5Ddebug(hid_t dset_id); @@ -118,4 +117,3 @@ H5_DLL herr_t H5Ddebug(hid_t dset_id); } #endif #endif /* _H5Dpublic_H */ - diff --git a/src/H5G.c b/src/H5G.c index e7fc1cf..90e08db 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -91,7 +91,6 @@ /* Interface initialization */ #define H5_INTERFACE_INIT_FUNC H5G_init_interface - /* Packages needed by this file... */ #include "H5private.h" /* Generic Functions */ #include "H5Aprivate.h" /* Attributes */ @@ -108,7 +107,6 @@ /* Local macros */ #define H5G_INIT_HEAP 8192 #define H5G_RESERVED_ATOMS 0 -#define H5G_SIZE_HINT 256 /*default root grp size hint */ /* * During name lookups (see H5G_namei()) we sometimes want information about @@ -149,6 +147,8 @@ typedef struct H5G_typeinfo_t { char *desc; /*description of object type */ } H5G_typeinfo_t; +/* Package variables */ + /* Local variables */ static H5G_typeinfo_t *H5G_type_g = NULL; /*object typing info */ static size_t H5G_ntypes_g = 0; /*entries in type table */ @@ -163,6 +163,9 @@ H5FL_DEFINE(H5G_shared_t); /* Declare extern the PQ free list for the wrapped strings */ H5FL_BLK_EXTERN(str_buf); +/* Declare a free list to manage haddr_t's */ +H5FL_DEFINE(haddr_t); + /* Private prototypes */ static herr_t H5G_register_type(H5G_obj_t type, htri_t(*isa)(H5G_entry_t*, hid_t), const char *desc); @@ -200,6 +203,8 @@ static htri_t H5G_common_path(const H5RS_str_t *fullpath_r, const H5RS_str_t *prefix_r); static H5RS_str_t *H5G_build_fullpath(const H5RS_str_t *prefix_r, const H5RS_str_t *name_r); static int H5G_replace_ent(void *obj_ptr, hid_t obj_id, void *key); +static herr_t H5G_copy(H5G_entry_t *ent_src, H5G_entry_t *loc_dst, + const char *name_dst, hid_t plist_id); /*------------------------------------------------------------------------- @@ -1036,6 +1041,50 @@ done: FUNC_LEAVE_API(ret_value); } + +/*------------------------------------------------------------------------- + * Function: H5Gcopy + * + * Purpose: Copy an object to destination location + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Peter Cao + * June 4, 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gcopy(hid_t id_src, hid_t loc_dst, const char *name_dst, hid_t plist_id) +{ + H5G_entry_t *ent_src = NULL, *ent_dst=NULL; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(H5Gcopy, FAIL) + + /* Check arguments */ + if(NULL == (ent_src = H5G_loc(id_src))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(NULL == (ent_dst = H5G_loc(loc_dst))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location") + if(!name_dst || !*name_dst) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name specified") + +/* Get correct property list */ +/* XXX: This is a kludge, to use the datatype creation property list - QAK */ +if(H5P_DEFAULT == plist_id) + plist_id = H5P_DATATYPE_CREATE_DEFAULT; +else + if(TRUE != H5P_isa_class(plist_id, H5P_DATATYPE_CREATE)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not object create property list") + + if(H5G_copy(ent_src, ent_dst, name_dst, plist_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Gcopy() */ + /* *------------------------------------------------------------------------- *------------------------------------------------------------------------- @@ -4214,3 +4263,60 @@ H5G_unmount(H5G_t *grp) FUNC_LEAVE_NOAPI(SUCCEED); } /* end H5G_unmount() */ + +/*------------------------------------------------------------------------- + * Function: H5G_copy + * + * Purpose: Copy an object to destination location + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Peter Cao + * June 4, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_copy(H5G_entry_t *ent_src, H5G_entry_t *loc_dst, + const char *name_dst, hid_t plist_id) +{ + H5P_genplist_t *oc_plist; /* Property list created */ + hid_t dxpl_id = H5AC_dxpl_id; + H5G_entry_t ent_new; + hbool_t entry_inserted = FALSE; /* Flag to indicate that the new entry was inserted into a group */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_copy, FAIL); + + HDassert(ent_src); + HDassert(ent_src->file); + HDassert(loc_dst); + HDassert(loc_dst->file); + HDassert(name_dst); + + /* Get the property list */ + if(NULL == (oc_plist = H5I_object(plist_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list") + + /* Reset group entry for new object */ + H5G_ent_reset(&ent_new); + ent_new.file = loc_dst->file; + + /* copy the object from the source file to the destination file */ + if(H5O_copy_header(ent_src, &ent_new, dxpl_id) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + + /* Insert the new object in the destination file's group */ + if(H5G_insert(loc_dst, name_dst, &ent_new, dxpl_id, oc_plist) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to insert the name") + entry_inserted = TRUE; + +done: + /* Free the ID to name buffers */ + if(entry_inserted) + H5G_free_ent_name(&ent_new); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_copy() */ diff --git a/src/H5Gnode.c b/src/H5Gnode.c index faff6ba..5e053fd 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -68,7 +68,6 @@ static herr_t H5G_node_clear(H5F_t *f, H5G_node_t *sym, hbool_t destroy); static herr_t H5G_compute_size(const H5F_t *f, const H5G_node_t *sym, size_t *size_ptr); /* B-tree callbacks */ -static size_t H5G_node_sizeof_rkey(const H5F_t *f, const void *_udata); static H5RC_t *H5G_node_get_shared(const H5F_t *f, const void *_udata); static herr_t H5G_node_create(H5F_t *f, hid_t dxpl_id, H5B_ins_t op, void *_lt_key, void *_udata, void *_rt_key, @@ -109,7 +108,6 @@ const H5AC_class_t H5AC_SNODE[1] = {{ H5B_class_t H5B_SNODE[1] = {{ H5B_SNODE_ID, /*id */ sizeof(H5G_node_key_t), /*sizeof_nkey */ - H5G_node_sizeof_rkey, /*get_sizeof_rkey */ H5G_node_get_shared, /*get_shared */ H5G_node_create, /*new */ H5G_node_cmp2, /*cmp2 */ @@ -124,9 +122,6 @@ H5B_class_t H5B_SNODE[1] = {{ H5G_node_debug_key, /*debug */ }}; -/* Declare a free list to manage the H5B_shared_t struct */ -H5FL_EXTERN(H5B_shared_t); - /* Declare a free list to manage the H5G_node_t struct */ H5FL_DEFINE_STATIC(H5G_node_t); @@ -142,33 +137,8 @@ H5FL_SEQ_DEFINE_STATIC(size_t); /* Declare a free list to manage the raw page information */ H5FL_BLK_DEFINE_STATIC(grp_page); - -/*------------------------------------------------------------------------- - * Function: H5G_node_sizeof_rkey - * - * Purpose: Returns the size of a raw B-link tree key for the specified - * file. - * - * Return: Success: Size of the key. - * - * Failure: never fails - * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 14 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static size_t -H5G_node_sizeof_rkey(const H5F_t *f, const void UNUSED * udata) -{ - /* Use FUNC_ENTER_NOAPI_NOINIT_NOFUNC here to avoid performance issues */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_node_sizeof_rkey); - - FUNC_LEAVE_NOAPI(H5F_SIZEOF_SIZE(f)); /*the name offset */ -} +/* Declare extern the free list to manage haddr_t's */ +H5FL_EXTERN(haddr_t); /*------------------------------------------------------------------------- @@ -1803,7 +1773,7 @@ H5G_node_init(H5F_t *f) /* Set up the "global" information for this file's groups */ shared->type= H5B_SNODE; shared->two_k=2*H5F_KVALUE(f,H5B_SNODE); - shared->sizeof_rkey = H5G_node_sizeof_rkey(f, NULL); + shared->sizeof_rkey = H5F_SIZEOF_SIZE(f); /*the name offset */ assert(shared->sizeof_rkey); shared->sizeof_rnode = H5B_nodesize(f, shared, &shared->sizeof_keys); assert(shared->sizeof_rnode); @@ -1894,6 +1864,106 @@ H5G_node_shared_free (void *_shared) /*------------------------------------------------------------------------- + * Function: H5G_node_copy + * + * Purpose: This function gets called during a group iterate operation + * to copy objects of this node into a new location. + * + * Return: 0(zero) on success/Negative on failure + * + * Programmer: Peter Cao + * Sept 10, 2005 + * + *------------------------------------------------------------------------- + */ +int +H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void UNUSED *_lt_key, haddr_t addr, + const void UNUSED *_rt_key, void *_udata) +{ + H5G_bt_it_ud5_t *udata = (H5G_bt_it_ud5_t *)_udata; + const H5HL_t *heap = NULL; + H5G_node_t *sn = NULL; + unsigned int i; /* Local index variable */ + int ret_value = H5B_ITER_CONT; + + FUNC_ENTER_NOAPI(H5G_node_copy, H5B_ITER_ERROR) + + /* Check arguments. */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(udata); + + /* load the symbol table into memory from the source file */ + if(NULL == (sn = H5AC_protect(f, dxpl_id, H5AC_SNODE, addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_SYM, H5E_CANTLOAD, H5B_ITER_ERROR, "unable to load symbol table node") + + /* get the base address of the heap */ + if(NULL == (heap = H5HL_protect(f, dxpl_id, udata->heap_addr))) + HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5B_ITER_ERROR, "unable to protect symbol name") + + /* copy object in this node one by one */ + for(i = 0; i < sn->nsyms; i++) { + H5G_entry_t ent_new; /* New entry to insert into dest. group */ + H5G_entry_t *ent_src = &(sn->entry[i]); /* Convenience variable to refer to current source group entry */ + const char *name; /* Name of source object */ + + /* Set up symbol table entry for destination */ + H5G_ent_reset(&ent_new); + ent_new.file = udata->loc_dst->file; + + /* Determine name of source object */ + name = H5HL_offset_into(f, heap, ent_src->name_off); + HDassert(name); + + /* Check if object in source group is a hard link */ + if(H5F_addr_defined(ent_src->header)) { + /* Copy the shared object from source to destination */ + /* (Increments link count on destination) */ + if(H5O_copy_header_map(ent_src, &ent_new, dxpl_id, udata->map_list) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, H5B_ITER_ERROR, "unable to copy object") + } /* ( H5F_addr_defined(ent_src->header)) */ + else if(H5G_CACHED_SLINK == ent_src->type) { + /* it is a soft link */ + H5O_stab_t stab_mesg; + size_t offset_link; + char *name_link = H5HL_offset_into(f, heap, ent_src->cache.slink.lval_offset); + + /* read the symbol table where the soft link to be inserted */ + if(NULL == H5O_read(udata->loc_dst, H5O_STAB_ID, 0, &stab_mesg, dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_ITER_ERROR, "unable to determine local heap address") + if((size_t)(-1) == (offset_link = H5HL_insert(udata->loc_dst->file, dxpl_id, + stab_mesg.heap_addr, HDstrlen(name_link) + 1, name_link))) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, H5B_ITER_ERROR, "unable to write link value to local heap") + H5O_reset (H5O_STAB_ID, &stab_mesg); + + /* Set up soft link to insert */ + ent_new.type = H5G_CACHED_SLINK; + ent_new.cache.slink.lval_offset = offset_link; + } /* else if */ + else + HDassert(0 && "Unknown entry type"); + + /* Insert the new object in the destination file's group */ + /* (Don't increment the link count - that's already done above for hard links) */ + if(H5G_stab_insert(udata->loc_dst, name, &ent_new, FALSE, dxpl_id) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5B_ITER_ERROR, "unable to insert the name") + + /* Free the ID to name buffers */ + H5G_free_ent_name(&ent_new); + } /* end of for (i=0; insyms; i++) */ + +done: + if (heap && H5HL_unprotect(f, dxpl_id, heap, udata->heap_addr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_ITER_ERROR, "unable to unprotect symbol name") + + if (sn && H5AC_unprotect(f, dxpl_id, H5AC_SNODE, addr, sn, H5AC__NO_FLAGS_SET) != SUCCEED) + HDONE_ERROR(H5E_SYM, H5E_PROTECT, H5B_ITER_ERROR, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_node_copy() */ + + +/*------------------------------------------------------------------------- * Function: H5G_node_debug * * Purpose: Prints debugging information about a symbol table node diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index adb546f..4c6ec68 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -31,8 +31,11 @@ #include "H5Gprivate.h" /* Other private headers needed by this file */ -#include "H5ACprivate.h" /* Metadata cache */ +#include "H5ACprivate.h" /* Metadata cache */ #include "H5Oprivate.h" /* Object headers */ +#include "H5SLprivate.h" /* Skip lists */ + +#define H5G_SIZE_HINT 256 /* default root grp size hint */ /* * A symbol table node is a collection of symbol table entries. It can @@ -166,6 +169,13 @@ typedef struct H5G_bt_it_ud4_t { /* upward */ } H5G_bt_it_ud4_t; +/* Data passed to B-tree iteration for copying copy symblol table content */ +typedef struct H5G_bt_it_ud5_t { + H5SL_t *map_list; /* skip list to map copied object addresses */ + haddr_t heap_addr; /* heap address of the source symbol table */ + H5G_entry_t *loc_dst; /* group where new object is inserted to */ +} H5G_bt_it_ud5_t; + /* * This is the class identifier to give to the B-tree functions. */ @@ -187,6 +197,9 @@ H5_DLL herr_t H5G_stab_insert(H5G_entry_t *grp_ent, const char *name, H5G_entry_t *obj_ent, hbool_t inc_link, hid_t dxpl_id); H5_DLL herr_t H5G_stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab, hbool_t adj_link); H5_DLL herr_t H5G_stab_remove(H5G_entry_t *grp_ent, const char *name, hid_t dxpl_id); +H5_DLL herr_t H5G_stab_copy_tmp(H5F_t *f_dst, H5O_stab_t *stab_dst, + hid_t dxpl_id); + /* * Functions that understand symbol table entries. @@ -206,4 +219,7 @@ H5_DLL int H5G_node_name(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t a const void *_rt_key, void *_udata); H5_DLL int H5G_node_type(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, const void *_rt_key, void *_udata); +H5_DLL int H5G_node_copy(H5F_t *f, hid_t dxpl_id, const void *_lt_key, haddr_t addr, + const void *_rt_key, void *_udata); + #endif diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index 2f82536..1a7807a 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -14,15 +14,13 @@ /*------------------------------------------------------------------------- * - * Created: H5Gproto.h + * Created: H5Gpublic.h * Jul 11 1997 * Robb Matzke * * Purpose: Public declarations for the H5G package (symbol * tables). * - * Modifications: - * *------------------------------------------------------------------------- */ #ifndef _H5Gpublic_H @@ -123,6 +121,8 @@ H5_DLL int H5Gget_comment(hid_t loc_id, const char *name, size_t bufsize, char *buf); H5_DLL hid_t H5Gcreate_expand(hid_t loc_id, const char *name, hid_t gcpl_id, hid_t gapl_id); +H5_DLL herr_t H5Gcopy(hid_t id_src, hid_t loc_dst, const char *name_dst, + hid_t plist_id); #ifdef __cplusplus } diff --git a/src/H5Gstab.c b/src/H5Gstab.c index 8c83859..b63e1cd 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -315,3 +315,50 @@ H5G_stab_delete(H5F_t *f, hid_t dxpl_id, const H5O_stab_t *stab, hbool_t adj_lin done: FUNC_LEAVE_NOAPI(ret_value); } /* end H5G_stab_delete() */ + + +/*------------------------------------------------------------------------- + * Function: H5G_stab_copy_tmp + * + * Purpose: copy a group symbol table and memeber objects from SRC file to DST file. + * + * Return: Non-negative on success + * Negative on failure. + * + * Programmer: Peter Cao + * September 10, 2005 + * + * Note: This routine should be replaced with proper call to "real" + * stab creation routine after the "big group revision" checkin + * occurs. -QAK + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_stab_copy_tmp(H5F_t *f_dst, H5O_stab_t *stab_dst, hid_t dxpl_id) +{ + size_t size_init, name_offset; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_stab_copy_tmp, FAIL) + + HDassert(f_dst); + HDassert(stab_dst); + + /* create B-tree private heap */ + size_init = MAX(H5G_SIZE_HINT, H5HL_SIZEOF_FREE(f_dst) + 2); + if (H5HL_create(f_dst, dxpl_id, size_init, &(stab_dst->heap_addr))<0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create heap") + + name_offset = H5HL_insert(f_dst, dxpl_id, stab_dst->heap_addr, 1, ""); + if ((size_t)(-1)==name_offset) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't initialize heap") + assert(0 == name_offset); + + /* create the B-tree */ + if (H5B_create(f_dst, dxpl_id, H5B_SNODE, NULL, &(stab_dst->btree_addr)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "can't create B-tree") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5G_stab_copy_tmp() */ diff --git a/src/H5O.c b/src/H5O.c index 2a3f39c..7522b4a 100644 --- a/src/H5O.c +++ b/src/H5O.c @@ -64,6 +64,12 @@ typedef struct { typedef herr_t (*H5O_operator_int_t)(H5O_mesg_t *mesg/*in,out*/, unsigned idx, unsigned * oh_flags_ptr, void *operator_data/*in,out*/); +/* Node in skip list to map addresses from one file to another during object header copy */ +typedef struct H5O_addr_map_t { + haddr_t src_addr; /* Address of object in source file */ + haddr_t dst_addr; /* Address of object in destination file */ +} H5O_addr_map_t; + /* PRIVATE PROTOTYPES */ static herr_t H5O_init(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/, haddr_t header); @@ -107,6 +113,14 @@ static herr_t H5O_write_mesg(H5O_t *oh, unsigned idx, const H5O_class_t *type, unsigned * oh_flags_ptr); static herr_t H5O_iterate_real(const H5G_entry_t *ent, const H5O_class_t *type, H5AC_protect_t prot, hbool_t internal, void *op, void *op_data, hid_t dxpl_id); +static void * H5O_copy_mesg_file(const H5O_class_t *type, H5F_t *file_src, + void *mesg_src, H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); +static herr_t H5O_post_copy_mesg_file(const H5O_class_t *type, H5F_t *file_src, + const void *mesg_src, H5G_entry_t *loc_dst, + hid_t dxpl_id, H5SL_t *map_list); +static herr_t H5O_copy_header_real(const H5G_entry_t *ent_src, + H5G_entry_t *ent_dst /*out */, hid_t dxpl_id, H5SL_t *map_list); +static herr_t H5O_copy_free_addrmap_cb(void *item, void *key, void *op_data); /* Metadata cache callbacks */ static H5O_t *H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_udata1, @@ -153,6 +167,8 @@ static const H5O_class_t *const message_type_g[] = { H5O_MTIME_NEW, /*0x0012 New Object modification date and time */ }; +/* Library private variables */ + /* * An array of functions indexed by symbol table entry cache type * (H5G_type_t) that are called to retrieve constant messages cached in the @@ -180,6 +196,9 @@ H5FL_EXTERN(time_t); /* Declare extern the free list for H5O_cont_t's */ H5FL_EXTERN(H5O_cont_t); +/* Declare a free list to manage the H5O_addr_map_t struct */ +H5FL_DEFINE_STATIC(H5O_addr_map_t); + /*------------------------------------------------------------------------- * Function: H5O_init_interface @@ -584,12 +603,8 @@ H5O_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED * _udata1, p += 3; /*reserved*/ /* Try to detect invalidly formatted object header messages */ - if (p + mesg_size > oh->chunk[chunkno].image + chunk_size) { - - HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, \ - "corrupt object header"); - } - + if (p + mesg_size > oh->chunk[chunkno].image + chunk_size) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "corrupt object header"); /* Skip header messages we don't know about */ /* (Usually from future versions of the library */ @@ -680,7 +695,6 @@ H5O_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5O_t *oh) int id; unsigned u; H5O_mesg_t *curr_msg; /* Pointer to current message being operated on */ - H5O_cont_t *cont = NULL; herr_t (*encode)(H5F_t*, uint8_t*, const void*) = NULL; unsigned combine=0; /* Whether to combine the object header prefix & the first chunk */ herr_t ret_value=SUCCEED; /* Return value */ @@ -2259,8 +2273,7 @@ H5O_new_mesg(H5F_t *f, H5O_t *oh, unsigned *flags, const H5O_class_t *orig_type, HGOTO_ERROR (H5E_OHDR, H5E_CANTINIT, UFAIL, "object header message is too large (16k max)"); /* Allocate space in the object headed for the message */ - if ((ret_value = H5O_alloc(f, dxpl_id, oh, - orig_type, size, oh_flags_ptr)) == UFAIL) + if ((ret_value = H5O_alloc(f, dxpl_id, oh, orig_type, size, oh_flags_ptr)) == UFAIL) HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, UFAIL, "unable to allocate space for message"); /* Increment any links in message */ @@ -3045,8 +3058,8 @@ H5O_alloc_new_chunk(H5F_t *f, H5O_cont_t *cont = NULL; /*native continuation message */ int chunkno; unsigned u; - unsigned ret_value; /*return value */ haddr_t new_chunk_addr; + unsigned ret_value; /*return value */ FUNC_ENTER_NOAPI_NOINIT(H5O_alloc_new_chunk); @@ -3088,10 +3101,8 @@ H5O_alloc_new_chunk(H5F_t *f, * message, then make sure the new chunk has enough room for that * other message. */ - if ( found_null < 0 ) { - + if (found_null < 0) size += H5O_SIZEOF_MSGHDR(f) + oh->mesg[found_other].raw_size; - } /* * The total chunk size must include the requested space plus enough @@ -3103,11 +3114,8 @@ H5O_alloc_new_chunk(H5F_t *f, /* allocate space in file to hold the new chunk */ new_chunk_addr = H5MF_alloc(f, H5FD_MEM_OHDR, dxpl_id, (hsize_t)size); - if ( HADDR_UNDEF == new_chunk_addr ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, \ - "unable to allocate space for new chunk"); - } + if(HADDR_UNDEF == new_chunk_addr) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "unable to allocate space for new chunk") /* * Create the new chunk giving it a file address. @@ -3117,11 +3125,8 @@ H5O_alloc_new_chunk(H5F_t *f, unsigned na = oh->alloc_nchunks + H5O_NCHUNKS; H5O_chunk_t *x = H5FL_SEQ_REALLOC (H5O_chunk_t, oh->chunk, (size_t)na); - if ( !x ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, \ - "memory allocation failed"); - } + if (!x) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed"); oh->alloc_nchunks = na; oh->chunk = x; } @@ -3142,11 +3147,8 @@ H5O_alloc_new_chunk(H5F_t *f, unsigned na = oh->alloc_nmesgs + MAX (H5O_NMESGS, 3); H5O_mesg_t *x = H5FL_SEQ_REALLOC (H5O_mesg_t, oh->mesg, (size_t)na); - if ( !x ) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, \ - "memory allocation failed"); - } + if (!x) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed"); oh->alloc_nmesgs = na; oh->mesg = x; @@ -3211,11 +3213,8 @@ H5O_alloc_new_chunk(H5F_t *f, */ oh->mesg[found_null].type = H5O_CONT; oh->mesg[found_null].dirty = TRUE; - if (NULL==(cont = H5FL_MALLOC(H5O_cont_t))) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, \ - "memory allocation failed"); - } + if (NULL==(cont = H5FL_MALLOC(H5O_cont_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed") cont->addr = oh->chunk[chunkno].addr; cont->size = oh->chunk[chunkno].size; cont->chunkno = chunkno; @@ -3226,7 +3225,6 @@ H5O_alloc_new_chunk(H5F_t *f, done: FUNC_LEAVE_NOAPI(ret_value); - } /* H5O_alloc_new_chunk() */ @@ -3270,7 +3268,7 @@ H5O_alloc(H5F_t *f, size_t size, unsigned * oh_flags_ptr) { - unsigned idx = UFAIL; + unsigned idx; H5O_mesg_t *msg; /* Pointer to newly allocated message */ size_t aligned_size = H5O_ALIGN(size); htri_t tri_result; @@ -3310,8 +3308,7 @@ H5O_alloc(H5F_t *f, * Note that in this new version of this function, all chunks * must have file space allocated to them. */ - for ( chunkno = 0; chunkno < oh->nchunks; chunkno++ ) - { + for (chunkno = 0; chunkno < oh->nchunks; chunkno++) { HDassert( H5F_addr_defined(oh->chunk[chunkno].addr) ); tri_result = H5O_alloc_extend_chunk(f, oh, chunkno, size, &idx); @@ -3334,13 +3331,9 @@ H5O_alloc(H5F_t *f, /* if idx is still UFAIL, we were not able to extend a chunk. * Create a new one. */ - if (idx == UFAIL) { - - if ( (idx = H5O_alloc_new_chunk(f, dxpl_id, oh, size)) == UFAIL ) { - - HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, UFAIL, \ - "unable to create a new object header data chunk"); - } + if(idx == UFAIL) { + if((idx = H5O_alloc_new_chunk(f, dxpl_id, oh, size)) == UFAIL) + HGOTO_ERROR(H5E_OHDR, H5E_NOSPACE, UFAIL, "unable to create a new object header data chunk") } } @@ -3349,35 +3342,26 @@ H5O_alloc(H5F_t *f, /* do we need to split the null message? */ if (msg->raw_size > aligned_size) { - H5O_mesg_t *null_msg; /* Pointer to null message */ + size_t mesg_size = aligned_size+ H5O_SIZEOF_MSGHDR(f); /* Total size of newly allocated message */ - size_t mesg_size = aligned_size + H5O_SIZEOF_MSGHDR(f); - /* Total size of newly allocated message */ - - HDassert( msg->raw_size - aligned_size >= H5O_SIZEOF_MSGHDR(f) ); + HDassert(msg->raw_size - aligned_size >= H5O_SIZEOF_MSGHDR(f)); if (oh->nmesgs >= oh->alloc_nmesgs) { - int old_alloc=oh->alloc_nmesgs; unsigned na = oh->alloc_nmesgs + H5O_NMESGS; H5O_mesg_t *x = H5FL_SEQ_REALLOC(H5O_mesg_t, oh->mesg, (size_t)na); - if (!x) { - - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, UFAIL, \ - "memory allocation failed"); - } - oh->alloc_nmesgs = na; - oh->mesg = x; + if (!x) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, UFAIL, "memory allocation failed"); + oh->alloc_nmesgs = na; + oh->mesg = x; /* Set new object header info to zeros */ HDmemset(&oh->mesg[old_alloc],0, (oh->alloc_nmesgs-old_alloc)*sizeof(H5O_mesg_t)); - /* "Retarget" local 'msg' pointer into newly allocated array - * of messages - */ + /* "Retarget" local 'msg' pointer into newly allocated array of messages */ msg=&oh->mesg[idx]; } null_msg = &(oh->mesg[oh->nmesgs++]); @@ -3402,7 +3386,6 @@ H5O_alloc(H5F_t *f, done: FUNC_LEAVE_NOAPI(ret_value); - } /* H5O_alloc() */ #ifdef NOT_YET @@ -4078,6 +4061,432 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_copy_mesg_file + * + * Purpose: Copies a message to file. If MESG is is the null pointer then a null + * pointer is returned with no error. + * + * Return: Success: Ptr to the new message + * + * Failure: NULL + * + * Programmer: Peter Cao + * June 4, 2005 + * + *------------------------------------------------------------------------- + */ +static void * +H5O_copy_mesg_file(const H5O_class_t *type, H5F_t *file_src, + void *native_src, H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata) +{ + void *ret_value; + + FUNC_ENTER_NOAPI_NOINIT(H5O_copy_mesg_file) + + /* check args */ + HDassert(type); + HDassert(type->copy_file); + HDassert(file_src); + HDassert(native_src); + HDassert(file_dst); + HDassert(map_list); + + if(NULL == (ret_value = (type->copy_file)(file_src, native_src, file_dst, dxpl_id, map_list, udata))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy object header message to file") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_mesg_file() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_post_copy_mesg_file + * + * Purpose: Copies what's left to file after the object a meesage is copied. + * This function is need for situations like copying symbol tables. + * Copying a member of symbol table requires the parent object header + * exists in file. For this case, the first round of the message will + * create symbol table enttries but will not go deep copying member + * objects in the symbol table. The post copy will do that. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Peter Cao + * September 28, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_post_copy_mesg_file (const H5O_class_t *type, H5F_t *file_src, + const void *mesg_src, H5G_entry_t *loc_dst, + hid_t dxpl_id, H5SL_t *map_list) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5O_post_copy_mesg_file) + + /* check args */ + HDassert(type); + HDassert(file_src); + HDassert(mesg_src); + HDassert(loc_dst->file); + HDassert(map_list); + + if(type->post_copy_file && (type->post_copy_file)(file_src, mesg_src, loc_dst, dxpl_id, map_list) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy object header message to file") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_post_copy_mesg_file */ + + +/*------------------------------------------------------------------------- + * Function: H5O_copy_header_real + * + * Purpose: copy header object from one location to another. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Peter Cao + * May 30, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_copy_header_real(const H5G_entry_t *ent_src, + H5G_entry_t *ent_dst /*out */, hid_t dxpl_id, H5SL_t *map_list) +{ + H5O_addr_map_t *addr_map; /* Address mapping of object copied */ + uint8_t buf[16], *p; + H5O_t *oh = NULL; + unsigned chunkno = 0, mesgno = 0; + size_t chunk_size, hdr_size; + haddr_t addr_new; + H5O_mesg_t *mesg_src; + H5O_chunk_t *chunk; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI_NOINIT(H5O_copy_header_real) + + HDassert(ent_src); + HDassert(ent_src->file); + HDassert(H5F_addr_defined(ent_src->header)); + HDassert(ent_dst->file); + HDassert(map_list); + + if(NULL == (oh = H5AC_protect(ent_src->file, dxpl_id, H5AC_OHDR, ent_src->header, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") + + /* get the size of the file header of the destination file */ + hdr_size = H5O_SIZEOF_HDR(ent_dst->file); + + /* allocate memory space for the destitnation chunks */ + if(NULL == (chunk = H5FL_SEQ_MALLOC(H5O_chunk_t, (size_t)oh->nchunks))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Allocate space for the first chunk */ + if(HADDR_UNDEF == (addr_new = H5MF_alloc(ent_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)hdr_size + oh->chunk[0].size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header") + + /* Return the first chunk address */ + ent_dst->header = addr_new; + + /* Set chunk's address */ + chunk[0].addr = addr_new + (hsize_t)hdr_size; + + /* Encode header information */ + p = buf; + + /* encode version */ + *p++ = H5O_VERSION; + + /* reserved */ + *p++ = 0; + + /* encode number of messages */ + UINT16ENCODE(p, oh->nmesgs); + + /* encode link count (at zero initially) */ + UINT32ENCODE(p, 0); + + /* encode body size */ + UINT32ENCODE(p, oh->chunk[0].size); + + /* zero to alignment */ + HDmemset(p, 0, (size_t)(hdr_size-12)); + + /* need to allocate all the chunks for the destination before copy the chunk message + because continuation chunk message will need to know the chunk address of address of + continuation block. + */ + for(chunkno = 1; chunkno < oh->nchunks; chunkno++) { + if(HADDR_UNDEF == (chunk[chunkno].addr = H5MF_alloc(ent_dst->file, H5FD_MEM_OHDR, dxpl_id, (hsize_t)oh->chunk[chunkno].size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for object header") + } /* end for */ + + /* Loop through chunks to copy chunk information */ + for(chunkno = 0; chunkno < oh->nchunks; chunkno++) { + chunk_size = oh->chunk[chunkno].size; + + /* copy chunk information */ + chunk[chunkno].dirty = oh->chunk[chunkno].dirty; + chunk[chunkno].size = chunk_size; + + /* create memory image for the new chunk */ + if(NULL == (chunk[chunkno].image = H5FL_BLK_MALLOC(chunk_image,chunk_size))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* copy the chunk image from source to destination in memory */ + /* (This copies over all the messages which don't require special + * callbacks to fix them up.) + */ + HDmemcpy(chunk[chunkno].image, oh->chunk[chunkno].image, chunk_size); + + /* Loop through messages, to fix up any which refer to addresses in the source file, etc. */ + for(mesgno = 0; mesgno < oh->nmesgs; mesgno++) { + const H5O_class_t *copy_type; + + mesg_src = &(oh->mesg[mesgno]); + + /* check if the message belongs to this chunk */ + if(mesg_src->chunkno != chunkno) + continue; + + if (mesg_src->flags & H5O_FLAG_SHARED) + copy_type = H5O_SHARED; + else + copy_type = mesg_src->type; + + /* copy this message into destination file */ + HDassert(copy_type); + if(copy_type->copy_file) { + void *dst_native; /* Pointer to copy of native information for current message */ + + /* + * Decode the message if necessary. If the message is shared then d + * a shared message, ignoring the message type. + */ + if(NULL == mesg_src->native) { + /* Decode the message if necessary */ + HDassert(copy_type->decode); + if(NULL == (mesg_src->native = (copy_type->decode)(ent_src->file, dxpl_id, mesg_src->raw, NULL))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTDECODE, FAIL, "unable to decode a message") + } /* end if (NULL == mesg_src->native) */ + + /* Copy the source message */ + if(H5O_CONT_ID == copy_type->id) { + if((dst_native = H5O_copy_mesg_file(copy_type, ent_src->file, mesg_src->native, + ent_dst->file, dxpl_id, map_list, chunk)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") + } /* end if */ + else { + if((dst_native = H5O_copy_mesg_file(copy_type, ent_src->file, mesg_src->native, + ent_dst->file, dxpl_id, map_list, NULL)) == NULL) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") + } /* end else */ + + /* Calculate address in destination raw chunk */ + p = chunk[chunkno].image + (mesg_src->raw - oh->chunk[chunkno].image); + + /* + * Encode the message. If the message is shared then we + * encode a Shared Object message instead of the object + * which is being shared. + */ + if((copy_type->encode)(ent_dst->file, p, dst_native) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTENCODE, FAIL, "unable to encode object header message") + + /* Release native destination info */ + H5O_free_real(copy_type, dst_native); + } /* end if (mesg_src->type && mesg_src->type->copy_file) */ + } /* end of mesgno loop */ + + /* Write the object header to the file if this is the first chunk */ + if(chunkno == 0) + if(H5F_block_write(ent_dst->file, H5FD_MEM_OHDR, addr_new, hdr_size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header hdr to disk") + + /* Write this chunk into disk */ + if(H5F_block_write(ent_dst->file, H5FD_MEM_OHDR, chunk[chunkno].addr, chunk[chunkno].size, dxpl_id, chunk[chunkno].image) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_WRITEERROR, FAIL, "unable to write object header data to disk") + } /* end of chunkno loop */ + + /* Allocate space for the address mapping of the object copied */ + if(NULL == (addr_map = H5FL_MALLOC(H5O_addr_map_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Insert the address mapping for the new object into the copied list */ + /* (Do this here, because "post copy" possibly checks it) */ + addr_map->src_addr = ent_src->header; + addr_map->dst_addr = ent_dst->header; + if(H5SL_insert(map_list, addr_map, &(addr_map->src_addr)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTINSERT, FAIL, "can't insert object into skip list") + + /* "post copy" loop over messages */ + for(mesgno = 0; mesgno < oh->nmesgs; mesgno++) { + const H5O_class_t *copy_type; + + mesg_src = &(oh->mesg[mesgno]); + + if (mesg_src->flags & H5O_FLAG_SHARED) + copy_type = H5O_SHARED; + else + copy_type = mesg_src->type; + + HDassert(copy_type); + if(mesg_src->native) { + if((H5O_post_copy_mesg_file(copy_type, ent_src->file, mesg_src->native, + ent_dst, dxpl_id, map_list)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object header message") + } /* end if */ + } /* end for */ + +done: + /* Release pointer to object header itself */ + if(oh != NULL) { + for(chunkno = 0; chunkno < oh->nchunks; chunkno++) + H5FL_BLK_FREE(chunk_image, chunk[chunkno].image); + H5FL_SEQ_FREE(H5O_chunk_t, chunk); + + if(H5AC_unprotect(ent_src->file, dxpl_id, H5AC_OHDR, ent_src->header, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_header_real() */ + + +/*------------------------------------------------------------------------- + * 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 H5G_entry_t *ent_src, + H5G_entry_t *ent_dst /*out */, hid_t dxpl_id, H5SL_t *map_list) +{ + H5O_addr_map_t *addr_map; /* Address mapping of object copied */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5O_copy_header_map, FAIL) + + /* Sanity check */ + HDassert(ent_src); + HDassert(ent_dst); + HDassert(ent_dst->file); + HDassert(map_list); + + /* Look up the address of the object to copy in the skip list */ + addr_map = (H5O_addr_map_t *)H5SL_search(map_list, &(ent_src->header)); + + /* Check if address is already in list of objects copied */ + if(addr_map == NULL) { + /* Copy object for the first time */ + + /* Copy object referred to */ + if(H5O_copy_header_real(ent_src, ent_dst, dxpl_id, map_list) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + } /* end if */ + else { + /* Object has already been copied, set it's address in destination file */ + ent_dst->header = addr_map->dst_addr; + } /* end else */ + + /* Increment destination object's link count */ + if(H5O_link(ent_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) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_copy_free_addrmap_cb) + + HDassert(item); + + /* Release the 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 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_copy_header(const H5G_entry_t *ent_src, + H5G_entry_t *ent_dst /*out */, hid_t dxpl_id) +{ + H5SL_t *map_list = NULL; /* Skip list to hold address mappings */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5O_copy_header, FAIL) + + HDassert(ent_src); + HDassert(ent_src->file); + HDassert(H5F_addr_defined(ent_src->header)); + HDassert(ent_dst->file); + + /* Create a skip list to keep track of which objects are copied */ + if((map_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, 16)) == 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(ent_src, ent_dst, dxpl_id, map_list) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, FAIL, "unable to copy object") + +done: + if(map_list) + H5SL_destroy(map_list, H5O_copy_free_addrmap_cb, NULL); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_copy_header() */ + + +/*------------------------------------------------------------------------- * Function: H5O_debug_id * * Purpose: Act as a proxy for calling the 'debug' method for a diff --git a/src/H5Oattr.c b/src/H5Oattr.c index abff4f3..9ac5570 100644 --- a/src/H5Oattr.c +++ b/src/H5Oattr.c @@ -35,6 +35,8 @@ static herr_t H5O_attr_reset (void *_mesg); static herr_t H5O_attr_free (void *mesg); static herr_t H5O_attr_delete (H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); static herr_t H5O_attr_link(H5F_t *f, hid_t dxpl_id, const void *_mesg); +static void *H5O_attr_copy_file(H5F_t *file_src, void *native_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); static herr_t H5O_attr_debug (H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -53,7 +55,9 @@ const H5O_class_t H5O_ATTR[1] = {{ H5O_attr_link, /* link method */ NULL, /* get share method */ NULL, /* set share method */ - H5O_attr_debug, /* debug the message */ + H5O_attr_copy_file, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_attr_debug /* debug the message */ }}; /* This is the initial version, which does not have support for shared datatypes */ @@ -65,12 +69,6 @@ const H5O_class_t H5O_ATTR[1] = {{ /* Flags for attribute flag encoding */ #define H5O_ATTR_FLAG_TYPE_SHARED 0x01 -/* Declare extern the free list for H5A_t's */ -H5FL_EXTERN(H5A_t); - -/* Declare extern the free list for attribute data buffers */ -H5FL_BLK_EXTERN(attr_buf); - /* Declare external the free list for H5S_t's */ H5FL_EXTERN(H5S_t); @@ -595,6 +593,95 @@ done: } /* end H5O_attr_link() */ +/*------------------------------------------------------------------------- + * Function: H5O_attr_copy_file + * + * Purpose: Copies a message from _MESG to _DEST in file + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * November 1, 2005 + * + *------------------------------------------------------------------------- + */ +static void * +H5O_attr_copy_file(H5F_t UNUSED *file_src, void *native_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void UNUSED *udata) +{ + H5A_t *attr_src = (H5A_t *)native_src; + H5A_t *attr_dst = NULL; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_attr_copy_file) + + /* check args */ + HDassert(attr_src); + HDassert(file_dst); + HDassert(map_list); + + /* Allocate space for the destination message */ + if(NULL == (attr_dst = H5FL_CALLOC(H5A_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Copy the top level of the attribute */ + *attr_dst = *attr_src; + + /* Don't have an opened group entry for copy */ + H5G_ent_reset(&(attr_dst->ent)); + attr_dst->ent_opened = 0; + + /* Copy attribute's name */ + attr_dst->name = H5MM_strdup(attr_src->name); + + /* Copy attribute's datatype */ + /* (Start destination datatype as transient, even if source is named) */ + attr_dst->dt = H5T_copy(attr_src->dt, H5T_COPY_ALL); + + /* Check for named datatype being copied */ + if(H5T_committed(attr_src->dt)) { + H5G_entry_t *ent_src; /* Pointer to source datatype's group entry */ + H5G_entry_t *ent_dst; /* Pointer to dest. datatype's group entry */ + + /* Get group entries for source & destination */ + ent_src = H5T_entof(attr_src->dt); + HDassert(ent_src); + ent_dst = H5T_entof(attr_dst->dt); + HDassert(ent_dst); + + /* Reset group entry for new object */ + H5G_ent_reset(ent_dst); + ent_dst->file = file_dst; + + /* Copy the shared object from source to destination */ + if(H5O_copy_header_map(ent_src, ent_dst, dxpl_id, map_list) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object") + } /* end if */ + + /* Copy the guts of the attribute */ + attr_dst->ds = H5S_copy(attr_src->ds, FALSE); + + if(attr_src->data) { + if(NULL == (attr_dst->data = H5FL_BLK_MALLOC(attr_buf, attr_src->data_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + HDmemcpy(attr_dst->data, attr_src->data, attr_src->data_size); + } /* end if */ + + /* Set return value */ + ret_value = attr_dst; + +done: + if(!ret_value) + if(attr_dst) + (void)H5A_free(attr_dst); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_attr_copy_file() */ + + /*-------------------------------------------------------------------------- NAME H5O_attr_debug diff --git a/src/H5Obogus.c b/src/H5Obogus.c index 54a52b2..7296860 100644 --- a/src/H5Obogus.c +++ b/src/H5Obogus.c @@ -60,7 +60,9 @@ const H5O_class_t H5O_BOGUS[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_bogus_debug, /*debug the message */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_bogus_debug /*debug the message */ }}; diff --git a/src/H5Ocont.c b/src/H5Ocont.c index e62ca07..afa5ab7 100644 --- a/src/H5Ocont.c +++ b/src/H5Ocont.c @@ -42,6 +42,8 @@ static void *H5O_cont_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shar static herr_t H5O_cont_encode(H5F_t *f, uint8_t *p, const void *_mesg); static size_t H5O_cont_size(const H5F_t *f, const void *_mesg); static herr_t H5O_cont_free(void *mesg); +static void *H5O_cont_copy_file(H5F_t *file_src, void *mesg_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); static herr_t H5O_cont_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -60,7 +62,9 @@ const H5O_class_t H5O_CONT[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_cont_debug, /*debugging */ + H5O_cont_copy_file, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_cont_debug /*debugging */ }}; /* Declare the free list for H5O_cont_t's */ @@ -209,6 +213,54 @@ H5O_cont_free (void *mesg) /*------------------------------------------------------------------------- + * Function: H5O_cont_copy_file + * + * Purpose: Copies a continuation block message from _MESG to _DEST in file + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Peter Cao + * September 22, 2005 + * + *------------------------------------------------------------------------- + */ +static void * +H5O_cont_copy_file(H5F_t UNUSED *file_src, void *mesg_src, + H5F_t *file_dst, hid_t UNUSED dxpl_id, H5SL_t UNUSED *map_list, void *udata) +{ + H5O_cont_t *cont_src = (H5O_cont_t *) mesg_src; + H5O_chunk_t *chunk = (H5O_chunk_t *)udata; + H5O_cont_t *cont_dst = NULL; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_cont_copy_file) + + /* check args */ + HDassert(cont_src); + HDassert(file_dst); + + /* Allocate space for the destination cont */ + if(NULL == (cont_dst = H5FL_MALLOC(H5O_cont_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + HDmemcpy(cont_dst, cont_src, sizeof(H5O_cont_t)); + cont_dst->addr = chunk[cont_src->chunkno].addr; + + /* Set return value */ + ret_value = cont_dst; + +done: + if(!ret_value) + if(cont_dst) + H5FL_FREE(H5O_cont_t, cont_dst); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_cont_copy_file() */ + + +/*------------------------------------------------------------------------- * Function: H5O_cont_debug * * Purpose: Prints debugging info. diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 0eed438..05ca879 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -53,7 +53,9 @@ const H5O_class_t H5O_DTYPE[1] = {{ NULL, /* link method */ H5O_dtype_get_share, /* get share method */ H5O_dtype_set_share, /* set share method */ - H5O_dtype_debug, /* debug the message */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_dtype_debug /* debug the message */ }}; /* This is the correct version to create all datatypes which don't contain diff --git a/src/H5Oefl.c b/src/H5Oefl.c index 9106310..8c78cae 100644 --- a/src/H5Oefl.c +++ b/src/H5Oefl.c @@ -33,6 +33,8 @@ static herr_t H5O_efl_encode(H5F_t *f, uint8_t *p, const void *_mesg); static void *H5O_efl_copy(const void *_mesg, void *_dest, unsigned update_flags); static size_t H5O_efl_size(const H5F_t *f, const void *_mesg); static herr_t H5O_efl_reset(void *_mesg); +static void *H5O_efl_copy_file(H5F_t *file_src, void *mesg_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); static herr_t H5O_efl_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -51,7 +53,9 @@ const H5O_class_t H5O_EFL[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_efl_debug, /*debug the message */ + H5O_efl_copy_file, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_efl_debug /*debug the message */ }}; #define H5O_EFL_VERSION 1 @@ -415,6 +419,86 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_efl_copy_file + * + * Purpose: Copies an efl message from _MESG to _DEST in file + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Peter Cao + * September 29, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_efl_copy_file(H5F_t UNUSED *file_src, void *mesg_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t UNUSED *map_list, void UNUSED *_udata) +{ + H5O_efl_t *efl_src = (H5O_efl_t *) mesg_src; + H5O_efl_t *efl_dst = NULL; + size_t idx, size, name_offset, heap_size; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_efl_copy_file) + + /* check args */ + HDassert(efl_src); + HDassert(file_dst); + + /* Allocate space for the destination efl */ + if(NULL == (efl_dst = H5MM_calloc(sizeof(H5O_efl_t)))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Copy the "top level" information */ + HDmemcpy(efl_dst, efl_src, sizeof(H5O_efl_t)); + + /* create name heap */ + heap_size = H5HL_ALIGN(1); + for(idx = 0; idx < efl_src->nused; idx++) + heap_size += H5HL_ALIGN(HDstrlen(efl_src->slot[idx].name) + 1); + + if(H5HL_create(file_dst, dxpl_id, heap_size, &efl_dst->heap_addr/*out*/) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't create heap") + + name_offset = H5HL_insert(file_dst, dxpl_id, efl_dst->heap_addr, 1, ""); + if((size_t)(-1) == name_offset) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, NULL, "can't initialize heap") + HDassert(0 == name_offset); + + /* allocate array of external file entries */ + if(efl_src->nalloc > 0) { + size = efl_src->nalloc * sizeof(H5O_efl_entry_t); + if((efl_dst->slot = H5MM_calloc(size)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* copy content from the source. Need to update later */ + HDmemcpy(efl_dst->slot, efl_src->slot, size); + } + + /* copy the name from the source */ + for(idx = 0; idx < efl_src->nused; idx++) { + efl_dst->slot[idx].name = H5MM_xstrdup(efl_src->slot[idx].name); + efl_dst->slot[idx].name_offset = H5HL_insert(file_dst, dxpl_id, efl_dst->heap_addr, + HDstrlen(efl_dst->slot[idx].name)+1, efl_dst->slot[idx].name); + } + + /* Set return value */ + ret_value = efl_dst; + +done: + if(!ret_value) + if(efl_dst) + H5MM_xfree(efl_dst); + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- * Function: H5O_efl_debug * * Purpose: Prints debugging info for a message. @@ -475,3 +559,4 @@ H5O_efl_debug(H5F_t UNUSED *f, hid_t UNUSED dxpl_id, const void *_mesg, FILE * s FUNC_LEAVE_NOAPI(SUCCEED); } + diff --git a/src/H5Ofill.c b/src/H5Ofill.c index d0bf381..b68c106 100644 --- a/src/H5Ofill.c +++ b/src/H5Ofill.c @@ -63,7 +63,9 @@ const H5O_class_t H5O_FILL[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_fill_debug, /*debug the message */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_fill_debug /*debug the message */ }}; /* This message derives from H5O, for new fill value after version 1.4 */ @@ -81,7 +83,9 @@ const H5O_class_t H5O_FILL_NEW[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_fill_new_debug, /*debug the message */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_fill_new_debug /*debug the message */ }}; /* Initial version of the "old" fill value information */ diff --git a/src/H5Olayout.c b/src/H5Olayout.c index 4a6fdfe..3103053 100644 --- a/src/H5Olayout.c +++ b/src/H5Olayout.c @@ -18,16 +18,18 @@ * Purpose: Messages related to data layout. */ +#define H5D_PACKAGE /*suppress error about including H5Dpkg */ #define H5O_PACKAGE /*suppress error about including H5Opkg */ -#include "H5private.h" -#include "H5Dprivate.h" -#include "H5Eprivate.h" -#include "H5FLprivate.h" /*Free Lists */ +#include "H5private.h" /* Generic Functions */ +#include "H5Dpkg.h" /* Dataset functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ #include "H5MFprivate.h" /* File space management */ -#include "H5MMprivate.h" -#include "H5Opkg.h" /* Object header functions */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Opkg.h" /* Object headers */ +#include "H5Pprivate.h" /* Property lists */ /* PRIVATE PROTOTYPES */ static void *H5O_layout_decode(H5F_t *f, hid_t dxpl_id, const uint8_t *p, H5O_shared_t *sh); @@ -37,6 +39,8 @@ static size_t H5O_layout_size(const H5F_t *f, const void *_mesg); static herr_t H5O_layout_reset(void *_mesg); static herr_t H5O_layout_free(void *_mesg); static herr_t H5O_layout_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); +static void *H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); static herr_t H5O_layout_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, FILE * stream, int indent, int fwidth); @@ -55,7 +59,9 @@ const H5O_class_t H5O_LAYOUT[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_layout_debug, /*debug the message */ + H5O_layout_copy_file, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_layout_debug /*debug the message */ }}; /* For forward and backward compatibility. Version is 1 when space is @@ -599,6 +605,113 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_layout_copy_file + * + * Purpose: Copies a data layout message from _MESG to _DEST in file + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Peter Cao + * July 23, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void * +H5O_layout_copy_file(H5F_t *file_src, void *mesg_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t UNUSED *map_list, void UNUSED *_udata) +{ + H5O_layout_t *layout_src = (H5O_layout_t *) mesg_src; + H5O_layout_t *layout_dst = NULL; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_layout_copy_file) + + /* check args */ + HDassert(layout_src); + HDassert(file_dst); + + /* Allocate space for the destination layout */ + if(NULL == (layout_dst = H5FL_MALLOC(H5O_layout_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Copy the "top level" information */ + HDmemcpy(layout_dst, layout_src, sizeof(H5O_layout_t)); + + /* Copy the layout type specific information */ + switch(layout_src->type) { + case H5D_COMPACT: + if(layout_src->u.compact.buf) { + if(NULL == (layout_dst->u.compact.buf = H5MM_malloc(layout_src->u.compact.size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory for compact dataset") + HDmemcpy(layout_dst->u.compact.buf, layout_src->u.compact.buf, layout_src->u.compact.size); + layout_dst->u.compact.dirty = TRUE; + } + break; + + case H5D_CONTIGUOUS: + if(H5F_addr_defined(layout_src->u.contig.addr)) { + haddr_t addr_src, addr_dst; + unsigned DRAW_BUF_SIZE = 4096; + uint8_t buf[4096]; + size_t nbytes=0, total_nbytes=0; + + /* create layout */ + if(H5D_contig_create (file_dst, dxpl_id, layout_dst)<0) + HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to initialize contiguous storage") + + /* copy raw data*/ + nbytes = total_nbytes = 0; + while(total_nbytes < layout_src->u.contig.size) { + addr_src = layout_src->u.contig.addr + total_nbytes; + addr_dst = layout_dst->u.contig.addr + total_nbytes; + + nbytes = layout_src->u.contig.size-total_nbytes; + if(nbytes > DRAW_BUF_SIZE) + nbytes = DRAW_BUF_SIZE; + total_nbytes += nbytes; + + if(H5F_block_read(file_src, H5FD_MEM_DRAW, addr_src, nbytes, H5P_DATASET_XFER_DEFAULT, buf)<0) + HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to read raw data") + + if(H5F_block_write(file_dst, H5FD_MEM_DRAW, addr_dst, nbytes, H5P_DATASET_XFER_DEFAULT, buf)<0) + HGOTO_ERROR(H5E_SYM, H5E_READERROR, NULL, "unable to write raw data") + } + } /* if ( H5F_addr_defined(layout_src->u.contig.addr)) */ + break; + + case H5D_CHUNKED: + if(H5F_addr_defined(layout_src->u.chunk.addr)) { + + /* layout is not created in the destination file, undef btree address */ + layout_dst->u.chunk.addr = HADDR_UNDEF; + + /* create chunked layout */ + if(H5D_istore_copy(file_src, layout_src, file_dst, layout_dst, dxpl_id) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to copy chunked storage") + } /* if ( H5F_addr_defined(layout_srct->u.chunk.addr)) */ + break; + + default: + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "Invalid layout class"); + } /* end switch */ + + /* Set return value */ + ret_value=layout_dst; + +done: + if(!ret_value) + if(layout_dst) + H5FL_FREE(H5O_layout_t, layout_dst); + + FUNC_LEAVE_NOAPI(ret_value) +} + + +/*------------------------------------------------------------------------- * Function: H5O_layout_debug * * Purpose: Prints debugging info for a message. diff --git a/src/H5Omtime.c b/src/H5Omtime.c index d3c2f3c..4244733 100644 --- a/src/H5Omtime.c +++ b/src/H5Omtime.c @@ -60,7 +60,9 @@ const H5O_class_t H5O_MTIME[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_mtime_debug, /*debug the message */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_mtime_debug /*debug the message */ }}; /* This message derives from H5O */ @@ -79,7 +81,9 @@ const H5O_class_t H5O_MTIME_NEW[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_mtime_debug, /*debug the message */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_mtime_debug /*debug the message */ }}; /* Current version of new mtime information */ diff --git a/src/H5Oname.c b/src/H5Oname.c index 64477af..ba4433a 100644 --- a/src/H5Oname.c +++ b/src/H5Oname.c @@ -57,7 +57,9 @@ const H5O_class_t H5O_NAME[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_name_debug, /*debug the message */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_name_debug /*debug the message */ }}; diff --git a/src/H5Onull.c b/src/H5Onull.c index 028a535..074026e 100644 --- a/src/H5Onull.c +++ b/src/H5Onull.c @@ -46,5 +46,7 @@ const H5O_class_t H5O_NULL[1] = {{ NULL, /*no link method */ NULL, /*no get share method */ NULL, /*no set share method */ - NULL, /*no debug method */ + NULL, /*no copy native value to file */ + NULL, /*no post copy native value to file */ + NULL /*no debug method */ }}; diff --git a/src/H5Opkg.h b/src/H5Opkg.h index 83889f6..fdca31a 100644 --- a/src/H5Opkg.h +++ b/src/H5Opkg.h @@ -19,8 +19,11 @@ #ifndef _H5Opkg_H #define _H5Opkg_H -/* Include private header file */ -#include "H5Oprivate.h" /* Object header functions */ +/* Get package's private header */ +#include "H5Oprivate.h" /* Object headers */ + +/* Other private headers needed by this file */ +#include "H5SLprivate.h" /* Skip lists */ /* * Align messages on 8-byte boundaries because we would like to copy the @@ -69,6 +72,8 @@ typedef struct H5O_class_t { herr_t (*link)(H5F_t *, hid_t, const void *); /* Increment any links in file reference by this message */ herr_t (*get_share)(H5F_t*, const void*, struct H5O_shared_t*); /* Get shared information */ herr_t (*set_share)(H5F_t*, void*, const struct H5O_shared_t*); /* Set shared information */ + void *(*copy_file)(H5F_t *, void *, H5F_t *, hid_t, H5SL_t *, void *); /*copy native value to file */ + herr_t (*post_copy_file)(H5F_t *, const void *, H5G_entry_t *, hid_t, H5SL_t *); /*"post copy" action when copying native value to file */ herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int); } H5O_class_t; diff --git a/src/H5Opline.c b/src/H5Opline.c index 280c8db..391c758 100644 --- a/src/H5Opline.c +++ b/src/H5Opline.c @@ -54,7 +54,9 @@ const H5O_class_t H5O_PLINE[1] = {{ NULL, /* link method */ NULL, /* get share method */ NULL, /* set share method */ - H5O_pline_debug, /* debug the message */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_pline_debug /* debug the message */ }}; diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index e3043af..d619806 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -28,16 +28,17 @@ #define _H5Oprivate_H /* Include the public header file for this API */ -#include "H5Opublic.h" /* Object header functions */ +#include "H5Opublic.h" /* Object header functions */ /* Public headers needed by this file */ -#include "H5Dpublic.h" /* Dataset functions */ -#include "H5Spublic.h" /* Dataspace functions */ +#include "H5Dpublic.h" /* Dataset functions */ +#include "H5Spublic.h" /* Dataspace functions */ /* Private headers needed by this file */ -#include "H5HGprivate.h" /* Global heap functions */ -#include "H5Tprivate.h" /* Datatype functions */ -#include "H5Zprivate.h" /* I/O pipeline filters */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5HGprivate.h" /* Global heap functions */ +#include "H5Tprivate.h" /* Datatype functions */ +#include "H5Zprivate.h" /* I/O pipeline filters */ /* Object header macros */ #define H5O_MIN_SIZE H5O_ALIGN(32) /*min obj header data size */ @@ -249,6 +250,9 @@ typedef struct H5O_stab_t { typedef herr_t (*H5O_operator_t)(const void *mesg/*in*/, unsigned idx, void *operator_data/*in,out*/); +/* Forward declarations for prototype arguments */ +struct H5SL_t; + /* General message operators */ H5_DLL herr_t H5O_create(H5F_t *f, hid_t dxpl_id, size_t size_hint, H5G_entry_t *ent/*out*/); @@ -291,6 +295,10 @@ H5_DLL herr_t H5O_delete(H5F_t *f, hid_t dxpl_id, haddr_t addr); H5_DLL herr_t H5O_get_info(H5G_entry_t *ent, H5O_stat_t *ostat, hid_t dxpl_id); H5_DLL herr_t H5O_iterate(const H5G_entry_t *ent, unsigned type_id, H5O_operator_t op, void *op_data, hid_t dxpl_id); +H5_DLL herr_t H5O_copy_header(const H5G_entry_t *ent_src, + H5G_entry_t *ent_dst /*out */, hid_t dxpl_id); +H5_DLL herr_t H5O_copy_header_map(const H5G_entry_t *ent_src, + H5G_entry_t *ent_dst /*out */, hid_t dxpl_id, struct H5SL_t *obj_list); H5_DLL herr_t H5O_debug_id(hid_t type_id, H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, int indent, int fwidth); H5_DLL herr_t H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream, int indent, int fwidth); diff --git a/src/H5Osdspace.c b/src/H5Osdspace.c index cc3beb1..f4c5500 100644 --- a/src/H5Osdspace.c +++ b/src/H5Osdspace.c @@ -49,7 +49,9 @@ const H5O_class_t H5O_SDSPACE[1] = {{ NULL, /* link method */ NULL, /* get share method */ NULL, /* set share method */ - H5O_sdspace_debug, /* debug the message */ + NULL, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_sdspace_debug /* debug the message */ }}; /* Initial version of the "old" data space information */ diff --git a/src/H5Oshared.c b/src/H5Oshared.c index 8a0a291..09f273d 100644 --- a/src/H5Oshared.c +++ b/src/H5Oshared.c @@ -42,6 +42,8 @@ static void *H5O_shared_copy(const void *_mesg, void *_dest, unsigned update_fla static size_t H5O_shared_size (const H5F_t*, const void *_mesg); static herr_t H5O_shared_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); static herr_t H5O_shared_link(H5F_t *f, hid_t dxpl_id, const void *_mesg); +static void *H5O_shared_copy_file(H5F_t *file_src, void *native_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); static herr_t H5O_shared_debug (H5F_t*, hid_t dxpl_id, const void*, FILE*, int, int); /* This message derives from H5O */ @@ -59,7 +61,9 @@ const H5O_class_t H5O_SHARED[1] = {{ H5O_shared_link, /*link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_shared_debug, /*debug method */ + H5O_shared_copy_file, /* copy native value to file */ + NULL, /* post copy native value to file */ + H5O_shared_debug /*debug method */ }}; /* Old version, with full symbol table entry as link for object header sharing */ @@ -472,6 +476,63 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_shared_copy_file + * + * Purpose: Copies a message from _MESG to _DEST in file + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * November 1, 2005 + * + *------------------------------------------------------------------------- + */ +static void * +H5O_shared_copy_file(H5F_t UNUSED *file_src, void *native_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void UNUSED *udata) +{ + H5O_shared_t *shared_src = (H5O_shared_t *)native_src; + H5O_shared_t *shared_dst = NULL; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_shared_copy_file) + + /* check args */ + HDassert(shared_src); + HDassert(file_dst); + HDassert(map_list); + + /* Allocate space for the destination message */ + if(NULL == (shared_dst = H5MM_malloc(sizeof(H5O_shared_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Can't handle copying message in global heap currently */ + HDassert(!shared_src->in_gh); + shared_dst->in_gh = FALSE; + + /* Reset group entry for new object */ + H5G_ent_reset(&(shared_dst->u.ent)); + shared_dst->u.ent.file = file_dst; + + /* Copy the shared object from source to destination */ + if(H5O_copy_header_map(&(shared_src->u.ent), &(shared_dst->u.ent), dxpl_id, map_list) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "unable to copy object") + + /* Set return value */ + ret_value = shared_dst; + +done: + if(!ret_value) + if(shared_dst) + H5MM_xfree(shared_dst); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_shared_copy_file() */ + + +/*------------------------------------------------------------------------- * Function: H5O_shared_debug * * Purpose: Prints debugging info for the message diff --git a/src/H5Ostab.c b/src/H5Ostab.c index 21391bd..e03d6b1 100644 --- a/src/H5Ostab.c +++ b/src/H5Ostab.c @@ -42,8 +42,12 @@ static void *H5O_stab_copy(const void *_mesg, void *_dest, unsigned update_flags static size_t H5O_stab_size(const H5F_t *f, const void *_mesg); static herr_t H5O_stab_free(void *_mesg); static herr_t H5O_stab_delete(H5F_t *f, hid_t dxpl_id, const void *_mesg, hbool_t adj_link); +static void *H5O_stab_copy_file(H5F_t *file_src, void *native_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t *map_list, void *udata); +static herr_t H5O_stab_post_copy_file(H5F_t *file_src, const void *mesg_src, + H5G_entry_t *loc_dst, hid_t dxpl_id, H5SL_t *map_list); static herr_t H5O_stab_debug(H5F_t *f, hid_t dxpl_id, const void *_mesg, - FILE * stream, int indent, int fwidth); + FILE * stream, int indent, int fwidth); /* This message derives from H5O */ const H5O_class_t H5O_STAB[1] = {{ @@ -60,7 +64,9 @@ const H5O_class_t H5O_STAB[1] = {{ NULL, /* link method */ NULL, /*get share method */ NULL, /*set share method */ - H5O_stab_debug, /*debug the message */ + H5O_stab_copy_file, /* copy native value to file */ + H5O_stab_post_copy_file, /* post copy native value to file */ + H5O_stab_debug /*debug the message */ }}; /* Declare a free list to manage the H5O_stab_t struct */ @@ -337,6 +343,95 @@ done: /*------------------------------------------------------------------------- + * Function: H5O_stab_copy_file + * + * Purpose: Copies a message from _MESG to _DEST in file + * + * Return: Success: Ptr to _DEST + * + * Failure: NULL + * + * Programmer: Peter Cao + * September 10, 2005 + * + *------------------------------------------------------------------------- + */ +static void * +H5O_stab_copy_file(H5F_t UNUSED *file_src, void *native_src, + H5F_t *file_dst, hid_t dxpl_id, H5SL_t UNUSED *map_list, void UNUSED *udata) +{ + H5O_stab_t *stab_src = (H5O_stab_t *) native_src; + H5O_stab_t *stab_dst = NULL; + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_stab_copy_file) + + /* check args */ + HDassert(stab_src); + HDassert(file_dst); + + /* Allocate space for the destination stab */ + if(NULL == (stab_dst = H5FL_MALLOC(H5O_stab_t))) + HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + if(H5G_stab_copy_tmp(file_dst, stab_dst, dxpl_id) < 0) + HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to copy group symbol table") + + /* Set return value */ + ret_value = stab_dst; + +done: + if(!ret_value) + if(stab_dst) + H5FL_FREE(H5O_stab_t, stab_dst); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_stab_copy_file() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_stab_post_copy_file + * + * Purpose: Copies entries of a symbol table message from _MESG to _DEST in file + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Peter Cao + * September 28, 2005 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5O_stab_post_copy_file(H5F_t *file_src, const void *mesg_src, + H5G_entry_t *loc_dst, hid_t dxpl_id, H5SL_t *map_list) +{ + H5G_bt_it_ud5_t udata; /* B-tree user data */ + const H5O_stab_t *stab_src = (const H5O_stab_t *) mesg_src; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5O_stab_post_copy_file) + + /* check args */ + HDassert(file_src); + HDassert(stab_src); + HDassert(loc_dst->file); + HDassert(map_list); + + /* Set up B-tree iteration user data */ + udata.map_list = map_list; + udata.heap_addr = stab_src->heap_addr; + udata.loc_dst = loc_dst; + + /* Iterate over objects in group, copying them */ + if((H5B_iterate(file_src, dxpl_id, H5B_SNODE, H5G_node_copy, stab_src->btree_addr, &udata)) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "iteration operator failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5O_stab_post_copy_file() */ + + +/*------------------------------------------------------------------------- * Function: H5O_stab_debug * * Purpose: Prints debugging info for a symbol table message. diff --git a/src/H5S.c b/src/H5S.c index db535f6..4190ca4 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -39,6 +39,7 @@ static herr_t H5S_set_extent_simple (H5S_t *space, unsigned rank, static htri_t H5S_is_simple(const H5S_t *sdim); static herr_t H5S_encode(H5S_t *obj, unsigned char *buf, size_t *nalloc); static H5S_t *H5S_decode(const unsigned char *buf); +static htri_t H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2); #ifdef H5S_DEBUG /* Names of the selection names, for debugging */ @@ -2225,6 +2226,106 @@ done: /*------------------------------------------------------------------------- + * Function: H5Sextent_equal + * + * Purpose: Determines if two dataspace extents are equal. + * + * Return: Success: TRUE if equal, FALSE if unequal + * + * Failure: Negative + * + * Programmer: Quincey Koziol + * Monday, October 24, 2005 + * + *------------------------------------------------------------------------- + */ +htri_t +H5Sextent_equal(hid_t space1_id, hid_t space2_id) +{ + const H5S_t *ds1, *ds2; /* Dataspaces to compare */ + htri_t ret_value; + + FUNC_ENTER_API(H5Sextent_equal, FAIL) + H5TRACE2("t","ii",space1_id,space2_id); + + /* check args */ + if(NULL == (ds1 = H5I_object_verify(space1_id, H5I_DATASPACE)) || + NULL == (ds2 = H5I_object_verify(space2_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + + /* Check dataspaces for extent's equality */ + if((ret_value = H5S_extent_equal(ds1, ds2)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "dataspace comparison failed") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Sextent_equal() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_extent_equal + PURPOSE + Check if two dataspaces have equal extents + USAGE + htri_t H5S_extent_equal(ds1, ds2) + H5S_t *ds1, *ds2; IN: Dataspace objects to compare + RETURNS + TRUE if equal, FALSE if unequal on succeess/Negative on failure + DESCRIPTION + Compare two dataspaces if their extents are identical. +--------------------------------------------------------------------------*/ +static htri_t +H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2) +{ + unsigned u; /* Local index variable */ + htri_t ret_value = TRUE; /* Return value */ + + FUNC_ENTER_NOAPI(H5S_extent_equal, FAIL) + + /* Check args */ + HDassert(ds1); + HDassert(ds2); + + /* Make certain the dataspaces are the same type */ + if(ds1->extent.type != ds2->extent.type) + HGOTO_DONE(FALSE) + + /* Make certain the dataspaces are the same rank */ + if(ds1->extent.rank != ds2->extent.rank) + HGOTO_DONE(FALSE) + + /* Make certain the dataspaces' current dimensions are the same size */ + if(ds1->extent.rank > 0) { + HDassert(ds1->extent.size); + HDassert(ds2->extent.size); + for(u = 0; u < ds1->extent.rank; u++) { + if(ds1->extent.size[u] != ds2->extent.size[u]) + HGOTO_DONE(FALSE) + } /* end for */ + } /* end if */ + + /* Make certain the dataspaces' maximum dimensions are the same size */ + if(ds1->extent.rank > 0) { + /* Check for no maximum dimensions on dataspaces */ + if(ds1->extent.max != NULL && ds2->extent.max != NULL) { + for(u = 0; u < ds1->extent.rank; u++) { + if(ds1->extent.max[u] != ds2->extent.max[u]) + HGOTO_DONE(FALSE) + } /* end for */ + } /* end if */ + else + if((ds1->extent.max == NULL && ds2->extent.max != NULL) || + (ds1->extent.max != NULL && ds2->extent.max == NULL)) + HGOTO_DONE(FALSE) + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_extent_equal() */ + + +/*------------------------------------------------------------------------- * Function: H5S_debug * * Purpose: Prints debugging information about a data space. diff --git a/src/H5Shyper.c b/src/H5Shyper.c index 1f75af4..83bebe9 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -5371,7 +5371,7 @@ H5S_hyper_rebuild_helper(const H5S_hyper_span_t *span, H5S_hyper_dim_t span_slab hsize_t curr_start; hsize_t curr_low; int outcount; - int i; + unsigned u; H5S_hyper_dim_t canon_down_span_slab_info[H5S_MAX_RANK]; hbool_t ret_value = TRUE; @@ -5414,17 +5414,17 @@ H5S_hyper_rebuild_helper(const H5S_hyper_span_t *span, H5S_hyper_dim_t span_slab /* Compare the slab information of the adjacent spans in the down span tree. We have to compare all the sub-tree slab information with the canon_down_span_slab_info.*/ - for( i = 0; i < rank - 1; i++) { - curr_down_span_slab_info = &span_slab_info[i]; + for( u = 0; u < rank - 1; u++) { + curr_down_span_slab_info = &span_slab_info[u]; - if(curr_down_span_slab_info->count > 0 && canon_down_span_slab_info[i].count > 0) { - if(curr_down_span_slab_info->start != canon_down_span_slab_info[i].start - || curr_down_span_slab_info->stride != canon_down_span_slab_info[i].stride - || curr_down_span_slab_info->block != canon_down_span_slab_info[i].block - || curr_down_span_slab_info->count != canon_down_span_slab_info[i].count) + if(curr_down_span_slab_info->count > 0 && canon_down_span_slab_info[u].count > 0) { + if(curr_down_span_slab_info->start != canon_down_span_slab_info[u].start + || curr_down_span_slab_info->stride != canon_down_span_slab_info[u].stride + || curr_down_span_slab_info->block != canon_down_span_slab_info[u].block + || curr_down_span_slab_info->count != canon_down_span_slab_info[u].count) HGOTO_DONE(FALSE) } /* end if */ - else if (!((curr_down_span_slab_info->count == 0) && (canon_down_span_slab_info[i].count == 0))) + else if (!((curr_down_span_slab_info->count == 0) && (canon_down_span_slab_info[u].count == 0))) HGOTO_DONE(FALSE) } } /* end if */ diff --git a/src/H5Spublic.h b/src/H5Spublic.h index 9efaeab..5e2177f 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -132,6 +132,7 @@ H5_DLL herr_t H5Sselect_elements(hid_t space_id, H5S_seloper_t op, H5_DLL H5S_class_t H5Sget_simple_extent_type(hid_t space_id); H5_DLL herr_t H5Sset_extent_none(hid_t space_id); H5_DLL herr_t H5Sextent_copy(hid_t dst_id,hid_t src_id); +H5_DLL herr_t H5Sextent_equal(hid_t sid1, hid_t sid2); H5_DLL herr_t H5Sselect_all(hid_t spaceid); H5_DLL herr_t H5Sselect_none(hid_t spaceid); H5_DLL herr_t H5Soffset_simple(hid_t space_id, const hssize_t *offset); diff --git a/src/H5T.c b/src/H5T.c index 59ae47d..f0800bb 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -3459,8 +3459,7 @@ H5T_copy(const H5T_t *old_dt, H5T_copy_t method) HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, NULL, "unable to copy entry"); } /* end if */ else { - HDmemset (&(new_dt->ent), 0, sizeof(new_dt->ent)); - new_dt->ent.header = HADDR_UNDEF; + H5G_ent_reset(&(new_dt->ent)); } /* end else */ /* Set return value */ diff --git a/src/Makefile.am b/src/Makefile.am index 15a09ed..b4307a0 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,7 +37,8 @@ libhdf5_la_LDFLAGS= -version-info $(LT_VERS_INTERFACE):$(LT_VERS_REVISION):$(LT_ MOSTLYCLEANFILES=H5Tinit.c # library sources -libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c \ +libhdf5_la_SOURCES= H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \ + H5B2dbg.c \ H5B2test.c H5BP.c H5BPcache.c H5BPdbg.c H5BPtest.c \ H5BT.c H5BTbtree2.c H5BTcache.c H5BTdbg.c H5BTtest.c H5C.c \ H5D.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 3d09c5a..516859b 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -82,10 +82,10 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(settingsdir)" \ libLTLIBRARIES_INSTALL = $(INSTALL) LTLIBRARIES = $(lib_LTLIBRARIES) libhdf5_la_LIBADD = -am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5B2.lo \ - H5B2cache.lo H5B2dbg.lo H5B2test.lo H5BP.lo H5BPcache.lo \ - H5BPdbg.lo H5BPtest.lo H5BT.lo H5BTbtree2.lo H5BTcache.lo \ - H5BTdbg.lo H5BTtest.lo H5C.lo H5D.lo H5Dcontig.lo \ +am_libhdf5_la_OBJECTS = H5.lo H5A.lo H5AC.lo H5B.lo H5Bcache.lo \ + H5B2.lo H5B2cache.lo H5B2dbg.lo H5B2test.lo H5BP.lo \ + H5BPcache.lo H5BPdbg.lo H5BPtest.lo H5BT.lo H5BTbtree2.lo \ + H5BTcache.lo H5BTdbg.lo H5BTtest.lo H5C.lo H5D.lo H5Dcontig.lo \ H5Dcompact.lo H5Defl.lo H5Dio.lo H5Distore.lo H5Dmpio.lo \ H5Dselect.lo H5Dtest.lo H5E.lo H5F.lo H5Fdbg.lo H5Fmount.lo \ H5Fsfile.lo H5Fsuper.lo H5FD.lo H5FDcore.lo H5FDfamily.lo \ @@ -384,7 +384,8 @@ libhdf5_la_LDFLAGS = -version-info $(LT_VERS_INTERFACE):$(LT_VERS_REVISION):$(LT MOSTLYCLEANFILES = H5Tinit.c # library sources -libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5B2.c H5B2cache.c H5B2dbg.c \ +libhdf5_la_SOURCES = H5.c H5A.c H5AC.c H5B.c H5Bcache.c H5B2.c H5B2cache.c \ + H5B2dbg.c \ H5B2test.c H5BP.c H5BPcache.c H5BPdbg.c H5BPtest.c \ H5BT.c H5BTbtree2.c H5BTcache.c H5BTdbg.c H5BTtest.c H5C.c \ H5D.c \ @@ -563,6 +564,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5BTcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5BTdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5BTtest.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Bcache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5C.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5D.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Dcompact.Plo@am__quote@ diff --git a/test/Makefile.am b/test/Makefile.am index 89ce616..a1df34a 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -34,7 +34,7 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) # This gives them more time to run when tests are executing in parallel. TEST_PROG=testhdf5 lheap ohdr stab gheap btree2 cache b+tree blocktrack sheap \ pool hyperslab istore bittests dt_arith \ - dtypes dsets cmpd_dset extend external links unlink big mtime \ + dtypes dsets cmpd_dset extend external objcopy links unlink big mtime \ fillval mount flush1 flush2 enum \ set_extent ttsafe stream_test \ getname vfd ntypes dangle dtransform reserved @@ -107,7 +107,8 @@ CHECK_CLEANFILES+=cmpd_dset.h5 compact_dataset.h5 dataset.h5 extend.h5 istore.h5 family_file000[0-3][0-9].h5 multi_file-[rs].h5 core_file \ new_move_[ab].h5 ntypes.h5 dangle.h5 error_test.h5 err_compat.h5 \ dtransform.h5 test_filters.h5 get_file_name.h5 tstint[1-2].h5 \ - unlink_chunked.h5 btree2.h5 blocktrack.h5 sheap.h5 b+tree.h5 + unlink_chunked.h5 btree2.h5 blocktrack.h5 sheap.h5 b+tree.h5 \ + objcopy_src.h5 objcopy_dst.h5 objcopy_ext.dat # Sources for testhdf5 executable testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tconfig.c tfile.c tgenprop.c \ diff --git a/test/Makefile.in b/test/Makefile.in index 510e69f..6aba9ea 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -31,7 +31,7 @@ # -SOURCES = $(libh5test_la_SOURCES) b+tree.c big.c bittests.c blocktrack.c btree2.c cache.c cmpd_dset.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c enum.c err_compat.c error_test.c extend.c external.c fillval.c flush1.c flush2.c gen_deflate.c gen_filters.c gen_new_array.c gen_new_fill.c gen_new_mtime.c gen_new_super.c gen_noencoder.c gen_nullspace.c getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c ntypes.c ohdr.c pool.c reserved.c set_extent.c sheap.c space_overflow.c stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c +SOURCES = $(libh5test_la_SOURCES) b+tree.c big.c bittests.c blocktrack.c btree2.c cache.c cmpd_dset.c dangle.c dsets.c dt_arith.c dtransform.c dtypes.c enum.c err_compat.c error_test.c extend.c external.c fillval.c flush1.c flush2.c gen_deflate.c gen_filters.c gen_new_array.c gen_new_fill.c gen_new_mtime.c gen_new_super.c gen_noencoder.c gen_nullspace.c getname.c gheap.c hyperslab.c istore.c lheap.c links.c mount.c mtime.c ntypes.c objcopy.c ohdr.c pool.c reserved.c set_extent.c sheap.c space_overflow.c stab.c stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c vfd.c srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -79,11 +79,11 @@ am__EXEEXT_1 = testhdf5$(EXEEXT) lheap$(EXEEXT) ohdr$(EXEEXT) \ pool$(EXEEXT) hyperslab$(EXEEXT) istore$(EXEEXT) \ bittests$(EXEEXT) dt_arith$(EXEEXT) dtypes$(EXEEXT) \ dsets$(EXEEXT) cmpd_dset$(EXEEXT) extend$(EXEEXT) \ - external$(EXEEXT) links$(EXEEXT) unlink$(EXEEXT) big$(EXEEXT) \ - mtime$(EXEEXT) fillval$(EXEEXT) mount$(EXEEXT) flush1$(EXEEXT) \ - flush2$(EXEEXT) enum$(EXEEXT) set_extent$(EXEEXT) \ - ttsafe$(EXEEXT) stream_test$(EXEEXT) getname$(EXEEXT) \ - vfd$(EXEEXT) ntypes$(EXEEXT) dangle$(EXEEXT) \ + external$(EXEEXT) objcopy$(EXEEXT) links$(EXEEXT) \ + unlink$(EXEEXT) big$(EXEEXT) mtime$(EXEEXT) fillval$(EXEEXT) \ + mount$(EXEEXT) flush1$(EXEEXT) flush2$(EXEEXT) enum$(EXEEXT) \ + set_extent$(EXEEXT) ttsafe$(EXEEXT) stream_test$(EXEEXT) \ + getname$(EXEEXT) vfd$(EXEEXT) ntypes$(EXEEXT) dangle$(EXEEXT) \ dtransform$(EXEEXT) reserved$(EXEEXT) @BUILD_ALL_CONDITIONAL_TRUE@am__EXEEXT_2 = gen_deflate$(EXEEXT) \ @BUILD_ALL_CONDITIONAL_TRUE@ gen_filters$(EXEEXT) \ @@ -244,6 +244,10 @@ ntypes_SOURCES = ntypes.c ntypes_OBJECTS = ntypes.$(OBJEXT) ntypes_LDADD = $(LDADD) ntypes_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1) +objcopy_SOURCES = objcopy.c +objcopy_OBJECTS = objcopy.$(OBJEXT) +objcopy_LDADD = $(LDADD) +objcopy_DEPENDENCIES = libh5test.la $(am__DEPENDENCIES_1) ohdr_SOURCES = ohdr.c ohdr_OBJECTS = ohdr.$(OBJEXT) ohdr_LDADD = $(LDADD) @@ -323,10 +327,10 @@ SOURCES = $(libh5test_la_SOURCES) b+tree.c big.c bittests.c \ gen_deflate.c gen_filters.c gen_new_array.c gen_new_fill.c \ gen_new_mtime.c gen_new_super.c gen_noencoder.c \ gen_nullspace.c getname.c gheap.c hyperslab.c istore.c lheap.c \ - links.c mount.c mtime.c ntypes.c ohdr.c pool.c reserved.c \ - set_extent.c sheap.c space_overflow.c stab.c stream_test.c \ - $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ - vfd.c + links.c mount.c mtime.c ntypes.c objcopy.c ohdr.c pool.c \ + reserved.c set_extent.c sheap.c space_overflow.c stab.c \ + stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) \ + unlink.c vfd.c DIST_SOURCES = $(libh5test_la_SOURCES) b+tree.c big.c bittests.c \ blocktrack.c btree2.c cache.c cmpd_dset.c dangle.c dsets.c \ dt_arith.c dtransform.c dtypes.c enum.c err_compat.c \ @@ -334,10 +338,10 @@ DIST_SOURCES = $(libh5test_la_SOURCES) b+tree.c big.c bittests.c \ gen_deflate.c gen_filters.c gen_new_array.c gen_new_fill.c \ gen_new_mtime.c gen_new_super.c gen_noencoder.c \ gen_nullspace.c getname.c gheap.c hyperslab.c istore.c lheap.c \ - links.c mount.c mtime.c ntypes.c ohdr.c pool.c reserved.c \ - set_extent.c sheap.c space_overflow.c stab.c stream_test.c \ - $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) unlink.c \ - vfd.c + links.c mount.c mtime.c ntypes.c objcopy.c ohdr.c pool.c \ + reserved.c set_extent.c sheap.c space_overflow.c stab.c \ + stream_test.c $(testhdf5_SOURCES) testmeta.c $(ttsafe_SOURCES) \ + unlink.c vfd.c ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -609,7 +613,7 @@ SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) # This gives them more time to run when tests are executing in parallel. TEST_PROG = testhdf5 lheap ohdr stab gheap btree2 cache b+tree blocktrack sheap \ pool hyperslab istore bittests dt_arith \ - dtypes dsets cmpd_dset extend external links unlink big mtime \ + dtypes dsets cmpd_dset extend external objcopy links unlink big mtime \ fillval mount flush1 flush2 enum \ set_extent ttsafe stream_test \ getname vfd ntypes dangle dtransform reserved @@ -831,6 +835,9 @@ mtime$(EXEEXT): $(mtime_OBJECTS) $(mtime_DEPENDENCIES) ntypes$(EXEEXT): $(ntypes_OBJECTS) $(ntypes_DEPENDENCIES) @rm -f ntypes$(EXEEXT) $(LINK) $(ntypes_LDFLAGS) $(ntypes_OBJECTS) $(ntypes_LDADD) $(LIBS) +objcopy$(EXEEXT): $(objcopy_OBJECTS) $(objcopy_DEPENDENCIES) + @rm -f objcopy$(EXEEXT) + $(LINK) $(objcopy_LDFLAGS) $(objcopy_OBJECTS) $(objcopy_LDADD) $(LIBS) ohdr$(EXEEXT): $(ohdr_OBJECTS) $(ohdr_DEPENDENCIES) @rm -f ohdr$(EXEEXT) $(LINK) $(ohdr_LDFLAGS) $(ohdr_OBJECTS) $(ohdr_LDADD) $(LIBS) @@ -915,6 +922,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mount.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mtime.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ntypes.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/objcopy.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ohdr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reserved.Po@am__quote@ diff --git a/test/objcopy.c b/test/objcopy.c new file mode 100755 index 0000000..43d5373 --- /dev/null +++ b/test/objcopy.c @@ -0,0 +1,3350 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Peter X. Cao + * May 01, 2005 + * + * Purpose: Test H5Gcopy(). + */ + +#include +#include "h5test.h" + +const char *FILENAME[] = { + "objcopy_src", + "objcopy_dst", + NULL +}; + +#define FILE_EXT "objcopy_ext.dat" + +#define NAME_DATATYPE_SIMPLE "H5T_NATIVE_INT" +#define NAME_DATASET_SIMPLE "dataset_simple" +#define NAME_DATASET_COMPOUND "dataset_compound" +#define NAME_DATASET_CHUNKED "dataset_chunked" +#define NAME_DATASET_COMPACT "dataset_compact" +#define NAME_DATASET_EXTERNAL "dataset_ext" +#define NAME_DATASET_NAMED_DTYPE "dataset_named_dtype" +#define NAME_DATASET_NAMED_DTYPE2 "dataset_named_dtype2" +#define NAME_DATASET_MULTI_OHDR "dataset_multi_ohdr" +#define NAME_DATASET_MULTI_OHDR2 "dataset_multi_ohdr2" +#define NAME_DATASET_VL "dataset_vl" +#define NAME_GROUP_EMPTY "/empty" +#define NAME_GROUP_TOP "/g0" +#define NAME_GROUP_SUB "/g0/g00" +#define NAME_GROUP_SUB_2 "/g0/g01" +#define NAME_GROUP_SUB_SUB "/g0/g00/g000" +#define NAME_GROUP_DATASET "/g0/dataset_simple" +#define NAME_GROUP_LINK "/g_links" +#define NAME_GROUP_LOOP "g_loop" +#define NAME_LINK_DATASET "/g_links/dataset_simple" +#define NAME_LINK_HARD "/g_links/hard_link_to_dataset_simple" +#define NAME_LINK_SOFT "/g_links/soft_link_to_nowhere" + +#define NAME_BUF_SIZE 1024 +#define NUM_ATTRIBUTES 8 +#define ATTR_NAME_LEN 40 +#define DIM_SIZE_1 12 +#define DIM_SIZE_2 6 +#define NUM_SUB_GROUPS 20 +#define NUM_DATASETS 10 + +/* Table containing object id and object name */ +/* (Used for detecting duplicate objects when comparing groups */ +static struct { + size_t nalloc; /* number of slots allocated */ + size_t nobjs; /* number of objects */ + haddr_t *obj; /* Addresses of objects seen */ +} idtab_g; + + +/*------------------------------------------------------------------------- + * Function: addr_insert + * + * Purpose: Add an address to the table. + * + * Return: void + * + * Programmer: Quincey Koziol + * Saturday, November 5, 2005 + * + *------------------------------------------------------------------------- + */ +static void +addr_insert(H5G_stat_t *sb) +{ + size_t n; + + /* Don't add it if the link count is 1 because such an object can only + * be encountered once. */ + if(sb->u.obj.nlink < 2) + return; + + /* Extend the table */ + if(idtab_g.nobjs >= idtab_g.nalloc) { + idtab_g.nalloc = MAX(256, 2*idtab_g.nalloc); + idtab_g.obj = HDrealloc(idtab_g.obj, idtab_g.nalloc * sizeof(idtab_g.obj[0])); + } /* end if */ + + /* Insert the entry */ + n = idtab_g.nobjs++; + idtab_g.obj[n] = sb->u.obj.objno; +} /* end addr_insert() */ + + +/*------------------------------------------------------------------------- + * Function: addr_lookup + * + * Purpose: Check if address has already been encountered + * + * Return: Success: TRUE/FALSE + * + * Failure: (can't fail) + * + * Programmer: Quincey Koziol + * Saturday, November 5, 2005 + * + *------------------------------------------------------------------------- + */ +static hbool_t +addr_lookup(H5G_stat_t *sb) +{ + size_t n; + + if (sb->u.obj.nlink<2) return NULL; /*only one link possible*/ + + for(n = 0; n < idtab_g.nobjs; n++) + if(idtab_g.obj[n] == sb->u.obj.objno) + return TRUE; + return FALSE; +} /* end addr_lookup() */ + + +/*------------------------------------------------------------------------- + * Function: addr_reset + * + * Purpose: Reset the address tracking data structures + * + * Return: void + * + * Programmer: Quincey Koziol + * Saturday, November 5, 2005 + * + *------------------------------------------------------------------------- + */ +static void +addr_reset(void) +{ + if(idtab_g.obj) + HDfree(idtab_g.obj); + idtab_g.obj = NULL; + idtab_g.nalloc = idtab_g.nobjs = 0; +} /* end addr_reset() */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_attach_attributes + * + * Purpose: Attach NUM_ATTRIBUTES attributes to the object to be copied + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Peter Cao + * Friday, September 30, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_copy_attach_attributes(hid_t loc_id, hid_t type_id) +{ + hid_t aid = -1, sid = -1; + char attr_name[ATTR_NAME_LEN]; + int attr_data[2], i=0; + hsize_t dim1=2; + int ret_value = -1; + + if ( (sid = H5Screate_simple(1, &dim1, NULL)) < 0 ) + goto done; + + for (i=0; i 0) + H5Aclose(aid); + + aid = -1; + } + + ret_value = 0; + +done: + if (sid > 0) + H5Sclose(sid); + if (aid > 0) + H5Aclose(aid); + + return ret_value; +} + + +/*------------------------------------------------------------------------- + * Function: test_copy_attach_paired_attributes + * + * Purpose: Attach NUM_ATTRIBUTES attributes to a pair of objects to be copied + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, November 1, 2005 + * + *------------------------------------------------------------------------- + */ +static int +test_copy_attach_paired_attributes(hid_t loc_id, hid_t loc_id2, hid_t type_id) +{ + hid_t aid = -1, sid = -1; + char attr_name[ATTR_NAME_LEN]; + int attr_data[2], i; + hsize_t dim1 = 2; + + if ( (sid = H5Screate_simple(1, &dim1, NULL)) < 0 ) goto done; + + for (i=0; i 0) + H5Sclose(sid); + if (aid > 0) + H5Aclose(aid); + + return -1; +} /* end test_copy_attach_paired_attributes() */ + + +/*------------------------------------------------------------------------- + * Function: compare_attributes + * + * Purpose: Compare attributes on two objects to check that they are equal + * + * Return: TRUE if objects have same attributes/FALSE if they are different + * + * Programmer: Quincey Koziol + * Monday, October 31, 2005 + * + * Note: This isn't very general, the attributes are assumed to be + * those written in test_copy_attach_attributes(). + * + *------------------------------------------------------------------------- + */ +static int +compare_attributes(hid_t oid, hid_t oid2) +{ + hid_t sid = -1, sid2 = -1; /* Dataspace IDs */ + hid_t tid = -1, tid2 = -1; /* Datatype IDs */ + hid_t aid = -1, aid2 = -1; /* Attribute IDs */ + int num_attrs; /* Number of attributes */ + int num_attrs2; /* Number of attributes */ + char attr_name[ATTR_NAME_LEN]; /* Attribute name */ + int wattr_data[2]; /* Attribute buffer for writing */ + int attr_data[2], attr_data2[2]; /* Attribute buffers for reading */ + htri_t is_committed; /* If the datatype is committed */ + htri_t is_committed2; /* If the datatype is committed */ + unsigned i; /* Local index variable */ + + /* Check the number of attributes on source dataset */ + if ( (num_attrs = H5Aget_num_attrs(oid)) < 0) TEST_ERROR; + + /* Check the number of attributes on destination dataset */ + if ( (num_attrs2 = H5Aget_num_attrs(oid2)) < 0) TEST_ERROR; + + /* Compare the number of attributes */ + if ( num_attrs != num_attrs2) TEST_ERROR; + + /* Check the attributes are equal */ + for(i = 0; i < (unsigned)num_attrs; i++) { + sprintf(attr_name, "%d attr", i); + + /* Set up attribute data buffers */ + wattr_data[0] = 100 * i; + wattr_data[1] = 200 * i; + + /* Open the attributes */ + if ( (aid = H5Aopen_name(oid, attr_name)) < 0) TEST_ERROR + if ( (aid2 = H5Aopen_name(oid2, attr_name)) < 0) TEST_ERROR + + /* Check the datatypes are equal */ + + /* Open the datatype for the source attribute */ + if ( (tid = H5Aget_type(aid)) < 0) TEST_ERROR; + + /* Open the datatype for the destination attribute */ + if ( (tid2 = H5Aget_type(aid2)) < 0) TEST_ERROR; + + /* Check that both datatypes are committed/not committed */ + if ( (is_committed = H5Tcommitted(tid)) < 0) TEST_ERROR; + if ( (is_committed2 = H5Tcommitted(tid2)) < 0) TEST_ERROR; + if ( is_committed != is_committed2) TEST_ERROR; + + /* Compare the datatypes */ + if ( H5Tequal(tid, tid2) != TRUE) TEST_ERROR; + + /* close the source datatype */ + if ( H5Tclose(tid) < 0) TEST_ERROR; + + /* close the destination datatype */ + if ( H5Tclose(tid2) < 0) TEST_ERROR; + + + /* Check the dataspaces are equal */ + + /* Open the dataspace for the source attribute */ + if ( (sid = H5Aget_space(aid)) < 0) TEST_ERROR; + + /* Open the dataspace for the destination attribute */ + if ( (sid2 = H5Aget_space(aid2)) < 0) TEST_ERROR; + + /* Compare the dataspaces */ + if ( H5Sextent_equal(sid, sid2) != TRUE) TEST_ERROR; + + /* close the source dataspace */ + if ( H5Sclose(sid) < 0) TEST_ERROR; + + /* close the destination dataspace */ + if ( H5Sclose(sid2) < 0) TEST_ERROR; + + + /* Check the attribute data is equal */ + + /* Read the attribute data */ + if ( (H5Aread(aid, H5T_NATIVE_INT, attr_data)) < 0) TEST_ERROR + if ( (H5Aread(aid2, H5T_NATIVE_INT, attr_data2)) < 0) TEST_ERROR + + /* Check attribute data read in against data written out */ + if(wattr_data[0] != attr_data[0] || wattr_data[0] != attr_data2[0]) TEST_ERROR + if(wattr_data[1] != attr_data[1] || wattr_data[1] != attr_data2[1]) TEST_ERROR + + /* Close the attributes */ + if ( H5Aclose(aid) < 0) TEST_ERROR + if ( H5Aclose(aid2) < 0) TEST_ERROR + } /* end for */ + + /* Objects should be the same. :-) */ + return TRUE; + +error: + H5E_BEGIN_TRY { + H5Aclose(aid2); + H5Aclose(aid); + H5Sclose(sid2); + H5Sclose(sid); + H5Tclose(tid2); + H5Tclose(tid); + } H5E_END_TRY; + return FALSE; +} /* end compare_attributes() */ + + +/*------------------------------------------------------------------------- + * Function: compare_datasets + * + * Purpose: Compare two datasets to check that they are equal + * + * Return: TRUE if datasets are equal/FALSE if they are different + * + * Programmer: Quincey Koziol + * Tuesday, October 25, 2005 + * + *------------------------------------------------------------------------- + */ +static int +compare_datasets(hid_t did, hid_t did2, void *wbuf) +{ + hid_t sid = -1, sid2 = -1; /* Dataspace IDs */ + hid_t tid = -1, tid2 = -1; /* Datatype IDs */ + hid_t tmp_tid = -1; /* Temporary datatype ID for reading data */ + hid_t dcpl = -1, dcpl2 = -1; /* Dataset creation property list IDs */ + size_t elem_size; /* Size of datatype */ + htri_t is_committed; /* If the datatype is committed */ + htri_t is_committed2; /* If the datatype is committed */ + hssize_t nelem; /* # of elements in dataspace */ + void *rbuf = NULL; /* Buffer for reading raw data */ + void *rbuf2 = NULL; /* Buffer for reading raw data */ + H5D_space_status_t space_status; /* Dataset's raw data space status */ + H5D_space_status_t space_status2; /* Dataset's raw data space status */ + hsize_t storage_size; /* Dataset's raw data storage size */ + hsize_t storage_size2; /* Dataset's raw data storage size */ + + /* Check the datatypes are equal */ + + /* Open the datatype for the source dataset */ + if ( (tid = H5Dget_type(did)) < 0) TEST_ERROR; + + /* Open the datatype for the destination dataset */ + if ( (tid2 = H5Dget_type(did2)) < 0) TEST_ERROR; + + /* Check that both datatypes are committed/not committed */ + if ( (is_committed = H5Tcommitted(tid)) < 0) TEST_ERROR; + if ( (is_committed2 = H5Tcommitted(tid2)) < 0) TEST_ERROR; + if ( is_committed != is_committed2) TEST_ERROR; + + /* Compare the datatypes */ + if ( H5Tequal(tid, tid2) != TRUE) TEST_ERROR; + + /* Determine the size of datatype (for later) */ + if ( (elem_size = H5Tget_size(tid)) == 0) TEST_ERROR; + + /* Make copy of the datatype (for later) */ + if ( (tmp_tid = H5Tcopy(tid)) < 0) TEST_ERROR; + + /* close the source datatype */ + if ( H5Tclose(tid) < 0) TEST_ERROR; + + /* close the destination datatype */ + if ( H5Tclose(tid2) < 0) TEST_ERROR; + + + /* Check the dataspaces are equal */ + + /* Open the dataspace for the source dataset */ + if ( (sid = H5Dget_space(did)) < 0) TEST_ERROR; + + /* Open the dataspace for the destination dataset */ + if ( (sid2 = H5Dget_space(did2)) < 0) TEST_ERROR; + + /* Compare the dataspaces */ + if ( H5Sextent_equal(sid, sid2) != TRUE) TEST_ERROR; + + /* Determine the number of elements in dataspace (for later) */ + if ( (nelem = H5Sget_simple_extent_npoints(sid)) < 0) TEST_ERROR + + /* close the source dataspace */ + if ( H5Sclose(sid) < 0) TEST_ERROR; + + /* close the destination dataspace */ + if ( H5Sclose(sid2) < 0) TEST_ERROR; + + + /* Check the dataset creation property lists are equal */ + + /* Open the dataset creation property list for the source dataset */ + if ( (dcpl = H5Dget_create_plist(did)) < 0) TEST_ERROR; + + /* Open the dataset creation property list for the destination dataset */ + if ( (dcpl2 = H5Dget_create_plist(did2)) < 0) TEST_ERROR; + + /* Compare the dataset creation property lists */ + if ( H5Pequal(dcpl, dcpl2) != TRUE) TEST_ERROR; + + /* close the source dataset creation property list */ + if ( H5Pclose(dcpl) < 0) TEST_ERROR; + + /* close the destination dataset creation property list */ + if ( H5Pclose(dcpl2) < 0) TEST_ERROR; + + + /* Check the allocated storage is the same */ + + /* Check that the space allocation status is the same */ + if(H5Dget_space_status(did, &space_status) < 0) TEST_ERROR; + if(H5Dget_space_status(did2, &space_status2) < 0) TEST_ERROR; + if(space_status != space_status2) TEST_ERROR; + + /* Check that the space used is the same */ + storage_size = H5Dget_storage_size(did); + storage_size2 = H5Dget_storage_size(did2); + if(storage_size != storage_size2) TEST_ERROR; + + + /* Check the raw data is equal */ + + /* Allocate & initialize space for the raw data buffers */ + if ( (rbuf = HDcalloc( elem_size, (size_t)nelem)) == NULL) TEST_ERROR; + if ( (rbuf2 = HDcalloc( elem_size, (size_t)nelem)) == NULL) TEST_ERROR; + + /* Read data from datasets */ + if ( H5Dread(did, tmp_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf) < 0) TEST_ERROR; + if ( H5Dread(did2, tmp_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, rbuf2) < 0) TEST_ERROR; + + /* Check raw data read in against data written out */ + if(wbuf) { + if ( HDmemcmp(wbuf, rbuf, (size_t)(elem_size * nelem))) TEST_ERROR + if ( HDmemcmp(wbuf, rbuf2, (size_t)(elem_size * nelem))) TEST_ERROR + } /* end if */ + /* Don't have written data, just compare data between the two datasets */ + else + if ( HDmemcmp(rbuf, rbuf2, (size_t)(elem_size * nelem))) TEST_ERROR + + /* Release raw data buffers */ + HDfree(rbuf); + HDfree(rbuf2); + + /* Release temporary datatype */ + if ( H5Tclose(tmp_tid) < 0) TEST_ERROR; + + + /* Check if the attributes are equal */ + if ( compare_attributes(did, did2) != TRUE) TEST_ERROR; + + + /* Datasets should be the same. :-) */ + return TRUE; + +error: + H5E_BEGIN_TRY { + if(rbuf) + HDfree(rbuf); + if(rbuf2) + HDfree(rbuf2); + H5Pclose(dcpl2); + H5Pclose(dcpl); + H5Sclose(sid2); + H5Sclose(sid); + H5Tclose(tmp_tid); + H5Tclose(tid2); + H5Tclose(tid); + } H5E_END_TRY; + return FALSE; +} /* end compare_datasets() */ + + +/*------------------------------------------------------------------------- + * Function: compare_groups + * + * Purpose: Compare two groups to check that they are "equal" + * + * Return: TRUE if group are equal/FALSE if they are different + * + * Programmer: Quincey Koziol + * Monday, October 31, 2005 + * + *------------------------------------------------------------------------- + */ +static int +compare_groups(hid_t gid, hid_t gid2) +{ + hsize_t num_objs; /* Number of objects in group */ + hsize_t num_objs2; /* Number of objects in group */ + hsize_t idx; /* Index over the objects in group */ + + /* Check if both groups have the same # of objects */ + if(H5Gget_num_objs(gid, &num_objs) < 0) TEST_ERROR; + if(H5Gget_num_objs(gid2, &num_objs2) < 0) TEST_ERROR; + if(num_objs != num_objs2) TEST_ERROR; + + /* Check contents of groups */ + if(num_objs > 0) { + char objname[NAME_BUF_SIZE]; /* Name of object in group */ + char objname2[NAME_BUF_SIZE]; /* Name of object in group */ + H5G_obj_t objtype; /* Type of object in group */ + H5G_obj_t objtype2; /* Type of object in group */ + H5G_stat_t objstat; /* Object info */ + H5G_stat_t objstat2; /* Object info */ + hid_t oid, oid2; /* IDs of objects within group */ + + /* Loop over contents of groups */ + for(idx = 0; idx < num_objs; idx++) { + /* Check name of objects */ + if(H5Gget_objname_by_idx(gid, idx, objname, NAME_BUF_SIZE) < 0) TEST_ERROR; + if(H5Gget_objname_by_idx(gid2, idx, objname2, NAME_BUF_SIZE) < 0) TEST_ERROR; + if(HDstrcmp(objname, objname2)) TEST_ERROR; + + /* Check type of objects */ + if((objtype = H5Gget_objtype_by_idx(gid, idx)) < 0) TEST_ERROR; + if((objtype2 = H5Gget_objtype_by_idx(gid2, idx)) < 0) TEST_ERROR; + if(objtype != objtype2) TEST_ERROR; + + /* Compare some pieces of the H5G_stat_t */ + if(H5Gget_objinfo(gid, objname, FALSE, &objstat) < 0) TEST_ERROR; + if(H5Gget_objinfo(gid2, objname2, FALSE, &objstat2) < 0) TEST_ERROR; + if(objstat.type != objstat2.type) TEST_ERROR; + if(objstat.type != H5G_LINK) { + if(objstat.u.obj.nlink != objstat2.u.obj.nlink) TEST_ERROR; + if(objstat.u.obj.ohdr.nmesgs != objstat2.u.obj.ohdr.nmesgs) TEST_ERROR; + if(objstat.u.obj.ohdr.nchunks != objstat2.u.obj.ohdr.nchunks) TEST_ERROR; + } /* end if */ + + /* Check for object already having been compared */ + if(addr_lookup(&objstat)) + continue; + else + addr_insert(&objstat); + + /* Compare objects within group */ + switch(objtype) { + case H5G_LINK: + { + char linkname[NAME_BUF_SIZE]; /* Link value */ + char linkname2[NAME_BUF_SIZE]; /* Link value */ + + /* Check link values */ + if(H5Gget_linkval(gid, objname, NAME_BUF_SIZE, linkname) < 0) TEST_ERROR; + if(H5Gget_linkval(gid2, objname2, NAME_BUF_SIZE, linkname2) < 0) TEST_ERROR; + if(HDstrcmp(linkname, linkname2)) TEST_ERROR; + } + break; + + case H5G_GROUP: + /* Open groups */ + if((oid = H5Gopen(gid, objname)) < 0) TEST_ERROR; + if((oid2 = H5Gopen(gid2, objname2)) < 0) TEST_ERROR; + + /* Compare groups */ + if(compare_groups(oid, oid2) != TRUE) TEST_ERROR; + + /* Close groups */ + if(H5Gclose(oid) < 0) TEST_ERROR; + if(H5Gclose(oid2) < 0) TEST_ERROR; + break; + + case H5G_DATASET: + /* Open datasets */ + if((oid = H5Dopen(gid, objname)) < 0) TEST_ERROR; + if((oid2 = H5Dopen(gid2, objname2)) < 0) TEST_ERROR; + + /* Compare datasets */ + if(compare_datasets(oid, oid2, NULL) != TRUE) TEST_ERROR; + + /* Close datasets */ + if(H5Dclose(oid) < 0) TEST_ERROR; + if(H5Dclose(oid2) < 0) TEST_ERROR; + break; + + case H5G_TYPE: + /* Open datatypes */ + if((oid = H5Topen(gid, objname)) < 0) TEST_ERROR; + if((oid2 = H5Topen(gid2, objname2)) < 0) TEST_ERROR; + + /* Compare datatypes */ + if(H5Tequal(oid, oid2) != TRUE) TEST_ERROR; + + /* Close datatypes */ + if(H5Tclose(oid) < 0) TEST_ERROR; + if(H5Tclose(oid2) < 0) TEST_ERROR; + break; + + default: +HDassert(0 && "Unknown type of object"); + break; + } /* end switch */ + } /* end for */ + } /* end if */ + + /* Check if the attributes are equal */ + if ( compare_attributes(gid, gid2) != TRUE) TEST_ERROR; + + /* Groups should be the same. :-) */ + return TRUE; + +error: + H5E_BEGIN_TRY { + } H5E_END_TRY; + return FALSE; +} /* end compare_groups() */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_named_datatype + * + * Purpose: Create name datatype in SRC file and copy it to DST file + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Peter Cao + * Friday, September 30, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_copy_named_datatype(hid_t fapl) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t tid = -1, tid2 = -1; /* Datatype IDs */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + TESTING("H5Gcopy(): named datatype"); + + /* Initialize the filenames */ + h5_fixname(FILENAME[0], fapl, src_filename, sizeof src_filename); + h5_fixname(FILENAME[1], fapl, dst_filename, sizeof dst_filename); + + /* Reset file address checking info */ + addr_reset(); + + /* create source file */ + if ( (fid_src = H5Fcreate(src_filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR; + + /* create datatype */ + if ( (tid = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR; + + /* create named datatype */ + if ( (H5Tcommit(fid_src, NAME_DATATYPE_SIMPLE, tid)) < 0) TEST_ERROR; + + /* close the datatype */ + if ( H5Tclose(tid) < 0) TEST_ERROR; + + /* close the SRC file */ + if ( H5Fclose(fid_src) < 0) TEST_ERROR; + + + /* open the source file with read-only */ + if ( (fid_src = H5Fopen(src_filename, H5F_ACC_RDONLY, fapl)) < 0) TEST_ERROR; + + /* create destination file */ + if ( (fid_dst = H5Fcreate(dst_filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR; + + /* open the datatype for copy */ + if ( (tid = H5Topen(fid_src, NAME_DATATYPE_SIMPLE)) < 0) TEST_ERROR; + + /* copy the datatype from SRC to DST */ + if ( H5Gcopy(tid, fid_dst, NAME_DATATYPE_SIMPLE, H5P_DEFAULT) < 0) TEST_ERROR; + + /* open the copied datatype */ + if ( (tid2 = H5Topen(fid_dst, NAME_DATATYPE_SIMPLE)) < 0) TEST_ERROR; + + /* Compare the datatypes */ + if ( H5Tequal(tid, tid2) != TRUE) TEST_ERROR; + + /* close the destination datatype */ + if ( H5Tclose(tid2) < 0) TEST_ERROR; + + /* close the source datatype */ + if ( H5Tclose(tid) < 0) TEST_ERROR; + + /* close the SRC file */ + if ( H5Fclose(fid_src) < 0) TEST_ERROR; + + /* close the DST file */ + if ( H5Fclose(fid_dst) < 0) TEST_ERROR; + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Tclose(tid2); + H5Tclose(tid); + H5Fclose(fid_dst); + H5Fclose(fid_src); + } H5E_END_TRY; + return 1; +} /* end test_copy_named_datatype */ + + +/*------------------------------------------------------------------------- + * Function: test_copy_dataset_simple + * + * Purpose: Create a simple dataset in SRC file and copy it to DST file + * + * Return: Success: 0 + * Failure: number of errors + * + * Programmer: Peter Cao + * Friday, September 30, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_copy_dataset_simple(hid_t fapl) +{ + hid_t fid_src = -1, fid_dst = -1; /* File IDs */ + hid_t sid = -1; /* Dataspace ID */ + hid_t did = -1, did2 = -1; /* Dataset IDs */ + int buf[DIM_SIZE_1][DIM_SIZE_2]; /* Buffer for writing data */ + hsize_t dim2d[2]; /* Dataset dimensions */ + int i, j; /* local index variables */ + char src_filename[NAME_BUF_SIZE]; + char dst_filename[NAME_BUF_SIZE]; + + TESTING("H5Gcopy(): simple dataset"); + + /* Initialize write buffer */ + for (i=0; i