diff options
Diffstat (limited to 'src/H5HLcache.c')
-rw-r--r-- | src/H5HLcache.c | 282 |
1 files changed, 194 insertions, 88 deletions
diff --git a/src/H5HLcache.c b/src/H5HLcache.c index 5697121..c53292a 100644 --- a/src/H5HLcache.c +++ b/src/H5HLcache.c @@ -71,7 +71,9 @@ /* Metadata cache callbacks */ /* Local heap prefix */ -static herr_t H5HL__cache_prefix_get_load_size(const void *udata, size_t *image_len); +static herr_t H5HL__cache_prefix_get_initial_load_size(void *udata, size_t *image_len); +static herr_t H5HL__cache_prefix_get_final_load_size(const void *_image, + size_t image_len, void *udata, size_t *actual_len); static void *H5HL__cache_prefix_deserialize(const void *image, size_t len, void *udata, hbool_t *dirty); static herr_t H5HL__cache_prefix_image_len(const void *thing, size_t *image_len); @@ -80,13 +82,13 @@ static herr_t H5HL__cache_prefix_serialize(const H5F_t *f, void *image, static herr_t H5HL__cache_prefix_free_icr(void *thing); /* Local heap data block */ -static herr_t H5HL__cache_datablock_get_load_size(const void *udata, - size_t *image_len); +static herr_t H5HL__cache_datablock_get_initial_load_size(void *udata, size_t *image_len); static void *H5HL__cache_datablock_deserialize(const void *image, size_t len, void *udata, hbool_t *dirty); static herr_t H5HL__cache_datablock_image_len(const void *thing, size_t *image_len); static herr_t H5HL__cache_datablock_serialize(const H5F_t *f, void *image, size_t len, void *thing); +static herr_t H5HL__cache_datablock_notify(H5C_notify_action_t action, void *_thing); static herr_t H5HL__cache_datablock_free_icr(void *thing); /* Free list de/serialization */ @@ -103,7 +105,9 @@ const H5AC_class_t H5AC_LHEAP_PRFX[1] = {{ "local heap prefix", /* Metadata client name (for debugging) */ H5FD_MEM_LHEAP, /* File space memory type for client */ H5AC__CLASS_SPECULATIVE_LOAD_FLAG, /* Client class behavior flags */ - H5HL__cache_prefix_get_load_size, /* 'get_load_size' callback */ + H5HL__cache_prefix_get_initial_load_size, /* 'get_initial_load_size' callback */ + H5HL__cache_prefix_get_final_load_size, /* 'get_final_load_size' callback */ + NULL, /* 'verify_chksum' callback */ H5HL__cache_prefix_deserialize, /* 'deserialize' callback */ H5HL__cache_prefix_image_len, /* 'image_len' callback */ NULL, /* 'pre_serialize' callback */ @@ -118,12 +122,14 @@ const H5AC_class_t H5AC_LHEAP_DBLK[1] = {{ "local heap datablock", /* Metadata client name (for debugging) */ H5FD_MEM_LHEAP, /* File space memory type for client */ H5AC__CLASS_NO_FLAGS_SET, /* Client class behavior flags */ - H5HL__cache_datablock_get_load_size,/* 'get_load_size' callback */ + H5HL__cache_datablock_get_initial_load_size,/* 'get_initial_load_size' callback */ + NULL, /* 'get_final_load_size' callback */ + NULL, /* 'verify_chksum' callback */ H5HL__cache_datablock_deserialize, /* 'deserialize' callback */ H5HL__cache_datablock_image_len, /* 'image_len' callback */ NULL, /* 'pre_serialize' callback */ H5HL__cache_datablock_serialize, /* 'serialize' callback */ - NULL, /* 'notify' callback */ + H5HL__cache_datablock_notify, /* 'notify' callback */ H5HL__cache_datablock_free_icr, /* 'free_icr' callback */ NULL, /* 'fsf_size' callback */ }}; @@ -254,18 +260,11 @@ H5HL__fl_serialize(const H5HL_t *heap) /*------------------------------------------------------------------------- - * Function: H5HL__cache_prefix_get_load_size() + * Function: H5HL__cache_prefix_get_initial_load_size() * - * Purpose: Return the size of the buffer the metadata cache should + * Purpose: Return the initial size of the buffer the metadata cache should * load from file and pass to the deserialize routine. * - * The version 2 metadata cache callbacks included a test to - * ensure that the read did not pass the end of file, but this - * functionality has been moved to H5C_load_entry(). Thus - * all this function does is set *image_len equal to - * H5HL_SPEC_READ_SIZE, leaving it to the metadata cache to - * reduce the size of the read if appropriate. - * * Return: Success: SUCCEED * Failure: FAIL * @@ -275,16 +274,91 @@ H5HL__fl_serialize(const H5HL_t *heap) *------------------------------------------------------------------------- */ static herr_t -H5HL__cache_prefix_get_load_size(const void H5_ATTR_UNUSED *_udata, size_t *image_len) +H5HL__cache_prefix_get_initial_load_size(void H5_ATTR_UNUSED *_udata, size_t *image_len) { FUNC_ENTER_STATIC_NOERR + /* Sanity check */ HDassert(image_len); + /* Set the image length size */ *image_len = H5HL_SPEC_READ_SIZE; FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HL__cache_prefix_get_load_size() */ +} /* end H5HL__cache_prefix_get_initial_load_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5HL__cache_prefix_get_final_load_size() + * + * Purpose: Return the final size of the buffer the metadata cache should + * load from file and pass to the deserialize routine. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * November 18, 2016 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL__cache_prefix_get_final_load_size(const void *_image, size_t image_len, + void *_udata, size_t *actual_len) +{ + const uint8_t *image = (const uint8_t *)_image; /* Pointer into raw data buffer */ + H5HL_cache_prfx_ud_t *udata = (H5HL_cache_prfx_ud_t *)_udata; /* User data for callback */ + H5HL_t heap; /* Local heap */ + htri_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity checks */ + HDassert(image); + HDassert(udata); + HDassert(actual_len); + HDassert(*actual_len == image_len); + + /* Check magic number */ + if(HDmemcmp(image, H5HL_MAGIC, (size_t)H5_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "bad local heap signature") + image += H5_SIZEOF_MAGIC; + + /* Version */ + if(H5HL_VERSION != *image++) + HGOTO_ERROR(H5E_HEAP, H5E_VERSION, FAIL, "wrong version number in local heap") + + /* Reserved */ + image += 3; + + /* Store the prefix's address & length */ + heap.prfx_addr = udata->prfx_addr; /* NEED */ + heap.prfx_size = udata->sizeof_prfx; /* NEED */ + + /* Heap data size */ + H5F_DECODE_LENGTH_LEN(image, heap.dblk_size, udata->sizeof_size); /* NEED */ + + /* Free list head */ + H5F_DECODE_LENGTH_LEN(image, heap.free_block, udata->sizeof_size); + if(heap.free_block != H5HL_FREE_NULL && heap.free_block >= heap.dblk_size) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "bad heap free list"); + + /* Heap data address */ + H5F_addr_decode_len(udata->sizeof_addr, &image, &(heap.dblk_addr)); /* NEED */ + + /* Set the final size for the cache image */ + *actual_len = heap.prfx_size; + + /* Check if heap block exists */ + if(heap.dblk_size) + /* Check if heap data block is contiguous with header */ + if(H5F_addr_eq((heap.prfx_addr + heap.prfx_size), heap.dblk_addr)) + /* Note that the heap should be a single object in the cache */ + *actual_len += heap.dblk_size; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL__cache_prefix_get_final_load_size() */ /*------------------------------------------------------------------------- @@ -353,7 +427,6 @@ H5HL__cache_prefix_deserialize(const void *_image, size_t len, void *_udata, /* Free list head */ H5F_DECODE_LENGTH_LEN(image, heap->free_block, udata->sizeof_size); - if((heap->free_block != H5HL_FREE_NULL) && (heap->free_block >= heap->dblk_size)) HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, NULL, "bad heap free list") @@ -367,53 +440,29 @@ H5HL__cache_prefix_deserialize(const void *_image, size_t len, void *_udata, /* Note that the heap should be a single object in the cache */ heap->single_cache_obj = TRUE; - /* Check if the current buffer from the speculative read - * already has the heap data - */ - if(len >= (heap->prfx_size + heap->dblk_size)) { - /* Allocate space for the heap data image */ - if(NULL == (heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, heap->dblk_size))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed") - - /* Set image to the start of the data block. This is necessary - * because there may be a gap between the used portion of the - * prefix and the data block due to alignment constraints. */ - image = ((const uint8_t *)_image) + heap->prfx_size; - - /* Copy the heap data from the speculative read buffer */ - HDmemcpy(heap->dblk_image, image, heap->dblk_size); - - /* Build free list */ - if(H5HL__fl_deserialize(heap) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list") - } /* end if */ - else { - /* the supplied buffer is too small -- We have already made note - * of the correct size, so simply return success. H5C_load_entry() - * will notice the size discrepency, and re-try the load. - */ - - /* Make certain that this is the first try ... */ - HDassert(!udata->made_attempt); - - /* ... and mark the udata so that we know that we have used up - * our first try. - */ - udata->made_attempt = TRUE; - } /* end else */ + /* Allocate space for the heap data image */ + if(NULL == (heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, heap->dblk_size))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed") + + /* Set image to the start of the data block. This is necessary + * because there may be a gap between the used portion of the + * prefix and the data block due to alignment constraints. */ + image = ((const uint8_t *)_image) + heap->prfx_size; + + /* Copy the heap data from the speculative read buffer */ + HDmemcpy(heap->dblk_image, image, heap->dblk_size); + + /* Build free list */ + if(H5HL__fl_deserialize(heap) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list") } /* end if */ - else { + else /* Note that the heap should _NOT_ be a single * object in the cache */ heap->single_cache_obj = FALSE; - - } /* end else */ } /* end if */ - /* Set flag to indicate prefix from loaded from file */ - udata->loaded = TRUE; - /* Set return value */ ret_value = prfx; @@ -568,10 +617,6 @@ H5HL__cache_prefix_serialize(const H5F_t *f, void *_image, size_t len, FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HL__cache_prefix_serialize() */ -/******************************************/ -/* no H5HL_cache_prefix_notify() function */ -/******************************************/ - /*------------------------------------------------------------------------- * Function: H5HL__cache_prefix_free_icr @@ -619,7 +664,7 @@ done: /*------------------------------------------------------------------------- - * Function: H5HL__cache_datablock_get_load_size() + * Function: H5HL__cache_datablock_get_initial_load_size() * * Purpose: Tell the metadata cache how large a buffer to read from * file when loading a datablock. In this case, we simply lookup @@ -634,22 +679,22 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HL__cache_datablock_get_load_size(const void *_udata, size_t *image_len) +H5HL__cache_datablock_get_initial_load_size(void *_udata, size_t *image_len) { - const H5HL_cache_dblk_ud_t *udata = (const H5HL_cache_dblk_ud_t *)_udata; /* User data for callback */ + H5HL_t *heap = (H5HL_t *)_udata; /* User data for callback */ FUNC_ENTER_STATIC_NOERR /* Check arguments */ - HDassert(udata); - HDassert(udata->heap); - HDassert(udata->heap->dblk_size > 0); + HDassert(heap); + HDassert(heap->dblk_size > 0); HDassert(image_len); - *image_len = udata->heap->dblk_size; + /* Set the image length size */ + *image_len = heap->dblk_size; FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HL__cache_datablock_get_load_size() */ +} /* end H5HL__cache_datablock_get_initial_load_size() */ /*------------------------------------------------------------------------- @@ -671,8 +716,8 @@ static void * H5HL__cache_datablock_deserialize(const void *image, size_t len, void *_udata, hbool_t H5_ATTR_UNUSED *dirty) { - H5HL_dblk_t *dblk = NULL; /* Local heap data block deserialized */ - H5HL_cache_dblk_ud_t *udata = (H5HL_cache_dblk_ud_t *)_udata; /* User data for callback */ + H5HL_dblk_t *dblk = NULL; /* Local heap data block deserialized */ + H5HL_t *heap = (H5HL_t *)_udata; /* User data for callback */ void *ret_value = NULL; /* Return value */ FUNC_ENTER_STATIC @@ -680,34 +725,30 @@ H5HL__cache_datablock_deserialize(const void *image, size_t len, void *_udata, /* Check arguments */ HDassert(image); HDassert(len > 0); - HDassert(udata); - HDassert(udata->heap); - HDassert(udata->heap->dblk_size == len); - HDassert(!udata->heap->single_cache_obj); - HDassert(NULL == udata->heap->dblk); + HDassert(heap); + HDassert(heap->dblk_size == len); + HDassert(!heap->single_cache_obj); + HDassert(NULL == heap->dblk); HDassert(dirty); /* Allocate space in memory for the heap data block */ - if(NULL == (dblk = H5HL__dblk_new(udata->heap))) + if(NULL == (dblk = H5HL__dblk_new(heap))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "memory allocation failed"); /* Check for heap still retaining image */ - if(NULL == udata->heap->dblk_image) { + if(NULL == heap->dblk_image) { /* Allocate space for the heap data image */ - if(NULL == (udata->heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, udata->heap->dblk_size))) + if(NULL == (heap->dblk_image = H5FL_BLK_MALLOC(lheap_chunk, heap->dblk_size))) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate data block image buffer"); /* copy the datablock from the read buffer */ - HDmemcpy(udata->heap->dblk_image, image, len); + HDmemcpy(heap->dblk_image, image, len); /* Build free list */ - if(FAIL == H5HL__fl_deserialize(udata->heap)) + if(FAIL == H5HL__fl_deserialize(heap)) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize free list"); } /* end if */ - /* Set flag to indicate data block from loaded from file */ - udata->loaded = TRUE; - /* Set return value */ ret_value = dblk; @@ -801,9 +842,73 @@ H5HL__cache_datablock_serialize(const H5F_t *f, void *image, size_t len, FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5HL__cache_datablock_serialize() */ -/*********************************************/ -/* no H5HL_cache_datablock_notify() function */ -/*********************************************/ + +/*------------------------------------------------------------------------- + * Function: H5HL__cache_datablock_notify + * + * Purpose: This function is used to create and destroy pinned + * relationships between datablocks and their prefix parent. + * + * Return: Success: SUCCEED + * Failure: FAIL + * + * Programmer: Quincey Koziol + * November 19, 2016 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HL__cache_datablock_notify(H5C_notify_action_t action, void *_thing) +{ + H5HL_dblk_t *dblk = (H5HL_dblk_t *)_thing; /* Pointer to the local heap data block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC + + /* Sanity check */ + HDassert(dblk); + + switch(action) { + case H5AC_NOTIFY_ACTION_AFTER_INSERT: + /* do nothing */ + break; + + case H5AC_NOTIFY_ACTION_AFTER_LOAD: + /* Sanity checks */ + HDassert(dblk->heap); + HDassert(dblk->heap->prfx); + + /* Pin the heap's prefix */ + if(FAIL == H5AC_pin_protected_entry(dblk->heap->prfx)) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPIN, FAIL, "unable to pin local heap prefix") + break; + + case H5AC_NOTIFY_ACTION_AFTER_FLUSH: + case H5AC_NOTIFY_ACTION_ENTRY_DIRTIED: + case H5AC_NOTIFY_ACTION_ENTRY_CLEANED: + case H5AC_NOTIFY_ACTION_CHILD_DIRTIED: + case H5AC_NOTIFY_ACTION_CHILD_CLEANED: + /* do nothing */ + break; + + case H5AC_NOTIFY_ACTION_BEFORE_EVICT: + /* Sanity checks */ + HDassert(dblk->heap); + HDassert(dblk->heap->prfx); + + /* Unpin the local heap prefix */ + if(FAIL == H5AC_unpin_entry(dblk->heap->prfx)) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin local heap prefix") + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "unknown action from metadata cache") + break; + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HL__cache_datablock_notify() */ /*------------------------------------------------------------------------- @@ -843,3 +948,4 @@ H5HL__cache_datablock_free_icr(void *_thing) done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HL__cache_datablock_free_icr() */ + |