summaryrefslogtreecommitdiffstats
path: root/src/H5HLcache.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2016-11-20 12:24:57 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2016-11-20 12:24:57 (GMT)
commit3b0c2b24da5689990c4bc0fcd3afecdf063086c8 (patch)
tree242d3501c98bef92e6befd920e8a9efdf2f1715b /src/H5HLcache.c
parentf6ad126673553838df0dec514c5d2c1b4b70df1a (diff)
downloadhdf5-3b0c2b24da5689990c4bc0fcd3afecdf063086c8.zip
hdf5-3b0c2b24da5689990c4bc0fcd3afecdf063086c8.tar.gz
hdf5-3b0c2b24da5689990c4bc0fcd3afecdf063086c8.tar.bz2
Bring over support for retrying metadata cache entry loads, along with all the
supporting metadata cache callback changes, etc.
Diffstat (limited to 'src/H5HLcache.c')
-rw-r--r--src/H5HLcache.c282
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() */
+