summaryrefslogtreecommitdiffstats
path: root/src/H5Dchunk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Dchunk.c')
-rw-r--r--src/H5Dchunk.c1014
1 files changed, 564 insertions, 450 deletions
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index 9f2a020..b0d935c 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -17,7 +17,7 @@
* Thursday, April 24, 2008
*
* Purpose: Abstract indexed (chunked) I/O functions. The logical
- * multi-dimensional data space is regularly partitioned into
+ * multi-dimensional dataspace is regularly partitioned into
* same-sized "chunks", the first of which is aligned with the
* logical origin. The chunks are indexed by different methods,
* that map a chunk index to disk address. Each chunk can be
@@ -59,6 +59,7 @@
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
+#include "H5MFprivate.h" /* File memory management */
#include "H5VMprivate.h" /* Vector and array functions */
@@ -201,7 +202,6 @@ static herr_t H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *ty
H5D_chunk_map_t *fm);
static herr_t H5D__chunk_flush(H5D_t *dset, hid_t dxpl_id);
static herr_t H5D__chunk_io_term(const H5D_chunk_map_t *fm);
-static herr_t H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
/* "Nonexistent" layout operation callback */
static ssize_t
@@ -212,10 +212,11 @@ H5D__nonexistent_readvv(const H5D_io_info_t *io_info,
/* Helper routines */
static herr_t H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims,
const hsize_t *curr_dims);
-static void *H5D__chunk_alloc(size_t size, const H5O_pline_t *pline);
-static void *H5D__chunk_xfree(void *chk, const H5O_pline_t *pline);
-static void *H5D__chunk_realloc(void *chk, size_t size,
+static void *H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline);
+static void *H5D__chunk_mem_xfree(void *chk, const H5O_pline_t *pline);
+static void *H5D__chunk_mem_realloc(void *chk, size_t size,
const H5O_pline_t *pline);
+static herr_t H5D__chunk_cinfo_cache_reset(H5D_chunk_cached_t *last);
static herr_t H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last,
const H5D_chunk_ud_t *udata);
static hbool_t H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last,
@@ -237,6 +238,8 @@ static herr_t H5D__chunk_cache_evict(const H5D_t *dset, hid_t dxpl_id,
static herr_t H5D__chunk_cache_prune(const H5D_t *dset, hid_t dxpl_id,
const H5D_dxpl_cache_t *dxpl_cache, size_t size);
static herr_t H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata);
+static herr_t H5D__chunk_file_alloc(const H5D_chk_idx_info_t *idx_info,
+ const H5F_block_t *old_chunk, H5F_block_t *new_chunk, hbool_t *need_insert);
#ifdef H5_HAVE_PARALLEL
static herr_t H5D__chunk_collective_fill(const H5D_t *dset, hid_t dxpl_id,
H5D_chunk_coll_info_t *chunk_info, size_t chunk_size, const void *fill_buf);
@@ -319,78 +322,88 @@ H5D__chunk_direct_write(const H5D_t *dset, hid_t dxpl_id, uint32_t filters, hsiz
{
const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */
H5D_chunk_ud_t udata; /* User data for querying chunk info */
- hsize_t chunk_idx;
- H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
- H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
- const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
- int space_ndims; /* Dataset's space rank */
- hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Dataset's dataspace dimensions */
+ hsize_t chunk_idx; /* Global index of chunk */
+ H5F_block_t old_chunk; /* Offset/length of old chunk */
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
+ hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC_TAG(dxpl_id, dset->oloc.addr, FAIL)
- /* Allocate data space and initialize it if it hasn't been. */
- if(!(*dset->shared->layout.ops->is_space_alloc)(&dset->shared->layout.storage))
+ /* Allocate dataspace and initialize it if it hasn't been. */
+ if(!(*layout->ops->is_space_alloc)(&layout->storage))
/* Allocate storage */
if(H5D__alloc_storage(dset, dxpl_id, H5D_ALLOC_WRITE, FALSE, NULL) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to initialize storage")
- /* Retrieve the dataset dimensions */
- if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim, NULL)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get simple dataspace info")
-
/* Calculate the index of this chunk */
- if(H5VM_chunk_index((unsigned)space_ndims, offset,
- layout->u.chunk.dim, layout->u.chunk.down_chunks, &chunk_idx) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't get chunk index")
+ chunk_idx = H5VM_chunk_index(dset->shared->ndims, offset, layout->u.chunk.dim, layout->u.chunk.down_chunks);
- /* Find out the file address of the chunk */
+ /* Find out the file address of the chunk (if any) */
if(H5D__chunk_lookup(dset, dxpl_id, offset, chunk_idx, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
- udata.filter_mask = filters;
+ /* Sanity check */
+ HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) ||
+ (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
+
+ /* Set the file block information for the old chunk */
+ /* (Which is only defined when overwriting an existing chunk) */
+ old_chunk.offset = udata.chunk_block.offset;
+ old_chunk.length = udata.chunk_block.length;
- /* Check if the chunk needs to be 'inserted' (could exist already and
- * the 'insert' operation could resize it)
+ /* Check if the chunk needs to be inserted (it also could exist already
+ * and the chunk allocate operation could resize it)
*/
- {
- H5D_chk_idx_info_t idx_info; /* Chunked index info */
-
- /* Compose chunked index info struct */
- idx_info.f = dset->oloc.file;
- idx_info.dxpl_id = dxpl_id;
- idx_info.pline = &(dset->shared->dcpl_cache.pline);
- idx_info.layout = &(dset->shared->layout.u.chunk);
- idx_info.storage = &(dset->shared->layout.storage.u.chunk);
- /* Set up the size of chunk for user data */
- udata.nbytes = data_size;
+ /* Compose chunked index info struct */
+ idx_info.f = dset->oloc.file;
+ idx_info.dxpl_id = dxpl_id;
+ idx_info.pline = &(dset->shared->dcpl_cache.pline);
+ idx_info.layout = &(dset->shared->layout.u.chunk);
+ idx_info.storage = &(dset->shared->layout.storage.u.chunk);
- /* Create the chunk it if it doesn't exist, or reallocate the chunk
- * if its size changed.
- */
- if((dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk")
+ /* Set up the size of chunk for user data */
+ udata.chunk_block.length = data_size;
- /* Make sure the address of the chunk is returned. */
- if(!H5F_addr_defined(udata.addr))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined")
- } /* end if */
+ /* Create the chunk it if it doesn't exist, or reallocate the chunk
+ * if its size changed.
+ */
+ if(H5D__chunk_file_alloc(&idx_info, &old_chunk, &udata.chunk_block, &need_insert) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "unable to allocate chunk")
- /* Fill the DXPL cache values for later use */
- if(H5D__get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+ /* Make sure the address of the chunk is returned. */
+ if(!H5F_addr_defined(udata.chunk_block.offset))
+ HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "chunk address isn't defined")
- /* Evict the entry from the cache if present, but do not flush
+ /* Evict the (old) entry from the cache if present, but do not flush
* it to disk */
- if(UINT_MAX != udata.idx_hint)
+ if(UINT_MAX != udata.idx_hint) {
+ H5D_dxpl_cache_t _dxpl_cache; /* Data transfer property cache buffer */
+ H5D_dxpl_cache_t *dxpl_cache = &_dxpl_cache; /* Data transfer property cache */
+ const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
+
+ /* Fill the DXPL cache values for later use */
+ if(H5D__get_dxpl_cache(dxpl_id, &dxpl_cache) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
+
if(H5D__chunk_cache_evict(dset, dxpl_id, dxpl_cache, rdcc->slot[udata.idx_hint], FALSE) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "unable to evict chunk")
+ } /* end if */
/* Write the data to the file */
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, data_size, dxpl_id, buf) < 0)
+ if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, data_size, dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
+ /* Insert the chunk record into the index */
+ if(need_insert && layout->storage.u.chunk.ops->insert) {
+ /* Set the chunk's filter mask to the new settings */
+ udata.filter_mask = filters;
+
+ if((layout->storage.u.chunk.ops->insert)(&idx_info, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk addr into index")
+ } /* end if */
+
done:
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
} /* end H5D__chunk_direct_write() */
@@ -454,23 +467,15 @@ done:
herr_t
H5D__chunk_set_info(const H5D_t *dset)
{
- hsize_t curr_dims[H5O_LAYOUT_NDIMS]; /* Curr. size of dataset dimensions */
- int sndims; /* Rank of dataspace */
- unsigned ndims; /* Rank of dataspace */
- herr_t ret_value = SUCCEED; /* Return value */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_PACKAGE
/* Sanity checks */
HDassert(dset);
- /* Get the dim info for dataset */
- if((sndims = H5S_get_simple_extent_dims(dset->shared->space, curr_dims, NULL)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataspace dimensions")
- H5_ASSIGN_OVERFLOW(ndims, sndims, int, unsigned);
-
/* Set the base layout information */
- if(H5D__chunk_set_info_real(&dset->shared->layout.u.chunk, ndims, curr_dims) < 0)
+ if(H5D__chunk_set_info_real(&dset->shared->layout.u.chunk, dset->shared->ndims, dset->shared->curr_dims) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set layout's chunk info")
/* Call the index's "resize" callback */
@@ -498,10 +503,7 @@ static herr_t
H5D__chunk_construct(H5F_t UNUSED *f, H5D_t *dset)
{
const H5T_t *type = dset->shared->type; /* Convenience pointer to dataset's datatype */
- hsize_t max_dims[H5O_LAYOUT_NDIMS]; /* Maximum size of data in elements */
- hsize_t dims[H5O_LAYOUT_NDIMS]; /* Dimension size of data in elements */
uint64_t chunk_size; /* Size of chunk in bytes */
- int ndims; /* Rank of dataspace */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -516,9 +518,7 @@ H5D__chunk_construct(H5F_t UNUSED *f, H5D_t *dset)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "no chunk information set?")
/* Set up layout information */
- if((ndims = H5S_GET_EXTENT_NDIMS(dset->shared->space)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "unable to get rank")
- if(dset->shared->layout.u.chunk.ndims != (unsigned)ndims)
+ if(dset->shared->layout.u.chunk.ndims != dset->shared->ndims)
HGOTO_ERROR(H5E_DATASET, H5E_BADVALUE, FAIL, "dimensionality of chunks doesn't match the dataspace")
/* Increment # of chunk dimensions, to account for datatype size as last element */
@@ -532,10 +532,6 @@ H5D__chunk_construct(H5F_t UNUSED *f, H5D_t *dset)
/* Set the last dimension of the chunk size to the size of the datatype */
dset->shared->layout.u.chunk.dim[dset->shared->layout.u.chunk.ndims - 1] = (uint32_t)H5T_GET_SIZE(type);
- /* Get local copy of dataset dimensions (for sanity checking) */
- if(H5S_get_simple_extent_dims(dset->shared->space, dims, max_dims) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to query maximum dimensions")
-
/* Sanity check dimensions */
for(u = 0; u < dset->shared->layout.u.chunk.ndims - 1; u++) {
/* Don't allow zero-sized chunk dimensions */
@@ -547,7 +543,7 @@ H5D__chunk_construct(H5F_t UNUSED *f, H5D_t *dset)
* the maximum dimension size. If any dimension size is zero, there
* will be no such restriction.
*/
- if(dims[u] && max_dims[u] != H5S_UNLIMITED && max_dims[u] < dset->shared->layout.u.chunk.dim[u])
+ if(dset->shared->curr_dims[u] && dset->shared->max_dims[u] != H5S_UNLIMITED && dset->shared->max_dims[u] < dset->shared->layout.u.chunk.dim[u])
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "chunk size must be <= maximum dimension size for fixed-sized dimensions")
} /* end for */
@@ -601,21 +597,21 @@ H5D__chunk_init(H5F_t *f, hid_t dxpl_id, const H5D_t *dset, hid_t dapl_id)
HDassert(dset);
if(NULL == (dapl = (H5P_genplist_t *)H5I_object(dapl_id)))
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for fapl ID");
+ HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't find object for fapl ID")
/* Use the properties in dapl_id if they have been set, otherwise use the properties from the file */
if(H5P_get(dapl, H5D_ACS_DATA_CACHE_NUM_SLOTS_NAME, &rdcc->nslots) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache number of slots");
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache number of slots")
if(rdcc->nslots == H5D_CHUNK_CACHE_NSLOTS_DEFAULT)
rdcc->nslots = H5F_RDCC_NSLOTS(f);
if(H5P_get(dapl, H5D_ACS_DATA_CACHE_BYTE_SIZE_NAME, &rdcc->nbytes_max) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache byte size");
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get data cache byte size")
if(rdcc->nbytes_max == H5D_CHUNK_CACHE_NBYTES_DEFAULT)
rdcc->nbytes_max = H5F_RDCC_NBYTES(f);
if(H5P_get(dapl, H5D_ACS_PREEMPT_READ_CHUNKS_NAME, &rdcc->w0) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get preempt read chunks");
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET,FAIL, "can't get preempt read chunks")
if(rdcc->w0 < 0)
rdcc->w0 = H5F_RDCC_W0(f);
@@ -724,10 +720,8 @@ H5D__chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
/* Set the number of dimensions for the memory dataspace */
H5_ASSIGN_OVERFLOW(fm->m_ndims, sm_ndims, int, unsigned);
- /* Get dim number and dimensionality for each dataspace */
+ /* Get rank for file dataspace */
fm->f_ndims = f_ndims = dataset->shared->layout.u.chunk.ndims - 1;
- if(H5S_get_simple_extent_dims(file_space, fm->f_dims, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
/* Normalize hyperslab selections by adjusting them by the offset */
/* (It might be worthwhile to normalize both the file and memory dataspaces
@@ -974,7 +968,7 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5D__chunk_alloc
+ * Function: H5D__chunk_mem_alloc
*
* Purpose: Allocate space for a chunk in memory. This routine allocates
* memory space for non-filtered chunks from a block free list
@@ -988,7 +982,7 @@ done:
*-------------------------------------------------------------------------
*/
static void *
-H5D__chunk_alloc(size_t size, const H5O_pline_t *pline)
+H5D__chunk_mem_alloc(size_t size, const H5O_pline_t *pline)
{
void *ret_value = NULL; /* Return value */
@@ -1003,11 +997,11 @@ H5D__chunk_alloc(size_t size, const H5O_pline_t *pline)
ret_value = H5FL_BLK_MALLOC(chunk, size);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D__chunk_alloc() */
+} /* H5D__chunk_mem_alloc() */
/*-------------------------------------------------------------------------
- * Function: H5D__chunk_xfree
+ * Function: H5D__chunk_mem_xfree
*
* Purpose: Free space for a chunk in memory. This routine allocates
* memory space for non-filtered chunks from a block free list
@@ -1021,7 +1015,7 @@ H5D__chunk_alloc(size_t size, const H5O_pline_t *pline)
*-------------------------------------------------------------------------
*/
static void *
-H5D__chunk_xfree(void *chk, const H5O_pline_t *pline)
+H5D__chunk_mem_xfree(void *chk, const H5O_pline_t *pline)
{
FUNC_ENTER_STATIC_NOERR
@@ -1035,11 +1029,11 @@ H5D__chunk_xfree(void *chk, const H5O_pline_t *pline)
} /* end if */
FUNC_LEAVE_NOAPI(NULL)
-} /* H5D__chunk_xfree() */
+} /* H5D__chunk_mem_xfree() */
/*-------------------------------------------------------------------------
- * Function: H5D__chunk_realloc
+ * Function: H5D__chunk_mem_realloc
*
* Purpose: Reallocate space for a chunk in memory. This routine allocates
* memory space for non-filtered chunks from a block free list
@@ -1053,7 +1047,7 @@ H5D__chunk_xfree(void *chk, const H5O_pline_t *pline)
*-------------------------------------------------------------------------
*/
static void *
-H5D__chunk_realloc(void *chk, size_t size, const H5O_pline_t *pline)
+H5D__chunk_mem_realloc(void *chk, size_t size, const H5O_pline_t *pline)
{
void *ret_value = NULL; /* Return value */
@@ -1068,7 +1062,7 @@ H5D__chunk_realloc(void *chk, size_t size, const H5O_pline_t *pline)
ret_value = H5FL_BLK_REALLOC(chunk, chk, size);
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5D__chunk_realloc() */
+} /* H5D__chunk_mem_realloc() */
/*--------------------------------------------------------------------------
@@ -1160,8 +1154,7 @@ H5D__create_chunk_map_single(H5D_chunk_map_t *fm, const H5D_io_info_t
chunk_info->coords[fm->f_ndims] = 0;
/* Calculate the index of this chunk */
- if(H5VM_chunk_index(fm->f_ndims, chunk_info->coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_info->index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+ chunk_info->index = H5VM_chunk_index(fm->f_ndims, chunk_info->coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks);
/* Copy selection for file's dataspace into chunk dataspace */
if(H5S_select_copy(fm->single_space, fm->file_space, FALSE) < 0)
@@ -1219,7 +1212,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
hsize_t sel_points; /* Number of elements in file selection */
hsize_t start_coords[H5O_LAYOUT_NDIMS]; /* Starting coordinates of selection */
hsize_t coords[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
- hsize_t end[H5O_LAYOUT_NDIMS]; /* Current coordinates of chunk */
+ hsize_t end[H5O_LAYOUT_NDIMS]; /* Final coordinates of chunk */
hsize_t chunk_index; /* Index of chunk */
int curr_dim; /* Current dimension to increment */
unsigned u; /* Local index variable */
@@ -1245,8 +1238,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
} /* end for */
/* Calculate the index of this chunk */
- if(H5VM_chunk_index(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+ chunk_index = H5VM_chunk_index(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks);
/* Iterate through each chunk in the dataset */
while(sel_points) {
@@ -1362,8 +1354,7 @@ H5D__create_chunk_file_map_hyper(H5D_chunk_map_t *fm, const H5D_io_info_t
} while(coords[curr_dim] > sel_end[curr_dim]);
/* Re-calculate the index of this chunk */
- if(H5VM_chunk_index(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+ chunk_index = H5VM_chunk_index(fm->f_ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks);
} /* end if */
} /* end while */
@@ -1505,14 +1496,14 @@ H5D__chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, cons
H5D_chunk_info_t *chunk_info; /* Chunk information for current chunk */
hsize_t coords_in_chunk[H5O_LAYOUT_NDIMS]; /* Coordinates of element in chunk */
hsize_t chunk_index; /* Chunk index */
+ hsize_t scaled[H5S_MAX_RANK]; /* Scaled coordinates for this chunk */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_STATIC
/* Calculate the index of this chunk */
- if(H5VM_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+ chunk_index = H5VM_chunk_index_scaled(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, scaled);
/* Find correct chunk in file & memory skip list */
if(chunk_index==fm->last_index) {
@@ -1565,7 +1556,7 @@ H5D__chunk_file_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, cons
/* Compute the chunk's coordinates */
for(u = 0; u < fm->f_ndims; u++) {
H5_CHECK_OVERFLOW(fm->layout->u.chunk.dim[u], hsize_t, hssize_t);
- chunk_info->coords[u] = (coords[u] / (hssize_t)fm->layout->u.chunk.dim[u]) * (hssize_t)fm->layout->u.chunk.dim[u];
+ chunk_info->coords[u] = scaled[u] * (hssize_t)fm->layout->u.chunk.dim[u];
} /* end for */
chunk_info->coords[fm->f_ndims] = 0;
@@ -1629,8 +1620,7 @@ H5D__chunk_mem_cb(void UNUSED *elem, hid_t UNUSED type_id, unsigned ndims, const
FUNC_ENTER_STATIC
/* Calculate the index of this chunk */
- if(H5VM_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks, &chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+ chunk_index = H5VM_chunk_index(ndims, coords, fm->layout->u.chunk.dim, fm->layout->u.chunk.down_chunks);
/* Find correct chunk in file & memory skip list */
if(chunk_index == fm->last_index) {
@@ -1835,10 +1825,7 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
while(chunk_node) {
H5D_chunk_info_t *chunk_info; /* Chunk information */
- H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
- void *chunk; /* Pointer to locked chunk buffer */
- H5D_chunk_ud_t udata; /* B-tree pass-through */
- htri_t cacheable; /* Whether the chunk is cacheable */
+ H5D_chunk_ud_t udata; /* Chunk index pass-through */
/* Get the actual chunk information from the skip list node */
chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
@@ -1847,11 +1834,19 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
if(H5D__chunk_lookup(io_info->dset, io_info->dxpl_id, chunk_info->coords, chunk_info->index, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
+ /* Sanity check */
+ HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) ||
+ (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
+
/* Check for non-existant chunk & skip it if appropriate */
- if(H5F_addr_defined(udata.addr) || UINT_MAX != udata.idx_hint
+ if(H5F_addr_defined(udata.chunk_block.offset) || UINT_MAX != udata.idx_hint
|| !skip_missing_chunks) {
- /* Load the chunk into cache and lock it. */
- if((cacheable = H5D__chunk_cacheable(io_info, udata.addr, FALSE)) < 0)
+ H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
+ void *chunk = NULL; /* Pointer to locked chunk buffer */
+ htri_t cacheable; /* Whether the chunk is cacheable */
+
+ /* Determine if we should use the chunk cache */
+ if((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, FALSE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable")
if(cacheable) {
/* Pass in chunk's coordinates in a union. */
@@ -1872,20 +1867,14 @@ H5D__chunk_read(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
/* Point I/O info at contiguous I/O info for this chunk */
chk_io_info = &cpt_io_info;
} /* end if */
- else if(H5F_addr_defined(udata.addr)) {
+ else if(H5F_addr_defined(udata.chunk_block.offset)) {
/* Set up the storage address information for this chunk */
- ctg_store.contig.dset_addr = udata.addr;
-
- /* No chunk cached */
- chunk = NULL;
+ ctg_store.contig.dset_addr = udata.chunk_block.offset;
/* Point I/O info at temporary I/O info for this chunk */
chk_io_info = &ctg_io_info;
} /* end else if */
else {
- /* No chunk cached */
- chunk = NULL;
-
/* Point I/O info at "nonexistent" I/O info for this chunk */
chk_io_info = &nonexistent_io_info;
} /* end else */
@@ -1963,21 +1952,30 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
chunk_node = H5D_CHUNK_GET_FIRST_NODE(fm);
while(chunk_node) {
H5D_chunk_info_t *chunk_info; /* Chunk information */
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
H5D_io_info_t *chk_io_info; /* Pointer to I/O info object for this chunk */
void *chunk; /* Pointer to locked chunk buffer */
H5D_chunk_ud_t udata; /* Index pass-through */
htri_t cacheable; /* Whether the chunk is cacheable */
+ hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */
/* Get the actual chunk information from the skip list node */
chunk_info = H5D_CHUNK_GET_NODE_INFO(fm, chunk_node);
- /* Load the chunk into cache. But if the whole chunk is written,
- * simply allocate space instead of load the chunk. */
+ /* Look up the chunk */
if(H5D__chunk_lookup(io_info->dset, io_info->dxpl_id, chunk_info->coords, chunk_info->index, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
- if((cacheable = H5D__chunk_cacheable(io_info, udata.addr, TRUE)) < 0)
+
+ /* Sanity check */
+ HDassert((H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length > 0) ||
+ (!H5F_addr_defined(udata.chunk_block.offset) && udata.chunk_block.length == 0));
+
+ /* Determine if we should use the chunk cache */
+ if((cacheable = H5D__chunk_cacheable(io_info, udata.chunk_block.offset, TRUE)) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't tell if chunk is cacheable")
if(cacheable) {
+ /* Load the chunk into cache. But if the whole chunk is written,
+ * simply allocate space instead of load the chunk. */
hbool_t entire_chunk = TRUE; /* Whether whole chunk is selected */
/* Pass in chunk's coordinates in a union. */
@@ -2005,9 +2003,7 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
} /* end if */
else {
/* If the chunk hasn't been allocated on disk, do so now. */
- if(!H5F_addr_defined(udata.addr)) {
- H5D_chk_idx_info_t idx_info; /* Chunked index info */
-
+ if(!H5F_addr_defined(udata.chunk_block.offset)) {
/* Compose chunked index info struct */
idx_info.f = io_info->dset->oloc.file;
idx_info.dxpl_id = io_info->dxpl_id;
@@ -2016,14 +2012,14 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
idx_info.storage = &(io_info->dset->shared->layout.storage.u.chunk);
/* Set up the size of chunk for user data */
- udata.nbytes = io_info->dset->shared->layout.u.chunk.size;
+ udata.chunk_block.length = io_info->dset->shared->layout.u.chunk.size;
- /* Create the chunk */
- if((io_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk")
+ /* Allocate the chunk */
+ if(H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk on chunk level")
/* Make sure the address of the chunk is returned. */
- if(!H5F_addr_defined(udata.addr))
+ if(!H5F_addr_defined(udata.chunk_block.offset))
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "chunk address isn't defined")
/* Cache the new chunk information */
@@ -2031,7 +2027,7 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
} /* end if */
/* Set up the storage address information for this chunk */
- ctg_store.contig.dset_addr = udata.addr;
+ ctg_store.contig.dset_addr = udata.chunk_block.offset;
/* No chunk cached */
chunk = NULL;
@@ -2045,9 +2041,16 @@ H5D__chunk_write(H5D_io_info_t *io_info, const H5D_type_info_t *type_info,
(hsize_t)chunk_info->chunk_points, chunk_info->fspace, chunk_info->mspace) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_READERROR, FAIL, "chunked write failed")
- /* Release the cache lock on the chunk. */
- if(chunk && H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+ /* Release the cache lock on the chunk, or insert chunk into index. */
+ if(chunk) {
+ if(H5D__chunk_unlock(io_info, &udata, TRUE, chunk, dst_accessed_bytes) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "unable to unlock raw data chunk")
+ } /* end if */
+ else {
+ if(need_insert && io_info->dset->shared->layout.storage.u.chunk.ops->insert)
+ if((io_info->dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk addr into index")
+ } /* end else */
/* Advance to next chunk in list */
chunk_node = H5D_CHUNK_GET_NEXT_NODE(fm, chunk_node);
@@ -2244,9 +2247,9 @@ H5D__chunk_cinfo_cache_update(H5D_chunk_cached_t *last, const H5D_chunk_ud_t *ud
/* Stored the information to cache */
HDmemcpy(last->offset, udata->common.offset, sizeof(hsize_t) * udata->common.layout->ndims);
- last->nbytes = udata->nbytes;
+ last->addr = udata->chunk_block.offset;
+ H5_ASSIGN_OVERFLOW(last->nbytes, udata->chunk_block.length, hsize_t, uint32_t);
last->filter_mask = udata->filter_mask;
- last->addr = udata->addr;
/* Indicate that the cached info is valid */
last->valid = TRUE;
@@ -2291,9 +2294,9 @@ H5D__chunk_cinfo_cache_found(const H5D_chunk_cached_t *last, H5D_chunk_ud_t *uda
HGOTO_DONE(FALSE)
/* Retrieve the information from the cache */
- udata->nbytes = last->nbytes;
+ udata->chunk_block.offset = last->addr;
+ udata->chunk_block.length = last->nbytes;
udata->filter_mask = last->filter_mask;
- udata->addr = last->addr;
/* Indicate that the data was found */
HGOTO_DONE(TRUE)
@@ -2389,12 +2392,11 @@ H5D__chunk_lookup(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset,
udata->common.layout = &(dset->shared->layout.u.chunk);
udata->common.storage = &(dset->shared->layout.storage.u.chunk);
udata->common.offset = chunk_offset;
- udata->common.rdcc = &(dset->shared->cache.chunk);
/* Reset information about the chunk we are looking for */
- udata->nbytes = 0;
+ udata->chunk_block.offset = HADDR_UNDEF;
+ udata->chunk_block.length = 0;
udata->filter_mask = 0;
- udata->addr = HADDR_UNDEF;
/* Check for chunk in cache */
if(dset->shared->cache.chunk.nslots > 0) {
@@ -2402,8 +2404,7 @@ H5D__chunk_lookup(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset,
ent = dset->shared->cache.chunk.slot[udata->idx_hint];
if(ent)
- for(u = 0, found = TRUE; u < dset->shared->layout.u.chunk.ndims - 1;
- u++)
+ for(u = 0, found = TRUE; u < dset->shared->ndims; u++)
if(chunk_offset[u] != ent->offset[u]) {
found = FALSE;
break;
@@ -2411,8 +2412,10 @@ H5D__chunk_lookup(const H5D_t *dset, hid_t dxpl_id, const hsize_t *chunk_offset,
} /* end if */
/* Find chunk addr */
- if(found)
- udata->addr = ent->chunk_addr;
+ if(found) {
+ udata->chunk_block.offset = ent->chunk_block.offset;
+ udata->chunk_block.length = ent->chunk_block.length;;
+ } /* end if */
else {
/* Invalidate idx_hint, to signal that the chunk is not in cache */
udata->idx_hint = UINT_MAX;
@@ -2474,22 +2477,23 @@ H5D__chunk_flush_entry(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t
HDassert(!ent->locked);
buf = ent->chunk;
- if(ent->dirty && !ent->deleted) {
+ if(ent->dirty) {
+ H5D_chk_idx_info_t idx_info; /* Chunked index info */
H5D_chunk_ud_t udata; /* pass through B-tree */
- hbool_t must_insert = FALSE; /* Whether the chunk must go through the "insert" method */
+ hbool_t must_alloc = FALSE; /* Whether the chunk must be allocated */
+ hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */
/* Set up user data for index callbacks */
udata.common.layout = &dset->shared->layout.u.chunk;
udata.common.storage = &dset->shared->layout.storage.u.chunk;
udata.common.offset = ent->offset;
- udata.common.rdcc = &(dset->shared->cache.chunk);
+ udata.chunk_block.offset = ent->chunk_block.offset;
+ udata.chunk_block.length = dset->shared->layout.u.chunk.size;
udata.filter_mask = 0;
- udata.nbytes = dset->shared->layout.u.chunk.size;
- udata.addr = ent->chunk_addr;
/* Should the chunk be filtered before writing it to disk? */
if(dset->shared->dcpl_cache.pline.nused) {
- size_t alloc = udata.nbytes; /* Bytes allocated for BUF */
+ size_t alloc = udata.chunk_block.length; /* Bytes allocated for BUF */
size_t nbytes; /* Chunk size (in bytes) */
if(!reset) {
@@ -2498,10 +2502,9 @@ H5D__chunk_flush_entry(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t
* the pipeline because we'll want to save the original buffer
* for later.
*/
- H5_ASSIGN_OVERFLOW(alloc, udata.nbytes, uint32_t, size_t);
if(NULL == (buf = H5MM_malloc(alloc)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline")
- HDmemcpy(buf, ent->chunk, udata.nbytes);
+ HDmemcpy(buf, ent->chunk, alloc);
} /* end if */
else {
/*
@@ -2514,7 +2517,7 @@ H5D__chunk_flush_entry(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t
point_of_no_return = TRUE;
ent->chunk = NULL;
} /* end else */
- H5_ASSIGN_OVERFLOW(nbytes, udata.nbytes, uint32_t, size_t);
+ H5_ASSIGN_OVERFLOW(nbytes, udata.chunk_block.length, hsize_t, size_t);
if(H5Z_pipeline(&(dset->shared->dcpl_cache.pline), 0, &(udata.filter_mask), dxpl_cache->err_detect,
dxpl_cache->filter_cb, &nbytes, &alloc, &buf) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, FAIL, "output pipeline failed")
@@ -2523,21 +2526,19 @@ H5D__chunk_flush_entry(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t
if(nbytes > ((size_t)0xffffffff))
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "chunk too large for 32-bit length")
#endif /* H5_SIZEOF_SIZE_T > 4 */
- H5_ASSIGN_OVERFLOW(udata.nbytes, nbytes, size_t, uint32_t);
+ H5_ASSIGN_OVERFLOW(udata.chunk_block.length, nbytes, size_t, hsize_t);
- /* Indicate that the chunk must go through 'insert' method */
- must_insert = TRUE;
+ /* Indicate that the chunk must be allocated */
+ must_alloc = TRUE;
} /* end if */
- else if(!H5F_addr_defined(udata.addr))
- /* Indicate that the chunk must go through 'insert' method */
- must_insert = TRUE;
+ else if(!H5F_addr_defined(udata.chunk_block.offset))
+ /* Indicate that the chunk must be allocated */
+ must_alloc = TRUE;
- /* Check if the chunk needs to be 'inserted' (could exist already and
- * the 'insert' operation could resize it)
+ /* Check if the chunk needs to be allocated (it also could exist already
+ * and the chunk alloc operation could resize it)
*/
- if(must_insert) {
- H5D_chk_idx_info_t idx_info; /* Chunked index info */
-
+ if(must_alloc) {
/* Compose chunked index info struct */
idx_info.f = dset->oloc.file;
idx_info.dxpl_id = dxpl_id;
@@ -2548,18 +2549,25 @@ H5D__chunk_flush_entry(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t
/* Create the chunk it if it doesn't exist, or reallocate the chunk
* if its size changed.
*/
- if((dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk")
+ if(H5D__chunk_file_alloc(&idx_info, &(ent->chunk_block), &udata.chunk_block, &need_insert) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk on chunk level")
- /* Update the chunk entry's address, in case it was allocated or relocated */
- ent->chunk_addr = udata.addr;
+ /* Update the chunk entry's info, in case it was allocated or relocated */
+ ent->chunk_block.offset = udata.chunk_block.offset;
+ ent->chunk_block.length = udata.chunk_block.length;
} /* end if */
/* Write the data to the file */
- HDassert(H5F_addr_defined(udata.addr));
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, udata.nbytes, dxpl_id, buf) < 0)
+ HDassert(H5F_addr_defined(udata.chunk_block.offset));
+ H5_CHECK_OVERFLOW(udata.chunk_block.length, hsize_t, size_t);
+ if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, (size_t)udata.chunk_block.length, dxpl_id, buf) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
+ /* Insert the chunk record into the index */
+ if(need_insert && dset->shared->layout.storage.u.chunk.ops->insert)
+ if((dset->shared->layout.storage.u.chunk.ops->insert)(&idx_info, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk addr into index")
+
/* Cache the chunk's info, in case it's accessed again shortly */
H5D__chunk_cinfo_cache_update(&dset->shared->cache.chunk.last, &udata);
@@ -2576,7 +2584,7 @@ H5D__chunk_flush_entry(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t
if(buf == ent->chunk)
buf = NULL;
if(ent->chunk != NULL)
- ent->chunk = (uint8_t *)H5D__chunk_xfree(ent->chunk, &(dset->shared->dcpl_cache.pline));
+ ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk, &(dset->shared->dcpl_cache.pline));
} /* end if */
done:
@@ -2590,10 +2598,9 @@ done:
* output pipeline failed. Do not free the entry or remove it from the
* list.
*/
- if(ret_value < 0 && point_of_no_return) {
+ if(ret_value < 0 && point_of_no_return)
if(ent->chunk)
- ent->chunk = (uint8_t *)H5D__chunk_xfree(ent->chunk, &(dset->shared->dcpl_cache.pline));
- } /* end if */
+ ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk, &(dset->shared->dcpl_cache.pline));
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
} /* end H5D__chunk_flush_entry() */
@@ -2635,7 +2642,7 @@ H5D__chunk_cache_evict(const H5D_t *dset, hid_t dxpl_id, const H5D_dxpl_cache_t
else {
/* Don't flush, just free chunk */
if(ent->chunk != NULL)
- ent->chunk = (uint8_t *)H5D__chunk_xfree(ent->chunk, &(dset->shared->dcpl_cache.pline));
+ ent->chunk = (uint8_t *)H5D__chunk_mem_xfree(ent->chunk, &(dset->shared->dcpl_cache.pline));
} /* end else */
/* Unlink from list */
@@ -2649,8 +2656,12 @@ 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;
+ /* Only clear hash table slot if chunk was not marked as deleted already */
+ if(!ent->deleted)
+ 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;
@@ -2802,14 +2813,13 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
hbool_t relax)
{
const H5D_t *dset = io_info->dset; /* Local pointer to the dataset info */
- const H5O_pline_t *pline = &(dset->shared->dcpl_cache.pline); /* I/O pipeline info - always equal to the pline passed to H5D__chunk_alloc */
+ const H5O_pline_t *pline = &(dset->shared->dcpl_cache.pline); /* I/O pipeline info - always equal to the pline passed to H5D__chunk_mem_alloc */
const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset layout */
const H5O_fill_t *fill = &(dset->shared->dcpl_cache.fill); /* Fill value info */
H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache*/
- H5D_rdcc_ent_t *ent = NULL; /*cache entry */
- haddr_t chunk_addr = HADDR_UNDEF; /* Address of chunk on disk */
+ H5D_rdcc_ent_t *ent; /*cache entry */
size_t chunk_size; /*size of a chunk */
void *chunk = NULL; /*the file chunk */
void *ret_value; /*return value */
@@ -2850,110 +2860,12 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
* Already in the cache. Count a hit.
*/
rdcc->stats.nhits++;
- } /* end if */
- else if(relax) {
- /*
- * Not in the cache, but we're about to overwrite the whole thing
- * anyway, so just allocate a buffer for it but don't initialize that
- * buffer with the file contents. Count this as a hit instead of a
- * miss because we saved ourselves lots of work.
- */
- rdcc->stats.nhits++;
-
- /* Still save the chunk address so the cache stays consistent */
- chunk_addr = udata->addr;
-
- if(NULL == (chunk = H5D__chunk_alloc(chunk_size, pline)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
-
- /* In the case that some dataset functions look through this data,
- * clear it to all 0s. */
- HDmemset(chunk, 0, chunk_size);
- } /* end if */
- else {
- /*
- * Not in the cache. Count this as a miss if it's in the file
- * or an init if it isn't.
- */
-
- /* Save the chunk address */
- chunk_addr = udata->addr;
-
- /* Check if the chunk exists on disk */
- if(H5F_addr_defined(chunk_addr)) {
- size_t chunk_alloc = 0; /*allocated chunk size */
-
- /* Chunk size on disk isn't [likely] the same size as the final chunk
- * size in memory, so allocate memory big enough. */
- H5_ASSIGN_OVERFLOW(chunk_alloc, udata->nbytes, uint32_t, size_t);
- if(NULL == (chunk = H5D__chunk_alloc(chunk_alloc, pline)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
- if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, chunk_addr, chunk_alloc, io_info->dxpl_id, chunk) < 0)
- HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk")
-
- if(pline->nused) {
- if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->filter_mask), io_info->dxpl_cache->err_detect,
- io_info->dxpl_cache->filter_cb, &chunk_alloc, &chunk_alloc, &chunk) < 0)
- HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, NULL, "data pipeline read failed")
- H5_ASSIGN_OVERFLOW(udata->nbytes, chunk_alloc, size_t, uint32_t);
- } /* end if */
- /* Increment # of cache misses */
- rdcc->stats.nmisses++;
- } /* end if */
- else {
- H5D_fill_value_t fill_status;
-
- /* Sanity check */
- HDassert(fill->alloc_time != H5D_ALLOC_TIME_EARLY);
-
- /* Chunk size on disk isn't [likely] the same size as the final chunk
- * size in memory, so allocate memory big enough. */
- if(NULL == (chunk = H5D__chunk_alloc(chunk_size, pline)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
-
- if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't tell if fill value defined")
-
- if(fill->fill_time == H5D_FILL_TIME_ALLOC ||
- (fill->fill_time == H5D_FILL_TIME_IFSET &&
- (fill_status == H5D_FILL_VALUE_USER_DEFINED ||
- fill_status == H5D_FILL_VALUE_DEFAULT))) {
- /*
- * The chunk doesn't exist in the file. Replicate the fill
- * value throughout the chunk, if the fill value is defined.
- */
-
- /* Initialize the fill value buffer */
- /* (use the compact dataset storage buffer as the fill value buffer) */
- if(H5D__fill_init(&fb_info, chunk, NULL, NULL, NULL, NULL,
- &dset->shared->dcpl_cache.fill, dset->shared->type,
- dset->shared->type_id, (size_t)0, chunk_size, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't initialize fill buffer info")
- fb_info_init = TRUE;
-
- /* Check for VL datatype & non-default fill value */
- if(fb_info.has_vlen_fill_type)
- /* Fill the buffer with VL datatype fill values */
- if(H5D__fill_refill_vl(&fb_info, fb_info.elmts_per_buf, io_info->dxpl_id) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, NULL, "can't refill fill value buffer")
- } /* end if */
- else
- HDmemset(chunk, 0, chunk_size);
-
- /* Increment # of creations */
- rdcc->stats.ninits++;
- } /* end else */
- } /* end else */
- HDassert(chunk_size > 0);
-
- if(ent) {
/*
- * The chunk is not at the beginning of the cache; move it backward
+ * If the chunk is not at the beginning of the cache; move it backward
* by one slot. This is how we implement the LRU preemption
* algorithm.
*/
- HDassert(ent);
if(ent->next) {
if(ent->next->next)
ent->next->next->prev = ent;
@@ -2969,67 +2881,166 @@ H5D__chunk_lock(const H5D_io_info_t *io_info, H5D_chunk_ud_t *udata,
ent->prev->next = ent;
} /* end if */
} /* end if */
- else if(rdcc->nslots > 0 && chunk_size <= rdcc->nbytes_max) {
- /* Calculate the index */
- udata->idx_hint = H5D_CHUNK_HASH(dset->shared, io_info->store->chunk.index);
+ else {
+ haddr_t chunk_addr; /* Address of chunk on disk */
+ hsize_t chunk_alloc; /* Length of chunk on disk */
+
+ /* Save the chunk info so the cache stays consistent */
+ chunk_addr = udata->chunk_block.offset;
+ chunk_alloc = udata->chunk_block.length;
+
+ if(relax) {
+ /*
+ * Not in the cache, but we're about to overwrite the whole thing
+ * anyway, so just allocate a buffer for it but don't initialize that
+ * buffer with the file contents. Count this as a hit instead of a
+ * miss because we saved ourselves lots of work.
+ */
+ rdcc->stats.nhits++;
- /* Add the chunk to the cache only if the slot is not already locked */
- ent = rdcc->slot[udata->idx_hint];
- if(!ent || !ent->locked) {
- /* Preempt enough things from the cache to make room */
- if(ent) {
- if(H5D__chunk_cache_evict(io_info->dset, io_info->dxpl_id, io_info->dxpl_cache, ent, TRUE) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk from cache")
+ if(NULL == (chunk = H5D__chunk_mem_alloc(chunk_size, pline)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
+
+ /* In the case that some dataset functions look through this data,
+ * clear it to all 0s. */
+ HDmemset(chunk, 0, chunk_size);
+ } /* end if */
+ else {
+ /*
+ * Not in the cache. Count this as a miss if it's in the file
+ * or an init if it isn't.
+ */
+
+ /* Check if the chunk exists on disk */
+ if(H5F_addr_defined(chunk_addr)) {
+ size_t my_chunk_alloc = chunk_alloc; /* Allocated buffer size */
+ size_t buf_alloc = chunk_alloc; /* [Re-]allocated buffer size */
+
+ /* Chunk size on disk isn't [likely] the same size as the final chunk
+ * size in memory, so allocate memory big enough. */
+ if(NULL == (chunk = H5D__chunk_mem_alloc(my_chunk_alloc, pline)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
+ if(H5F_block_read(dset->oloc.file, H5FD_MEM_DRAW, chunk_addr, my_chunk_alloc, io_info->dxpl_id, chunk) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "unable to read raw data chunk")
+
+ if(pline->nused)
+ if(H5Z_pipeline(pline, H5Z_FLAG_REVERSE, &(udata->filter_mask), io_info->dxpl_cache->err_detect,
+ io_info->dxpl_cache->filter_cb, &my_chunk_alloc, &buf_alloc, &chunk) < 0)
+ HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, NULL, "data pipeline read failed")
+
+ /* Increment # of cache misses */
+ rdcc->stats.nmisses++;
} /* end if */
- if(H5D__chunk_cache_prune(io_info->dset, io_info->dxpl_id, io_info->dxpl_cache, chunk_size) < 0)
- HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk(s) from cache")
-
- /* Create a new entry */
- if(NULL == (ent = H5FL_CALLOC(H5D_rdcc_ent_t)))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate raw data chunk entry")
-
- /* Initialize the new entry */
- ent->chunk_addr = chunk_addr;
- HDmemcpy(ent->offset, io_info->store->chunk.offset, sizeof(hsize_t) * layout->u.chunk.ndims);
- H5_ASSIGN_OVERFLOW(ent->rd_count, chunk_size, size_t, uint32_t);
- H5_ASSIGN_OVERFLOW(ent->wr_count, chunk_size, size_t, uint32_t);
- ent->chunk = (uint8_t *)chunk;
-
- /* Add it to the cache */
- HDassert(NULL == rdcc->slot[udata->idx_hint]);
- rdcc->slot[udata->idx_hint] = ent;
- ent->idx = udata->idx_hint;
- rdcc->nbytes_used += chunk_size;
- rdcc->nused++;
-
- /* Add it to the linked list */
- if(rdcc->tail) {
- rdcc->tail->next = ent;
- ent->prev = rdcc->tail;
- rdcc->tail = ent;
+ else {
+ H5D_fill_value_t fill_status;
+
+ /* Sanity check */
+ HDassert(fill->alloc_time != H5D_ALLOC_TIME_EARLY);
+
+ /* Chunk size on disk isn't [likely] the same size as the final chunk
+ * size in memory, so allocate memory big enough. */
+ if(NULL == (chunk = H5D__chunk_mem_alloc(chunk_size, pline)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for raw data chunk")
+
+ if(H5P_is_fill_value_defined(fill, &fill_status) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, NULL, "can't tell if fill value defined")
+
+ if(fill->fill_time == H5D_FILL_TIME_ALLOC ||
+ (fill->fill_time == H5D_FILL_TIME_IFSET &&
+ (fill_status == H5D_FILL_VALUE_USER_DEFINED ||
+ fill_status == H5D_FILL_VALUE_DEFAULT))) {
+ /*
+ * The chunk doesn't exist in the file. Replicate the fill
+ * value throughout the chunk, if the fill value is defined.
+ */
+
+ /* Initialize the fill value buffer */
+ /* (use the compact dataset storage buffer as the fill value buffer) */
+ if(H5D__fill_init(&fb_info, chunk, NULL, NULL, NULL, NULL,
+ &dset->shared->dcpl_cache.fill, dset->shared->type,
+ dset->shared->type_id, (size_t)0, chunk_size, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "can't initialize fill buffer info")
+ fb_info_init = TRUE;
+
+ /* Check for VL datatype & non-default fill value */
+ if(fb_info.has_vlen_fill_type)
+ /* Fill the buffer with VL datatype fill values */
+ if(H5D__fill_refill_vl(&fb_info, fb_info.elmts_per_buf, io_info->dxpl_id) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, NULL, "can't refill fill value buffer")
+ } /* end if */
+ else
+ HDmemset(chunk, 0, chunk_size);
+
+ /* Increment # of creations */
+ rdcc->stats.ninits++;
+ } /* end else */
+ } /* end else */
+
+ /* See if the chunk can be cached */
+ if(rdcc->nslots > 0 && chunk_size <= rdcc->nbytes_max) {
+ /* Calculate the index */
+ udata->idx_hint = H5D_CHUNK_HASH(dset->shared, io_info->store->chunk.index);
+
+ /* Add the chunk to the cache only if the slot is not already locked */
+ ent = rdcc->slot[udata->idx_hint];
+ if(!ent || !ent->locked) {
+ /* Preempt enough things from the cache to make room */
+ if(ent) {
+ if(H5D__chunk_cache_evict(io_info->dset, io_info->dxpl_id, io_info->dxpl_cache, ent, TRUE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk from cache")
+ } /* end if */
+ if(H5D__chunk_cache_prune(io_info->dset, io_info->dxpl_id, io_info->dxpl_cache, chunk_size) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "unable to preempt chunk(s) from cache")
+
+ /* Create a new entry */
+ if(NULL == (ent = H5FL_CALLOC(H5D_rdcc_ent_t)))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, NULL, "can't allocate raw data chunk entry")
+
+ /* Initialize the new entry */
+ ent->chunk_block.offset = chunk_addr;
+ ent->chunk_block.length = chunk_alloc;
+ HDmemcpy(ent->offset, io_info->store->chunk.offset, sizeof(hsize_t) * layout->u.chunk.ndims);
+ H5_ASSIGN_OVERFLOW(ent->rd_count, chunk_size, size_t, uint32_t);
+ H5_ASSIGN_OVERFLOW(ent->wr_count, chunk_size, size_t, uint32_t);
+ ent->chunk = (uint8_t *)chunk;
+
+ /* Add it to the cache */
+ HDassert(NULL == rdcc->slot[udata->idx_hint]);
+ rdcc->slot[udata->idx_hint] = ent;
+ ent->idx = udata->idx_hint;
+ rdcc->nbytes_used += chunk_size;
+ rdcc->nused++;
+
+ /* Add it to the linked list */
+ if(rdcc->tail) {
+ rdcc->tail->next = ent;
+ ent->prev = rdcc->tail;
+ rdcc->tail = ent;
+ } /* end if */
+ else
+ rdcc->head = rdcc->tail = ent;
} /* end if */
else
- rdcc->head = rdcc->tail = ent;
- } /* end if */
- else
- /* We did not add the chunk to cache */
+ /* We did not add the chunk to cache */
+ ent = NULL;
+ } /* end else */
+ else /* No cache set up, or chunk is too large: chunk is uncacheable */
ent = NULL;
} /* end else */
- if(!ent)
- /*
- * The chunk cannot be placed in cache so we don't cache it. This is the
- * reason all those arguments have to be repeated for the unlock
- * function.
- */
- udata->idx_hint = UINT_MAX;
-
/* Lock the chunk into the cache */
if(ent) {
HDassert(!ent->locked);
ent->locked = TRUE;
chunk = ent->chunk;
} /* end if */
+ else
+ /*
+ * The chunk cannot be placed in cache so we don't cache it. This is the
+ * reason all those arguments have to be repeated for the unlock
+ * function.
+ */
+ udata->idx_hint = UINT_MAX;
/* Set return value */
ret_value = chunk;
@@ -3042,7 +3053,7 @@ done:
/* Release the chunk allocated, on error */
if(!ret_value)
if(chunk)
- chunk = H5D__chunk_xfree(chunk, pline);
+ chunk = H5D__chunk_mem_xfree(chunk, pline);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_lock() */
@@ -3097,7 +3108,8 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata,
fake_ent.dirty = TRUE;
HDmemcpy(fake_ent.offset, io_info->store->chunk.offset, layout->u.chunk.ndims * sizeof(fake_ent.offset[0]));
HDassert(layout->u.chunk.size > 0);
- fake_ent.chunk_addr = udata->addr;
+ fake_ent.chunk_block.offset = udata->chunk_block.offset;
+ fake_ent.chunk_block.length = udata->chunk_block.length;
fake_ent.chunk = (uint8_t *)chunk;
if(H5D__chunk_flush_entry(io_info->dset, io_info->dxpl_id, io_info->dxpl_cache, &fake_ent, TRUE) < 0)
@@ -3105,7 +3117,7 @@ H5D__chunk_unlock(const H5D_io_info_t *io_info, const H5D_chunk_ud_t *udata,
} /* end if */
else {
if(chunk)
- chunk = H5D__chunk_xfree(chunk, &(io_info->dset->shared->dcpl_cache.pline));
+ chunk = H5D__chunk_mem_xfree(chunk, &(io_info->dset->shared->dcpl_cache.pline));
} /* end else */
} /* end if */
else {
@@ -3261,10 +3273,10 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
H5D_chunk_coll_info_t chunk_info; /* chunk address information for doing I/O */
#endif /* H5_HAVE_PARALLEL */
hbool_t carry; /* Flag to indicate that chunk increment carrys to higher dimension (sorta) */
- int space_ndims; /* Dataset's space rank */
- hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Dataset's dataspace dimensions */
+ unsigned space_ndims; /* Dataset's space rank */
+ const hsize_t *space_dim; /* Dataset's dataspace dimensions */
const uint32_t *chunk_dim = layout->u.chunk.dim; /* Convenience pointer to chunk dimensions */
- int op_dim; /* Current operationg dimension */
+ unsigned op_dim; /* Current operating dimension */
H5D_fill_buf_info_t fb_info; /* Dataset's fill buffer info */
hbool_t fb_info_init = FALSE; /* Whether the fill value buffer has been initialized */
herr_t ret_value = SUCCEED; /* Return value */
@@ -3277,16 +3289,15 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
HDassert(TRUE == H5P_isa_class(dxpl_id, H5P_DATASET_XFER));
/* Retrieve the dataset dimensions */
- if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim, NULL)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to get simple dataspace info")
- space_dim[space_ndims] = layout->u.chunk.dim[space_ndims];
+ space_dim = dset->shared->curr_dims;
+ space_ndims = dset->shared->ndims;
/* The last dimension in chunk_offset is always 0 */
chunk_offset[space_ndims] = (hsize_t)0;
/* Check if any space dimensions are 0, if so we do not have to do anything
*/
- for(op_dim=0; op_dim<space_ndims; op_dim++)
+ for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++)
if(space_dim[op_dim] == 0) {
/* Reset any cached chunk info for this dataset */
H5D__chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
@@ -3333,8 +3344,8 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
/* Initialize the fill value buffer */
/* (delay allocating fill buffer for VL datatypes until refilling) */
/* (casting away const OK - QAK) */
- if(H5D__fill_init(&fb_info, NULL, (H5MM_allocate_t)H5D__chunk_alloc,
- (void *)pline, (H5MM_free_t)H5D__chunk_xfree, (void *)pline,
+ if(H5D__fill_init(&fb_info, NULL, (H5MM_allocate_t)H5D__chunk_mem_alloc,
+ (void *)pline, (H5MM_free_t)H5D__chunk_mem_xfree, (void *)pline,
&dset->shared->dcpl_cache.fill, dset->shared->type,
dset->shared->type_id, (size_t)0, orig_chunk_size, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize fill buffer info")
@@ -3367,8 +3378,8 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
/* Calculate the minimum and maximum chunk offsets in each dimension. Note
* that we assume here that all elements of space_dim are > 0. This is
- * checked at the top of this function */
- for(op_dim=0; op_dim<space_ndims; op_dim++) {
+ * checked at the top of this function. */
+ for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++) {
min_unalloc[op_dim] = ((old_dim[op_dim] + chunk_dim[op_dim] - 1)
/ chunk_dim[op_dim]) * chunk_dim[op_dim];
max_unalloc[op_dim] = ((space_dim[op_dim] - 1) / chunk_dim[op_dim])
@@ -3393,7 +3404,7 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
* certain dimension, max_unalloc is updated in order to avoid allocating
* those chunks again.
*/
- for(op_dim=0; op_dim<space_ndims; op_dim++) {
+ for(op_dim = 0; op_dim < space_ndims; op_dim++) {
H5D_chunk_ud_t udata; /* User data for querying chunk info */
int i; /* Local index variable */
@@ -3402,13 +3413,15 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
continue;
else {
/* Reset the chunk offset indices */
- HDmemset(chunk_offset, 0, ((unsigned)space_ndims * sizeof(chunk_offset[0])));
+ HDmemset(chunk_offset, 0, (space_ndims * sizeof(chunk_offset[0])));
chunk_offset[op_dim] = min_unalloc[op_dim];
carry = FALSE;
} /* end else */
while(!carry) {
+ hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */
+
/* Reset size of chunk in bytes, in case filtered size changes */
chunk_size = orig_chunk_size;
@@ -3417,16 +3430,12 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
{
hsize_t chunk_idx;
- /* Calculate the index of this chunk */
- if(H5VM_chunk_index((unsigned)space_ndims, chunk_offset,
- layout->u.chunk.dim, layout->u.chunk.down_chunks,
- &chunk_idx) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't get chunk index")
-
+ /* Look up this chunk */
+ chunk_idx = H5VM_chunk_index(space_ndims, chunk_offset, layout->u.chunk.dim, layout->u.chunk.down_chunks);
if(H5D__chunk_lookup(dset, dxpl_id, chunk_offset, chunk_idx, &udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
- HDassert(!H5F_addr_defined(udata.addr));
+ HDassert(!H5F_addr_defined(udata.chunk_block.offset));
} /* end block */
/* Make sure the chunk is really in the dataset and outside the
@@ -3435,7 +3444,7 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
unsigned u; /* Local index variable */
hbool_t outside_orig = FALSE;
- for(u = 0; u < (unsigned)space_ndims; u++) {
+ for(u = 0; u < space_ndims; u++) {
HDassert(chunk_offset[u] < space_dim[u]);
if(chunk_offset[u] >= old_dim[u])
outside_orig = TRUE;
@@ -3456,8 +3465,7 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
* possible (though ill-advised) for the filter to shrink the
* buffer. */
if(fb_info.fill_buf_size < orig_chunk_size) {
- if(NULL == (fb_info.fill_buf = H5D__chunk_realloc(
- fb_info.fill_buf, orig_chunk_size, pline)))
+ if(NULL == (fb_info.fill_buf = H5D__chunk_mem_realloc(fb_info.fill_buf, orig_chunk_size, pline)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory reallocation failed for raw data chunk")
fb_info.fill_buf_size = orig_chunk_size;
} /* end if */
@@ -3489,21 +3497,20 @@ H5D__chunk_allocate(const 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;
- H5_ASSIGN_OVERFLOW(udata.nbytes, chunk_size, size_t, uint32_t);
+ udata.chunk_block.offset = HADDR_UNDEF;
+ H5_ASSIGN_OVERFLOW(udata.chunk_block.length, chunk_size, size_t, uint32_t);
udata.filter_mask = filter_mask;
- udata.addr = HADDR_UNDEF;
- /* Allocate the chunk with all processes */
- if((ops->insert)(&idx_info, &udata) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert record into chunk index")
- HDassert(H5F_addr_defined(udata.addr));
+ /* Allocate the chunk (with all processes) */
+ if(H5D__chunk_file_alloc(&idx_info, NULL, &udata.chunk_block, &need_insert) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk on chunk level")
+ HDassert(H5F_addr_defined(udata.chunk_block.offset));
/* Check if fill values should be written to chunks */
if(should_fill) {
/* Sanity check */
HDassert(fb_info_init);
- HDassert(udata.nbytes == chunk_size);
+ HDassert(udata.chunk_block.length == chunk_size);
#ifdef H5_HAVE_PARALLEL
/* Check if this file is accessed with an MPI-capable file driver */
@@ -3511,14 +3518,12 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
/* collect all chunk addresses to be written to
write collectively at the end */
/* allocate/resize address array if no more space left */
- if(0 == chunk_info.num_io % 1024) {
- if(NULL == (chunk_info.addr = (haddr_t *)HDrealloc
- (chunk_info.addr, (chunk_info.num_io + 1024) * sizeof(haddr_t))))
- HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed for chunk addresses");
- } /* end if */
+ if(0 == chunk_info.num_io % 1024)
+ if(NULL == (chunk_info.addr = (haddr_t *)HDrealloc(chunk_info.addr, (chunk_info.num_io + 1024) * sizeof(haddr_t))))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "memory allocation failed for chunk addresses")
/* Store the chunk's address for later */
- chunk_info.addr[chunk_info.num_io] = udata.addr;
+ chunk_info.addr[chunk_info.num_io] = udata.chunk_block.offset;
chunk_info.num_io++;
/* Indicate that blocks will be written */
@@ -3526,20 +3531,27 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
} /* end if */
else {
#endif /* H5_HAVE_PARALLEL */
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.addr, chunk_size,
- dxpl_id, fb_info.fill_buf) < 0)
+ if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, udata.chunk_block.offset, chunk_size, dxpl_id, fb_info.fill_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
#ifdef H5_HAVE_PARALLEL
} /* end else */
#endif /* H5_HAVE_PARALLEL */
} /* end if */
- /* Increment indices */
+ /* Insert the chunk record into the index */
+ /* (Note that this isn't safe, from a SWMR perspective, unlike
+ * serial operation. -QAK
+ */
+ if(need_insert && ops->insert)
+ if((ops->insert)(&idx_info, &udata) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert chunk addr into index")
+
+ /* Increment indices and adjust the edge chunk state */
carry = TRUE;
for(i = ((int)space_ndims - 1); i >= 0; --i) {
chunk_offset[i] += chunk_dim[i];
if(chunk_offset[i] > max_unalloc[i]) {
- if(i == op_dim)
+ if((unsigned)i == op_dim)
chunk_offset[i] = min_unalloc[i];
else
chunk_offset[i] = 0;
@@ -3562,10 +3574,9 @@ H5D__chunk_allocate(const H5D_t *dset, hid_t dxpl_id, hbool_t full_overwrite,
#ifdef H5_HAVE_PARALLEL
/* do final collective I/O */
- if(using_mpi && blocks_written) {
+ if(using_mpi && blocks_written)
if(H5D__chunk_collective_fill(dset, dxpl_id, &chunk_info, chunk_size, fb_info.fill_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
- } /* end if */
#endif /* H5_HAVE_PARALLEL */
/* Reset any cached chunk info for this dataset */
@@ -3577,10 +3588,8 @@ done:
HDONE_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "Can't release fill buffer info")
#ifdef H5_HAVE_PARALLEL
- if(using_mpi) {
- if(chunk_info.addr)
- HDfree(chunk_info.addr);
- } /* end if */
+ if(using_mpi && chunk_info.addr)
+ HDfree(chunk_info.addr);
#endif
FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL)
@@ -3684,8 +3693,7 @@ H5D__chunk_collective_fill(const H5D_t *dset, hid_t dxpl_id,
* should use this if MPI_type_create_hindexed block is working
* mpi_code = MPI_Type_create_hindexed_block(blocks, block_len, chunk_disp_array, MPI_BYTE, &file_type);
*/
- mpi_code = MPI_Type_create_hindexed(blocks, block_lens, chunk_disp_array,
- MPI_BYTE, &file_type);
+ mpi_code = MPI_Type_create_hindexed(blocks, block_lens, chunk_disp_array, MPI_BYTE, &file_type);
if(mpi_code != MPI_SUCCESS)
HMPI_GOTO_ERROR(FAIL, "MPI_Type_create_hindexed failed", mpi_code)
if(MPI_SUCCESS != (mpi_code = MPI_Type_commit(&file_type)))
@@ -3718,9 +3726,8 @@ H5D__chunk_collective_fill(const H5D_t *dset, hid_t dxpl_id,
HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "can't set transfer mode")
}
- /* low level write */
- if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, (haddr_t)0, (blocks) ? (size_t)1 : (size_t)0,
- data_dxpl_id, fill_buf) < 0)
+ /* low level write (collective) */
+ if(H5F_block_write(dset->oloc.file, H5FD_MEM_DRAW, (haddr_t)0, (blocks) ? (size_t)1 : (size_t)0, data_dxpl_id, fill_buf) < 0)
HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write raw data to file")
/* Barrier so processes don't race ahead */
@@ -3786,9 +3793,8 @@ H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata)
if(H5D__chunk_lookup(dset, io_info->dxpl_id, chunk_offset, io_info->store->chunk.index, &chk_udata) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "error looking up chunk address")
- /* If this chunk does not exist in cache or on disk, no need to do anything
- */
- if(!H5F_addr_defined(chk_udata.addr) && UINT_MAX == chk_udata.idx_hint)
+ /* If this chunk does not exist in cache or on disk, no need to do anything */
+ if(!H5F_addr_defined(chk_udata.chunk_block.offset) && UINT_MAX == chk_udata.idx_hint)
HGOTO_DONE(SUCCEED)
/* Initialize the fill value buffer, if necessary */
@@ -3804,8 +3810,7 @@ H5D__chunk_prune_fill(H5D_chunk_it_ud1_t *udata)
/* Compute the # of elements to leave with existing value, in each dimension */
for(u = 0; u < rank; u++) {
- count[u] = MIN(layout->u.chunk.dim[u], (udata->space_dim[u]
- - chunk_offset[u]));
+ count[u] = MIN(layout->u.chunk.dim[u], (udata->space_dim[u] - chunk_offset[u]));
HDassert(count[u] > 0);
} /* end for */
@@ -3983,14 +3988,13 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
const H5O_layout_t *layout = &(dset->shared->layout); /* Dataset's layout */
const H5D_rdcc_t *rdcc = &(dset->shared->cache.chunk); /*raw data chunk cache */
H5D_rdcc_ent_t *ent = NULL; /* Cache entry */
- int space_ndims; /* Dataset's space rank */
- hsize_t space_dim[H5O_LAYOUT_NDIMS]; /* Current dataspace dimensions */
- int op_dim; /* Current operationg dimension */
+ unsigned space_ndims; /* Dataset's space rank */
+ const hsize_t *space_dim; /* Current dataspace dimensions */
+ unsigned op_dim; /* Current operating dimension */
hbool_t shrunk_dim[H5O_LAYOUT_NDIMS]; /* Dimensions which have shrunk */
H5D_chunk_it_ud1_t udata; /* Chunk index iterator user data */
hbool_t udata_init = FALSE; /* Whether the chunk index iterator user data has been initialized */
H5D_chunk_common_ud_t idx_udata; /* User data for index removal routine */
- H5D_chunk_ud_t chk_udata; /* User data for getting chunk info */
H5S_t *chunk_space = NULL; /* Dataspace for a chunk */
hsize_t chunk_dim[H5O_LAYOUT_NDIMS]; /* Chunk dimensions */
hsize_t chunk_offset[H5O_LAYOUT_NDIMS]; /* Offset of current chunk */
@@ -4012,16 +4016,14 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't fill dxpl cache")
/* Go get the rank & dimensions (including the element size) */
- if((space_ndims = H5S_get_simple_extent_dims(dset->shared->space, space_dim,
- NULL)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get dataset dimensions")
- space_dim[space_ndims] = layout->u.chunk.dim[space_ndims];
+ space_dim = dset->shared->curr_dims;
+ space_ndims = dset->shared->ndims;
/* The last dimension in chunk_offset is always 0 */
chunk_offset[space_ndims] = (hsize_t)0;
/* Check if any old dimensions are 0, if so we do not have to do anything */
- for(op_dim=0; op_dim<space_ndims; op_dim++)
+ for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++)
if(old_dim[op_dim] == 0) {
/* Reset any cached chunk info for this dataset */
H5D__chunk_cinfo_cache_reset(&dset->shared->cache.chunk.last);
@@ -4034,14 +4036,14 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
/* (also copy the chunk dimensions into 'hsize_t' array for creating dataspace) */
/* (also compute the dimensions which have been shrunk) */
elmts_per_chunk = 1;
- for(u = 0; u < (unsigned)space_ndims; u++) {
+ for(u = 0; u < space_ndims; u++) {
elmts_per_chunk *= layout->u.chunk.dim[u];
chunk_dim[u] = layout->u.chunk.dim[u];
shrunk_dim[u] = space_dim[u] < old_dim[u];
} /* end for */
/* Create a dataspace for a chunk & set the extent */
- if(NULL == (chunk_space = H5S_create_simple((unsigned)space_ndims, chunk_dim, NULL)))
+ if(NULL == (chunk_space = H5S_create_simple(space_ndims, chunk_dim, NULL)))
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "can't create simple dataspace")
/* Reset hyperslab start array */
@@ -4065,7 +4067,6 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = &layout->u.chunk;
udata.common.storage = &layout->storage.u.chunk;
- udata.common.rdcc = rdcc;
udata.io_info = &chk_io_info;
udata.idx_info = &idx_info;
udata.space_dim = space_dim;
@@ -4084,7 +4085,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
*/
HDmemset(min_mod_chunk_off, 0, sizeof(min_mod_chunk_off));
HDmemset(max_mod_chunk_off, 0, sizeof(max_mod_chunk_off));
- for(op_dim = 0; op_dim < space_ndims; op_dim++) {
+ for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++) {
/* Calculate the largest offset of chunks that might need to be
* modified in this dimension */
max_mod_chunk_off[op_dim] = chunk_dim[op_dim] * ((old_dim[op_dim] - 1)
@@ -4119,21 +4120,8 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
fill_dim[op_dim] = FALSE;
} /* end for */
- /* Check the cache for any entries that are outside the bounds. Mark these
- * entries as deleted so they are not flushed to disk accidentally. This is
- * only necessary if there are chunks that need to be filled. */
- if(has_fill)
- for(ent = rdcc->head; ent; ent = ent->next)
- /* Check for chunk offset outside of new dimensions */
- for(u = 0; u < (unsigned)space_ndims; u++)
- if((hsize_t)ent->offset[u] >= space_dim[u]) {
- /* Mark the entry as "deleted" */
- ent->deleted = TRUE;
- break;
- } /* end if */
-
/* Main loop: fill or remove chunks */
- for(op_dim=0; op_dim<space_ndims; op_dim++) {
+ for(op_dim = 0; op_dim < (unsigned)space_ndims; op_dim++) {
/* Check if modification along this dimension is really necessary */
if(!shrunk_dim[op_dim])
continue;
@@ -4141,12 +4129,12 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
HDassert((hsize_t) max_mod_chunk_off[op_dim] >= min_mod_chunk_off[op_dim]);
/* Reset the chunk offset indices */
- HDmemset(chunk_offset, 0, ((unsigned)space_ndims * sizeof(chunk_offset[0])));
+ HDmemset(chunk_offset, 0, (space_ndims * sizeof(chunk_offset[0])));
chunk_offset[op_dim] = min_mod_chunk_off[op_dim];
/* Initialize "dims_outside_fill" array */
ndims_outside_fill = 0;
- for(u = 0; u < (unsigned)space_ndims; u++)
+ for(u = 0; u < space_ndims; u++)
if((hssize_t)chunk_offset[u] > max_fill_chunk_off[u]) {
dims_outside_fill[u] = TRUE;
ndims_outside_fill++;
@@ -4161,10 +4149,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
int i; /* Local index variable */
/* Calculate the index of this chunk */
- if(H5VM_chunk_index((unsigned)space_ndims, chunk_offset,
- layout->u.chunk.dim, layout->u.chunk.down_chunks,
- &(chk_io_info.store->chunk.index)) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't get chunk index")
+ chk_io_info.store->chunk.index = H5VM_chunk_index(space_ndims, chunk_offset, layout->u.chunk.dim, layout->u.chunk.down_chunks);
if(0 == ndims_outside_fill) {
HDassert(fill_dim[op_dim]);
@@ -4175,12 +4160,14 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to write fill value")
} /* end if */
else {
+ H5D_chunk_ud_t chk_udata; /* User data for getting chunk info */
+
#ifndef NDEBUG
/* Make sure this chunk is really outside the new dimensions */
{
hbool_t outside_dim = FALSE;
- for(u = 0; u < (unsigned)space_ndims; u++)
+ for(u = 0; u < space_ndims; u++)
if(chunk_offset[u] >= space_dim[u]) {
outside_dim = TRUE;
break;
@@ -4200,7 +4187,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
HGOTO_ERROR(H5E_DATASET, H5E_CANTREMOVE, FAIL, "unable to evict chunk")
/* Remove the chunk from disk, if present */
- if(H5F_addr_defined(chk_udata.addr)) {
+ if(H5F_addr_defined(chk_udata.chunk_block.offset)) {
/* Update the offset in idx_udata */
idx_udata.offset = chunk_offset;
@@ -4217,7 +4204,7 @@ H5D__chunk_prune_by_extent(H5D_t *dset, hid_t dxpl_id, const hsize_t *old_dim)
if(chunk_offset[i] > (hsize_t) max_mod_chunk_off[i]) {
/* Left maximum dimensions, "wrap around" and check if this
* dimension is no longer outside the fill dimension */
- if(i == op_dim) {
+ if((unsigned)i == op_dim) {
chunk_offset[i] = min_mod_chunk_off[i];
if(dims_outside_fill[i] && fill_dim[i]) {
dims_outside_fill[i] = FALSE;
@@ -4295,8 +4282,7 @@ H5D__chunk_addrmap_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
FUNC_ENTER_STATIC
/* Compute the index for this chunk */
- if(H5VM_chunk_index(rank, chunk_rec->offset, udata->common.layout->dim, udata->common.layout->down_chunks, &chunk_index) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, H5_ITER_ERROR, "can't get chunk index")
+ chunk_index = H5VM_chunk_index(rank, chunk_rec->offset, udata->common.layout->dim, udata->common.layout->down_chunks);
/* Set it in the userdata to return */
udata->chunk_addr[chunk_index] = chunk_rec->chunk_addr;
@@ -4337,7 +4323,6 @@ H5D__chunk_addrmap(const H5D_io_info_t *io_info, haddr_t chunk_addr[])
HDmemset(&udata, 0, sizeof(udata));
udata.common.layout = &dset->shared->layout.u.chunk;
udata.common.storage = &dset->shared->layout.storage.u.chunk;
- udata.common.rdcc = &(dset->shared->cache.chunk);
udata.chunk_addr = chunk_addr;
/* Compose chunked index info struct */
@@ -4453,7 +4438,6 @@ 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_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 */
@@ -4466,7 +4450,7 @@ H5D__chunk_update_cache(H5D_t *dset, hid_t dxpl_id)
HDassert(dset->shared->layout.u.chunk.ndims > 0 && dset->shared->layout.u.chunk.ndims <= H5O_LAYOUT_NDIMS);
/* Get the rank */
- rank = dset->shared->layout.u.chunk.ndims-1;
+ rank = dset->shared->layout.u.chunk.ndims - 1;
HDassert(rank > 0);
/* 1-D dataset's chunks can't have their index change */
@@ -4486,36 +4470,51 @@ H5D__chunk_update_cache(H5D_t *dset, hid_t dxpl_id)
next = ent->next;
/* Calculate the index of this chunk */
- if(H5VM_chunk_index(rank, ent->offset, dset->shared->layout.u.chunk.dim, dset->shared->layout.u.chunk.down_chunks, &idx) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "can't get chunk index")
+ idx = H5VM_chunk_index(rank, ent->offset, dset->shared->layout.u.chunk.dim, dset->shared->layout.u.chunk.down_chunks);
/* Compute the index for the chunk entry */
old_idx = ent->idx; /* Save for later */
ent->idx = H5D_CHUNK_HASH(dset->shared, idx);
if(old_idx != ent->idx) {
+ H5D_rdcc_ent_t *old_ent; /* Old cache entry */
+
/* Check if there is already a chunk at this chunk's new location */
old_ent = rdcc->slot[ent->idx];
if(old_ent != NULL) {
- HDassert(old_ent->locked == 0);
+ HDassert(old_ent->locked == FALSE);
+ HDassert(old_ent->deleted == FALSE);
- /* 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")
+ /* Mark the old entry as deleted, but do not evict (yet).
+ * Make sure we do not make any calls to the index
+ * until all chunks have updated indices! */
+ old_ent->deleted = TRUE;
} /* 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 marked as deleted and therefore
+ * not in the hash table, reset the deleted flag.
+ * Otherwise clear the old hash table slot. */
+ if(ent->deleted)
+ ent->deleted = FALSE;
+ else
+ rdcc->slot[old_idx] = NULL;
} /* end if */
} /* end for */
+ /* Evict chunks that are still marked as deleted */
+ for(ent = rdcc->head; ent; ent = next) {
+ /* Get the pointer to the next cache entry */
+ next = ent->next;
+
+ /* Remove the old entry from the cache */
+ if(ent->deleted)
+ if(H5D__chunk_cache_evict(dset, dxpl_id, dxpl_cache, ent, TRUE) < 0)
+ HGOTO_ERROR(H5E_IO, H5E_CANTFLUSH, FAIL, "unable to flush one or more raw data chunks")
+ } /* end for */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_update_cache() */
@@ -4541,6 +4540,7 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
H5D_chunk_ud_t udata_dst; /* User data about new destination chunk */
hbool_t is_vlen = FALSE; /* Whether datatype is variable-length */
hbool_t fix_ref = FALSE; /* Whether to fix up references in the dest. file */
+ hbool_t need_insert = FALSE; /* Whether the chunk needs to be inserted into the index */
/* General information about chunk copy */
void *bkg = udata->bkg; /* Background buffer for datatype conversion */
@@ -4662,13 +4662,12 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
udata_dst.common.layout = udata->idx_info_dst->layout;
udata_dst.common.storage = udata->idx_info_dst->storage;
udata_dst.common.offset = chunk_rec->offset;
- udata_dst.common.rdcc = NULL;
- udata_dst.nbytes = chunk_rec->nbytes;
+ udata_dst.chunk_block.offset = HADDR_UNDEF;
+ udata_dst.chunk_block.length = chunk_rec->nbytes;
udata_dst.filter_mask = chunk_rec->filter_mask;
- udata_dst.addr = HADDR_UNDEF;
/* Need to compress variable-length & reference data elements before writing to file */
- if(has_filters && (is_vlen || fix_ref) ) {
+ if(has_filters && (is_vlen || fix_ref)) {
if(H5Z_pipeline(pline, 0, &(udata_dst.filter_mask), H5Z_NO_EDC, cb_struct, &nbytes, &buf_size, &buf) < 0)
HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "output pipeline failed")
#if H5_SIZEOF_SIZE_T > 4
@@ -4676,26 +4675,31 @@ H5D__chunk_copy_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata)
if(nbytes > ((size_t)0xffffffff))
HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, H5_ITER_ERROR, "chunk too large for 32-bit length")
#endif /* H5_SIZEOF_SIZE_T > 4 */
- H5_ASSIGN_OVERFLOW(udata_dst.nbytes, nbytes, size_t, uint32_t);
+ H5_ASSIGN_OVERFLOW(udata_dst.chunk_block.length, nbytes, size_t, uint32_t);
udata->buf = buf;
udata->buf_size = buf_size;
} /* end if */
+ /* Allocate chunk in the file */
+ if(H5D__chunk_file_alloc(udata->idx_info_dst, NULL, &udata_dst.chunk_block, &need_insert) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, FAIL, "unable to insert/resize chunk on chunk level")
+
+ /* Write chunk data to destination file */
+ HDassert(H5F_addr_defined(udata_dst.chunk_block.offset));
+ if(H5F_block_write(udata->idx_info_dst->f, H5FD_MEM_DRAW, udata_dst.chunk_block.offset, nbytes, udata->idx_info_dst->dxpl_id, buf) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, H5_ITER_ERROR, "unable to write raw data to file")
+
/* Set metadata tag in dxpl_id */
H5_BEGIN_TAG(udata->idx_info_dst->dxpl_id, H5AC__COPIED_TAG, H5_ITER_ERROR);
- /* Insert chunk into the destination index */
- if((udata->idx_info_dst->storage->ops->insert)(udata->idx_info_dst, &udata_dst) < 0)
- HGOTO_ERROR_TAG(H5E_DATASET, H5E_CANTINSERT, H5_ITER_ERROR, "unable to insert chunk into index")
+ /* Insert chunk record into index */
+ if(need_insert && udata->idx_info_dst->storage->ops->insert)
+ if((udata->idx_info_dst->storage->ops->insert)(udata->idx_info_dst, &udata_dst) < 0)
+ HGOTO_ERROR_TAG(H5E_DATASET, H5E_CANTINSERT, H5_ITER_ERROR, "unable to insert chunk addr into index")
/* Reset metadata tag in dxpl_id */
H5_END_TAG(H5_ITER_ERROR);
- /* Write chunk data to destination file */
- HDassert(H5F_addr_defined(udata_dst.addr));
- if(H5F_block_write(udata->idx_info_dst->f, H5FD_MEM_DRAW, udata_dst.addr, nbytes, udata->idx_info_dst->dxpl_id, buf) < 0)
- HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, H5_ITER_ERROR, "unable to write raw data to file")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5D__chunk_copy_cb() */
@@ -4906,7 +4910,6 @@ H5D__chunk_copy(H5F_t *f_src, H5O_storage_chunk_t *storage_src,
HDmemset(&udata, 0, sizeof udata);
udata.common.layout = layout_src;
udata.common.storage = storage_src;
- udata.common.rdcc = NULL;
udata.file_src = f_src;
udata.idx_info_dst = &idx_info_dst;
udata.buf = buf;
@@ -4952,7 +4955,7 @@ done:
/* Clean up any index information */
if(copy_setup_done)
- if((storage_src->ops->copy_shutdown)(storage_src, storage_dst, dxpl_id) < 0)
+ if(storage_src->ops->copy_shutdown && (storage_src->ops->copy_shutdown)(storage_src, storage_dst, dxpl_id) < 0)
HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "unable to shut down index copying info")
FUNC_LEAVE_NOAPI(ret_value)
@@ -5337,3 +5340,114 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5D__nonexistent_readvv() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5D__chunk_file_alloc()
+ *
+ * Purpose: Chunk allocation:
+ * Create the chunk if it doesn't exist, or reallocate the
+ * chunk if its size changed.
+ * The coding is moved and modified from each index structure.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Vailin Choi; June 2014
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5D__chunk_file_alloc(const H5D_chk_idx_info_t *idx_info, const H5F_block_t *old_chunk,
+ H5F_block_t *new_chunk, hbool_t *need_insert)
+{
+ hbool_t alloc_chunk = FALSE; /* Whether to allocate chunk */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_STATIC
+
+ /* Sanity check */
+ HDassert(idx_info);
+ HDassert(idx_info->f);
+ HDassert(idx_info->pline);
+ HDassert(idx_info->layout);
+ HDassert(idx_info->storage);
+ HDassert(H5F_addr_defined(idx_info->storage->idx_addr));
+ HDassert(new_chunk);
+ HDassert(need_insert);
+
+ /* Check for filters on chunks */
+ if(idx_info->pline->nused > 0) {
+ /* Sanity/error checking block */
+ {
+ unsigned allow_chunk_size_len; /* Allowed size of encoded chunk size */
+ unsigned new_chunk_size_len; /* Size of encoded chunk size */
+
+ /* Compute the size required for encoding the size of a chunk, allowing
+ * for an extra byte, in case the filter makes the chunk larger.
+ */
+ allow_chunk_size_len = 1 + ((H5VM_log2_gen((uint64_t)(idx_info->layout->size)) + 8) / 8);
+ if(allow_chunk_size_len > 8)
+ allow_chunk_size_len = 8;
+
+ /* Compute encoded size of chunk */
+ new_chunk_size_len = (H5VM_log2_gen((uint64_t)(new_chunk->length)) + 8) / 8;
+ if(new_chunk_size_len > 8)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "encoded chunk size is more than 8 bytes?!?")
+
+ /* Check if the chunk became too large to be encoded */
+ if(new_chunk_size_len > allow_chunk_size_len)
+ HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "chunk size can't be encoded")
+ } /* end block */
+
+ if(old_chunk && H5F_addr_defined(old_chunk->offset)) {
+ /* Sanity check */
+ HDassert(!H5F_addr_defined(new_chunk->offset) || H5F_addr_eq(new_chunk->offset, old_chunk->offset));
+
+ /* Check for chunk being same size */
+ if(new_chunk->length != old_chunk->length) {
+ /* Release previous chunk */
+ if(H5MF_xfree(idx_info->f, H5FD_MEM_DRAW, idx_info->dxpl_id, old_chunk->offset, old_chunk->length) < 0)
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to free chunk")
+ alloc_chunk = TRUE;
+ } /* end if */
+ else {
+ /* Don't need to reallocate chunk, but send its address back up */
+ if(!H5F_addr_defined(new_chunk->offset))
+ new_chunk->offset = old_chunk->offset;
+ } /* end else */
+ } /* end if */
+ else {
+ HDassert(!H5F_addr_defined(new_chunk->offset));
+ alloc_chunk = TRUE;
+ } /* end else */
+ } /* end if */
+ else {
+ HDassert(!H5F_addr_defined(new_chunk->offset));
+ HDassert(new_chunk->length == idx_info->layout->size);
+ alloc_chunk = TRUE;
+ } /* end else */
+
+ /* Actually allocate space for the chunk in the file */
+ if(alloc_chunk) {
+ switch(idx_info->storage->idx_type) {
+ case H5D_CHUNK_IDX_BTREE:
+ HDassert(new_chunk->length > 0);
+ H5_CHECK_OVERFLOW(new_chunk->length, /*From: */uint32_t, /*To: */hsize_t);
+ new_chunk->offset = H5MF_alloc(idx_info->f, H5FD_MEM_DRAW, idx_info->dxpl_id, (hsize_t)new_chunk->length);
+ if(!H5F_addr_defined(new_chunk->offset))
+ HGOTO_ERROR(H5E_DATASET, H5E_CANTALLOC, FAIL, "file allocation failed")
+ *need_insert = TRUE;
+ break;
+
+ case H5D_CHUNK_IDX_NTYPES:
+ default:
+ HDassert(0 && "This should never be executed!");
+ break;
+ } /* end switch */
+ } /* end if */
+
+ HDassert(H5F_addr_defined(new_chunk->offset));
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5D__chunk_file_alloc() */
+