diff options
Diffstat (limited to 'src/H5HF.c')
-rw-r--r-- | src/H5HF.c | 325 |
1 files changed, 271 insertions, 54 deletions
@@ -39,6 +39,7 @@ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5Eprivate.h" /* Error handling */ +#include "H5FOprivate.h" /* File objects */ #include "H5HFpkg.h" /* Fractal heaps */ #include "H5MFprivate.h" /* File memory management */ @@ -66,8 +67,8 @@ /* Package Variables */ /*********************/ -/* Declare a free list to manage the H5HF_t struct */ -H5FL_DEFINE(H5HF_t); +/* Declare a free list to manage the H5HF_hdr_t struct */ +H5FL_DEFINE(H5HF_hdr_t); /*****************************/ @@ -79,6 +80,9 @@ H5FL_DEFINE(H5HF_t); /* Local Variables */ /*******************/ +/* Declare a free list to manage the H5HF_t struct */ +H5FL_DEFINE_STATIC(H5HF_t); + /*------------------------------------------------------------------------- @@ -86,8 +90,8 @@ H5FL_DEFINE(H5HF_t); * * Purpose: Creates a new empty fractal heap in the file. * - * Return: Non-negative on success (with address of new fractal heap - * filled in), negative on failure + * Return: Pointer to heap wrapper on success + * NULL on failure * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu @@ -95,48 +99,79 @@ H5FL_DEFINE(H5HF_t); * *------------------------------------------------------------------------- */ -herr_t -H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam, haddr_t *addr_p, - size_t *id_len_p) +H5HF_t * +H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam) { - H5HF_t *hdr = NULL; /* The new fractal heap header information */ - herr_t ret_value = SUCCEED; /* Return value */ + H5HF_t *fh = NULL; /* Pointer to new fractal heap */ + H5HF_hdr_t *hdr = NULL; /* The new fractal heap header information */ + haddr_t hdr_addr; /* Heap header address */ + H5HF_t *ret_value; /* Return value */ - FUNC_ENTER_NOAPI(H5HF_create, FAIL) + FUNC_ENTER_NOAPI(H5HF_create, NULL) /* * Check arguments. */ HDassert(f); HDassert(cparam); - HDassert(addr_p); - HDassert(id_len_p); /* Allocate & basic initialization for the shared header */ if(NULL == (hdr = H5HF_hdr_alloc(f))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate space for shared heap info") + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for shared heap info") /* Allocate space for the header on disk */ - if(HADDR_UNDEF == (*addr_p = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(hdr)))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap header") + if(HADDR_UNDEF == (hdr_addr = H5MF_alloc(f, H5FD_MEM_FHEAP_HDR, dxpl_id, (hsize_t)H5HF_HEADER_SIZE(hdr)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for fractal heap header") /* Initialize shared fractal heap header */ - if(H5HF_hdr_init(hdr, *addr_p, cparam) < 0) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't initialize shared fractal heap header") + /* (This routine is only called for newly created heaps) */ + if(H5HF_hdr_init(hdr, hdr_addr, cparam) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't initialize shared fractal heap header") - /* Set the length of heap IDs */ - *id_len_p = hdr->id_len; #ifdef QAK HDfprintf(stderr, "%s: hdr->id_len = %Zu\n", FUNC, hdr->id_len); #endif /* QAK */ /* Cache the new fractal heap header */ - if(H5AC_set(f, dxpl_id, H5AC_FHEAP_HDR, *addr_p, hdr, H5AC__NO_FLAGS_SET) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap header to cache") + if(H5AC_set(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't add fractal heap header to cache") + + /* Create fractal heap wrapper */ + if(NULL == (fh = H5FL_MALLOC(H5HF_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap info") + + /* Lock the heap header into memory */ +#ifdef QAK +HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr); +#endif /* QAK */ + if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load fractal heap header") + + /* Point fractal heap wrapper at header */ + fh->hdr = hdr; + if(H5HF_hdr_incr(fh->hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header") + + /* Unlock heap header, now pinned */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap header") + hdr = NULL; + + /* Add heap to list of open objects in file */ + if(H5FO_insert(f, fh->hdr->heap_addr, fh) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert heap into list of open objects") + + /* Set open object count */ + fh->fo_count = 1; + + /* Set the return value */ + ret_value = fh; done: - if(ret_value < 0) { - if(hdr) + if(!ret_value) { + if(fh) + (void)H5HF_close(fh); + else if(hdr) (void)H5HF_cache_hdr_dest(f, hdr); } /* end if */ @@ -145,6 +180,149 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_open + * + * Purpose: Opens an existing fractal heap in the file. + * + * Return: Pointer to heap wrapper on success + * NULL on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 18 2006 + * + *------------------------------------------------------------------------- + */ +H5HF_t * +H5HF_open(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr) +{ + H5HF_t *fh = NULL; /* Pointer to new fractal heap */ + H5HF_hdr_t *hdr = NULL; /* The new fractal heap header information */ + H5HF_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5HF_open, NULL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(fh_addr)); + + /* Check if group was already open */ + if((fh = H5FO_opened(f, fh_addr)) == NULL) { + + /* Clear any errors from H5FO_opened() */ + H5E_clear_stack(NULL); + + /* Load the heap header into memory */ +#ifdef QAK +HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr); +#endif /* QAK */ + if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, NULL, "unable to load fractal heap header") +#ifdef QAK +HDfprintf(stderr, "%s: hdr->rc = %u\n", FUNC, hdr->rc); +#endif /* QAK */ + + /* Create fractal heap info */ + if(NULL == (fh = H5FL_MALLOC(H5HF_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap info") + + /* Point fractal heap wrapper at header */ + fh->hdr = hdr; + if(H5HF_hdr_incr(fh->hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header") + + /* Add heap to list of open objects in file */ + if(H5FO_insert(f, fh->hdr->heap_addr, fh) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTINSERT, NULL, "can't insert heap into list of open objects") + + /* Set open object count */ + fh->fo_count = 1; + } /* end if */ + else { + /* Increment shared reference count */ + fh->fo_count++; + } /* end else */ + + /* Set the return value */ + ret_value = fh; + +done: + if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, NULL, "unable to release fractal heap header") + if(!ret_value) { + if(fh) + (void)H5HF_close(fh); + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_get_id_len + * + * Purpose: Get the size of IDs for entries in a fractal heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 17 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_get_id_len(H5HF_t *fh, size_t *id_len_p) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5HF_get_id_len) + + /* + * Check arguments. + */ + HDassert(fh); + HDassert(id_len_p); + + /* Retrieve the ID length for entries in this heap */ + *id_len_p = fh->hdr->id_len; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_get_id_len() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_get_heap_addr + * + * Purpose: Get the address of a fractal heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 18 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_get_heap_addr(H5HF_t *fh, haddr_t *heap_addr_p) +{ + FUNC_ENTER_NOAPI_NOFUNC(H5HF_get_heap_addr) + + /* + * Check arguments. + */ + HDassert(fh); + HDassert(heap_addr_p); + + /* Retrieve the heap header address for this heap */ + *heap_addr_p = fh->hdr->heap_addr; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_get_heap_addr() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_insert * * Purpose: Insert a new object into a fractal heap. @@ -159,11 +337,10 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, size_t size, - const void *obj, void *id/*out*/) +H5HF_insert(H5HF_t *fh, hid_t dxpl_id, size_t size, const void *obj, + void *id/*out*/) { - H5HF_t *hdr = NULL; /* The fractal heap header information */ - unsigned hdr_flags = H5AC__NO_FLAGS_SET; /* Metadata cache flags for header */ + H5HF_hdr_t *hdr = NULL; /* The fractal heap header information */ herr_t ret_value = SUCCEED; FUNC_ENTER_NOAPI(H5HF_insert, FAIL) @@ -174,17 +351,13 @@ HDfprintf(stderr, "%s: size = %Zu\n", FUNC, size); /* * Check arguments. */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + HDassert(fh); HDassert(size > 0); HDassert(obj); HDassert(id); - /* - * Load the fractal heap header. - */ - if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") + /* Get the fractal heap header */ + hdr = fh->hdr; /* Check if object is large enough to be standalone */ if(size >= hdr->standalone_size) { @@ -208,14 +381,7 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'write once' managed blocks not su } /* end else */ } /* end else */ - /* Check for making header dirty */ - if(hdr->dirty) - hdr_flags |= H5AC__DIRTIED_FLAG; - done: - if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, hdr_flags) < 0) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") - FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_insert() */ @@ -234,10 +400,9 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_id, - void *obj/*out*/) +H5HF_read(H5HF_t *fh, hid_t dxpl_id, const void *_id, void *obj/*out*/) { - H5HF_t *hdr = NULL; /* The fractal heap header information */ + H5HF_hdr_t *hdr = NULL; /* The fractal heap header information */ const uint8_t *id = (const uint8_t *)_id; /* Object ID */ hsize_t obj_off; /* Object's offset in heap */ size_t obj_len; /* Object's length in heap */ @@ -248,16 +413,12 @@ H5HF_read(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_id, /* * Check arguments. */ - HDassert(f); - HDassert(H5F_addr_defined(addr)); + HDassert(fh); HDassert(id); HDassert(obj); - /* - * Load the fractal heap header. - */ - if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, addr, NULL, NULL, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") + /* Get the fractal heap header */ + hdr = fh->hdr; /* Decode the object offset within the heap & it's length */ UINT64DECODE_VAR(id, obj_off, hdr->heap_off_size); @@ -277,9 +438,65 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "standalone blocks not supported ye } /* end else */ done: - if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, addr, hdr, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") - FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_read() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_close + * + * Purpose: Close a fractal heap wrapper + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 17 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_close(H5HF_t *fh) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5HF_close, FAIL) + + /* + * Check arguments. + */ + HDassert(fh); + + /* Decrement shared object count */ + --fh->fo_count; + + /* Check if this is the last reference to the shared heap wrapper */ + if(0 == fh->fo_count) { + /* Remove the heap from the list of opened objects in the file */ + if(H5FO_delete(fh->hdr->f, H5AC_dxpl_id, fh->hdr->heap_addr) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects") + + /* Reset the free list information */ + /* (Bump the "generation" counter in case this heap header is still + * in the cache when the heap is re-opened -QAK) + */ + H5HF_flist_reset(fh->hdr->flist); + fh->hdr->fl_gen++; + fh->hdr->freelist_sync = FALSE; + + /* Reset the block iterator */ + if(H5HF_man_iter_reset(&fh->hdr->next_block) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't reset block iterator") + + /* Decrement the reference count on the heap header */ + if(H5HF_hdr_decr(fh->hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header") + + /* Release the fractal heap wrapper */ + H5FL_FREE(H5HF_t, fh); + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_close() */ + |