summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5Dbtree.c7
-rw-r--r--src/H5Dbtree2.c1
-rw-r--r--src/H5Dchunk.c195
-rw-r--r--src/H5Dfarray.c1
-rw-r--r--src/H5Dpkg.h3
-rw-r--r--src/H5Dproxy.c1
6 files changed, 159 insertions, 49 deletions
diff --git a/src/H5Dbtree.c b/src/H5Dbtree.c
index f511d90..88fe4a5 100644
--- a/src/H5Dbtree.c
+++ b/src/H5Dbtree.c
@@ -151,7 +151,7 @@ static herr_t H5D_btree_idx_size(const H5D_chk_idx_info_t *idx_info,
hsize_t *size);
static herr_t H5D_btree_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr);
static herr_t H5D_btree_idx_support(const H5D_chk_idx_info_t *idx_info,
- H5D_chunk_ud_t *udata, H5AC_info_t *child_entry);
+ H5D_chunk_common_ud_t *udata, H5AC_info_t *child_entry);
static herr_t H5D_btree_idx_unsupport(const H5D_chk_idx_info_t *idx_info,
H5D_chunk_common_ud_t *udata, H5AC_info_t *child_entry);
static herr_t H5D_btree_idx_dump(const H5O_storage_chunk_t *storage,
@@ -993,6 +993,7 @@ H5D_btree_idx_create(const H5D_chk_idx_info_t *idx_info)
/* Initialize "user" data for B-tree callbacks, etc. */
udata.layout = idx_info->layout;
udata.storage = idx_info->storage;
+ udata.rdcc = NULL;
/* Check for SWMR writes to the file */
if(H5F_INTENT(idx_info->f) & H5F_ACC_SWMR_WRITE) {
@@ -1614,7 +1615,7 @@ H5D_btree_idx_reset(H5O_storage_chunk_t *storage, hbool_t reset_addr)
*/
static htri_t
H5D_btree_idx_support(const H5D_chk_idx_info_t *idx_info,
- H5D_chunk_ud_t *udata, H5AC_info_t *child_entry)
+ H5D_chunk_common_ud_t *udata, H5AC_info_t *child_entry)
{
H5O_loc_t oloc; /* Temporary object header location for dataset */
H5O_t *oh = NULL; /* Dataset's object header */
@@ -1698,7 +1699,7 @@ H5D_btree_idx_unsupport(const H5D_chk_idx_info_t *idx_info,
if(NULL == (oh = H5O_pin(&oloc, idx_info->dxpl_id)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header")
- /* Add the flush dependency on the chunk */
+ /* Remove the flush dependency on the chunk */
if((ret_value = H5B_unsupport(idx_info->f, idx_info->dxpl_id, H5B_BTREE, idx_info->storage->idx_addr,
udata, oh, child_entry)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency on b-tree array metadata")
diff --git a/src/H5Dbtree2.c b/src/H5Dbtree2.c
index a28a33b..4aec4be 100644
--- a/src/H5Dbtree2.c
+++ b/src/H5Dbtree2.c
@@ -1332,6 +1332,7 @@ H5D_bt2_idx_iterate(const H5D_chk_idx_info_t *idx_info,
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = idx_info->layout;
udata.common.storage = idx_info->storage;
+ udata.common.rdcc = NULL;
udata.filtered = idx_info->pline->nused > 0;
HDmemset(&udata.chunk_rec, 0, sizeof(udata.chunk_rec));
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 48a7c20..304e235 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -219,6 +219,9 @@ static herr_t H5D_chunk_cache_evict(const H5D_t *dset, hid_t dxpl_id,
static htri_t H5D_chunk_is_partial_edge_chunk(const hsize_t offset[],
const H5D_t *dset, unsigned dset_ndims, const hsize_t *dset_dims,
const uint32_t *chunk_dims);
+static herr_t H5D_chunk_find_flush_dep(const H5D_rdcc_t *rdcc,
+ const H5O_layout_chunk_t *layout, const hsize_t offset[],
+ H5D_rdcc_ent_t **ent);
/*********************/
@@ -2644,8 +2647,23 @@ H5D_chunk_cache_evict(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t *
rdcc->tail = ent->prev;
ent->prev = ent->next = NULL;
+ /* Unlink from temporary list */
+ if(ent->tmp_prev) {
+ HDassert(rdcc->tmp_head->tmp_next);
+ ent->tmp_prev->tmp_next = ent->tmp_next;
+ if(ent->tmp_next) {
+ ent->tmp_next->tmp_prev = ent->tmp_prev;
+ ent->tmp_next = NULL;
+ } /* end if */
+ ent->tmp_prev = NULL;
+ } /* end if */
+ else
+ /* Only clear hash table slot if the chunk was not on the temporary list
+ */
+ rdcc->slot[ent->idx] = NULL;
+
/* Remove from cache */
- rdcc->slot[ent->idx] = NULL;
+ HDassert(rdcc->slot[ent->idx] != ent);
ent->idx = UINT_MAX;
rdcc->nbytes_used -= dset->shared->layout.u.chunk.size;
--rdcc->nused;
@@ -2822,6 +2840,7 @@ H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
HDassert(dset);
HDassert(TRUE == H5P_isa_class(io_info->dxpl_id, H5P_DATASET_XFER));
HDassert(!(udata->new_unfilt_chunk && prev_unfilt_chunk));
+ HDassert(!rdcc->tmp_head);
/* Get the chunk's size */
HDassert(layout->u.chunk.size > 0);
@@ -3129,6 +3148,8 @@ H5D_chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
rdcc->head = rdcc->tail = ent;
ent->prev = NULL;
} /* end else */
+ ent->tmp_next = NULL;
+ ent->tmp_prev = NULL;
/* Check for SWMR writes to the file */
if(io_info->dset->shared->layout.storage.u.chunk.ops->can_swim
@@ -3744,7 +3765,7 @@ H5D_chunk_allocate(H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
udata.common.layout = &layout->u.chunk;
udata.common.storage = &layout->storage.u.chunk;
udata.common.offset = chunk_offset;
- udata.common.rdcc = NULL;
+ udata.common.rdcc = &dset->shared->cache.chunk;
H5_ASSIGN_OVERFLOW(udata.nbytes, chunk_size, size_t, uint32_t);
udata.filter_mask = filter_mask;
udata.addr = HADDR_UNDEF;
@@ -4414,6 +4435,7 @@ H5D_chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
/* Initialize user data for removal */
idx_udata.layout = &layout->u.chunk;
idx_udata.storage = &layout->storage.u.chunk;
+ idx_udata.rdcc = rdcc;
/* Determine if partial edge chunk filters are disabled */
disable_edge_filters = (layout->u.chunk.flags
@@ -4861,6 +4883,8 @@ H5D_chunk_update_cache(H5D_t *dset, hid_t dxpl_id)
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
H5D_rdcc_ent_t *ent, *next; /*cache entry */
H5D_rdcc_ent_t *old_ent; /* Old cache entry */
+ H5D_rdcc_ent_t tmp_head; /* Sentinel entry for temporary entry list */
+ H5D_rdcc_ent_t *tmp_tail; /* Tail pointer for temporary entry list */
H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
unsigned rank; /*current # of dimensions */
@@ -4884,6 +4908,11 @@ H5D_chunk_update_cache(H5D_t *dset, hid_t dxpl_id)
if(H5D_get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+ /* Add temporary entry list to rdcc */
+ (void)HDmemset(&tmp_head, 0, sizeof(tmp_head));
+ rdcc->tmp_head = &tmp_head;
+ tmp_tail = &tmp_head;
+
/* Recompute the index for each cached chunk that is in a dataset */
for(ent = rdcc->head; ent; ent = next) {
hsize_t idx; /* Chunk index */
@@ -4906,24 +4935,58 @@ H5D_chunk_update_cache(H5D_t *dset, hid_t dxpl_id)
if(old_ent != NULL) {
HDassert(old_ent->locked == 0);
- /* Check if we are removing the entry we would walk to next */
- if(old_ent == next)
- next = old_ent->next;
-
- /* Remove the old entry from the cache */
- if(H5D_chunk_cache_evict(dset, dxpl_id, dxpl_cache, old_ent, TRUE) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
+ /* Insert the old entry into the temporary list, but do not
+ * evict (yet). Make sure we do not make any calls to the index
+ * until all chunks have updated indices! */
+ HDassert(!old_ent->tmp_next);
+ HDassert(!old_ent->tmp_prev);
+ tmp_tail->tmp_next = old_ent;
+ old_ent->tmp_prev = tmp_tail;
+ tmp_tail = old_ent;
} /* end if */
/* Insert this chunk into correct location in hash table */
rdcc->slot[ent->idx] = ent;
- /* Null out previous location */
- rdcc->slot[old_idx] = NULL;
+ /* If this chunk was previously on the temporary list and therefore
+ * not in the hash table, remove it from the temporary list.
+ * Otherwise clear the old hash table slot. */
+ if(ent->tmp_prev) {
+ HDassert(tmp_head.tmp_next);
+ HDassert(tmp_tail != &tmp_head);
+ ent->tmp_prev->tmp_next = ent->tmp_next;
+ if(ent->tmp_next) {
+ ent->tmp_next->tmp_prev = ent->tmp_prev;
+ ent->tmp_next = NULL;
+ } /* end if */
+ else {
+ HDassert(tmp_tail == ent);
+ tmp_tail = ent->tmp_prev;
+ } /* end else */
+ ent->tmp_prev = NULL;
+ } /* end if */
+ else
+ rdcc->slot[old_idx] = NULL;
} /* end if */
} /* end for */
+ /* tmp_tail is no longer needed, and will be invalidated by
+ * H5D_chunk_cache_evict anyways. */
+ tmp_tail = NULL;
+
+ /* Evict chunks that are still on the temporary list */
+ while(tmp_head.tmp_next) {
+ ent = tmp_head.tmp_next;
+
+ /* Remove the old entry from the cache */
+ if(H5D_chunk_cache_evict(dset, dxpl_id, dxpl_cache, ent, TRUE) < 0)
+ HDONE_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
+ } /* end while */
+
done:
+ /* Remove temporary list from rdcc */
+ rdcc->tmp_head = NULL;
+
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D_chunk_update_cache() */
@@ -5875,33 +5938,33 @@ done:
/*-------------------------------------------------------------------------
* Function: H5D_chunk_create_flush_dep
*
- * Purpose: Creates a flush dependency between the specified chunk
- * (child) and parent.
+ * Purpose: Check cache (including temporary list of entries to be
+ * evicted) for the specified chunk.
*
* Return: Non-negative on success/Negative on failure
*
* Programmer: Neil Fortner
- * Tuesday, September 21, 2010
+ * Monday, March 12, 2012
*
*-------------------------------------------------------------------------
*/
-herr_t
-H5D_chunk_create_flush_dep(const H5D_rdcc_t *rdcc,
- const H5O_layout_chunk_t *layout, const hsize_t offset[], void *parent)
+static herr_t
+H5D_chunk_find_flush_dep(const H5D_rdcc_t *rdcc,
+ const H5O_layout_chunk_t *layout, const hsize_t offset[],
+ H5D_rdcc_ent_t **ent)
{
hsize_t chunk_idx; /* Chunk index */
- H5D_rdcc_ent_t *ent = NULL; /* Cache entry */
hbool_t found = FALSE; /* In cache? */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_create_flush_dep)
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_find_flush_dep)
/* Check args */
HDassert(rdcc);
HDassert(layout);
HDassert(offset);
- HDassert(parent);
+ HDassert(ent);
/* Calculate the index of this chunk */
if(H5V_chunk_index(layout->ndims - 1, offset, layout->dim,
@@ -5910,18 +5973,74 @@ H5D_chunk_create_flush_dep(const H5D_rdcc_t *rdcc,
/* Check for chunk in cache */
if(rdcc->nslots > 0) {
- ent = rdcc->slot[H5F_addr_hash(chunk_idx, rdcc->nslots)];
+ *ent = rdcc->slot[H5F_addr_hash(chunk_idx, rdcc->nslots)];
- if(ent)
- for(u = 0, found = TRUE; u < layout->ndims - 1; u++)
- if(offset[u] != ent->offset[u]) {
- found = FALSE;
+ if(*ent)
+ for(u = 0; u < layout->ndims - 1; u++)
+ if(offset[u] != (*ent)->offset[u]) {
+ *ent = NULL;
break;
} /* end if */
+
+ /* Search temporary list if present */
+ if(!(*ent) && rdcc->tmp_head) {
+ *ent = rdcc->tmp_head->tmp_next;
+
+ while(*ent) {
+ for(u = 0, found = TRUE; u < layout->ndims - 1; u++)
+ if(offset[u] != (*ent)->offset[u]) {
+ found = FALSE;
+ break;
+ } /* end if */
+ if(found)
+ break;
+ else
+ *ent = (*ent)->tmp_next;
+ } /* end while */
+
+ HDassert(!(*ent) == !found);
+ } /* end if */
} /* end if */
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5D_chunk_find_flush_dep() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5D_chunk_create_flush_dep
+ *
+ * Purpose: Creates a flush dependency between the specified chunk
+ * (child) and parent.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Neil Fortner
+ * Tuesday, September 21, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5D_chunk_create_flush_dep(const H5D_rdcc_t *rdcc,
+ const H5O_layout_chunk_t *layout, const hsize_t offset[], void *parent)
+{
+ H5D_rdcc_ent_t *ent = NULL; /* Cache entry */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_create_flush_dep)
+
+ /* Check args */
+ HDassert(rdcc);
+ HDassert(layout);
+ HDassert(offset);
+ HDassert(parent);
+
+ /* Look for this chunk in cache */
+ if(H5D_chunk_find_flush_dep(rdcc, layout, offset, &ent) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk entry")
+
/* Create the dependency on the chunk proxy */
- if(found)
+ if(ent)
if(H5D_chunk_proxy_create_flush_dep(ent, parent) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to create flush dependency")
@@ -5949,10 +6068,7 @@ H5D_chunk_update_flush_dep(const H5D_rdcc_t *rdcc,
const H5O_layout_chunk_t *layout, const hsize_t offset[], void *old_parent,
void *new_parent)
{
- hsize_t chunk_idx; /* Chunk index */
H5D_rdcc_ent_t *ent = NULL; /* Cache entry */
- hbool_t found = FALSE; /* In cache? */
- unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5D_chunk_update_flush_dep)
@@ -5964,25 +6080,12 @@ H5D_chunk_update_flush_dep(const H5D_rdcc_t *rdcc,
HDassert(old_parent);
HDassert(new_parent);
- /* Calculate the index of this chunk */
- if(H5V_chunk_index(layout->ndims - 1, offset, layout->dim,
- layout->down_chunks, &chunk_idx) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
-
- /* Check for chunk in cache */
- if(rdcc->nslots > 0) {
- ent = rdcc->slot[H5F_addr_hash(chunk_idx, rdcc->nslots)];
-
- if(ent)
- for(u = 0, found = TRUE; u < layout->ndims - 1; u++)
- if(offset[u] != ent->offset[u]) {
- found = FALSE;
- break;
- } /* end if */
- } /* end if */
+ /* Look for this chunk in cache */
+ if(H5D_chunk_find_flush_dep(rdcc, layout, offset, &ent) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk entry")
/* Update the dependencies on the chunk proxy */
- if(found)
+ if(ent)
if(H5D_chunk_proxy_update_flush_dep(ent, old_parent, new_parent) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTDEPEND, FAIL, "unable to update flush dependency")
diff --git a/src/H5Dfarray.c b/src/H5Dfarray.c
index 738a407..196fc43 100644
--- a/src/H5Dfarray.c
+++ b/src/H5Dfarray.c
@@ -1220,6 +1220,7 @@ H5D_farray_idx_iterate(const H5D_chk_idx_info_t *idx_info,
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = idx_info->layout;
udata.common.storage = idx_info->storage;
+ udata.common.rdcc = NULL;
HDmemset(&udata.chunk_rec, 0, sizeof(udata.chunk_rec));
HDmemset(&udata.chunk_offset, 0, sizeof(udata.chunk_offset));
udata.filtered = (idx_info->pline->nused > 0);
diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h
index 50a10ef..7fe7e3e 100644
--- a/src/H5Dpkg.h
+++ b/src/H5Dpkg.h
@@ -416,6 +416,7 @@ typedef struct H5D_rdcc_t {
double w0; /* Chunk preemption policy */
struct H5D_rdcc_ent_t *head; /* Head of doubly linked list */
struct H5D_rdcc_ent_t *tail; /* Tail of doubly linked list */
+ struct H5D_rdcc_ent_t *tmp_head; /* Head of temporary doubly linked list. Chunks on this list are not in the hash table (slot). The head entry is a sentinel (does not refer to an actual chunk). */
size_t nbytes_used; /* Current cached raw data in bytes */
int nused; /* Number of chunk slots in use */
H5D_chunk_cached_t last; /* Cached copy of last chunk information */
@@ -544,6 +545,8 @@ typedef struct H5D_rdcc_ent_t {
unsigned idx; /*index in hash table */
struct H5D_rdcc_ent_t *next;/*next item in doubly-linked list */
struct H5D_rdcc_ent_t *prev;/*previous item in doubly-linked list */
+ struct H5D_rdcc_ent_t *tmp_next;/*next item in temporary doubly-linked list */
+ struct H5D_rdcc_ent_t *tmp_prev;/*previous item in temporary doubly-linked list */
} H5D_rdcc_ent_t;
typedef H5D_rdcc_ent_t *H5D_rdcc_ent_ptr_t; /* For free lists */
diff --git a/src/H5Dproxy.c b/src/H5Dproxy.c
index 7be2121..9124dac 100644
--- a/src/H5Dproxy.c
+++ b/src/H5Dproxy.c
@@ -425,6 +425,7 @@ HDfprintf(stderr, "%s: ent->proxy_addr = %a\n", FUNC, ent->proxy_addr);
udata.layout = &(dset->shared->layout.u.chunk);
udata.storage = &(dset->shared->layout.storage.u.chunk);
udata.offset = ent->offset;
+ udata.rdcc = &(dset->shared->cache.chunk);
/* Remove flush dependency between the proxy (as the child) and the
* metadata object in the index (as the parent).