diff options
Diffstat (limited to 'src/H5Bcache.c')
| -rw-r--r-- | src/H5Bcache.c | 438 |
1 files changed, 197 insertions, 241 deletions
diff --git a/src/H5Bcache.c b/src/H5Bcache.c index 2992986..cd0a0ba 100644 --- a/src/H5Bcache.c +++ b/src/H5Bcache.c @@ -1,23 +1,20 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * - * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * - * the files COPYING and Copyright.html. COPYING can be found at the root * - * of the source code distribution tree; Copyright.html can be found at the * - * root level of an installed copy of the electronic HDF5 document set and * - * is linked from the top-level documents page. It can also be found at * - * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have * - * access to either file, you may request a copy from help@hdfgroup.org. * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*------------------------------------------------------------------------- * * Created: H5Bcache.c * Oct 31 2005 - * Quincey Koziol <koziol@ncsa.uiuc.edu> + * Quincey Koziol * * Purpose: Implement B-tree metadata cache methods. * @@ -28,39 +25,34 @@ /* Module Setup */ /****************/ -#define H5B_PACKAGE /*suppress error about including H5Bpkg */ - +#include "H5Bmodule.h" /* This source code file is part of the H5B module */ /***********/ /* Headers */ /***********/ -#include "H5private.h" /* Generic Functions */ -#include "H5Bpkg.h" /* B-link trees */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5MFprivate.h" /* File memory management */ - +#include "H5private.h" /* Generic Functions */ +#include "H5Bpkg.h" /* B-link trees */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ /****************/ /* Local Macros */ /****************/ - /******************/ /* Local Typedefs */ /******************/ - /********************/ /* Local Prototypes */ /********************/ /* Metadata cache callbacks */ -static H5B_t *H5B__load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata); -static herr_t H5B__flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *b, unsigned UNUSED * flags_ptr); -static herr_t H5B__dest(H5F_t *f, H5B_t *bt); -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); - +static herr_t H5B__cache_get_initial_load_size(void *udata, size_t *image_len); +static void *H5B__cache_deserialize(const void *image, size_t len, void *udata, hbool_t *dirty); +static herr_t H5B__cache_image_len(const void *thing, size_t *image_len); +static herr_t H5B__cache_serialize(const H5F_t *f, void *image, size_t len, void *thing); +static herr_t H5B__cache_free_icr(void *thing); /*********************/ /* Package Variables */ @@ -68,55 +60,94 @@ static herr_t H5B__compute_size(const H5F_t *f, const H5B_t *bt, size_t *size_pt /* 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_notify_func_t)NULL, - (H5AC_size_func_t)H5B__compute_size, + H5AC_BT_ID, /* Metadata client ID */ + "v1 B-tree", /* Metadata client name (for debugging) */ + H5FD_MEM_BTREE, /* File space memory type for client */ + H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */ + H5B__cache_get_initial_load_size, /* 'get_initial_load_size' callback */ + NULL, /* 'get_final_load_size' callback */ + NULL, /* 'verify_chksum' callback */ + H5B__cache_deserialize, /* 'deserialize' callback */ + H5B__cache_image_len, /* 'image_len' callback */ + NULL, /* 'pre_serialize' callback */ + H5B__cache_serialize, /* 'serialize' callback */ + NULL, /* 'notify' callback */ + H5B__cache_free_icr, /* 'free_icr' callback */ + NULL, /* 'fsf_size' callback */ }}; /*******************/ /* Local Variables */ /*******************/ +/*------------------------------------------------------------------------- + * Function: H5B__cache_get_initial_load_size + * + * Purpose: Compute the size of the data structure on disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * May 18, 2010 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B__cache_get_initial_load_size(void *_udata, size_t *image_len) +{ + H5B_cache_ud_t *udata = (H5B_cache_ud_t *)_udata; /* User data for callback */ + H5B_shared_t *shared; /* Pointer to shared B-tree info */ + + FUNC_ENTER_PACKAGE_NOERR + + /* Check arguments */ + HDassert(udata); + HDassert(image_len); + + /* Get shared info for B-tree */ + shared = (H5B_shared_t *)H5UC_GET_OBJ(udata->rc_shared); + HDassert(shared); + + /* Set the image length size */ + *image_len = shared->sizeof_rnode; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5B__cache_get_initial_load_size() */ - /*------------------------------------------------------------------------- - * Function: H5B__load + * Function: H5B__cache_deserialize * - * Purpose: Loads a B-tree node from the disk. + * Purpose: Deserialize the data structure from disk. * * Return: Success: Pointer to a new B-tree node. * Failure: NULL * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 23 1997 + * Programmer: Quincey Koziol + * Mar 24, 2008 * *------------------------------------------------------------------------- */ -static H5B_t * -H5B__load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) +static void * +H5B__cache_deserialize(const void *_image, size_t H5_ATTR_UNUSED len, void *_udata, + hbool_t H5_ATTR_UNUSED *dirty) { - H5B_t *bt = NULL; /* Pointer to the deserialized B-tree node */ - H5B_cache_ud_t *udata = (H5B_cache_ud_t *)_udata; /* User data for callback */ - H5B_shared_t *shared; /* Pointer to shared B-tree info */ - const uint8_t *p; /* Pointer into raw data buffer */ - uint8_t *native; /* Pointer to native keys */ - unsigned u; /* Local index variable */ - H5B_t *ret_value; /* Return value */ + H5B_t *bt = NULL; /* Pointer to the deserialized B-tree node */ + H5B_cache_ud_t *udata = (H5B_cache_ud_t *)_udata; /* User data for callback */ + H5B_shared_t *shared; /* Pointer to shared B-tree info */ + const uint8_t *image = (const uint8_t *)_image; /* Pointer into image buffer */ + uint8_t *native; /* Pointer to native keys */ + unsigned u; /* Local index variable */ + H5B_t *ret_value = NULL; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE - /* Check arguments */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + /* check arguments */ + HDassert(image); HDassert(udata); - if(NULL == (bt = H5FL_MALLOC(H5B_t))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "can't allocate B-tree struct") + /* Allocate the B-tree node in memory */ + if (NULL == (bt = H5FL_MALLOC(H5B_t))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "can't allocate B-tree struct") HDmemset(&bt->cache_info, 0, sizeof(H5AC_info_t)); /* Set & increment the ref-counted "shared" B-tree information for the node */ @@ -128,284 +159,209 @@ H5B__load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata) HDassert(shared); /* Allocate space for the native keys and child addresses */ - if(NULL == (bt->native = H5FL_BLK_MALLOC(native_block, shared->sizeof_keys))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "can't allocate buffer for native keys") - if(NULL == (bt->child = H5FL_SEQ_MALLOC(haddr_t, (size_t)shared->two_k))) - HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "can't allocate buffer for child addresses") - - 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") - - /* Set the pointer into the raw data buffer */ - p = shared->page; + if (NULL == (bt->native = H5FL_BLK_MALLOC(native_block, shared->sizeof_keys))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "can't allocate buffer for native keys") + if (NULL == (bt->child = H5FL_SEQ_MALLOC(haddr_t, (size_t)shared->two_k))) + HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "can't allocate buffer for child addresses") /* magic number */ - if(HDmemcmp(p, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC)) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree signature") - p += 4; + if (HDmemcmp(image, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC) != 0) + HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "wrong B-tree signature") + image += H5_SIZEOF_MAGIC; /* node type and level */ - if(*p++ != (uint8_t)udata->type->id) - HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree node type") - bt->level = *p++; + if (*image++ != (uint8_t)udata->type->id) + HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "incorrect B-tree node type") + bt->level = *image++; /* entries used */ - UINT16DECODE(p, bt->nchildren); + UINT16DECODE(image, bt->nchildren); /* Check if bt->nchildren is greater than two_k */ - if(bt->nchildren > shared->two_k) + if (bt->nchildren > shared->two_k) HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "number of children is greater than maximum") /* sibling pointers */ - H5F_addr_decode(udata->f, (const uint8_t **)&p, &(bt->left)); - H5F_addr_decode(udata->f, (const uint8_t **)&p, &(bt->right)); + H5F_addr_decode(udata->f, (const uint8_t **)&image, &(bt->left)); + H5F_addr_decode(udata->f, (const uint8_t **)&image, &(bt->right)); /* the child/key pairs */ native = bt->native; - for(u = 0; u < bt->nchildren; u++) { + for (u = 0; u < bt->nchildren; u++) { /* Decode native key value */ - if((udata->type->decode)(shared, p, native) < 0) + if ((udata->type->decode)(shared, image, native) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode key") - p += shared->sizeof_rkey; + image += shared->sizeof_rkey; native += udata->type->sizeof_nkey; /* Decode address value */ - H5F_addr_decode(udata->f, (const uint8_t **)&p, bt->child + u); + H5F_addr_decode(udata->f, (const uint8_t **)&image, bt->child + u); } /* end for */ /* Decode final key */ - if(bt->nchildren > 0) { + if (bt->nchildren > 0) { /* Decode native key value */ - if((udata->type->decode)(shared, p, native) < 0) + if ((udata->type->decode)(shared, image, native) < 0) HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode key") } /* end if */ + /* Sanity check */ + HDassert((size_t)((const uint8_t *)image - (const uint8_t *)_image) <= len); + /* Set return value */ ret_value = bt; done: - if(!ret_value && bt) - if(H5B_node_dest(bt) < 0) + if (!ret_value && bt) + if (H5B__node_dest(bt) < 0) HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, NULL, "unable to destroy B-tree node") FUNC_LEAVE_NOAPI(ret_value) -} /* end H5B__load() */ /*lint !e818 Can't make udata a pointer to const */ +} /* end H5B__cache_deserialize() */ - /*------------------------------------------------------------------------- - * Function: H5B__flush + * Function: H5B__cache_image_len * - * Purpose: Flushes a dirty B-tree node to disk. + * Purpose: Compute the size of the data structure on disk. * * Return: Non-negative on success/Negative on failure * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jun 23 1997 + * Programmer: Quincey Koziol + * May 20, 2010 * *------------------------------------------------------------------------- */ static herr_t -H5B__flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B_t *bt, unsigned UNUSED * flags_ptr) +H5B__cache_image_len(const void *_thing, size_t *image_len) { - H5B_shared_t *shared; /* Pointer to shared B-tree info */ - herr_t ret_value = SUCCEED; /* Return value */ + const H5B_t *bt = (const H5B_t *)_thing; /* Pointer to the B-tree node */ + H5B_shared_t *shared; /* Pointer to shared B-tree info */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE_NOERR - /* check arguments */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + /* Check arguments */ HDassert(bt); + HDassert(image_len); + + /* Get shared info for B-tree */ shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared); HDassert(shared); - HDassert(shared->type); - HDassert(shared->type->encode); - if(bt->cache_info.is_dirty) { - uint8_t *p; /* Pointer into raw data buffer */ - uint8_t *native; /* Pointer to native keys */ - unsigned u; /* Local index variable */ - - p = shared->page; - - /* magic number */ - HDmemcpy(p, H5B_MAGIC, (size_t)H5_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(shared, 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(shared, p, native) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key") - } /* end if */ - - /* - * 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 */ + /* Set the image length size */ + *image_len = shared->sizeof_rnode; - 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() */ + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5B__cache_image_len() */ - /*------------------------------------------------------------------------- - * Function: H5B__dest + * Function: H5B__cache_serialize * - * Purpose: Destroys a B-tree node in memory. + * Purpose: Serialize the data structure for writing to disk. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Jan 15 2003 + * Programmer: Quincey Koziol + * Mar 24, 2008 * *------------------------------------------------------------------------- */ static herr_t -H5B__dest(H5F_t *f, H5B_t *bt) +H5B__cache_serialize(const H5F_t *f, void *_image, size_t H5_ATTR_UNUSED len, void *_thing) { - herr_t ret_value = SUCCEED; /* Return value */ + H5B_t *bt = (H5B_t *)_thing; /* Pointer to the B-tree node */ + H5B_shared_t *shared; /* Pointer to shared B-tree info */ + uint8_t *image = (uint8_t *)_image; /* Pointer into image buffer */ + uint8_t *native; /* Pointer to native keys */ + unsigned u; /* Local index counter */ + herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_STATIC + FUNC_ENTER_PACKAGE - /* - * Check arguments. - */ - HDassert(f); + /* check arguments */ + HDassert(image); HDassert(bt); HDassert(bt->rc_shared); + shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared); + HDassert(shared); + HDassert(shared->type); + HDassert(shared->type->encode); - /* If we're going to free the space on disk, the address must be valid */ - HDassert(!bt->cache_info.free_file_space_on_destroy || H5F_addr_defined(bt->cache_info.addr)); - - /* Check for freeing file space for B-tree node */ - if(bt->cache_info.free_file_space_on_destroy) { - H5B_shared_t *shared; /* Pointer to shared B-tree info */ + /* magic number */ + H5MM_memcpy(image, H5B_MAGIC, (size_t)H5_SIZEOF_MAGIC); + image += 4; - /* Get the pointer to the shared B-tree info */ - shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared); - HDassert(shared); + /* node type and level */ + *image++ = (uint8_t)shared->type->id; - /* Release the space on disk */ - /* (XXX: Nasty usage of internal DXPL value! -QAK) */ - if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, bt->cache_info.addr, (hsize_t)shared->sizeof_rnode) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free B-tree node") - } /* end if */ + /* 2^8 limit: only 1 byte is used to store node level */ + if (bt->level >= HDpow(2, LEVEL_BITS)) + HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode node level") - /* Destroy B-tree node */ - if(H5B_node_dest(bt) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node") + H5_CHECK_OVERFLOW(bt->level, unsigned, uint8_t); + *image++ = (uint8_t)bt->level; -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* 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; + /* entries used */ + UINT16ENCODE(image, bt->nchildren); - FUNC_ENTER_STATIC + /* sibling pointers */ + H5F_addr_encode(f, &image, bt->left); + H5F_addr_encode(f, &image, bt->right); - /* - * Check arguments. - */ - HDassert(bt); + /* child keys and pointers */ + native = bt->native; + for (u = 0; u < bt->nchildren; ++u) { + /* encode the key */ + if (shared->type->encode(shared, image, native) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key") + image += shared->sizeof_rkey; + native += shared->type->sizeof_nkey; + + /* encode the child address */ + H5F_addr_encode(f, &image, bt->child[u]); + } /* end for */ + if (bt->nchildren > 0) { + /* Encode the final key */ + if (shared->type->encode(shared, image, native) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree key") + image += shared->sizeof_rkey; + } /* end if */ - /* Reset the dirty flag. */ - bt->cache_info.is_dirty = FALSE; + /* Sanity check */ + HDassert((size_t)(image - (uint8_t *)_image) <= len); - if(destroy) - if(H5B__dest(f, bt) < 0) - HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node") + /* Clear rest of node */ + HDmemset(image, 0, len - (size_t)(image - (uint8_t *)_image)); done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5B__clear() */ +} /* end H5B__cache_serialize() */ - /*------------------------------------------------------------------------- - * Function: H5B__compute_size + * Function: H5B__cache_free_icr * - * 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. + * Purpose: Destroy/release an "in core representation" of a data structure * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * - * Programmer: John Mainzer - * 5/13/04 + * Programmer: Quincey Koziol + * Mar 26, 2008 * *------------------------------------------------------------------------- */ static herr_t -H5B__compute_size(const H5F_t UNUSED *f, const H5B_t *bt, size_t *size_ptr) +H5B__cache_free_icr(void *thing) { - H5B_shared_t *shared; /* Pointer to shared B-tree info */ - - FUNC_ENTER_STATIC_NOERR + herr_t ret_value = SUCCEED; /* Return value */ - /* check arguments */ - HDassert(f); - HDassert(bt); - HDassert(bt->rc_shared); - shared = (H5B_shared_t *)H5UC_GET_OBJ(bt->rc_shared); - HDassert(shared); - HDassert(shared->type); - HDassert(size_ptr); + FUNC_ENTER_PACKAGE - /* Set size value */ - *size_ptr = shared->sizeof_rnode; + /* Check arguments */ + HDassert(thing); - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5B__compute_size() */ + /* Destroy B-tree node */ + if (H5B__node_dest((H5B_t *)thing) < 0) + HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree node") +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5B__cache_free_icr() */ |
