From 780fefb82913150a4f95ca25e8d72758e764dbad Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Mon, 30 Oct 2006 15:03:46 -0500 Subject: [svn-r12830] Description: Finish internal work necessary to track creation order in v2 B-tree when group is in "dense" storage form. Tested on: Linux/32 2.6 (chicago) Linux/64 2.6 (chicago2) --- src/H5Gdense.c | 62 ++++++--- src/H5Gdeprec.c | 42 +++---- src/H5Gent.c | 38 ------ src/H5Gpkg.h | 48 +++++-- src/H5Gtest.c | 103 +++++++++++++++ test/links.c | 383 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 581 insertions(+), 95 deletions(-) diff --git a/src/H5Gdense.c b/src/H5Gdense.c index 76970fc..52aa5ce 100644 --- a/src/H5Gdense.c +++ b/src/H5Gdense.c @@ -121,6 +121,8 @@ typedef struct { H5G_bt2_ud_common_t common; /* Common info for B-tree user data (must be first) */ hbool_t adj_link; /* Whether to adjust link count on object */ hbool_t rem_from_fheap; /* Whether to remove the link from the fractal heap */ + hbool_t rem_from_corder_index; /* Whether to remove the link from the creation order index */ + haddr_t corder_bt2_addr; /* Address of v2 B-tree indexing creation order */ /* upward (for application) */ H5G_obj_t *obj_type; /* Type of object being removed */ @@ -135,6 +137,8 @@ typedef struct { H5F_t *f; /* Pointer to file that fractal heap is in */ hid_t dxpl_id; /* DXPL for operation */ hbool_t adj_link; /* Whether to adjust link count on object */ + hbool_t rem_from_corder_index; /* Whether to remove the link from the creation order index */ + haddr_t corder_bt2_addr; /* Address of v2 B-tree indexing creation order */ /* upward (for application) */ H5G_obj_t *obj_type; /* Type of object being removed */ @@ -216,12 +220,6 @@ typedef struct { /* Package Variables */ /*********************/ -/* The v2 B-tree class for indexing 'name' field on links */ -H5_DLLVAR const H5B2_class_t H5G_BT2_NAME[1]; - -/* The v2 B-tree class for indexing 'creation order' field on links */ -H5_DLLVAR const H5B2_class_t H5G_BT2_CORDER[1]; - /*****************************/ /* Library Private Variables */ @@ -403,6 +401,7 @@ HDfprintf(stderr, "%s: HDstrlen(lnk->name) = %Zu, link_size = %Zu\n", FUNC, HDst udata.common.fheap = fheap; udata.common.name = lnk->name; udata.common.name_hash = H5_checksum_lookup3(lnk->name, HDstrlen(lnk->name), 0); + udata.common.corder = lnk->corder; udata.common.found_op = NULL; udata.common.found_op_data = NULL; /* udata.id already set in H5HF_insert() call */ @@ -411,8 +410,13 @@ HDfprintf(stderr, "%s: HDstrlen(lnk->name) = %Zu, link_size = %Zu\n", FUNC, HDst if(H5B2_insert(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert record into v2 B-tree") - /* XXX: Check if we should create a creation order index v2 B-tree record */ - /* XXX: Insert the record into the creation order index v2 B-tree */ + /* Check if we should create a creation order index v2 B-tree record */ + if(linfo->index_corder) { + /* Insert the record into the creation order index v2 B-tree */ + HDassert(H5F_addr_defined(linfo->corder_bt2_addr)); + if(H5B2_insert(f, dxpl_id, H5G_BT2_CORDER, linfo->corder_bt2_addr, &udata) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, FAIL, "unable to insert record into v2 B-tree") + } /* end if */ done: /* Release resources */ @@ -619,7 +623,7 @@ H5G_dense_build_table(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") /* Sort link table in correct iteration order */ - /* (XXX: by name, currently) */ +/* (XXX: by name, currently) */ if(order == H5_ITER_INC) HDqsort(ltable->lnks, ltable->nlinks, sizeof(H5O_link_t), H5G_obj_cmp_name_inc); else if(order == H5_ITER_INC) @@ -785,8 +789,8 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, H5_iter_order_t order, hid_t gid, udata.op = op; udata.op_data = op_data; - /* Iterate over the records in the v2 B-tree */ - /* (XXX: by name, currently) */ + /* Iterate over the records in the v2 B-tree's "native" order */ + /* (by hash of name) */ if((ret_value = H5B2_iterate(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, H5G_dense_iterate_bt2_cb, &udata)) < 0) HERROR(H5E_SYM, H5E_BADITER, "link iteration failed"); @@ -797,7 +801,7 @@ H5G_dense_iterate(H5F_t *f, hid_t dxpl_id, H5_iter_order_t order, hid_t gid, /* Build the table of links for this group */ if(H5G_dense_build_table(f, dxpl_id, linfo, order, <able) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTNEXT, FAIL, "error iterating over links") + HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "error building iteration table of links") /* Iterate over link messages */ for(u = 0, ret_value = H5B_ITER_CONT; u < ltable.nlinks && !ret_value; u++) { @@ -966,7 +970,7 @@ H5G_dense_get_name_by_idx(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, udata.name_size = size; /* Retrieve the name according to the v2 B-tree's index order */ - /* (XXX: using name index currently) */ +/* (XXX: using name index currently) */ if(H5B2_index(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, idx, H5G_dense_get_name_by_idx_bt2_cb, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTLIST, FAIL, "can't locate object in v2 B-tree") @@ -1120,7 +1124,7 @@ H5G_dense_get_type_by_idx(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, udata.fheap = fheap; /* Retrieve the name according to the v2 B-tree's index order */ - /* (XXX: using name index currently) */ +/* (XXX: using name index currently) */ if(H5B2_index(f, dxpl_id, H5G_BT2_NAME, linfo->name_bt2_addr, idx, H5G_dense_get_type_by_idx_bt2_cb, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTLIST, FAIL, "can't locate object in v2 B-tree") @@ -1164,6 +1168,21 @@ H5G_dense_remove_fh_cb(const void *obj, size_t UNUSED obj_len, void *_udata) if(NULL == (lnk = H5O_decode(udata->f, udata->dxpl_id, obj, H5O_LINK_ID))) HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, H5B2_ITER_ERROR, "can't decode link") + /* Check for removing the link from the creation order index */ + if(udata->rem_from_corder_index) { + H5G_bt2_ud_common_t bt2_udata; /* Info for B-tree callbacks */ + + /* Set up the user data for the v2 B-tree 'record remove' callback */ + HDassert(lnk->corder_valid); + bt2_udata.corder = lnk->corder; + + /* Remove the record from the name index v2 B-tree */ + HDassert(H5F_addr_defined(udata->corder_bt2_addr)); + if(H5B2_remove(udata->f, udata->dxpl_id, H5G_BT2_CORDER, udata->corder_bt2_addr, + &bt2_udata, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, H5B2_ITER_ERROR, "unable to remove link from creation order index v2 B-tree") + } /* end if */ + /* Retrieve the link's object type & decr. the ref. count on hard links, if requested */ switch(lnk->type) { case H5L_TYPE_HARD: @@ -1233,6 +1252,8 @@ H5G_dense_remove_bt2_cb(const void *_record, void *_bt2_udata) fh_udata.f = bt2_udata->common.f; fh_udata.dxpl_id = bt2_udata->common.dxpl_id; fh_udata.adj_link = bt2_udata->adj_link; + fh_udata.rem_from_corder_index = bt2_udata->rem_from_corder_index; + fh_udata.corder_bt2_addr = bt2_udata->corder_bt2_addr; fh_udata.obj_type = bt2_udata->obj_type; /* Call fractal heap 'op' routine, to perform user callback */ @@ -1295,6 +1316,8 @@ H5G_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, udata.common.found_op_data = NULL; udata.adj_link = TRUE; udata.rem_from_fheap = TRUE; + udata.rem_from_corder_index = H5F_addr_defined(linfo->corder_bt2_addr); + udata.corder_bt2_addr = linfo->corder_bt2_addr; udata.obj_type = obj_type; /* Remove the record from the name index v2 B-tree */ @@ -1302,8 +1325,6 @@ H5G_dense_remove(H5F_t *f, hid_t dxpl_id, const H5O_linfo_t *linfo, &udata, H5G_dense_remove_bt2_cb, &udata) < 0) HGOTO_ERROR(H5E_SYM, H5E_CANTREMOVE, FAIL, "unable to remove link from name index v2 B-tree") -/* XXX: Remove the link from the creation order index v2 B-tree */ - done: /* Release resources */ if(fheap) @@ -1359,6 +1380,7 @@ H5G_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hbool_t adj_link) udata.common.found_op_data = NULL; udata.adj_link = TRUE; udata.rem_from_fheap = FALSE; + udata.rem_from_corder_index = FALSE; udata.obj_type = NULL; /* Delete the name index, adjusting the ref. count on links removed */ @@ -1376,7 +1398,13 @@ H5G_dense_delete(H5F_t *f, hid_t dxpl_id, H5O_linfo_t *linfo, hbool_t adj_link) } /* end else */ linfo->name_bt2_addr = HADDR_UNDEF; -/* XXX: Check if we should delete the creation order index v2 B-tree */ + /* Check if we should delete the creation order index v2 B-tree */ + if(linfo->index_corder) { + /* Delete the creation order index, without adjusting the ref. count on the links */ + HDassert(H5F_addr_defined(linfo->corder_bt2_addr)); + if(H5B2_delete(f, dxpl_id, H5G_BT2_CORDER, linfo->corder_bt2_addr, NULL, NULL) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete v2 B-tree for creation order index") + } /* end if */ /* Delete the fractal heap */ if(H5HF_delete(f, dxpl_id, linfo->link_fheap_addr) < 0) diff --git a/src/H5Gdeprec.c b/src/H5Gdeprec.c index 35fe13a..ee7b520 100644 --- a/src/H5Gdeprec.c +++ b/src/H5Gdeprec.c @@ -50,18 +50,16 @@ H5Glink(hid_t cur_loc_id, H5L_type_t type, const char *cur_name, const char *new FUNC_ENTER_API(H5Glink, FAIL) H5TRACE4("e","iLlss",cur_loc_id,type,cur_name,new_name); - if(type == H5L_TYPE_HARD) - { + if(type == H5L_TYPE_HARD) { if((ret_value = H5Lcreate_hard(cur_loc_id, cur_name, H5L_SAME_LOC, new_name, H5P_DEFAULT, H5P_DEFAULT)) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "Couldn't create link") - } - else if(type == H5L_TYPE_SOFT) - { + } /* end if */ + else if(type == H5L_TYPE_SOFT) { if((ret_value = H5Lcreate_soft(cur_name, cur_loc_id, new_name, H5P_DEFAULT, H5P_DEFAULT)) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "Couldn't create link") - } + } /* end else if */ else - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not a valid link type") + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not a valid link type") done: FUNC_LEAVE_API(ret_value) @@ -88,7 +86,7 @@ H5Glink2(hid_t cur_loc_id, const char *cur_name, H5L_type_t type, if(type == H5L_TYPE_HARD) { if((ret_value = H5Lcreate_hard(cur_loc_id, cur_name, new_loc_id, new_name, H5P_DEFAULT, H5P_DEFAULT)) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "Couldn't create link") - } + } /* end if */ else if(type == H5L_TYPE_SOFT) { /* Soft links only need one location, the new_loc_id, but it's possible that * new_loc_id is H5L_SAME_LOC */ @@ -97,13 +95,13 @@ H5Glink2(hid_t cur_loc_id, const char *cur_name, H5L_type_t type, if((ret_value = H5Lcreate_soft(cur_name, new_loc_id, new_name, H5P_DEFAULT, H5P_DEFAULT)) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "Couldn't create link") - } + } /* end else if */ else HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not a valid link type") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Glink2() */ /*------------------------------------------------------------------------- @@ -121,12 +119,12 @@ H5Gmove(hid_t src_loc_id, const char *src_name, const char *dst_name) FUNC_ENTER_API(H5Gmove, FAIL) H5TRACE3("e","iss",src_loc_id,src_name,dst_name); - if((ret_value=H5Lmove(src_loc_id, src_name, H5L_SAME_LOC, dst_name, H5P_DEFAULT, H5P_DEFAULT)) < 0) + if((ret_value = H5Lmove(src_loc_id, src_name, H5L_SAME_LOC, dst_name, H5P_DEFAULT, H5P_DEFAULT)) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "Couldn't move link") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Gmove() */ /*------------------------------------------------------------------------- @@ -136,19 +134,19 @@ done: * *------------------------------------------------------------------------- */ -herr_t H5Gmove2(hid_t src_loc_id, const char *src_name, - hid_t dst_loc_id, const char *dst_name) +herr_t +H5Gmove2(hid_t src_loc_id, const char *src_name, hid_t dst_loc_id, const char *dst_name) { herr_t ret_value; FUNC_ENTER_API(H5Gmove2, FAIL) - if((ret_value=H5Lmove(src_loc_id, src_name, dst_loc_id, dst_name, H5P_DEFAULT, H5P_DEFAULT)) < 0) + if((ret_value = H5Lmove(src_loc_id, src_name, dst_loc_id, dst_name, H5P_DEFAULT, H5P_DEFAULT)) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTINIT, FAIL, "couldn't move link") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Gmove2() */ /*------------------------------------------------------------------------- @@ -166,12 +164,12 @@ H5Gunlink(hid_t loc_id, const char *name) FUNC_ENTER_API(H5Gunlink, FAIL) H5TRACE2("e","is",loc_id,name); - if((ret_value=H5Lunlink(loc_id, name, H5P_DEFAULT)) < 0) + if((ret_value = H5Lunlink(loc_id, name, H5P_DEFAULT)) < 0) HGOTO_ERROR(H5E_LINK, H5E_CANTDELETE, FAIL, "Couldn't delete link") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Gunlink() */ /*------------------------------------------------------------------------- @@ -182,17 +180,17 @@ done: * *------------------------------------------------------------------------- */ -herr_t H5Gget_linkval(hid_t loc_id, const char *name, - size_t size, char *buf/*out*/) +herr_t +H5Gget_linkval(hid_t loc_id, const char *name, size_t size, char *buf/*out*/) { herr_t ret_value; FUNC_ENTER_API(H5Gget_linkval, FAIL) - if((ret_value=H5Lget_linkval(loc_id, name, size, buf, H5P_DEFAULT)) < 0) + if((ret_value = H5Lget_linkval(loc_id, name, size, buf, H5P_DEFAULT)) < 0) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "couldn't get link info") done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Gget_linkval() */ diff --git a/src/H5Gent.c b/src/H5Gent.c index ad6a083..412a2f6 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -31,12 +31,8 @@ #include "H5MMprivate.h" /* Memory Management */ /* Private macros */ -#define H5G_NO_CHANGE (-1) /*see H5G_ent_modified() */ /* Private prototypes */ -#ifdef NOT_YET -static herr_t H5G_ent_modified(H5G_entry_t *ent, H5G_type_t cache_type); -#endif /* NOT_YET */ static herr_t H5G_ent_encode(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent); static herr_t H5G_ent_decode(H5F_t *f, const uint8_t **pp, H5G_entry_t *ent/*out*/); @@ -46,40 +42,6 @@ H5FL_BLK_EXTERN(str_buf); /*------------------------------------------------------------------------- - * Function: H5G_ent_modified - * - * Purpose: This function should be called after you make any - * modifications to a symbol table entry cache. Supply the new - * type for the cache. If CACHE_TYPE is the constant - * H5G_NO_CHANGE then the cache type isn't changed--just the - * dirty bit is set. - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Robb Matzke - * Friday, September 19, 1997 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5G_ent_modified(H5G_entry_t *ent, H5G_type_t cache_type) -{ - FUNC_ENTER_NOAPI_NOFUNC(H5G_ent_modified) - - HDassert(ent); - - /* Update cache type, if requested */ - if (H5G_NO_CHANGE != cache_type) - ent->type = cache_type; - ent->dirty = TRUE; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5G_ent_modified */ - - -/*------------------------------------------------------------------------- * Function: H5G_ent_decode_vec * * Purpose: Same as H5G_ent_decode() except it does it for an array of diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index 1051846..db4d8c1 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -37,10 +37,29 @@ #include "H5Oprivate.h" /* Object headers */ #include "H5SLprivate.h" /* Skip lists */ +/**************************/ +/* Package Private Macros */ +/**************************/ + /* Standard length of fractal heap ID for link */ #define H5G_DENSE_FHEAP_ID_LEN 7 /* + * During name lookups (see H5G_traverse()) we sometimes want information about + * a symbolic link or a mount point. The normal operation is to follow the + * symbolic link or mount point and return information about its target. + */ +#define H5G_TARGET_NORMAL 0x0000 +#define H5G_TARGET_SLINK 0x0001 +#define H5G_TARGET_MOUNT 0x0002 +#define H5G_TARGET_UDLINK 0x0004 +#define H5G_CRT_INTMD_GROUP 0x0008 + +/****************************/ +/* Package Private Typedefs */ +/****************************/ + +/* * Various types of object header information can be cached in a symbol * table entry (it's normal home is the object header to which the entry * points). This datatype determines what (if anything) is cached in the @@ -299,23 +318,16 @@ typedef herr_t (*H5G_traverse_t)(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk/*in*/, H5G_loc_t *obj_loc/*out*/, void *operator_data/*in,out*/, H5G_own_loc_t *own_loc/*out*/); -/* - * During name lookups (see H5G_traverse()) we sometimes want information about - * a symbolic link or a mount point. The normal operation is to follow the - * symbolic link or mount point and return information about its target. - */ -#define H5G_TARGET_NORMAL 0x0000 -#define H5G_TARGET_SLINK 0x0001 -#define H5G_TARGET_MOUNT 0x0002 -#define H5G_TARGET_UDLINK 0x0004 -#define H5G_CRT_INTMD_GROUP 0x0008 - /* Data structure to hold table of links for a group */ typedef struct { size_t nlinks; /* # of links in table */ H5O_link_t *lnks; /* Pointer to array of links */ } H5G_link_table_t; +/*****************************/ +/* Package Private Variables */ +/*****************************/ + /* * This is the class identifier to give to the B-tree functions. */ @@ -324,6 +336,12 @@ H5_DLLVAR H5B_class_t H5B_SNODE[1]; /* The cache subclass */ H5_DLLVAR const H5AC_class_t H5AC_SNODE[1]; +/* The v2 B-tree class for indexing 'name' field on links */ +H5_DLLVAR const H5B2_class_t H5G_BT2_NAME[1]; + +/* The v2 B-tree class for indexing 'creation order' field on links */ +H5_DLLVAR const H5B2_class_t H5G_BT2_CORDER[1]; + /* * Utility functions */ @@ -334,6 +352,10 @@ H5_DLL herr_t H5G_traverse(const H5G_loc_t *loc, const char *name, unsigned target, H5G_traverse_t op, void *op_data, hid_t lapl_id, hid_t dxpl_id); +/******************************/ +/* Package Private Prototypes */ +/******************************/ + /* * Functions that understand symbol tables but not names. The * functions that understand names are exported to the rest of @@ -370,7 +392,6 @@ H5_DLL herr_t H5G_ent_decode_vec(H5F_t *f, const uint8_t **pp, H5G_entry_t *ent, unsigned n); H5_DLL herr_t H5G_ent_encode_vec(H5F_t *f, uint8_t **pp, const H5G_entry_t *ent, unsigned n); -H5_DLL herr_t H5G_ent_modified(H5G_entry_t *ent, H5G_type_t cache_type); H5_DLL herr_t H5G_ent_convert(H5F_t *f, haddr_t heap_addr, const char *name, const H5O_link_t *lnk, H5G_entry_t *ent, hid_t dxpl_id); H5_DLL herr_t H5G_ent_debug(H5F_t *f, hid_t dxpl_id, const H5G_entry_t *ent, FILE * stream, @@ -475,9 +496,10 @@ H5_DLL htri_t H5G_is_empty_test(hid_t gid); H5_DLL htri_t H5G_has_links_test(hid_t gid, unsigned *nmsgs); H5_DLL htri_t H5G_has_stab_test(hid_t gid); H5_DLL htri_t H5G_is_new_dense_test(hid_t gid); +H5_DLL herr_t H5G_new_dense_info_test(hid_t gid, hsize_t *name_count, hsize_t *corder_count); H5_DLL herr_t H5G_lheap_size_test(hid_t gid, size_t *lheap_size); H5_DLL herr_t H5G_user_path_test(hid_t obj_id, char *user_path, size_t *user_path_len, unsigned *user_path_hidden); #endif /* H5G_TESTING */ -#endif +#endif /* _H5Gpkg_H */ diff --git a/src/H5Gtest.c b/src/H5Gtest.c index a142dfd..f84f30b 100644 --- a/src/H5Gtest.c +++ b/src/H5Gtest.c @@ -18,10 +18,17 @@ * Purpose: Group testing functions. */ +/****************/ +/* Module Setup */ +/****************/ + #define H5G_PACKAGE /*suppress error about including H5Gpkg */ #define H5G_TESTING /*suppress warning about H5G testing funcs*/ +/***********/ +/* Headers */ +/***********/ #include "H5private.h" /* Generic Functions */ #include "H5Dprivate.h" /* Datasets */ #include "H5Eprivate.h" /* Error handling */ @@ -29,6 +36,40 @@ #include "H5HLprivate.h" /* Local Heaps */ #include "H5Iprivate.h" /* IDs */ +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + /*-------------------------------------------------------------------------- NAME @@ -318,6 +359,68 @@ done: /*-------------------------------------------------------------------------- NAME + H5G_new_dense_info_test + PURPOSE + Retrieve information about the state of the new "dense" storage for groups + USAGE + herr_t H5G_new_dense_info_test(gid, name_count, corder_count) + hid_t gid; IN: group to check + hsize_t *name_count; OUT: Number of links in name index + hsize_t *corder_count; OUT: Number of links in creation order index + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + Currently, just retrieves the number of links in each index and returns + them. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + DO NOT USE THIS FUNCTION FOR ANYTHING EXCEPT TESTING + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5G_new_dense_info_test(hid_t gid, hsize_t *name_count, hsize_t *corder_count) +{ + H5O_linfo_t linfo; /* Link info message */ + H5G_t *grp = NULL; /* Pointer to group */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5G_new_dense_info_test, FAIL) + + /* Get group structure */ + if(NULL == (grp = H5I_object_verify(gid, H5I_GROUP))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a group") + + /* Get the link info */ + if(NULL == H5O_read(&(grp->oloc), H5O_LINFO_ID, 0, &linfo, H5AC_dxpl_id)) + HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "can't get link info") + + /* Check for 'dense' link storage file addresses being defined */ + if(!H5F_addr_defined(linfo.link_fheap_addr)) + HGOTO_DONE(FAIL) + if(!H5F_addr_defined(linfo.name_bt2_addr)) + HGOTO_DONE(FAIL) + + /* Retrieve # of records in name index */ + if(H5B2_get_nrec(grp->oloc.file, H5AC_dxpl_id, H5G_BT2_NAME, linfo.name_bt2_addr, name_count) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from name index") + + /* Check if there is a creation order index */ + if(H5F_addr_defined(linfo.corder_bt2_addr)) { + /* Retrieve # of records in creation order index */ + if(H5B2_get_nrec(grp->oloc.file, H5AC_dxpl_id, H5G_BT2_CORDER, linfo.corder_bt2_addr, corder_count) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTCOUNT, FAIL, "unable to retrieve # of records from creation order index") + } /* end if */ + else + *corder_count = 0; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5G_new_dense_info_test() */ + + +/*-------------------------------------------------------------------------- + NAME H5G_lheap_size_test PURPOSE Determine the size of a local heap for a group diff --git a/test/links.c b/test/links.c index e33057e..4c22b6e 100644 --- a/test/links.c +++ b/test/links.c @@ -74,6 +74,7 @@ const char *FILENAME[] = { /* Creation order macros */ #define CORDER_GROUP_NAME "corder_group" +#define CORDER_EST_ENTRY_LEN 9 #ifndef QAK @@ -5180,7 +5181,7 @@ corder_create_empty(hid_t fapl) hbool_t index_corder; /* Status of creation order indexing for GCPL */ char filename[NAME_BUF_SIZE];/* File name */ - TESTING("creating empty group with creation order tracking") + TESTING("creating empty group with creation order indexing") /* Create file */ /* (with creation order tracking for the root group) */ @@ -5299,7 +5300,7 @@ corder_create_compact(hid_t fapl) char filename[NAME_BUF_SIZE];/* File name */ unsigned u; /* Local index variable */ - TESTING("creating compact group with creation order tracking") + TESTING("creating compact group with creation order indexing") /* Create file */ /* (with creation order tracking for the root group) */ @@ -5416,11 +5417,13 @@ corder_create_dense(hid_t fapl) unsigned max_compact; /* Maximum # of links to store in group compactly */ unsigned min_dense; /* Minimum # of links to store in group "densely" */ unsigned nlinks; /* Number of link messages in group's header */ + hsize_t name_count; /* # of records in name index */ + hsize_t corder_count; /* # of records in creation order index */ char objname[NAME_BUF_SIZE]; /* Object name */ char filename[NAME_BUF_SIZE];/* File name */ unsigned u; /* Local index variable */ - TESTING("creating dense group with creation order tracking") + TESTING("creating dense group with creation order indexing") /* Create file */ /* (with creation order tracking for the root group) */ @@ -5459,7 +5462,7 @@ corder_create_dense(hid_t fapl) if(H5G_is_new_dense_test(group_id) == TRUE) TEST_ERROR } /* end for */ - /* Create another group, to push group into dense form */ + /* Create another link, to push group into dense form */ sprintf(objname, "filler %u", max_compact); if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) TEST_ERROR if(H5Gclose(group_id2) < 0) TEST_ERROR @@ -5469,6 +5472,10 @@ corder_create_dense(hid_t fapl) if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR if(H5G_is_new_dense_test(group_id) != TRUE) TEST_ERROR + /* Retrieve & verify # of records in the name & creation order indices */ + if(H5G_new_dense_info_test(group_id, &name_count, &corder_count) < 0) TEST_ERROR + if(name_count != corder_count) TEST_ERROR + /* Close the group */ if(H5Gclose(group_id) < 0) TEST_ERROR @@ -5520,7 +5527,369 @@ error: H5Fclose(file_id); } H5E_END_TRY; return -1; -} /* end corder_create_compact() */ +} /* end corder_create_dense() */ + + +/*------------------------------------------------------------------------- + * Function: corder_transition + * + * Purpose: Create a group with creation order indices and verify correct + * transitions between compact & dense forms + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Monday, October 30, 2006 + * + *------------------------------------------------------------------------- + */ +static int +corder_transition(hid_t fapl) +{ + hid_t file_id = (-1); /* File ID */ + hid_t group_id = (-1), group_id2 = (-1); /* Group IDs */ + hid_t gcpl_id = (-1); /* Group creation property list ID */ + unsigned max_compact; /* Maximum # of links to store in group compactly */ + unsigned min_dense; /* Minimum # of links to store in group "densely" */ + unsigned nlinks; /* Number of link messages in group's header */ + hsize_t name_count; /* # of records in name index */ + hsize_t corder_count; /* # of records in creation order index */ + off_t empty_size; /* Size of empty file */ + off_t file_size; /* Size of file after operating on it */ + char objname[NAME_BUF_SIZE]; /* Object name */ + char filename[NAME_BUF_SIZE];/* File name */ + unsigned u; /* Local index variable */ + + TESTING("transitioning group with creation order indexing between dense & compact forms") + + /* Create file */ + /* (with creation order tracking for the root group) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) TEST_ERROR + + /* Create group creation property list */ + if((gcpl_id = H5Pcreate(H5P_GROUP_CREATE)) < 0) FAIL_STACK_ERROR + + /* Set creation order tracking & indexing on group */ + if(H5Pset_creation_order_index(gcpl_id, TRUE) < 0) FAIL_STACK_ERROR + if(H5Pset_creation_order_tracking(gcpl_id, TRUE) < 0) FAIL_STACK_ERROR + + /* Query the group creation properties */ + if(H5Pget_link_phase_change(gcpl_id, &max_compact, &min_dense) < 0) FAIL_STACK_ERROR + + /* Increase estimated link info, so the group's object header is large + * enough to hold all the link messages in one chunk + */ + if(H5Pset_est_link_info(gcpl_id, max_compact, CORDER_EST_ENTRY_LEN) < 0) TEST_ERROR + + /* Create group with creation order indexing & tracking on */ + if((group_id = H5Gcreate_expand(file_id, gcpl_id, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + if(H5Llink(file_id, CORDER_GROUP_NAME, group_id, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + + /* Close the group creation property list */ + if(H5Pclose(gcpl_id) < 0) FAIL_STACK_ERROR + + /* Close the group */ + if(H5Gclose(group_id) < 0) FAIL_STACK_ERROR + + /* Close the file */ + if(H5Fclose(file_id) < 0) FAIL_STACK_ERROR + + /* Get the size of the file with an empty group */ + if((empty_size = h5_get_file_size(filename)) < 0) TEST_ERROR + + + /* Re-open the file */ + if((file_id = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) FAIL_STACK_ERROR + + /* Open group created */ + if((group_id = H5Gopen(file_id, CORDER_GROUP_NAME)) < 0) TEST_ERROR + + /* Create several links, up to limit of compact form */ + for(u = 0; u < max_compact; u++) { + sprintf(objname, "filler %u", u); + if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(group_id2) < 0) TEST_ERROR + } /* end for */ + + /* Create another link, to push group into dense form */ + sprintf(objname, "filler %u", max_compact); + if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(group_id2) < 0) TEST_ERROR + + /* Verify state of group */ + if(H5G_has_links_test(group_id, NULL) == TRUE) TEST_ERROR + if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) != TRUE) TEST_ERROR + + /* Retrieve & verify # of records in the name & creation order indices */ + if(H5G_new_dense_info_test(group_id, &name_count, &corder_count) < 0) TEST_ERROR + if(name_count != corder_count) TEST_ERROR + + /* Delete several links from group, until it resumes compact form */ + for(u = max_compact; u >= min_dense; u--) { + sprintf(objname, "filler %u", u); + if(H5Lunlink(group_id, objname, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify state of group */ + if(H5G_has_links_test(group_id, NULL) == TRUE) TEST_ERROR + if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) != TRUE) TEST_ERROR + + /* Retrieve & verify # of records in the name & creation order indices */ + if(H5G_new_dense_info_test(group_id, &name_count, &corder_count) < 0) TEST_ERROR + if(name_count != corder_count) TEST_ERROR + } /* end for */ + + /* Delete another link, to push group into compact form */ + sprintf(objname, "filler %u", (min_dense - 1)); + if(H5Lunlink(group_id, objname, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify state of group */ + if(H5G_has_links_test(group_id, &nlinks) != TRUE) TEST_ERROR + if(nlinks != (min_dense - 1)) TEST_ERROR + if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) == TRUE) TEST_ERROR + + /* Re-add links to get back into dense form */ + for(u = (min_dense - 1); u < (max_compact + 1); u++) { + sprintf(objname, "filler %u", u); + if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(group_id2) < 0) TEST_ERROR + } /* end for */ + + /* Verify state of group */ + if(H5G_has_links_test(group_id, NULL) == TRUE) TEST_ERROR + if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) != TRUE) TEST_ERROR + + /* Retrieve & verify # of records in the name & creation order indices */ + if(H5G_new_dense_info_test(group_id, &name_count, &corder_count) < 0) TEST_ERROR + if(name_count != corder_count) TEST_ERROR + + /* Close the group */ + if(H5Gclose(group_id) < 0) TEST_ERROR + + /* Close the file */ + if(H5Fclose(file_id) < 0) TEST_ERROR + + + /* Re-open the file */ + if((file_id = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) TEST_ERROR + + /* Open group created */ + if((group_id = H5Gopen(file_id, CORDER_GROUP_NAME)) < 0) TEST_ERROR + + /* Verify state of group */ + if(H5G_has_links_test(group_id, NULL) == TRUE) TEST_ERROR + if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) != TRUE) TEST_ERROR + + /* Retrieve & verify # of records in the name & creation order indices */ + if(H5G_new_dense_info_test(group_id, &name_count, &corder_count) < 0) TEST_ERROR + if(name_count != corder_count) TEST_ERROR + + /* Delete several links from group, until it resumes compact form */ + for(u = max_compact; u >= min_dense; u--) { + sprintf(objname, "filler %u", u); + if(H5Lunlink(group_id, objname, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify state of group */ + if(H5G_has_links_test(group_id, NULL) == TRUE) TEST_ERROR + if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) != TRUE) TEST_ERROR + + /* Retrieve & verify # of records in the name & creation order indices */ + if(H5G_new_dense_info_test(group_id, &name_count, &corder_count) < 0) TEST_ERROR + if(name_count != corder_count) TEST_ERROR + } /* end for */ + + /* Delete another link, to push group into compact form */ + sprintf(objname, "filler %u", (min_dense - 1)); + if(H5Lunlink(group_id, objname, H5P_DEFAULT) < 0) TEST_ERROR + + /* Verify state of group */ + if(H5G_has_links_test(group_id, &nlinks) != TRUE) TEST_ERROR + if(nlinks != (min_dense - 1)) TEST_ERROR + if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) == TRUE) TEST_ERROR + + /* Re-add links to get back into dense form */ + for(u = (min_dense - 1); u < (max_compact + 1); u++) { + sprintf(objname, "filler %u", u); + if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) TEST_ERROR + if(H5Gclose(group_id2) < 0) TEST_ERROR + } /* end for */ + + /* Verify state of group */ + if(H5G_has_links_test(group_id, NULL) == TRUE) TEST_ERROR + if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) != TRUE) TEST_ERROR + + /* Retrieve & verify # of records in the name & creation order indices */ + if(H5G_new_dense_info_test(group_id, &name_count, &corder_count) < 0) TEST_ERROR + if(name_count != corder_count) TEST_ERROR + + /* Delete all the links */ + for(u = max_compact; u > 0; u--) { + sprintf(objname, "filler %u", u); + if(H5Lunlink(group_id, objname, H5P_DEFAULT) < 0) TEST_ERROR + } /* end for */ + sprintf(objname, "filler %u", 0); + if(H5Lunlink(group_id, objname, H5P_DEFAULT) < 0) TEST_ERROR + + /* Close the group */ + if(H5Gclose(group_id) < 0) TEST_ERROR + + /* Close the file */ + if(H5Fclose(file_id) < 0) TEST_ERROR + + /* Get the size of the file now */ + if((file_size = h5_get_file_size(filename)) < 0) TEST_ERROR + if(file_size != empty_size) TEST_ERROR + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Pclose(gcpl_id); + H5Gclose(group_id); + H5Fclose(file_id); + } H5E_END_TRY; + return -1; +} /* end corder_transition() */ + + +/*------------------------------------------------------------------------- + * Function: corder_delete + * + * Purpose: Create a group with creation order indices and verify correct + * deletion of creation order index when the group is in dense + * storage form and the group is unlinked + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Quincey Koziol + * Monday, October 30, 2006 + * + *------------------------------------------------------------------------- + */ +static int +corder_delete(hid_t fapl) +{ + hid_t file_id = (-1); /* File ID */ + hid_t group_id = (-1), group_id2 = (-1); /* Group IDs */ + hid_t gcpl_id = (-1); /* Group creation property list ID */ + unsigned max_compact; /* Maximum # of links to store in group compactly */ + unsigned min_dense; /* Minimum # of links to store in group "densely" */ + hsize_t name_count; /* # of records in name index */ + hsize_t corder_count; /* # of records in creation order index */ + hbool_t reopen_file; /* Whether to re-open the file before deleting group */ + off_t empty_size; /* Size of empty file */ + off_t file_size; /* Size of file after operating on it */ + char objname[NAME_BUF_SIZE]; /* Object name */ + char filename[NAME_BUF_SIZE];/* File name */ + unsigned u; /* Local index variable */ + + TESTING("deleting group with creation order indexing in dense form") + + /* Loop to leave file open when deleting group, or to close & re-open file + * before deleting group */ + for(reopen_file = FALSE; reopen_file <= TRUE; reopen_file++) { + /* Create file */ + /* (with creation order tracking for the root group) */ + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + if((file_id = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) FAIL_STACK_ERROR + + /* Close file */ + if(H5Fclose(file_id) < 0) FAIL_STACK_ERROR + + /* Get the size of an empty file */ + if((empty_size = h5_get_file_size(filename)) < 0) TEST_ERROR + + /* Re-open the file */ + if((file_id = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) FAIL_STACK_ERROR + + /* Create group creation property list */ + if((gcpl_id = H5Pcreate(H5P_GROUP_CREATE)) < 0) FAIL_STACK_ERROR + + /* Set creation order tracking & indexing on group */ + if(H5Pset_creation_order_index(gcpl_id, TRUE) < 0) FAIL_STACK_ERROR + if(H5Pset_creation_order_tracking(gcpl_id, TRUE) < 0) FAIL_STACK_ERROR + + /* Query the group creation properties */ + if(H5Pget_link_phase_change(gcpl_id, &max_compact, &min_dense) < 0) FAIL_STACK_ERROR + + /* Increase estimated link info, so the group's object header is large + * enough to hold all the link messages in one chunk + */ + if(H5Pset_est_link_info(gcpl_id, max_compact, CORDER_EST_ENTRY_LEN) < 0) TEST_ERROR + + /* Create group with creation order indexing & tracking on */ + if((group_id = H5Gcreate_expand(file_id, gcpl_id, H5P_DEFAULT)) < 0) FAIL_STACK_ERROR + if(H5Llink(file_id, CORDER_GROUP_NAME, group_id, H5P_DEFAULT, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + + /* Close the group creation property list */ + if(H5Pclose(gcpl_id) < 0) FAIL_STACK_ERROR + + /* Create links until the group is in dense form */ + for(u = 0; u < max_compact * 2; u++) { + sprintf(objname, "filler %u", u); + if((group_id2 = H5Gcreate(group_id, objname, (size_t)0)) < 0) FAIL_STACK_ERROR + if(H5Gclose(group_id2) < 0) FAIL_STACK_ERROR + } /* end for */ + + /* Verify state of group */ + if(H5G_has_links_test(group_id, NULL) == TRUE) TEST_ERROR + if(H5G_has_stab_test(group_id) == TRUE) TEST_ERROR + if(H5G_is_new_dense_test(group_id) != TRUE) TEST_ERROR + + /* Retrieve & verify # of records in the name & creation order indices */ + if(H5G_new_dense_info_test(group_id, &name_count, &corder_count) < 0) TEST_ERROR + if(name_count != corder_count) TEST_ERROR + + /* Close the group */ + if(H5Gclose(group_id) < 0) FAIL_STACK_ERROR + + /* Check for deleting group without re-opening file */ + if(!reopen_file) + /* Delete the group with the creation order index */ + if(H5Lunlink(file_id, CORDER_GROUP_NAME, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + + /* Close the file */ + if(H5Fclose(file_id) < 0) FAIL_STACK_ERROR + + /* Check for deleting group after re-opening file */ + if(reopen_file) { + /* Re-open the file */ + if((file_id = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) FAIL_STACK_ERROR + + /* Delete the group with the creation order index */ + if(H5Lunlink(file_id, CORDER_GROUP_NAME, H5P_DEFAULT) < 0) FAIL_STACK_ERROR + + /* Close the file */ + if(H5Fclose(file_id) < 0) FAIL_STACK_ERROR + } /* end if */ + + /* Get the size of the file now */ + if((file_size = h5_get_file_size(filename)) < 0) TEST_ERROR + if(file_size != empty_size) TEST_ERROR + } /* end for */ + + PASSED(); + return 0; + +error: + H5E_BEGIN_TRY { + H5Pclose(gcpl_id); + H5Gclose(group_id); + H5Fclose(file_id); + } H5E_END_TRY; + return -1; +} /* end corder_delete() */ /*------------------------------------------------------------------------- @@ -5624,6 +5993,8 @@ main(void) */ nerrors += corder_create_compact(fapl2) < 0 ? 1 : 0; nerrors += corder_create_dense(fapl2) < 0 ? 1 : 0; + nerrors += corder_transition(fapl2) < 0 ? 1 : 0; + nerrors += corder_delete(fapl2) < 0 ? 1 : 0; } /* end if */ } /* end for */ #else /* QAK */ @@ -5634,6 +6005,8 @@ main(void) */ nerrors += corder_create_compact(fapl2) < 0 ? 1 : 0; nerrors += corder_create_dense(fapl2) < 0 ? 1 : 0; + nerrors += corder_transition(fapl2) < 0 ? 1 : 0; + nerrors += corder_delete(fapl2) < 0 ? 1 : 0; #endif /* QAK */ /* Close 2nd FAPL */ -- cgit v0.12