diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2016-05-12 20:47:03 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2016-05-12 20:47:03 (GMT) |
commit | 18ad868b231754e4da03c79828e8b18a2d63c80a (patch) | |
tree | b1d25c0dd14fc2cfb50108a53e55f103488719c1 /src | |
parent | 92806fb5e6778373638c29d36ef3e4c1c1ac3ab0 (diff) | |
download | hdf5-18ad868b231754e4da03c79828e8b18a2d63c80a.zip hdf5-18ad868b231754e4da03c79828e8b18a2d63c80a.tar.gz hdf5-18ad868b231754e4da03c79828e8b18a2d63c80a.tar.bz2 |
[svn-r29924] Description:
Bring h5format_convert tool from revise_chunks branch to trunk.
Tested on:
MacoSX/64 10.11.4 (amazon) w/serial, parallel & production
(h5committest forthcoming)
Diffstat (limited to 'src')
-rw-r--r-- | src/H5D.c | 104 | ||||
-rw-r--r-- | src/H5Dchunk.c | 142 | ||||
-rw-r--r-- | src/H5Dint.c | 120 | ||||
-rw-r--r-- | src/H5Dpkg.h | 4 | ||||
-rw-r--r-- | src/H5Dpublic.h | 4 | ||||
-rw-r--r-- | src/H5F.c | 70 | ||||
-rw-r--r-- | src/H5Fprivate.h | 1 | ||||
-rw-r--r-- | src/H5Fpublic.h | 1 | ||||
-rw-r--r-- | src/H5MF.c | 188 | ||||
-rw-r--r-- | src/H5MFprivate.h | 1 |
10 files changed, 584 insertions, 51 deletions
@@ -379,7 +379,7 @@ H5Dget_space(hid_t dset_id) done: FUNC_LEAVE_API(ret_value) -} +} /* end H5Dget_space() */ /*------------------------------------------------------------------------- @@ -415,7 +415,7 @@ H5Dget_space_status(hid_t dset_id, H5D_space_status_t *allocation) done: FUNC_LEAVE_API(ret_value) -} +} /* H5Dget_space_status() */ /*------------------------------------------------------------------------- @@ -955,3 +955,103 @@ done: FUNC_LEAVE_API(ret_value) } /* H5Dflush */ + +/*------------------------------------------------------------------------- + * Function: H5Dformat_convert (Internal) + * + * Purpose: For chunked: + * Convert the chunk indexing type to version 1 B-tree if not + * For compact/contiguous: + * Downgrade layout version to 3 if greater than 3 + * For virtual: no conversion + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Vailin Choi + * Feb 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dformat_convert(hid_t dset_id) +{ + H5D_t *dset; /* Dataset to refresh */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", dset_id); + + /* Check args */ + if(NULL == (dset = (H5D_t *)H5I_object_verify(dset_id, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + + switch(dset->shared->layout.type) { + case H5D_CHUNKED: + /* Convert the chunk indexing type to version 1 B-tree if not */ + if(dset->shared->layout.u.chunk.idx_type != H5D_CHUNK_IDX_BTREE) + if((H5D__format_convert(dset, H5AC_ind_read_dxpl_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, FAIL, "unable to downgrade chunk indexing type for dataset") + break; + + case H5D_CONTIGUOUS: + case H5D_COMPACT: + /* Downgrade the layout version to 3 if greater than 3 */ + if(dset->shared->layout.version > H5O_LAYOUT_VERSION_DEFAULT) + if((H5D__format_convert(dset, H5AC_ind_read_dxpl_id)) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTLOAD, FAIL, "unable to downgrade layout version for dataset") + break; + + case H5D_VIRTUAL: + /* Nothing to do even though layout is version 4 */ + break; + + case H5D_LAYOUT_ERROR: + case H5D_NLAYOUTS: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset layout type") + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown dataset layout type") + } /* end switch */ + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Dformat_convert */ + + +/*------------------------------------------------------------------------- + * Function: H5Dget_chunk_index_type (Internal) + * + * Purpose: Retrieve a dataset's chunk indexing type + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Vailin Choi + * Feb 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Dget_chunk_index_type(hid_t did, H5D_chunk_index_t *idx_type) +{ + H5D_t *dset; /* Dataset to refresh */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE2("e", "i*Dk", did, idx_type); + + /* Check args */ + if(NULL == (dset = (H5D_t *)H5I_object_verify(did, H5I_DATASET))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataset") + + /* Should be a chunked dataset */ + if(dset->shared->layout.type != H5D_CHUNKED) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "dataset is not chunked") + + /* Get the chunk indexing type */ + if(idx_type) + *idx_type = dset->shared->layout.u.chunk.idx_type; + +done: + FUNC_LEAVE_API(ret_value) +} /* H5Dget_chunk_index_type() */ + diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c index da6a717..f4f9104 100644 --- a/src/H5Dchunk.c +++ b/src/H5Dchunk.c @@ -200,6 +200,13 @@ typedef struct H5D_chunk_it_ud4_t { uint32_t *chunk_dim; /* Chunk dimensions */ } H5D_chunk_it_ud4_t; +/* Callback info for iteration to format convert chunks */ +typedef struct H5D_chunk_it_ud5_t { + H5D_chk_idx_info_t *new_idx_info; /* Dest. chunk index info object */ + unsigned dset_ndims; /* Number of dimensions in dataset */ + hsize_t *dset_dims; /* Dataset dimensions */ +} H5D_chunk_it_ud5_t; + /* Callback info for nonexistent readvv operation */ typedef struct H5D_chunk_readvv_ud_t { unsigned char *rbuf; /* Read buffer to initialize */ @@ -250,6 +257,9 @@ H5D__nonexistent_readvv(const H5D_io_info_t *io_info, size_t chunk_max_nseq, size_t *chunk_curr_seq, size_t chunk_len_arr[], hsize_t chunk_offset_arr[], size_t mem_max_nseq, size_t *mem_curr_seq, size_t mem_len_arr[], hsize_t mem_offset_arr[]); +/* format convert cb */ +static int H5D__chunk_format_convert_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata); + /* Helper routines */ static herr_t H5D__chunk_set_info_real(H5O_layout_chunk_t *layout, unsigned ndims, const hsize_t *curr_dims, const hsize_t *max_dims); @@ -6336,3 +6346,135 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* H5D__chunk_file_alloc() */ + +/*------------------------------------------------------------------------- + * Function: H5D__chunk_format_convert_cb + * + * Purpose: Callback routine to insert chunk address into v1 B-tree + * chunk index. + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Vailin Choi + * Feb 2015 + * + *------------------------------------------------------------------------- + */ +static int +H5D__chunk_format_convert_cb(const H5D_chunk_rec_t *chunk_rec, void *_udata) +{ + H5D_chunk_it_ud5_t *udata = (H5D_chunk_it_ud5_t *)_udata; /* User data */ + H5D_chk_idx_info_t *new_idx_info; /* The new chunk index information */ + H5D_chunk_ud_t insert_udata; /* Chunk information to be inserted */ + haddr_t chunk_addr; /* Chunk address */ + size_t nbytes; /* Chunk size */ + void *buf = NULL; /* Pointer to buffer of chunk data */ + int ret_value = H5_ITER_CONT; /* Return value */ + + FUNC_ENTER_STATIC + + /* Set up */ + new_idx_info = udata->new_idx_info; + H5_CHECKED_ASSIGN(nbytes, size_t, chunk_rec->nbytes, uint32_t); + chunk_addr = chunk_rec->chunk_addr; + + if(new_idx_info->pline->nused && + (new_idx_info->layout->flags & H5O_LAYOUT_CHUNK_DONT_FILTER_PARTIAL_BOUND_CHUNKS) && + (H5D__chunk_is_partial_edge_chunk(udata->dset_ndims, new_idx_info->layout->dim, chunk_rec->scaled, udata->dset_dims))) { + /* This is a partial non-filtered edge chunk */ + /* Convert the chunk to a filtered edge chunk for v1 B-tree chunk index */ + + unsigned filter_mask = chunk_rec->filter_mask; + H5Z_cb_t cb_struct; /* Filter failure callback struct */ + size_t read_size = nbytes; /* Bytes to read */ + + HDassert(read_size == new_idx_info->layout->size); + + cb_struct.func = NULL; /* no callback function when failed */ + + /* Allocate buffer for chunk data */ + if(NULL == (buf = H5MM_malloc(read_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5_ITER_ERROR, "memory allocation failed for raw data chunk") + + /* Read the non-filtered edge chunk */ + if(H5F_block_read(new_idx_info->f, H5FD_MEM_DRAW, chunk_addr, read_size, H5AC_rawdata_dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_IO, H5E_READERROR, H5_ITER_ERROR, "unable to read raw data chunk") + + /* Pass the chunk through the pipeline */ + if(H5Z_pipeline(new_idx_info->pline, 0, &filter_mask, H5Z_NO_EDC, cb_struct, &nbytes, &read_size, &buf) < 0) + HGOTO_ERROR(H5E_PLINE, H5E_CANTFILTER, H5_ITER_ERROR, "output pipeline failed") + +#if H5_SIZEOF_SIZE_T > 4 + /* Check for the chunk expanding too much to encode in a 32-bit value */ + 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 */ + + /* Allocate space for the filtered chunk */ + if((chunk_addr = H5MF_alloc(new_idx_info->f, H5FD_MEM_DRAW, new_idx_info->dxpl_id, (hsize_t)nbytes)) == HADDR_UNDEF) + HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, H5_ITER_ERROR, "file allocation failed for filtered chunk") + HDassert(H5F_addr_defined(chunk_addr)); + + /* Write the filtered chunk to disk */ + if(H5F_block_write(new_idx_info->f, H5FD_MEM_DRAW, chunk_addr, nbytes, H5AC_rawdata_dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_WRITEERROR, H5_ITER_ERROR, "unable to write raw data to file") + } /* end if */ + + /* Set up chunk information for insertion to chunk index */ + insert_udata.chunk_block.offset = chunk_addr; + insert_udata.chunk_block.length = nbytes; + insert_udata.filter_mask = chunk_rec->filter_mask; + insert_udata.common.scaled = chunk_rec->scaled; + insert_udata.common.layout = new_idx_info->layout; + insert_udata.common.storage = new_idx_info->storage; + + /* Insert chunk into the v1 B-tree chunk index */ + if((new_idx_info->storage->ops->insert)(new_idx_info, &insert_udata, NULL) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINSERT, H5_ITER_ERROR, "unable to insert chunk addr into index") + +done: + if(buf) + H5MM_xfree(buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5D__chunk_format_convert_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5D__chunk_format_convert + * + * Purpose: Iterate over the chunks for the current chunk index and insert the + * the chunk addresses into v1 B-tree chunk index via callback. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi + * Feb 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D__chunk_format_convert(H5D_t *dset, H5D_chk_idx_info_t *idx_info, H5D_chk_idx_info_t *new_idx_info) +{ + H5D_chunk_it_ud5_t udata; /* User data */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Check args */ + HDassert(dset); + + /* Set up user data */ + udata.new_idx_info = new_idx_info; + udata.dset_ndims = dset->shared->ndims; + udata.dset_dims = dset->shared->curr_dims; + + /* terate over the chunks in the current index and insert the chunk addresses into version 1 B-tree index */ + if((dset->shared->layout.storage.u.chunk.ops->iterate)(idx_info, H5D__chunk_format_convert_cb, &udata) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk index to chunk info") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5D__chunk_format_convert() */ + diff --git a/src/H5Dint.c b/src/H5Dint.c index ae25d17..322776b 100644 --- a/src/H5Dint.c +++ b/src/H5Dint.c @@ -2832,6 +2832,126 @@ done: /*------------------------------------------------------------------------- + * Function: H5D__format_convert + * + * Purpose: For chunked: downgrade the chunk indexing type to version 1 B-tree + * For compact/contiguous: downgrade layout version to 3 + * + * Return: Success: Non-negative + * Failure: Negative + * + * Programmer: Vailin Choi + * Feb 2015 + * + *------------------------------------------------------------------------- + */ +herr_t +H5D__format_convert(H5D_t *dataset, hid_t dxpl_id) +{ + H5O_t *oh = NULL; /* Pointer to dataset's object header */ + H5D_chk_idx_info_t new_idx_info; /* Index info for the new layout */ + H5D_chk_idx_info_t idx_info; /* Index info for the current layout */ + H5O_layout_t newlayout; /* The new layout */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_PACKAGE_TAG(dxpl_id, dataset->oloc.addr, FAIL) + + /* Check args */ + HDassert(dataset); + + switch(dataset->shared->layout.type) { + case H5D_CHUNKED: + HDassert(dataset->shared->layout.u.chunk.idx_type != H5D_CHUNK_IDX_BTREE); + + /* Set up the current index info */ + idx_info.f = dataset->oloc.file; + idx_info.dxpl_id = dxpl_id; + idx_info.pline = &dataset->shared->dcpl_cache.pline; + idx_info.layout = &dataset->shared->layout.u.chunk; + idx_info.storage = &dataset->shared->layout.storage.u.chunk; + + /* Copy the current layout info to the new layout */ + HDmemcpy(&newlayout, &dataset->shared->layout, sizeof(H5O_layout_t)); + + /* Set up info for version 1 B-tree in the new layout */ + newlayout.version = H5O_LAYOUT_VERSION_3; + newlayout.storage.u.chunk.idx_type = H5D_CHUNK_IDX_BTREE; + newlayout.storage.u.chunk.idx_addr = HADDR_UNDEF; + newlayout.storage.u.chunk.ops = H5D_COPS_BTREE; + newlayout.storage.u.chunk.u.btree.shared = NULL; + + /* Set up the index info to version 1 B-tree */ + new_idx_info.f = dataset->oloc.file; + new_idx_info.dxpl_id = dxpl_id; + new_idx_info.pline = &dataset->shared->dcpl_cache.pline; + new_idx_info.layout = &newlayout.u.chunk; + new_idx_info.storage = &newlayout.storage.u.chunk; + + /* Initialize version 1 B-tree */ + if(newlayout.storage.u.chunk.ops->init && (newlayout.storage.u.chunk.ops->init)(&new_idx_info, dataset->shared->space, dataset->oloc.addr) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't initialize indexing information") + + /* If the current chunk index exists */ + if(H5F_addr_defined(dataset->shared->layout.storage.u.chunk.idx_addr)) { + /* Create v1 B-tree chunk index */ + if((newlayout.storage.u.chunk.ops->create)(&new_idx_info) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "can't create chunk index") + + /* Iterate over the chunks in the current index and insert the chunk addresses + * into the version 1 B-tree chunk index */ + if(H5D__chunk_format_convert(dataset, &idx_info, &new_idx_info) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_BADITER, FAIL, "unable to iterate over chunk index to chunk info") + } /* end if */ + + /* Release the old (i.e. current) chunk index */ + if(dataset->shared->layout.storage.u.chunk.ops->dest && (dataset->shared->layout.storage.u.chunk.ops->dest)(&idx_info) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTFREE, FAIL, "unable to release chunk index info") + + /* Delete the "layout" message */ + if(H5O_msg_remove(&dataset->oloc, H5O_LAYOUT_ID, H5O_ALL, TRUE, dxpl_id) < 0) + HGOTO_ERROR(H5E_SYM, H5E_CANTDELETE, FAIL, "unable to delete layout message") + + HDmemcpy(&dataset->shared->layout, &newlayout, sizeof(H5O_layout_t)); + + if(NULL == (oh = H5O_pin(&dataset->oloc, dxpl_id))) + HGOTO_ERROR(H5E_DATASET, H5E_CANTPIN, FAIL, "unable to pin dataset object header") + + /* Append the new layout message to the object header */ + if(H5O_msg_append_oh(dataset->oloc.file, dxpl_id, oh, H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &newlayout) < 0) + HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to update old fill value header message") + + break; + + case H5D_CONTIGUOUS: + case H5D_COMPACT: + HDassert(dataset->shared->layout.version > H5O_LAYOUT_VERSION_DEFAULT); + dataset->shared->layout.version = H5O_LAYOUT_VERSION_DEFAULT; + if(H5O_msg_write(&(dataset->oloc), H5O_LAYOUT_ID, 0, H5O_UPDATE_TIME, &(dataset->shared->layout), dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to update layout message") + break; + + case H5D_VIRTUAL: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "virtual dataset layout not supported") + + case H5D_LAYOUT_ERROR: + case H5D_NLAYOUTS: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid dataset layout type") + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "unknown dataset layout type") + } /* end switch */ + +done: + /* Release pointer to object header */ + if(oh != NULL) + if(H5O_unpin(oh) < 0) + HDONE_ERROR(H5E_DATASET, H5E_CANTUNPIN, FAIL, "unable to unpin dataset object header") + + FUNC_LEAVE_NOAPI_TAG(ret_value, FAIL) +} /* end H5D__format_convert() */ + + +/*------------------------------------------------------------------------- * Function: H5D__mark * * Purpose: Mark some aspect of a dataset as dirty diff --git a/src/H5Dpkg.h b/src/H5Dpkg.h index c0b8b28..3b2727f 100644 --- a/src/H5Dpkg.h +++ b/src/H5Dpkg.h @@ -583,6 +583,9 @@ H5_DLL herr_t H5D__mark(const H5D_t *dataset, hid_t dxpl_id, unsigned flags); H5_DLL herr_t H5D_set_io_info_dxpls(H5D_io_info_t *io_info, hid_t dxpl_id); #endif /* H5_DEBUG_BUILD */ +/* To convert a dataset's chunk indexing type to v1 B-tree */ +H5_DLL herr_t H5D__format_convert(H5D_t *dataset, hid_t dxpl_id); + /* Internal I/O routines */ H5_DLL herr_t H5D__read(H5D_t *dataset, hid_t mem_type_id, const H5S_t *mem_space, const H5S_t *file_space, hid_t dset_xfer_plist, @@ -675,6 +678,7 @@ H5_DLL herr_t H5D__chunk_direct_write(const H5D_t *dset, hid_t dxpl_id, uint32_t #ifdef H5D_CHUNK_DEBUG H5_DLL herr_t H5D__chunk_stats(const H5D_t *dset, hbool_t headers); #endif /* H5D_CHUNK_DEBUG */ +H5_DLL herr_t H5D__chunk_format_convert(H5D_t *dset, H5D_chk_idx_info_t *idx_info, H5D_chk_idx_info_t *new_idx_info); /* Functions that operate on compact dataset storage */ H5_DLL herr_t H5D__compact_fill(const H5D_t *dset, hid_t dxpl_id); diff --git a/src/H5Dpublic.h b/src/H5Dpublic.h index e1555b9..831e811 100644 --- a/src/H5Dpublic.h +++ b/src/H5Dpublic.h @@ -167,6 +167,10 @@ H5_DLL herr_t H5Dgather(hid_t src_space_id, const void *src_buf, hid_t type_id, size_t dst_buf_size, void *dst_buf, H5D_gather_func_t op, void *op_data); H5_DLL herr_t H5Ddebug(hid_t dset_id); +/* Internal API routines */ +H5_DLL herr_t H5Dformat_convert(hid_t dset_id); +H5_DLL herr_t H5Dget_chunk_index_type(hid_t did, H5D_chunk_index_t *idx_type); + /* Symbols defined for compatibility with previous versions of the HDF5 API. * * Use of these symbols is deprecated. @@ -1442,3 +1442,73 @@ done: FUNC_LEAVE_API(ret_value) } /* end H5Fclear_elink_file_cache() */ + +/*------------------------------------------------------------------------- + * Function: H5Fformat_convert_super (Internal) + * + * Purpose: Downgrade the superblock version to v2 and + * downgrade persistent file space to non-persistent + * for 1.8 library. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Vailin Choi + * Jan 2016 + * + *------------------------------------------------------------------------- + */ +herr_t +H5Fformat_convert(hid_t fid) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_API(FAIL) + H5TRACE1("e", "i", fid); + + if(H5I_FILE == H5I_get_type(fid)) { + H5F_t *f; /* File to flush */ + hbool_t mark_dirty = FALSE; + + /* Get file object */ + if(NULL == (f = (H5F_t *)H5I_object(fid))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid file identifier") + + /* Check if the superblock should be downgraded */ + if(f->shared->sblock->super_vers > HDF5_SUPERBLOCK_VERSION_V18_LATEST) { + f->shared->sblock->super_vers = HDF5_SUPERBLOCK_VERSION_V18_LATEST; + mark_dirty = TRUE; + } /* end if */ + + /* Check for persistent freespace manager, which needs to be downgraded */ + if(!(f->shared->fs_strategy == H5F_FILE_SPACE_STRATEGY_DEF && + f->shared->fs_threshold == H5F_FREE_SPACE_THRESHOLD_DEF)) { + /* Check to remove free-space manager info message from superblock extension */ + if(H5F_addr_defined(f->shared->sblock->ext_addr)) + if(H5F_super_ext_remove_msg(f, H5AC_ind_read_dxpl_id, H5O_FSINFO_ID) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "error in removing message from superblock extension") + + /* Close freespace manager */ + if(H5MF_try_close(f, H5AC_ind_read_dxpl_id) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "unable to free free-space address") + + /* Set non-persistent freespace manager */ + f->shared->fs_strategy = H5F_FILE_SPACE_STRATEGY_DEF; + f->shared->fs_threshold = H5F_FREE_SPACE_THRESHOLD_DEF; + + /* Indicate that the superblock should be marked dirty */ + mark_dirty = TRUE; + } /* end if */ + + /* Check if we should mark the superblock dirty */ + if(mark_dirty) + /* Mark superblock as dirty */ + if(H5F_super_dirty(f) < 0) + HGOTO_ERROR(H5E_FILE, H5E_CANTMARKDIRTY, FAIL, "unable to mark superblock as dirty") + } /* end if */ + else + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object") + +done: + FUNC_LEAVE_API(ret_value) +} /* end H5Fformat_convert() */ + diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 93965e0..7d45ed9 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -484,6 +484,7 @@ #define HDF5_SUPERBLOCK_VERSION_1 1 /* Version with non-default B-tree 'K' value */ #define HDF5_SUPERBLOCK_VERSION_2 2 /* Revised version with superblock extension and checksum */ #define HDF5_SUPERBLOCK_VERSION_LATEST HDF5_SUPERBLOCK_VERSION_2 /* The maximum super block format */ +#define HDF5_SUPERBLOCK_VERSION_V18_LATEST HDF5_SUPERBLOCK_VERSION_2 /* The latest superblock version for v18 */ #define HDF5_FREESPACE_VERSION 0 /* of the Free-Space Info */ #define HDF5_OBJECTDIR_VERSION 0 /* of the Object Directory format */ #define HDF5_SHAREDHEADER_VERSION 0 /* of the Shared-Header Info */ diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 6fa18e1..fcccf07 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -219,6 +219,7 @@ H5_DLL herr_t H5Fget_info2(hid_t obj_id, H5F_info2_t *finfo); H5_DLL ssize_t H5Fget_free_sections(hid_t file_id, H5F_mem_t type, size_t nsects, H5F_sect_info_t *sect_info/*out*/); H5_DLL herr_t H5Fclear_elink_file_cache(hid_t file_id); +H5_DLL herr_t H5Fformat_convert(hid_t fid); #ifdef H5_HAVE_PARALLEL H5_DLL herr_t H5Fset_mpi_atomicity(hid_t file_id, hbool_t flag); H5_DLL herr_t H5Fget_mpi_atomicity(hid_t file_id, hbool_t *flag); @@ -86,6 +86,7 @@ typedef struct { /* Allocator routines */ static herr_t H5MF_alloc_create(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type); static herr_t H5MF_alloc_close(H5F_t *f, hid_t dxpl_id, H5FD_mem_t type); +static herr_t H5MF__close_delete(H5F_t *f, hid_t dxpl_id); /*********************/ @@ -1147,6 +1148,141 @@ done: /*------------------------------------------------------------------------- + * Function: H5MF__close_delete + * + * Purpose: Common code for closing and deleting freespace managers from + * the file. + * + * Return: SUCCEED/FAIL + * + * Programmer: Vailin Choi + * Jan 2016 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5MF__close_delete(H5F_t *f, hid_t dxpl_id) +{ + H5FD_mem_t type; /* Memory type for iteration */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_STATIC +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Entering\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG */ + + /* check args */ + HDassert(f); + HDassert(f->shared); + + /* Iterate over all the free space types that have managers and get each free list's space */ + for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) { +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + /* If the free space manager for this type is open, close it */ + if(f->shared->fs_man[type]) { +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Before closing free space manager\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + if(H5FS_close(f, dxpl_id, f->shared->fs_man[type]) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release free space info") + f->shared->fs_man[type] = NULL; + f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; + } /* end if */ +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* If there is free space manager info for this type, delete it */ + if(H5F_addr_defined(f->shared->fs_addr[type])) { + haddr_t tmp_fs_addr; /* Temporary holder for free space manager address */ + + /* Put address into temporary variable and reset it */ + /* (Avoids loopback in file space freeing routine) */ + tmp_fs_addr = f->shared->fs_addr[type]; + f->shared->fs_addr[type] = HADDR_UNDEF; + + /* Shift to "deleting" state, to make certain we don't track any + * file space freed as a result of deleting the free space manager. + */ + f->shared->fs_state[type] = H5F_FS_STATE_DELETING; + +#ifdef H5MF_ALLOC_DEBUG_MORE +HDfprintf(stderr, "%s: Before deleting free space manager\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG_MORE */ + + /* Delete free space manager for this type */ + if(H5FS_delete(f, dxpl_id, tmp_fs_addr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't delete free space manager") + + /* Shift [back] to closed state */ + HDassert(f->shared->fs_state[type] == H5F_FS_STATE_DELETING); + f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; + + /* Sanity check that the free space manager for this type wasn't started up again */ + HDassert(!H5F_addr_defined(f->shared->fs_addr[type])); + } /* end if */ + } /* end for */ + +done: +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Leaving\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF__close_delete() */ + + +/*------------------------------------------------------------------------- + * Function: H5MF_try_close + * + * Purpose: This is called by H5Fformat_convert() to close and delete + * free-space managers when downgrading persistent free-space + * to non-persistent. + * + * Return: SUCCEED/FAIL + * + * Programmer: Vailin Choi + * Jan 2016 + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_try_close(H5F_t *f, hid_t dxpl_id) +{ + H5P_genplist_t *dxpl = NULL; /* DXPL for setting ring */ + H5AC_ring_t orig_ring = H5AC_RING_INV; /* Original ring value */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(FAIL) +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Entering\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG */ + + /* check args */ + HDassert(f); + + /* Set the ring type in the DXPL */ + if(H5AC_set_ring(dxpl_id, H5AC_RING_FSM, &dxpl, &orig_ring) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSET, FAIL, "unable to set ring value") + + /* Close and delete freespace managers from the file */ + if(H5MF__close_delete(f, dxpl_id) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSET, FAIL, "unable to close delete free-space managers") + +done: + /* Reset the ring in the DXPL */ + if(H5AC_reset_ring(dxpl, orig_ring) < 0) + HDONE_ERROR(H5E_RESOURCE, H5E_CANTSET, FAIL, "unable to set property value") + +#ifdef H5MF_ALLOC_DEBUG +HDfprintf(stderr, "%s: Leaving\n", FUNC); +#endif /* H5MF_ALLOC_DEBUG */ + FUNC_LEAVE_NOAPI(ret_value) +} /* H5MF_try_close() */ + + +/*------------------------------------------------------------------------- * Function: H5MF_close * * Purpose: Close the free space tracker(s) for a file @@ -1287,55 +1423,9 @@ HDfprintf(stderr, "%s: Entering\n", FUNC); } /* end for */ } /* end if */ else { /* super_vers can be 0, 1, 2 */ - /* Iterate over all the free space types that have managers and get each free list's space */ - for(type = H5FD_MEM_DEFAULT; type < H5FD_MEM_NTYPES; H5_INC_ENUM(H5FD_mem_t, type)) { -#ifdef H5MF_ALLOC_DEBUG_MORE -HDfprintf(stderr, "%s: Check 1.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]); -#endif /* H5MF_ALLOC_DEBUG_MORE */ - /* If the free space manager for this type is open, close it */ - if(f->shared->fs_man[type]) { -#ifdef H5MF_ALLOC_DEBUG_MORE -HDfprintf(stderr, "%s: Before closing free space manager\n", FUNC); -#endif /* H5MF_ALLOC_DEBUG_MORE */ - if(H5FS_close(f, dxpl_id, f->shared->fs_man[type]) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't release free space info") - f->shared->fs_man[type] = NULL; - f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; - } /* end if */ -#ifdef H5MF_ALLOC_DEBUG_MORE -HDfprintf(stderr, "%s: Check 2.0 - f->shared->fs_man[%u] = %p, f->shared->fs_addr[%u] = %a\n", FUNC, (unsigned)type, f->shared->fs_man[type], (unsigned)type, f->shared->fs_addr[type]); -#endif /* H5MF_ALLOC_DEBUG_MORE */ - - /* If there is free space manager info for this type, delete it */ - if(H5F_addr_defined(f->shared->fs_addr[type])) { - haddr_t tmp_fs_addr; /* Temporary holder for free space manager address */ - - /* Put address into temporary variable and reset it */ - /* (Avoids loopback in file space freeing routine) */ - tmp_fs_addr = f->shared->fs_addr[type]; - f->shared->fs_addr[type] = HADDR_UNDEF; - - /* Shift to "deleting" state, to make certain we don't track any - * file space freed as a result of deleting the free space manager. - */ - f->shared->fs_state[type] = H5F_FS_STATE_DELETING; - -#ifdef H5MF_ALLOC_DEBUG_MORE -HDfprintf(stderr, "%s: Before deleting free space manager\n", FUNC); -#endif /* H5MF_ALLOC_DEBUG_MORE */ - - /* Delete free space manager for this type */ - if(H5FS_delete(f, dxpl_id, tmp_fs_addr) < 0) - HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't delete free space manager") - - /* Shift [back] to closed state */ - HDassert(f->shared->fs_state[type] == H5F_FS_STATE_DELETING); - f->shared->fs_state[type] = H5F_FS_STATE_CLOSED; - - /* Sanity check that the free space manager for this type wasn't started up again */ - HDassert(!H5F_addr_defined(f->shared->fs_addr[type])); - } /* end if */ - } /* end for */ + /* Close and delete freespace managers from the file */ + if(H5MF__close_delete(f, dxpl_id) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, FAIL, "can't initialize file free space") } /* end else */ /* Free the space in aggregators (again) */ diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h index 766834d..22ed308 100644 --- a/src/H5MFprivate.h +++ b/src/H5MFprivate.h @@ -54,6 +54,7 @@ H5_DLL herr_t H5MF_init_merge_flags(H5F_t *f); H5_DLL herr_t H5MF_get_freespace(H5F_t *f, hid_t dxpl_id, hsize_t *tot_space, hsize_t *meta_size); H5_DLL herr_t H5MF_close(H5F_t *f, hid_t dxpl_id); +H5_DLL herr_t H5MF_try_close(H5F_t *f, hid_t dxpl_id); /* File space allocation routines */ H5_DLL haddr_t H5MF_alloc(H5F_t *f, H5FD_mem_t type, hid_t dxpl_id, hsize_t size); |