summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDana Robinson <43805+derobins@users.noreply.github.com>2022-05-08 10:43:32 (GMT)
committerGitHub <noreply@github.com>2022-05-08 10:43:32 (GMT)
commit6e6dbf2e81660a65d3aec955c85d59fa479f3b3b (patch)
treee8985303be6ca8bbd1ad5ebd34640f357fdaece7
parent3dd97b88e9f28dc38e1be413be0b80c6b805dd76 (diff)
downloadhdf5-6e6dbf2e81660a65d3aec955c85d59fa479f3b3b.zip
hdf5-6e6dbf2e81660a65d3aec955c85d59fa479f3b3b.tar.gz
hdf5-6e6dbf2e81660a65d3aec955c85d59fa479f3b3b.tar.bz2
Onion VFD: Refactoring (#1756)
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/H5FDonion.c1866
-rw-r--r--src/H5FDonion_history.c480
-rw-r--r--src/H5FDonion_history.h88
-rw-r--r--src/H5FDonion_index.c934
-rw-r--r--src/H5FDonion_index.h146
-rw-r--r--src/H5FDonion_priv.h183
-rw-r--r--src/Makefile.am5
-rw-r--r--test/onion.c451
9 files changed, 2122 insertions, 2035 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b1bd4a2..3ff3610 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -241,6 +241,8 @@ set (H5FD_SOURCES
${HDF5_SRC_DIR}/H5FDmpio.c
${HDF5_SRC_DIR}/H5FDmulti.c
${HDF5_SRC_DIR}/H5FDonion.c
+ ${HDF5_SRC_DIR}/H5FDonion_history.c
+ ${HDF5_SRC_DIR}/H5FDonion_index.c
${HDF5_SRC_DIR}/H5FDperform.c
${HDF5_SRC_DIR}/H5FDros3.c
${HDF5_SRC_DIR}/H5FDs3comms.c
@@ -875,6 +877,8 @@ set (H5_PRIVATE_HEADERS
${HDF5_SRC_DIR}/H5FAprivate.h
${HDF5_SRC_DIR}/H5FDmirror_priv.h
+ ${HDF5_SRC_DIR}/H5FDonion_history.h
+ ${HDF5_SRC_DIR}/H5FDonion_index.h
${HDF5_SRC_DIR}/H5FDonion_priv.h
${HDF5_SRC_DIR}/H5FDpkg.h
${HDF5_SRC_DIR}/H5FDprivate.h
diff --git a/src/H5FDonion.c b/src/H5FDonion.c
index ae8483d..efcf945 100644
--- a/src/H5FDonion.c
+++ b/src/H5FDonion.c
@@ -63,7 +63,7 @@ static hid_t H5FD_ONION_g = 0;
*
* `backing_recov` (H5FD_t *)
*
- * Virtual file handle for the whole-history recovery file.
+ * Virtual file handle for the history recovery file.
*
* `name_recov` (char *)
*
@@ -84,9 +84,9 @@ static hid_t H5FD_ONION_g = 0;
*
* In-memory copy of the onion history data header.
*
- * `summary` (H5FD_onion_whole_history_t)
+ * `history` (H5FD_onion_history_t)
*
- * In-memory copy of the onion history "whole-history".
+ * In-memory copy of the onion history.
*
* `rev_record` (H5FD_onion_revision_record_t)
*
@@ -122,31 +122,28 @@ static hid_t H5FD_ONION_g = 0;
******************************************************************************
*/
typedef struct H5FD_onion_t {
- H5FD_t pub;
- H5FD_onion_fapl_info_t fa;
- H5FD_t * backing_canon;
- H5FD_t * backing_onion;
- H5FD_t * backing_recov;
- char * name_recov;
- hbool_t is_open_rw;
- hbool_t page_align_history;
- H5FD_onion_history_header_t header;
- H5FD_onion_whole_history_t summary;
- H5FD_onion_revision_record_t rev_record;
- H5FD__onion_revision_index_t *rev_index;
- haddr_t history_eof;
- haddr_t origin_eof;
- haddr_t logi_eoa;
- haddr_t logi_eof;
+ H5FD_t pub;
+ H5FD_onion_fapl_info_t fa;
+ H5FD_t * backing_canon;
+ H5FD_t * backing_onion;
+ H5FD_t * backing_recov;
+ char * name_recov;
+ hbool_t is_open_rw;
+ hbool_t page_align_history;
+ H5FD_onion_history_header_t header;
+ H5FD_onion_history_t history;
+ H5FD_onion_revision_record_t rev_record;
+ H5FD_onion_revision_index_t *rev_index;
+ haddr_t history_eof;
+ haddr_t origin_eof;
+ haddr_t logi_eoa;
+ haddr_t logi_eof;
} H5FD_onion_t;
H5FL_DEFINE_STATIC(H5FD_onion_t);
#define MAXADDR (((haddr_t)1 << (8 * sizeof(HDoff_t) - 1)) - 1)
-/* 2^n for uint64_t types -- H5_EXP2 unsafe past 32 bits */
-#define U64_EXP2(n) ((uint64_t)1 << (n))
-
#define H5FD_CTL__GET_NUM_REVISIONS 20001
/* Prototypes */
@@ -159,14 +156,7 @@ static herr_t H5FD__onion_set_eoa(H5FD_t *, H5FD_mem_t, haddr_t);
static herr_t H5FD__onion_term(void);
static herr_t H5FD__onion_write(H5FD_t *, H5FD_mem_t, hid_t, haddr_t, size_t, const void *);
-static int H5FD__onion_archival_index_list_sort_cmp(const void *, const void *);
-static herr_t H5FD__onion_ingest_whole_history(H5FD_onion_whole_history_t *whs_out, H5FD_t *raw_file,
- haddr_t addr, haddr_t size);
-static herr_t H5FD__onion_open_rw(H5FD_onion_t *, unsigned int, haddr_t, bool new_open);
-static herr_t H5FD__onion_revision_index_resize(H5FD__onion_revision_index_t *);
-static uint64_t H5FD__onion_whole_history_write(H5FD_onion_whole_history_t *whs, H5FD_t *file_dest,
- haddr_t off_start, haddr_t filesize_curr);
-
+static herr_t H5FD__onion_open_rw(H5FD_onion_t *, unsigned int, haddr_t, bool new_open);
static herr_t H5FD__onion_sb_encode(H5FD_t *_file, char *name /*out*/, unsigned char *buf /*out*/);
static herr_t H5FD__onion_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf);
static hsize_t H5FD__onion_sb_size(H5FD_t *_file);
@@ -174,6 +164,9 @@ static herr_t H5FD__onion_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags,
const void H5_ATTR_UNUSED *input, void H5_ATTR_UNUSED **output);
static herr_t H5FD__get_onion_revision_count(H5FD_t *file, size_t *revision_count);
+/* Temporary */
+H5_DLL herr_t H5FD__onion_write_final_history(H5FD_onion_t *file);
+
static const H5FD_class_t H5FD_onion_g = {
H5FD_CLASS_VERSION, /* struct version */
H5FD_ONION_VALUE, /* value */
@@ -286,15 +279,13 @@ H5Pget_fapl_onion(hid_t fapl_id, H5FD_onion_fapl_info_t *fa_out)
if (NULL == fa_out)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "NULL info-out pointer")
- plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS);
- if (NULL == plist)
+ if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Not a valid FAPL ID")
if (H5FD_ONION != H5P_peek_driver(plist))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Incorrect VFL driver")
- info_ptr = (const H5FD_onion_fapl_info_t *)H5P_peek_driver_info(plist);
- if (NULL == info_ptr)
+ if (NULL == (info_ptr = (const H5FD_onion_fapl_info_t *)H5P_peek_driver_info(plist)))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "bad VFL driver info")
HDmemcpy(fa_out, info_ptr, sizeof(H5FD_onion_fapl_info_t));
@@ -337,14 +328,14 @@ H5Pset_fapl_onion(hid_t fapl_id, const H5FD_onion_fapl_info_t *fa)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid info page size")
if (H5P_DEFAULT != fa->backing_fapl_id) {
- H5P_genplist_t *_plist_ret = NULL;
+ H5P_genplist_t *backing_fapl = NULL;
H5E_BEGIN_TRY
{
- _plist_ret = H5P_object_verify(fa->backing_fapl_id, H5P_FILE_ACCESS);
+ backing_fapl = H5P_object_verify(fa->backing_fapl_id, H5P_FILE_ACCESS);
}
H5E_END_TRY;
- if (_plist_ret == NULL)
+ if (backing_fapl == NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid backing fapl id")
}
@@ -355,83 +346,6 @@ done:
} /* end H5Pset_fapl_onion() */
/*-------------------------------------------------------------------------
- * Function: H5FDget_onion_revision_count
- *
- * Purpose: Get the number of revisions in an onion file
- *
- * Return: SUCCEED/FAIL
- *-------------------------------------------------------------------------
- */
-herr_t
-H5FDonion_get_revision_count(const char *filename, hid_t fapl_id, size_t *revision_count /*out*/)
-{
- H5P_genplist_t *plist = NULL;
- H5FD_t * file = NULL;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_API(FAIL)
- H5TRACE3("e", "*six", filename, fapl_id, revision_count);
-
- /* Check args */
- if (!filename || !HDstrcmp(filename, ""))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid file name")
- if (!revision_count)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "revision count can't be null")
-
- /* Make sure using the correct driver */
- if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid FAPL ID")
- if (H5FD_ONION != H5P_peek_driver(plist))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Onion VFL driver")
-
- /* Open the file with the driver */
- if (NULL == (file = H5FD_open(filename, H5F_ACC_RDONLY, fapl_id, HADDR_UNDEF)))
- HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, FAIL, "unable to open file with onion driver")
-
- /* Call the private function */
- if (H5FD__get_onion_revision_count(file, revision_count) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "failed to get the number of revisions")
-
-done:
- /* Close H5FD_t structure pointer */
- if (file && H5FD_close(file) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
-
- FUNC_LEAVE_API(ret_value)
-}
-
-/*-------------------------------------------------------------------------
- * Function: H5FD__get_onion_revision_count
- *
- * Purpose: Private version of H5FDget_onion_revision_count()
- *
- * Return: SUCCEED/FAIL
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD__get_onion_revision_count(H5FD_t *file, size_t *revision_count)
-{
- uint64_t op_code;
- uint64_t flags;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_PACKAGE
-
- HDassert(file);
- HDassert(revision_count);
-
- op_code = H5FD_CTL__GET_NUM_REVISIONS;
- flags = H5FD_CTL__FAIL_IF_UNKNOWN_FLAG;
-
- /* Get the number of revisions via the ctl callback */
- if (H5FD_ctl(file, op_code, flags, NULL, (void **)&revision_count) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "VFD ctl request failed")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-}
-
-/*-------------------------------------------------------------------------
* Function: H5FD__onion_sb_size
*
* Purpose: Returns the size of the private information to be stored in
@@ -513,116 +427,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD__onion_sb_decode */
-/*-------------------------------------------------------------------------
- * Function: H5FD__onion_update_and_write_header
- *
- * Purpose: Write in-memory history header to appropriate backing file.
- * Overwrites existing header data.
- *
- * Return: SUCCEED/FAIL
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5FD__onion_update_and_write_header(H5FD_onion_t *file)
-{
- uint32_t _sum = 0; /* required */
- uint64_t size = 0;
- unsigned char *buf = NULL;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_PACKAGE;
-
- /* Unset write-lock flag */
- if (file->is_open_rw)
- file->header.flags &= (uint32_t)~H5FD__ONION_HEADER_FLAG_WRITE_LOCK;
-
- if (NULL == (buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_HEADER)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for updated history header")
-
- if (0 == (size = H5FD_onion_history_header_encode(&file->header, buf, &_sum)))
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "problem encoding updated history header")
-
- if (H5FDwrite(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, 0, (haddr_t)size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write updated history header")
-
-done:
- H5MM_xfree(buf);
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD__onion_update_and_write_header()*/
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD__onion_whole_history_write
- *
- * Purpose: Encode and write whole-history to file at the given address.
- *
- * Returns: Success: Number of bytes written to destination file (always non-zero)
- * Failure: 0
- *-----------------------------------------------------------------------------
- */
-static uint64_t
-H5FD__onion_whole_history_write(H5FD_onion_whole_history_t *whs, H5FD_t *file_dest, haddr_t off_start,
- haddr_t filesize_curr)
-{
- uint32_t _sum = 0; /* Required by the API call but unused here */
- uint64_t size = 0;
- unsigned char *buf = NULL;
- uint64_t ret_value = 0;
-
- FUNC_ENTER_PACKAGE;
-
- if (NULL == (buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY +
- (H5FD__ONION_ENCODED_SIZE_RECORD_POINTER * whs->n_revisions))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, 0, "can't allocate buffer for updated whole-history")
-
- if (0 == (size = H5FD_onion_whole_history_encode(whs, buf, &_sum)))
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, 0, "problem encoding updated whole-history")
-
- if ((size + off_start > filesize_curr) && (H5FD_set_eoa(file_dest, H5FD_MEM_DRAW, off_start + size) < 0))
- HGOTO_ERROR(H5E_VFL, H5E_CANTSET, 0, "can't modify EOA for updated whole-history")
-
- if (H5FDwrite(file_dest, H5FD_MEM_DRAW, H5P_DEFAULT, off_start, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, 0, "can't write whole-history as intended")
-
- ret_value = size;
-
-done:
- H5MM_xfree(buf);
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD__onion_whole_history_write() */
-
-/*-----------------------------------------------------------------------------
- * Write in-memory whole-history summary to appropriate backing file.
- * Update information in other in-memory components.
- *-----------------------------------------------------------------------------
- */
-static herr_t
-H5FD__onion_update_and_write_whole_history(H5FD_onion_t *file)
-{
- uint64_t size = 0;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_PACKAGE;
-
- /* TODO: history EOF may not be correct (under what circumstances?) */
-
- if (0 == (size = H5FD__onion_whole_history_write(&file->summary, file->backing_onion, file->history_eof,
- file->history_eof)))
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write updated whole-history")
-
- if (size != file->header.whole_history_size)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "written whole-history differed from expected size")
-
- /* Is last write operation to history file; no need to extend to page
- * boundary if set to page-align.
- */
- file->history_eof += size;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD__onion_update_and_write_whole_history() */
-
/*-----------------------------------------------------------------------------
* Write in-memory revision record to appropriate backing file.
* Update information in other in-memory components.
@@ -632,13 +436,13 @@ static herr_t
H5FD__onion_commit_new_revision_record(H5FD_onion_t *file)
{
uint32_t _sum = 0; /* required */
- uint64_t size = 0;
- uint64_t phys_addr = 0; /* offset in history file to record start */
+ size_t size = 0;
+ haddr_t phys_addr = 0; /* offset in history file to record start */
unsigned char * buf = NULL;
herr_t ret_value = SUCCEED;
- H5FD_onion_revision_record_t *rec_p = &file->rev_record;
- H5FD_onion_whole_history_t * whs_p = &file->summary;
- H5FD_onion_record_pointer_t * new_list = NULL;
+ H5FD_onion_revision_record_t *rec = &file->rev_record;
+ H5FD_onion_history_t * history = &file->history;
+ H5FD_onion_record_loc_t * new_list = NULL;
time_t rawtime;
struct tm *info;
@@ -647,25 +451,25 @@ H5FD__onion_commit_new_revision_record(H5FD_onion_t *file)
HDtime(&rawtime);
info = HDgmtime(&rawtime);
- HDstrftime(rec_p->time_of_creation, sizeof(rec_p->time_of_creation), "%Y%m%dT%H%M%SZ", info);
+ HDstrftime(rec->time_of_creation, sizeof(rec->time_of_creation), "%Y%m%dT%H%M%SZ", info);
- rec_p->logi_eof = file->logi_eof;
+ rec->logi_eof = file->logi_eof;
- if ((TRUE == file->is_open_rw) && (H5FD_onion_merge_revision_index_into_archival_index(
+ if ((TRUE == file->is_open_rw) && (H5FD__onion_merge_revision_index_into_archival_index(
file->rev_index, &file->rev_record.archival_index) < 0))
HGOTO_ERROR(H5E_VFL, H5E_INTERNAL, FAIL, "unable to update index to write")
- if (NULL == (buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_REVISION_RECORD + (size_t)rec_p->comment_size +
- (H5FD__ONION_ENCODED_SIZE_INDEX_ENTRY * rec_p->archival_index.n_entries))))
+ if (NULL == (buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_REVISION_RECORD + (size_t)rec->comment_size +
+ (H5FD__ONION_ENCODED_SIZE_INDEX_ENTRY * rec->archival_index.n_entries))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer for encoded revision record")
- if (0 == (size = H5FD_onion_revision_record_encode(rec_p, buf, &_sum)))
+ if (0 == (size = H5FD__onion_revision_record_encode(rec, buf, &_sum)))
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "problem encoding revision record")
phys_addr = file->history_eof;
if (H5FD_set_eoa(file->backing_onion, H5FD_MEM_DRAW, phys_addr + size) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA for new revision record")
- if (H5FDwrite(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, phys_addr, size, buf) < 0)
+ if (H5FD_write(file->backing_onion, H5FD_MEM_DRAW, phys_addr, size, buf) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write new revision record")
file->history_eof = phys_addr + size;
@@ -673,48 +477,47 @@ H5FD__onion_commit_new_revision_record(H5FD_onion_t *file)
file->history_eof =
(file->history_eof + (file->header.page_size - 1)) & (~(file->header.page_size - 1));
- /* Update whole-history info to accommodate new revision */
+ /* Update history info to accommodate new revision */
- if (whs_p->n_revisions == 0) {
+ if (history->n_revisions == 0) {
unsigned char *ptr = buf; /* re-use buffer space to compute checksum */
- HDassert(whs_p->record_pointer_list == NULL);
- whs_p->n_revisions = 1;
- if (NULL == (whs_p->record_pointer_list = H5MM_calloc(sizeof(H5FD_onion_record_pointer_t))))
+ HDassert(history->record_locs == NULL);
+ history->n_revisions = 1;
+ if (NULL == (history->record_locs = H5MM_calloc(sizeof(H5FD_onion_record_loc_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate temporary record pointer list")
- whs_p->record_pointer_list[0].phys_addr = phys_addr;
- whs_p->record_pointer_list[0].record_size = size;
+ history->record_locs[0].phys_addr = phys_addr;
+ history->record_locs[0].record_size = size;
UINT64ENCODE(ptr, phys_addr);
UINT64ENCODE(ptr, size);
- whs_p->record_pointer_list[0].checksum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
+ history->record_locs[0].checksum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
/* TODO: size-reset belongs where? */
- file->header.whole_history_size += H5FD__ONION_ENCODED_SIZE_RECORD_POINTER;
+ file->header.history_size += H5FD__ONION_ENCODED_SIZE_RECORD_POINTER;
} /* end if no extant revisions in history */
else {
unsigned char *ptr = buf; /* re-use buffer space to compute checksum */
- HDassert(whs_p->record_pointer_list != NULL);
+ HDassert(history->record_locs != NULL);
- if (NULL == (new_list = H5MM_calloc((whs_p->n_revisions + 1) * sizeof(H5FD_onion_record_pointer_t))))
+ if (NULL == (new_list = H5MM_calloc((history->n_revisions + 1) * sizeof(H5FD_onion_record_loc_t))))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to resize record pointer list")
- HDmemcpy(new_list, whs_p->record_pointer_list,
- sizeof(H5FD_onion_record_pointer_t) * whs_p->n_revisions);
- H5MM_xfree(whs_p->record_pointer_list);
- whs_p->record_pointer_list = new_list;
- new_list = NULL;
- whs_p->record_pointer_list[whs_p->n_revisions].phys_addr = phys_addr;
- whs_p->record_pointer_list[whs_p->n_revisions].record_size = size;
+ HDmemcpy(new_list, history->record_locs, sizeof(H5FD_onion_record_loc_t) * history->n_revisions);
+ H5MM_xfree(history->record_locs);
+ history->record_locs = new_list;
+ new_list = NULL;
+ history->record_locs[history->n_revisions].phys_addr = phys_addr;
+ history->record_locs[history->n_revisions].record_size = size;
UINT64ENCODE(ptr, phys_addr);
UINT64ENCODE(ptr, size);
- whs_p->record_pointer_list[whs_p->n_revisions].checksum =
+ history->record_locs[history->n_revisions].checksum =
H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
- file->header.whole_history_size += H5FD__ONION_ENCODED_SIZE_RECORD_POINTER;
- whs_p->n_revisions += 1;
+ file->header.history_size += H5FD__ONION_ENCODED_SIZE_RECORD_POINTER;
+ history->n_revisions += 1;
} /* end if one or more revisions present in history */
- file->header.whole_history_addr = file->history_eof;
+ file->header.history_addr = file->history_eof;
done:
H5MM_xfree(buf);
@@ -752,10 +555,13 @@ H5FD__onion_close(H5FD_t *_file)
if (H5FD__onion_commit_new_revision_record(file) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "Can't write revision record to backing store")
- if (H5FD__onion_update_and_write_whole_history(file) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "Can't write whole-history to backing store")
+ if (H5FD__onion_write_final_history(file) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "Can't write history to backing store")
- if (H5FD__onion_update_and_write_header(file) < 0)
+ /* Unset write-lock flag */
+ if (file->is_open_rw)
+ file->header.flags &= (uint32_t)~H5FD__ONION_HEADER_FLAG_WRITE_LOCK;
+ if (H5FD__onion_write_header(&(file->header), file->backing_onion) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "Can't write updated header to backing store")
}
}
@@ -782,11 +588,11 @@ done:
HDremove(file->name_recov);
}
if (file->rev_index)
- if (H5FD_onion_revision_index_destroy(file->rev_index) < 0)
+ if (H5FD__onion_revision_index_destroy(file->rev_index) < 0)
HDONE_ERROR(H5E_VFL, H5E_CANTRELEASE, FAIL, "can't close revision index")
H5MM_xfree(file->name_recov);
- H5MM_xfree(file->summary.record_pointer_list);
+ H5MM_xfree(file->history.record_locs);
H5MM_xfree(file->rev_record.comment);
H5MM_xfree(file->rev_record.archival_index.list);
@@ -847,563 +653,22 @@ H5FD__onion_get_legit_fapl_id(hid_t fapl_id)
}
/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_history_header_decode
- *
- * Purpose: Attempt to read a buffer and store it as a history-header
- * structure.
- *
- * Implementation must correspond with
- * H5FD_onion_history_header_encode().
- *
- * Return: Success: Number of bytes read from buffer
- * Failure: 0
- *-----------------------------------------------------------------------------
- */
-uint64_t
-H5FD_onion_history_header_decode(unsigned char *buf, H5FD_onion_history_header_t *header)
-{
- uint32_t ui32 = 0;
- uint32_t sum = 0;
- uint64_t ui64 = 0;
- uint8_t * ui8p = NULL;
- unsigned char *ptr = NULL;
- uint64_t ret_value = 0;
-
- FUNC_ENTER_NOAPI_NOINIT;
-
- HDassert(buf != NULL);
- HDassert(header != NULL);
- HDassert(H5FD__ONION_HEADER_VERSION_CURR == header->version);
-
- if (HDstrncmp((const char *)buf, H5FD__ONION_HEADER_SIGNATURE, 4))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid header signature")
-
- if (buf[4] != H5FD__ONION_HEADER_VERSION_CURR)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid header version")
-
- ptr = buf + 5;
- ui32 = 0;
- HDmemcpy(&ui32, ptr, 3);
- ui8p = (uint8_t *)&ui32;
- UINT32DECODE(ui8p, header->flags);
- ptr += 3;
-
- HDmemcpy(&ui32, ptr, 4);
- ui8p = (uint8_t *)&ui32;
- UINT32DECODE(ui8p, header->page_size);
- ptr += 4;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT32DECODE(ui8p, header->origin_eof);
- ptr += 8;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT32DECODE(ui8p, header->whole_history_addr);
- ptr += 8;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT32DECODE(ui8p, header->whole_history_size);
- ptr += 8;
-
- sum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
-
- HDmemcpy(&ui32, ptr, 4);
- ui8p = (uint8_t *)&ui32;
- UINT32DECODE(ui8p, header->checksum);
- ptr += 4;
-
- if (sum != header->checksum)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "checksum mismatch")
-
- ret_value = (uint64_t)(ptr - buf);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_history_header_decode() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_history_header_encode
- *
- * Purpose: Write history-header structure to the given buffer.
- * All multi-byte elements are stored in little-endian word order.
- *
- * Implementation must correspond with
- * H5FD_onion_history_header_decode().
- *
- * The destination buffer must be sufficiently large to hold the
- * encoded contents (H5FD__ONION_ENCODED_SIZE_HEADER).
- *
- * Return: Number of bytes written to buffer.
- * The checksum of the generated buffer contents (excluding the
- * checksum itself) is stored in the pointer `sum_out`).
- *-----------------------------------------------------------------------------
- */
-uint64_t
-H5FD_onion_history_header_encode(H5FD_onion_history_header_t *header, unsigned char *buf, uint32_t *sum_out)
-{
- unsigned char *ptr = buf;
- uint64_t ret_value = 0;
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR;
-
- HDassert(buf != NULL);
- HDassert(sum_out != NULL);
- HDassert(header != NULL);
- HDassert(H5FD__ONION_HEADER_VERSION_CURR == header->version);
- HDassert(0 == (header->flags & 0xFF000000)); /* max three bits long */
-
- HDmemcpy(ptr, H5FD__ONION_HEADER_SIGNATURE, 4);
- ptr += 4;
- HDmemcpy(ptr, (unsigned char *)&header->version, 1);
- ptr += 1;
- UINT32ENCODE(ptr, header->flags);
- ptr -= 1; /* truncate to three bytes */
- UINT32ENCODE(ptr, header->page_size);
- UINT64ENCODE(ptr, header->origin_eof);
- UINT64ENCODE(ptr, header->whole_history_addr);
- UINT64ENCODE(ptr, header->whole_history_size);
- *sum_out = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
- UINT32ENCODE(ptr, *sum_out);
- ret_value = (uint64_t)(ptr - buf);
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_history_header_encode() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_revision_record_decode
- *
- * Purpose: Attempt to read a buffer and store it as a revision record
- * structure.
+ * Function: H5FD_onion_create_truncate_onion
*
- * Implementation must correspond with
- * H5FD_onion_revision_record_encode().
+ * Purpose: Create/truncate HDF5 and onion data for a fresh file
*
- * MUST BE CALLED TWICE:
- * On the first call, n_entries and comment_size in the
- * destination structure must all all be zero, and their
- * respective variable-length components (index_entry_list,
- * comment) must all be NULL.
+ * Special open operation required to instantiate the canonical file and
+ * history simultaneously. If successful, the required backing files are
+ * craeated and given initial population on the backing store, and the Onion
+ * virtual file handle is set; open effects a write-mode open.
*
- * If the buffer is well-formed, the destination structure is
- * tentatively populated with fixed-size values, and the number of
- * bytes read are returned.
+ * Cannot create 'template' history and proceed with normal write-mode open,
+ * as this would in effect create an empty first revision, making the history
+ * unintuitive. (create file -> initialize and commit empty first revision
+ * (revision 0); any data written to file during the 'create' open, as seen by
+ * the user, would be in the second revision (revision 1).)
*
- * Prior to the second call, the user must allocate space for the
- * variable-length components, in accordance with the associated
- * indicators (array of index-entry structures for
- * index_entry_list, of size n_entries; character arrays for
- * comment, allocated with the *_size number of bytes -- space
- * for NULL-terminator is included in _size).
- *
- * Then the decode operation is called a second time, and all
- * components will be populated (and again number of bytes read is
- * returned).
- *
- * Return: Success: Number of bytes read from buffer
- * Failure: 0
- *-----------------------------------------------------------------------------
- */
-uint64_t
-H5FD_onion_revision_record_decode(unsigned char *buf, H5FD_onion_revision_record_t *record)
-{
- uint32_t ui32 = 0;
- uint32_t page_size = 0;
- uint32_t sum = 0;
- uint64_t ui64 = 0;
- uint64_t n_entries = 0;
- uint32_t comment_size = 0;
- uint8_t * ui8p = NULL;
- unsigned char *ptr = NULL;
- uint64_t ret_value = 0;
-
- FUNC_ENTER_NOAPI_NOINIT;
-
- HDassert(buf != NULL);
- HDassert(record != NULL);
- HDassert(H5FD__ONION_REVISION_RECORD_VERSION_CURR == record->version);
- HDassert(H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR == record->archival_index.version);
-
- if (HDstrncmp((const char *)buf, H5FD__ONION_REVISION_RECORD_SIGNATURE, 4))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid signature")
-
- if (H5FD__ONION_REVISION_RECORD_VERSION_CURR != buf[4])
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid record version")
-
- ptr = buf + 8;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT64DECODE(ui8p, record->revision_num);
- ptr += 8;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT64DECODE(ui8p, record->parent_revision_num);
- ptr += 8;
-
- HDmemcpy(record->time_of_creation, ptr, 16);
- ptr += 16;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT64DECODE(ui8p, record->logi_eof);
- ptr += 8;
-
- HDmemcpy(&ui32, ptr, 4);
- ui8p = (uint8_t *)&ui32;
- UINT32DECODE(ui8p, page_size);
- ptr += 4;
-
- if (page_size == 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "page size is zero")
- if (!POWER_OF_TWO(page_size))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "page size not power of two")
-
- for (record->archival_index.page_size_log2 = 0;
- (((uint32_t)1 << record->archival_index.page_size_log2) & page_size) == 0;
- record->archival_index.page_size_log2++)
- ;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT64DECODE(ui8p, n_entries);
- ptr += 8;
-
- HDmemcpy(&ui32, ptr, 4);
- ui8p = (uint8_t *)&ui32;
- UINT32DECODE(ui8p, comment_size);
- ptr += 4;
-
- if (record->archival_index.n_entries == 0) {
- record->archival_index.n_entries = n_entries;
- ptr += H5FD__ONION_ENCODED_SIZE_INDEX_ENTRY * n_entries;
- }
- else if (n_entries != record->archival_index.n_entries) {
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "n_entries in archival index does not match decoded")
- }
- else {
- H5FD_onion_index_entry_t *entry_p = NULL;
- size_t i = 0;
-
- if (record->archival_index.list == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "no archival index entry list")
-
- for (i = 0; i < n_entries; i++) {
- entry_p = &record->archival_index.list[i];
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT64DECODE(ui8p, entry_p->logi_page);
- ptr += 8;
-
- /* logi_page actually encoded as address; check and convert */
- if (entry_p->logi_page & (page_size - 1))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "logical address does not align with page size")
-
- entry_p->logi_page = entry_p->logi_page >> record->archival_index.page_size_log2;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT64DECODE(ui8p, entry_p->phys_addr);
- ptr += 8;
-
- HDmemcpy(&ui32, ptr, 4);
- ui8p = (uint8_t *)&ui32;
- UINT32DECODE(ui8p, sum);
- ptr += 4;
-
- ui32 = H5_checksum_fletcher32((ptr - 20), 16);
- if (ui32 != sum)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "index entry checksum mismatch")
- }
- }
-
- if (record->comment_size == 0) {
- if (record->comment != NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "comment pointer prematurely allocated")
- record->comment_size = comment_size;
- }
- else {
- if (record->comment == NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "no comment pointer")
- HDmemcpy(record->comment, ptr, comment_size);
- }
- ptr += comment_size;
-
- sum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
-
- HDmemcpy(&ui32, ptr, 4);
- ui8p = (uint8_t *)&ui32;
- UINT32DECODE(ui8p, record->checksum);
- ptr += 4;
-
- if (sum != record->checksum)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "checksum mismatch")
-
- ret_value = (uint64_t)(ptr - buf);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_revision_record_decode() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_revision_record_encode
- *
- * Purpose: Write revision-record structure to the given buffer.
- * All multi-byte elements are stored in little-endian word order.
- *
- * Implementation must correspond with
- * H5FD_onion_revision_record_decode().
- *
- * The destination buffer must be sufficiently large to hold the
- * encoded contents.
- * (Hint: `sizeof(revision-record-struct) + comment-size +
- * sizeof(index-entry-struct) * n_entries)`
- * guarantees ample/excess space.)
- *
- * Return: Number of bytes written to buffer.
- * The checksum of the generated buffer contents (excluding the
- * checksum itself) is stored in the pointer `sum_out`).
- *-----------------------------------------------------------------------------
- */
-uint64_t
-H5FD_onion_revision_record_encode(H5FD_onion_revision_record_t *record, unsigned char *buf, uint32_t *sum_out)
-{
- unsigned char *ptr = buf; /* original pointer */
- uint32_t vers_u32 = (uint32_t)record->version; /* pad out unused bytes */
- uint32_t page_size = 0;
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR;
-
- HDassert(sum_out != NULL);
- HDassert(buf != NULL);
- HDassert(record != NULL);
- HDassert(vers_u32 < 0x100);
- HDassert(H5FD__ONION_REVISION_RECORD_VERSION_CURR == record->version);
- HDassert(H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR == record->archival_index.version);
-
- page_size = (uint32_t)(1 << record->archival_index.page_size_log2);
-
- HDmemcpy(ptr, H5FD__ONION_REVISION_RECORD_SIGNATURE, 4);
- ptr += 4;
- UINT32ENCODE(ptr, vers_u32);
- UINT64ENCODE(ptr, record->revision_num);
- UINT64ENCODE(ptr, record->parent_revision_num);
- HDmemcpy(ptr, record->time_of_creation, 16);
- ptr += 16;
- UINT64ENCODE(ptr, record->logi_eof);
- UINT32ENCODE(ptr, page_size);
- UINT64ENCODE(ptr, record->archival_index.n_entries);
- UINT32ENCODE(ptr, record->comment_size);
-
- if (record->archival_index.n_entries > 0) {
- uint64_t i = 0;
- uint64_t page_size_log2 = record->archival_index.page_size_log2;
-
- HDassert(record->archival_index.list != NULL);
- for (i = 0; i < record->archival_index.n_entries; i++) {
- uint32_t sum = 0;
- H5FD_onion_index_entry_t *entry_p = NULL;
- uint64_t logi_addr = 0;
-
- entry_p = &record->archival_index.list[i];
- logi_addr = entry_p->logi_page << page_size_log2;
-
- UINT64ENCODE(ptr, logi_addr);
- UINT64ENCODE(ptr, entry_p->phys_addr);
- sum = H5_checksum_fletcher32((ptr - 16), 16);
- UINT32ENCODE(ptr, sum);
- }
- }
-
- if (record->comment_size > 0) {
- HDassert(record->comment != NULL && *record->comment != '\0');
- HDmemcpy(ptr, record->comment, record->comment_size);
- ptr += record->comment_size;
- }
-
- *sum_out = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
- UINT32ENCODE(ptr, *sum_out);
-
- FUNC_LEAVE_NOAPI((uint64_t)(ptr - buf));
-} /* end H5FD_onion_revision_record_encode() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_whole_history_decode
- *
- * Purpose: Attempt to read a buffer and store it as a whole-history
- * structure.
- *
- * Implementation must correspond with
- * H5FD_onion_whole_history_encode().
- *
- * MUST BE CALLED TWICE:
- * On the first call, n_records in the destination structure must
- * be zero, and record_pointer_list be NULL.
- *
- * If the buffer is well-formed, the destination structure is
- * tentatively populated with fixed-size values, and the number of
- * bytes read are returned.
- *
- * Prior to the second call, the user must allocate space for
- * record_pointer_list to hold n_records record-pointer structs.
- *
- * Then the decode operation is called a second time, and all
- * components will be populated (and again number of bytes read is
- * returned).
- *
- * Return: Success: Number of bytes read from buffer
- * Failure: 0
- *-----------------------------------------------------------------------------
- */
-uint64_t
-H5FD_onion_whole_history_decode(unsigned char *buf, H5FD_onion_whole_history_t *summary)
-{
- uint32_t ui32 = 0;
- uint32_t sum = 0;
- uint64_t ui64 = 0;
- uint64_t n_revisions = 0;
- uint8_t * ui8p = NULL;
- unsigned char *ptr = NULL;
- uint64_t ret_value = 0;
-
- FUNC_ENTER_NOAPI_NOINIT;
-
- HDassert(buf != NULL);
- HDassert(summary != NULL);
- HDassert(H5FD__ONION_WHOLE_HISTORY_VERSION_CURR == summary->version);
-
- if (HDstrncmp((const char *)buf, "OWHS", 4))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid signature")
-
- if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != buf[4])
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid version")
-
- ptr = buf + 8;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT64DECODE(ui8p, n_revisions);
- ptr += 8;
-
- if (0 == summary->n_revisions) {
- summary->n_revisions = n_revisions;
- ptr += H5FD__ONION_ENCODED_SIZE_RECORD_POINTER * n_revisions;
- }
- else {
- uint64_t i = 0;
-
- if (summary->n_revisions != n_revisions)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0,
- "summary argument suggests different revision count than encoded buffer")
- if (NULL == summary->record_pointer_list)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "list is NULL -- cannot populate")
-
- for (i = 0; i < n_revisions; i++) {
- H5FD_onion_record_pointer_t *rpp = &summary->record_pointer_list[i];
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT64DECODE(ui8p, rpp->phys_addr);
- ptr += 8;
-
- HDmemcpy(&ui64, ptr, 8);
- ui8p = (uint8_t *)&ui64;
- UINT64DECODE(ui8p, rpp->record_size);
- ptr += 8;
-
- HDmemcpy(&ui32, ptr, 4);
- ui8p = (uint8_t *)&ui32;
- UINT64DECODE(ui8p, rpp->checksum);
- ptr += 4;
- }
- }
-
- sum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
-
- HDmemcpy(&ui32, ptr, 4);
- ui8p = (uint8_t *)&ui32;
- UINT32DECODE(ui8p, summary->checksum);
- ptr += 4;
-
- if (sum != summary->checksum)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "checksum mismatch")
-
- ret_value = (uint64_t)(ptr - buf);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_whole_history_decode() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_whole_history_encode
- *
- * Purpose: Write whole-history structure to the given buffer.
- * All multi-byte elements are stored in little-endian word order.
- *
- * Implementation must correspond with
- * H5FD_onion_whole_history_decode().
- *
- * The destination buffer must be sufficiently large to hold the
- * encoded contents.
- * (Hint: `sizeof(whole-history-struct) +
- * sizeof(record-pointer-struct) * n_records)` guarantees
- * ample/excess space.)
- *
- * Return: Number of bytes written to buffer.
- * The checksum of the generated buffer contents (excluding the
- * checksum itself) is stored in the pointer `sum_out`).
- *-----------------------------------------------------------------------------
- */
-uint64_t
-H5FD_onion_whole_history_encode(H5FD_onion_whole_history_t *summary, unsigned char *buf, uint32_t *sum_out)
-{
- unsigned char *ptr = buf;
- uint32_t vers_u32 = (uint32_t)summary->version; /* pad out unused bytes */
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR;
-
- HDassert(summary != NULL);
- HDassert(H5FD__ONION_WHOLE_HISTORY_VERSION_CURR == summary->version);
- HDassert(buf != NULL);
- HDassert(sum_out != NULL);
-
- HDmemcpy(ptr, H5FD__ONION_WHOLE_HISTORY_SIGNATURE, 4);
- ptr += 4;
- UINT32ENCODE(ptr, vers_u32);
- UINT64ENCODE(ptr, summary->n_revisions);
- if (summary->n_revisions > 0) {
- uint64_t i = 0;
-
- HDassert(summary->record_pointer_list != NULL); /* TODO: error? */
- for (i = 0; i < summary->n_revisions; i++) {
- UINT64ENCODE(ptr, summary->record_pointer_list[i].phys_addr);
- UINT64ENCODE(ptr, summary->record_pointer_list[i].record_size);
- UINT32ENCODE(ptr, summary->record_pointer_list[i].checksum);
- }
- }
- *sum_out = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
- UINT32ENCODE(ptr, *sum_out);
-
- FUNC_LEAVE_NOAPI((uint64_t)(ptr - buf));
-} /* end H5FD_onion_whole_history_encode() */
-
-/*-----------------------------------------------------------------------------
- * Create/truncate HDF5 and onion data for a fresh file.
- *
- * Special open operation required to instantiate the canonical file and
- * history simultaneously. If successful, the required backing files are
- * craeated and given initial population on the backing store, and the Onion
- * virtual file handle is set; open effects a write-mode open.
- *
- * Cannot create 'template' history and proceed with normal write-mode open,
- * as this would in effect create an empty first revision, making the history
- * unintuitive. (create file -> initialize and commit empty first revision
- * (revision 0); any data written to file during the 'create' open, as seen by
- * the user, would be in the second revision (revision 1).)
+ * Return: SUCCEED/FAIL
*-----------------------------------------------------------------------------
*/
static herr_t
@@ -1411,9 +676,9 @@ H5FD__onion_create_truncate_onion(H5FD_onion_t *file, const char *filename, cons
const char *name_recovery, unsigned int flags, haddr_t maxaddr)
{
hid_t backing_fapl_id = H5I_INVALID_HID;
- H5FD_onion_history_header_t * hdr_p = NULL;
- H5FD_onion_whole_history_t * whs_p = NULL;
- H5FD_onion_revision_record_t *rec_p = NULL;
+ H5FD_onion_history_header_t * hdr = NULL;
+ H5FD_onion_history_t * history = NULL;
+ H5FD_onion_revision_record_t *rec = NULL;
unsigned char * buf = NULL;
uint64_t size = 0;
herr_t ret_value = SUCCEED;
@@ -1422,17 +687,17 @@ H5FD__onion_create_truncate_onion(H5FD_onion_t *file, const char *filename, cons
HDassert(file != NULL);
- hdr_p = &file->header;
- whs_p = &file->summary;
- rec_p = &file->rev_record;
+ hdr = &file->header;
+ history = &file->history;
+ rec = &file->rev_record;
- hdr_p->flags = H5FD__ONION_HEADER_FLAG_WRITE_LOCK;
+ hdr->flags = H5FD__ONION_HEADER_FLAG_WRITE_LOCK;
if (H5FD_ONION_FAPL_INFO_CREATE_FLAG_ENABLE_DIVERGENT_HISTORY & file->fa.creation_flags)
- hdr_p->flags |= H5FD__ONION_HEADER_FLAG_DIVERGENT_HISTORY;
+ hdr->flags |= H5FD__ONION_HEADER_FLAG_DIVERGENT_HISTORY;
if (H5FD_ONION_FAPL_INFO_CREATE_FLAG_ENABLE_PAGE_ALIGNMENT & file->fa.creation_flags)
- hdr_p->flags |= H5FD__ONION_HEADER_FLAG_PAGE_ALIGNMENT;
+ hdr->flags |= H5FD__ONION_HEADER_FLAG_PAGE_ALIGNMENT;
- hdr_p->origin_eof = 0;
+ hdr->origin_eof = 0;
backing_fapl_id = H5FD__onion_get_legit_fapl_id(file->fa.backing_fapl_id);
if (H5I_INVALID_HID == backing_fapl_id)
@@ -1453,51 +718,44 @@ H5FD__onion_create_truncate_onion(H5FD_onion_t *file, const char *filename, cons
if (H5FD_set_eoa(file->backing_canon, H5FD_MEM_DRAW, 8) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't extend EOA")
- /* must use public API to correctly set DXPL context :( */
- if (H5FDwrite(file->backing_canon, H5FD_MEM_DRAW, H5P_DEFAULT, 0, 8, "ONIONEOF") < 0)
+ if (H5FD_write(file->backing_canon, H5FD_MEM_DRAW, 0, 8, "ONIONEOF") < 0)
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "cannot write header to the backing h5 file")
- /* Write nascent whole-history summary (with no revisions) to "recovery" */
+ /* Write nascent history (with no revisions) to "recovery" */
if (NULL == (buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY)))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer")
- size = H5FD_onion_whole_history_encode(whs_p, buf, &whs_p->checksum);
+ size = H5FD__onion_history_encode(history, buf, &history->checksum);
if (H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY != size)
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't encode whole-history")
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't encode history")
if (H5FD_set_eoa(file->backing_recov, H5FD_MEM_DRAW, size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't extend EOA")
- /* Must use public API to correctly set DXPL context :(
- * TODO: Revisit this...
- */
- if (H5FDwrite(file->backing_recov, H5FD_MEM_DRAW, H5P_DEFAULT, 0, size, buf) < 0)
- HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "cannot write summary to the backing recovery file")
- hdr_p->whole_history_size = size; /* record for later use */
+ if (H5FD_write(file->backing_recov, H5FD_MEM_DRAW, 0, size, buf) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "cannot write history to the backing recovery file")
+ hdr->history_size = size; /* record for later use */
H5MM_xfree(buf);
buf = NULL;
- /* Write history header with "no" whole-history summary to history.
+ /* Write history header with "no" history.
* Size of the "recovery" history recorded for later use on close.
*/
if (NULL == (buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_HEADER)))
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer")
- size = H5FD_onion_history_header_encode(hdr_p, buf, &hdr_p->checksum);
+ size = H5FD__onion_history_header_encode(hdr, buf, &hdr->checksum);
if (H5FD__ONION_ENCODED_SIZE_HEADER != size)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "can't encode history header")
if (H5FD_set_eoa(file->backing_onion, H5FD_MEM_DRAW, size) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "can't extend EOA")
- /* Must use public API to correctly set DXPL context :(
- * TODO: Revisit this...
- */
- if (H5FDwrite(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, 0, size, buf) < 0)
+ if (H5FD_write(file->backing_onion, H5FD_MEM_DRAW, 0, size, buf) < 0)
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, FAIL, "cannot write header to the backing onion file")
file->history_eof = (haddr_t)size;
if (TRUE == file->page_align_history)
- file->history_eof = (file->history_eof + (hdr_p->page_size - 1)) & (~(hdr_p->page_size - 1));
+ file->history_eof = (file->history_eof + (hdr->page_size - 1)) & (~(hdr->page_size - 1));
- rec_p->archival_index.list = NULL;
+ rec->archival_index.list = NULL;
- if (NULL == (file->rev_index = H5FD_onion_revision_index_init(file->fa.page_size)))
+ if (NULL == (file->rev_index = H5FD__onion_revision_index_init(file->fa.page_size)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't initialize revision index")
done:
@@ -1510,234 +768,6 @@ done:
} /* end H5FD__onion_create_truncate_onion() */
/*-----------------------------------------------------------------------------
- * Read and decode the history header information from `raw_file` at `addr`,
- * and store the decoded information in the structure at `hdr_out`.
- *-----------------------------------------------------------------------------
- */
-static herr_t
-H5FD__onion_ingest_history_header(H5FD_onion_history_header_t *hdr_out, H5FD_t *raw_file, haddr_t addr)
-{
- unsigned char *buf = NULL;
- herr_t ret_value = SUCCEED;
- haddr_t size = (haddr_t)H5FD__ONION_ENCODED_SIZE_HEADER;
- uint32_t sum = 0;
-
- FUNC_ENTER_PACKAGE;
-
- if (H5FD_get_eof(raw_file, H5FD_MEM_DRAW) < (addr + size))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "header indicates whole-history beyond EOF")
-
- if (NULL == (buf = H5MM_malloc(sizeof(char) * size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer space")
-
- if (H5FD_set_eoa(raw_file, H5FD_MEM_DRAW, (addr + size)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA")
-
- if (H5FDread(raw_file, H5FD_MEM_DRAW, H5P_DEFAULT, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read history header from file")
-
- if (H5FD_onion_history_header_decode(buf, hdr_out) == 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode history header")
-
- sum = H5_checksum_fletcher32(buf, size - 4);
- if (hdr_out->checksum != sum)
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored")
-
-done:
- H5MM_xfree(buf);
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD__onion_ingest_history_header() */
-
-/*-----------------------------------------------------------------------------
- * Read and decode the revision_record information from `raw_file` at
- * `addr` .. `addr + size` (taken from whole-history), and store the decoded
- * information in the structure at `r_out`.
- *-----------------------------------------------------------------------------
- */
-static herr_t
-H5FD__onion_ingest_revision_record(H5FD_onion_revision_record_t *r_out, H5FD_t *raw_file,
- const H5FD_onion_whole_history_t *whs, uint64_t revision_num)
-{
- unsigned char *buf = NULL;
- herr_t ret_value = SUCCEED;
- uint64_t n = 0;
- uint64_t high = 0;
- uint64_t low = 0;
- uint64_t range = 0;
- uint32_t sum = 0;
- haddr_t addr = 0;
- haddr_t size = 0;
-
- FUNC_ENTER_PACKAGE;
-
- HDassert(r_out);
- HDassert(raw_file);
- HDassert(whs);
- HDassert(whs->record_pointer_list);
- HDassert(whs->n_revisions > 0);
-
- high = whs->n_revisions - 1;
- range = high;
- addr = (haddr_t)whs->record_pointer_list[high].phys_addr;
- size = (haddr_t)whs->record_pointer_list[high].record_size;
-
- /* Initialize r_out
- *
- * TODO: This function should completely initialize r_out. Relying on
- * other code to some of the work while we just paste over parts
- * of the struct here is completely bananas.
- */
- r_out->comment = H5MM_xfree(r_out->comment);
- r_out->archival_index.list = H5MM_xfree(r_out->archival_index.list);
-
- if (H5FD_get_eof(raw_file, H5FD_MEM_DRAW) < (addr + size))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "at least one record extends beyond EOF")
-
- /* recovery-open may have EOA below revision record */
- if ((H5FD_get_eoa(raw_file, H5FD_MEM_DRAW) < (addr + size)) &&
- (H5FD_set_eoa(raw_file, H5FD_MEM_DRAW, (addr + size)) < 0)) {
- HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA");
- }
-
- /* Perform binary search on records to find target revision by ID.
- * As IDs are added sequentially, they are "guaranteed" to be sorted.
- */
- while (range > 0) {
- n = (range / 2) + low;
- addr = (haddr_t)whs->record_pointer_list[n].phys_addr;
- size = (haddr_t)whs->record_pointer_list[n].record_size;
-
- if (NULL == (buf = H5MM_malloc(sizeof(char) * size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer space")
-
- if (H5FDread(raw_file, H5FD_MEM_DRAW, H5P_DEFAULT, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read revision record from file")
-
- if (H5FD_onion_revision_record_decode(buf, r_out) != size)
- HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode revision record (initial)")
-
- sum = H5_checksum_fletcher32(buf, size - 4);
- if (r_out->checksum != sum)
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored")
-
- if (revision_num == r_out->revision_num)
- break;
-
- H5MM_xfree(buf);
- buf = NULL;
-
- r_out->archival_index.n_entries = 0;
- r_out->comment_size = 0;
-
- if (r_out->revision_num < revision_num)
- low = (n == high) ? high : n + 1;
- else
- high = (n == low) ? low : n - 1;
- range = high - low;
- } /* end while 'non-leaf' binary search */
-
- if (range == 0) {
- n = low;
- addr = (haddr_t)whs->record_pointer_list[n].phys_addr;
- size = (haddr_t)whs->record_pointer_list[n].record_size;
-
- if (NULL == (buf = H5MM_malloc(sizeof(char) * size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer space")
-
- if (H5FDread(raw_file, H5FD_MEM_DRAW, H5P_DEFAULT, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read revision record from file")
-
- if (H5FD_onion_revision_record_decode(buf, r_out) != size)
- HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode revision record (initial)")
-
- sum = H5_checksum_fletcher32(buf, size - 4);
- if (r_out->checksum != sum)
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored")
-
- if (revision_num != r_out->revision_num)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL,
- "could not find target revision!") /* TODO: corrupted? */
- } /* end if revision ID at 'leaf' in binary search */
-
- if (r_out->comment_size > 0)
- if (NULL == (r_out->comment = H5MM_malloc(sizeof(char) * r_out->comment_size)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate comment space")
-
- if (r_out->archival_index.n_entries > 0)
- if (NULL == (r_out->archival_index.list =
- H5MM_calloc(r_out->archival_index.n_entries * sizeof(H5FD_onion_index_entry_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate index entry list")
-
- if (H5FD_onion_revision_record_decode(buf, r_out) != size)
- HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode revision record (final)")
-
-done:
- H5MM_xfree(buf);
- if (ret_value == FAIL) {
- H5MM_xfree(r_out->comment);
- H5MM_xfree(r_out->archival_index.list);
- }
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD__onion_ingest_revision_record() */
-
-/*-----------------------------------------------------------------------------
- * Read and decode the whole-history information from `raw_file` at
- * `addr` .. `addr + size` (taken from history header), and store the decoded
- * information in the structure at `whs_out`.
- *
- * If successful, `whs_out->record_pointer_list` is always allocated, even if
- * there is zero revisions.
- *-----------------------------------------------------------------------------
- */
-static herr_t
-H5FD__onion_ingest_whole_history(H5FD_onion_whole_history_t *whs_out, H5FD_t *raw_file, haddr_t addr,
- haddr_t size)
-{
- unsigned char *buf = NULL;
- herr_t ret_value = SUCCEED;
- uint32_t sum = 0;
-
- FUNC_ENTER_PACKAGE;
-
- if (H5FD_get_eof(raw_file, H5FD_MEM_DRAW) < (addr + size))
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "header indicates whole-history beyond EOF")
-
- buf = H5MM_malloc(sizeof(char) * size);
- if (NULL == buf) {
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer space");
- }
-
- if (H5FD_set_eoa(raw_file, H5FD_MEM_DRAW, (addr + size)) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA")
-
- if (H5FDread(raw_file, H5FD_MEM_DRAW, H5P_DEFAULT, addr, size, buf) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read whole-history from file")
-
- if (H5FD_onion_whole_history_decode(buf, whs_out) != size)
- HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode whole-history (initial)")
-
- sum = H5_checksum_fletcher32(buf, size - 4);
- if (whs_out->checksum != sum)
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored")
-
- whs_out->record_pointer_list = H5MM_calloc(whs_out->n_revisions * sizeof(H5FD_onion_record_pointer_t));
- if (whs_out->n_revisions > 0 && NULL == whs_out->record_pointer_list)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate record pointer list")
-
- if (H5FD_onion_whole_history_decode(buf, whs_out) != size)
- HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode whole-history (final)")
-
-done:
- H5MM_xfree(buf);
- if (ret_value == FAIL)
- H5MM_xfree(whs_out->record_pointer_list);
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD__onion_ingest_whole_history() */
-
-/*-----------------------------------------------------------------------------
* Function: H5FD__onion_open
*
* Purpose: Open an onionized file
@@ -1809,7 +839,7 @@ H5FD__onion_open(const char *filename, unsigned flags, hid_t fapl_id, haddr_t ma
file->header.version = H5FD__ONION_HEADER_VERSION_CURR;
file->header.page_size = file->fa.page_size; /* guarded on FAPL-set */
- file->summary.version = H5FD__ONION_WHOLE_HISTORY_VERSION_CURR;
+ file->history.version = H5FD__ONION_WHOLE_HISTORY_VERSION_CURR;
file->rev_record.version = H5FD__ONION_REVISION_RECORD_VERSION_CURR;
file->rev_record.archival_index.version = H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR;
@@ -1864,9 +894,9 @@ H5FD__onion_open(const char *filename, unsigned flags, hid_t fapl_id, haddr_t ma
/* TODO: Move to a new function */
if (NULL == file->backing_onion) {
if (H5F_ACC_RDWR & flags) {
- H5FD_onion_history_header_t * hdr_p = NULL;
- H5FD_onion_whole_history_t * whs_p = NULL;
- H5FD_onion_revision_record_t *rec_p = NULL;
+ H5FD_onion_history_header_t * hdr = NULL;
+ H5FD_onion_history_t * history = NULL;
+ H5FD_onion_revision_record_t *rec = NULL;
unsigned char * head_buf = NULL;
unsigned char * wh_buf = NULL;
uint64_t size = 0;
@@ -1874,16 +904,16 @@ H5FD__onion_open(const char *filename, unsigned flags, hid_t fapl_id, haddr_t ma
HDassert(file != NULL);
- hdr_p = &file->header;
- whs_p = &file->summary;
- rec_p = &file->rev_record;
+ hdr = &file->header;
+ history = &file->history;
+ rec = &file->rev_record;
new_open = true;
if (H5FD_ONION_FAPL_INFO_CREATE_FLAG_ENABLE_DIVERGENT_HISTORY & file->fa.creation_flags)
- hdr_p->flags |= H5FD__ONION_HEADER_FLAG_DIVERGENT_HISTORY;
+ hdr->flags |= H5FD__ONION_HEADER_FLAG_DIVERGENT_HISTORY;
if (H5FD_ONION_FAPL_INFO_CREATE_FLAG_ENABLE_PAGE_ALIGNMENT & file->fa.creation_flags) {
- hdr_p->flags |= H5FD__ONION_HEADER_FLAG_PAGE_ALIGNMENT;
+ hdr->flags |= H5FD__ONION_HEADER_FLAG_PAGE_ALIGNMENT;
file->page_align_history = TRUE;
}
@@ -1892,8 +922,8 @@ H5FD__onion_open(const char *filename, unsigned flags, hid_t fapl_id, haddr_t ma
}
if (H5FD_set_eoa(file->backing_canon, H5FD_MEM_DRAW, canon_eof) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't extend EOA")
- hdr_p->origin_eof = canon_eof;
- file->logi_eof = canon_eof;
+ hdr->origin_eof = canon_eof;
+ file->logi_eof = canon_eof;
backing_fapl_id = H5FD__onion_get_legit_fapl_id(file->fa.backing_fapl_id);
if (H5I_INVALID_HID == backing_fapl_id)
@@ -1907,54 +937,50 @@ H5FD__onion_open(const char *filename, unsigned flags, hid_t fapl_id, haddr_t ma
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "cannot open the backing onion file")
}
- /* Write history header with "no" whole-history summary to history */
- hdr_p->whole_history_size = H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY; /* record for later use */
- hdr_p->whole_history_addr =
+ /* Write history header with "no" history */
+ hdr->history_size = H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY; /* record for later use */
+ hdr->history_addr =
H5FD__ONION_ENCODED_SIZE_HEADER + 1; /* TODO: comment these 2 or do some other way */
head_buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_HEADER);
if (NULL == head_buf)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't allocate buffer")
- size = H5FD_onion_history_header_encode(hdr_p, head_buf, &hdr_p->checksum);
+ size = H5FD__onion_history_header_encode(hdr, head_buf, &hdr->checksum);
if (H5FD__ONION_ENCODED_SIZE_HEADER != size)
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "can't encode history header")
- /* must use public API to correctly set DXPL context :( */
wh_buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY);
if (NULL == wh_buf)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't allocate buffer")
- saved_size = size;
- whs_p->n_revisions = 0;
- size = H5FD_onion_whole_history_encode(whs_p, wh_buf, &whs_p->checksum);
- file->header.whole_history_size = size; /* record for later use */
+ saved_size = size;
+ history->n_revisions = 0;
+ size = H5FD__onion_history_encode(history, wh_buf, &history->checksum);
+ file->header.history_size = size; /* record for later use */
if (H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY != size) {
- HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "can't encode whole-history")
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, NULL, "can't encode history")
}
if (H5FD_set_eoa(file->backing_onion, H5FD_MEM_DRAW, saved_size + size + 1) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't extend EOA")
- /* must use public API to correctly set DXPL context :( */
- if (H5FDwrite(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, 0, saved_size, head_buf) < 0) {
+ if (H5FD_write(file->backing_onion, H5FD_MEM_DRAW, 0, saved_size, head_buf) < 0) {
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, NULL,
"cannot write header to the backing onion file")
}
file->history_eof = (haddr_t)saved_size;
if (TRUE == file->page_align_history)
- file->history_eof =
- (file->history_eof + (hdr_p->page_size - 1)) & (~(hdr_p->page_size - 1));
+ file->history_eof = (file->history_eof + (hdr->page_size - 1)) & (~(hdr->page_size - 1));
- rec_p->archival_index.list = NULL;
+ rec->archival_index.list = NULL;
- file->header.whole_history_addr = file->history_eof;
+ file->header.history_addr = file->history_eof;
- /* Write nascent whole-history summary (with no revisions) to the backing onion file */
- if (H5FDwrite(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, saved_size + 1, size, wh_buf) <
- 0) {
+ /* Write nascent history (with no revisions) to the backing onion file */
+ if (H5FD_write(file->backing_onion, H5FD_MEM_DRAW, saved_size + 1, size, wh_buf) < 0) {
HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, NULL,
- "cannot write summary to the backing onion file")
+ "cannot write history to the backing onion file")
}
- file->header.whole_history_size = size; /* record for later use */
+ file->header.history_size = size; /* record for later use */
H5MM_xfree(head_buf);
H5MM_xfree(wh_buf);
@@ -1982,23 +1008,22 @@ H5FD__onion_open(const char *filename, unsigned flags, hid_t fapl_id, haddr_t ma
}
else {
/* Read in the history from the onion file */
- if (H5FD__onion_ingest_whole_history(&file->summary, file->backing_onion,
- file->header.whole_history_addr,
- file->header.whole_history_size) < 0)
- HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, NULL, "can't get whole-history from backing store")
+ if (H5FD__onion_ingest_history(&file->history, file->backing_onion, file->header.history_addr,
+ file->header.history_size) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, NULL, "can't get history from backing store")
/* Sanity check on revision ID */
- if (fa->revision_num > file->summary.n_revisions &&
+ if (fa->revision_num > file->history.n_revisions &&
fa->revision_num != H5FD_ONION_FAPL_INFO_REVISION_ID_LATEST)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "target revision ID out of range")
if (fa->revision_num == 0) {
file->rev_record.logi_eof = canon_eof;
}
- else if (file->summary.n_revisions > 0 &&
+ else if (file->history.n_revisions > 0 &&
H5FD__onion_ingest_revision_record(
- &file->rev_record, file->backing_onion, &file->summary,
- MIN(fa->revision_num - 1, (file->summary.n_revisions - 1))) < 0) {
+ &file->rev_record, file->backing_onion, &file->history,
+ MIN(fa->revision_num - 1, (file->history.n_revisions - 1))) < 0) {
HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, NULL, "can't get revision record from backing store")
}
@@ -2050,10 +1075,10 @@ done:
HDONE_ERROR(H5E_VFL, H5E_CANTRELEASE, NULL, "can't destroy backing recov")
if (file->rev_index)
- if (H5FD_onion_revision_index_destroy(file->rev_index) < 0)
+ if (H5FD__onion_revision_index_destroy(file->rev_index) < 0)
HDONE_ERROR(H5E_VFL, H5E_CANTRELEASE, NULL, "can't destroy revision index")
- H5MM_xfree(file->summary.record_pointer_list);
+ H5MM_xfree(file->history.record_locs);
H5MM_xfree(file->name_recov);
H5MM_xfree(file->rev_record.comment);
@@ -2094,16 +1119,16 @@ H5FD__onion_open_rw(H5FD_onion_t *file, unsigned int flags, haddr_t maxaddr, boo
if (file->header.flags & H5FD__ONION_HEADER_FLAG_WRITE_LOCK)
HGOTO_ERROR(H5E_VFL, H5E_UNSUPPORTED, FAIL, "can't write-open write-locked file")
- /* Copy whole-history to recovery file */
+ /* Copy history to recovery file */
if (NULL == (file->backing_recov = H5FD_open(file->name_recov, (flags | H5F_ACC_CREAT | H5F_ACC_TRUNC),
file->fa.backing_fapl_id, maxaddr)))
HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, FAIL, "unable to create recovery file")
- if (0 == (size = H5FD__onion_whole_history_write(&file->summary, file->backing_recov, 0, 0)))
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write whole-history to recovery file")
- if (size != file->header.whole_history_size)
- HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "written whole-history differed from expected size")
+ if (0 == (size = H5FD__onion_write_history(&file->history, file->backing_recov, 0, 0)))
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write history to recovery file")
+ if (size != file->header.history_size)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "written history differed from expected size")
/* Set write-lock flag in onion header */
@@ -2112,15 +1137,15 @@ H5FD__onion_open_rw(H5FD_onion_t *file, unsigned int flags, haddr_t maxaddr, boo
file->header.flags |= H5FD__ONION_HEADER_FLAG_WRITE_LOCK;
- if (0 == (size = H5FD_onion_history_header_encode(&file->header, buf, &_sum)))
+ if (0 == (size = H5FD__onion_history_header_encode(&file->header, buf, &_sum)))
HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "problem encoding history header")
- if (H5FDwrite(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, 0, (haddr_t)size, buf) < 0)
+ if (H5FD_write(file->backing_onion, H5FD_MEM_DRAW, 0, (haddr_t)size, buf) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write updated history header")
/* Prepare revision index and finalize write-mode open */
- if (NULL == (file->rev_index = H5FD_onion_revision_index_init(file->fa.page_size)))
+ if (NULL == (file->rev_index = H5FD__onion_revision_index_init(file->fa.page_size)))
HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, FAIL, "can't initialize revision index")
file->rev_record.parent_revision_num = file->rev_record.revision_num;
if (!new_open)
@@ -2136,7 +1161,7 @@ done:
}
if (file->rev_index != NULL) {
- if (H5FD_onion_revision_index_destroy(file->rev_index) < 0)
+ if (H5FD__onion_revision_index_destroy(file->rev_index) < 0)
HDONE_ERROR(H5E_VFL, H5E_CANTRELEASE, FAIL, "can't destroy revision index")
file->rev_index = NULL;
}
@@ -2164,8 +1189,6 @@ H5FD__onion_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h
size_t n_pages = 0;
uint32_t page_size = 0;
uint32_t page_size_log2 = 0;
- size_t i = 0;
- size_t j = 0;
size_t bytes_to_read = len;
unsigned char *buf_out = (unsigned char *)_buf_out;
herr_t ret_value = SUCCEED;
@@ -2187,8 +1210,8 @@ H5FD__onion_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h
n_pages = (len + page_size - 1) >> page_size_log2;
/* Read, page-by-page */
- for (i = 0; i < n_pages; i++) {
- const H5FD_onion_index_entry_t *entry_out_p = NULL;
+ for (size_t i = 0; i < n_pages; i++) {
+ const H5FD_onion_index_entry_t *entry_out = NULL;
haddr_t page_gap_head = 0; /* start of page to start of buffer */
haddr_t page_gap_tail = 0; /* end of buffer to end of page */
size_t page_readsize = 0;
@@ -2209,15 +1232,15 @@ H5FD__onion_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h
page_readsize = (size_t)page_size - page_gap_head - page_gap_tail;
if (TRUE == file->is_open_rw && file->fa.revision_num != 0 &&
- H5FD_onion_revision_index_find(file->rev_index, page_i, &entry_out_p)) {
- if (H5FDread(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT,
- (haddr_t)entry_out_p->phys_addr + page_gap_head, page_readsize, buf_out) < 0)
+ H5FD__onion_revision_index_find(file->rev_index, page_i, &entry_out)) {
+ if (H5FD_read(file->backing_onion, H5FD_MEM_DRAW, entry_out->phys_addr + page_gap_head,
+ page_readsize, buf_out) < 0)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't get working file data")
} /* end if page exists in 'live' revision index */
else if (file->fa.revision_num != 0 &&
- H5FD_onion_archival_index_find(&file->rev_record.archival_index, page_i, &entry_out_p)) {
- if (H5FDread(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT,
- (haddr_t)entry_out_p->phys_addr + page_gap_head, page_readsize, buf_out) < 0)
+ H5FD__onion_archival_index_find(&file->rev_record.archival_index, page_i, &entry_out)) {
+ if (H5FD_read(file->backing_onion, H5FD_MEM_DRAW, entry_out->phys_addr + page_gap_head,
+ page_readsize, buf_out) < 0)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't get previously-amended file data")
} /* end if page exists in 'dead' archival index */
else {
@@ -2227,15 +1250,14 @@ H5FD__onion_read(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id, h
haddr_t read_size = MIN(overlap_size, page_readsize);
/* Get all original bytes in page range */
- if ((read_size > 0) &&
- H5FDread(file->backing_canon, type, H5P_DEFAULT, addr_start, read_size, buf_out) < 0) {
+ if ((read_size > 0) && H5FD_read(file->backing_canon, type, addr_start, read_size, buf_out) < 0) {
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't get original file data")
}
/* Fill with 0s any gaps after end of original bytes
* and before end of page.
*/
- for (j = read_size; j < page_readsize; j++)
+ for (size_t j = read_size; j < page_readsize; j++)
buf_out[j] = 0;
} /* end if page exists in neither index */
@@ -2250,13 +1272,11 @@ done:
} /* end H5FD__onion_read() */
/*-----------------------------------------------------------------------------
- *
* Function: H5FD__onion_set_eoa
*
* Purpose: Set end-of-address marker of the logical file.
*
* Return: SUCCEED/FAIL
- *
*-----------------------------------------------------------------------------
*/
static herr_t
@@ -2289,8 +1309,6 @@ H5FD__onion_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
unsigned char * page_buf = NULL;
uint32_t page_size = 0;
uint32_t page_size_log2 = 0;
- size_t i = 0;
- size_t j = 0;
size_t bytes_to_write = len;
const unsigned char *buf = (const unsigned char *)_buf;
herr_t ret_value = SUCCEED;
@@ -2317,10 +1335,10 @@ H5FD__onion_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "cannot allocate temporary buffer")
/* Write, page-by-page */
- for (i = 0; i < n_pages; i++) {
+ for (size_t i = 0; i < n_pages; i++) {
const unsigned char * write_buf = buf;
H5FD_onion_index_entry_t new_entry;
- const H5FD_onion_index_entry_t *entry_out_p = NULL;
+ const H5FD_onion_index_entry_t *entry_out = NULL;
haddr_t page_gap_head = 0; /* start of page to start of buffer */
haddr_t page_gap_tail = 0; /* end of buffer to end of page */
size_t page_n_used = 0; /* nbytes from buffer for this page-write */
@@ -2342,19 +1360,19 @@ H5FD__onion_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
page_n_used = page_size - page_gap_head - page_gap_tail;
/* Modify page in revision index, if present */
- if (H5FD_onion_revision_index_find(file->rev_index, page_i, &entry_out_p)) {
+ if (H5FD__onion_revision_index_find(file->rev_index, page_i, &entry_out)) {
if (page_gap_head | page_gap_tail) {
/* Copy existing page verbatim. */
- if (H5FDread(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, (haddr_t)entry_out_p->phys_addr,
- page_size, page_buf) < 0)
+ if (H5FD_read(file->backing_onion, H5FD_MEM_DRAW, entry_out->phys_addr, page_size, page_buf) <
+ 0)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't get working file data")
/* Overlay delta from input buffer onto page buffer. */
HDmemcpy(page_buf + page_gap_head, buf, page_n_used);
write_buf = page_buf;
} /* end if partial page */
- if (H5FDwrite(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, (haddr_t)entry_out_p->phys_addr,
- page_size, write_buf) < 0)
+ if (H5FD_write(file->backing_onion, H5FD_MEM_DRAW, entry_out->phys_addr, page_size, write_buf) <
+ 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "write amended page data to backing file")
buf += page_n_used; /* overflow never touched */
@@ -2365,10 +1383,10 @@ H5FD__onion_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
if (page_gap_head || page_gap_tail) {
/* Fill gaps with existing data or zeroes. */
- if (H5FD_onion_archival_index_find(&file->rev_record.archival_index, page_i, &entry_out_p)) {
+ if (H5FD__onion_archival_index_find(&file->rev_record.archival_index, page_i, &entry_out)) {
/* Copy existing page verbatim. */
- if (H5FDread(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, (haddr_t)entry_out_p->phys_addr,
- page_size, page_buf) < 0)
+ if (H5FD_read(file->backing_onion, H5FD_MEM_DRAW, entry_out->phys_addr, page_size, page_buf) <
+ 0)
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't get previously-amended data")
} /* end if page exists in 'dead' archival index */
else {
@@ -2378,20 +1396,20 @@ H5FD__onion_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
/* Get all original bytes in page range */
if ((read_size > 0) &&
- H5FDread(file->backing_canon, type, H5P_DEFAULT, addr_start, read_size, page_buf) < 0) {
+ H5FD_read(file->backing_canon, type, addr_start, read_size, page_buf) < 0) {
HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't get original file data")
}
/* Fill with 0s any gaps after end of original bytes
* or start of page and before start of new data.
*/
- for (j = read_size; j < page_gap_head; j++)
+ for (size_t j = read_size; j < page_gap_head; j++)
page_buf[j] = 0;
/* Fill with 0s any gaps after end of original bytes
* or end of new data and before end of page.
*/
- for (j = MAX(read_size, page_size - page_gap_tail); j < page_size; j++)
+ for (size_t j = MAX(read_size, page_size - page_gap_tail); j < page_size; j++)
page_buf[j] = 0;
} /* end if page exists in neither index */
@@ -2408,11 +1426,10 @@ H5FD__onion_write(H5FD_t *_file, H5FD_mem_t type, hid_t H5_ATTR_UNUSED dxpl_id,
if (H5FD_set_eoa(file->backing_onion, H5FD_MEM_DRAW, file->history_eof + page_size) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA for new page amendment")
- if (H5FDwrite(file->backing_onion, H5FD_MEM_DRAW, H5P_DEFAULT, file->history_eof, page_size,
- write_buf) < 0)
+ if (H5FD_write(file->backing_onion, H5FD_MEM_DRAW, file->history_eof, page_size, write_buf) < 0)
HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "write amended page data to backing file")
- if (H5FD_onion_revision_index_insert(file->rev_index, &new_entry) < 0)
+ if (H5FD__onion_revision_index_insert(file->rev_index, &new_entry) < 0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINSERT, FAIL, "can't insert new index entry into revision index")
file->history_eof += page_size;
@@ -2465,7 +1482,7 @@ H5FD__onion_ctl(H5FD_t *_file, uint64_t op_code, uint64_t flags, const void H5_A
if (!output || !*output)
HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "the output parameter is null")
- **((uint64_t **)output) = file->summary.n_revisions;
+ **((uint64_t **)output) = file->history.n_revisions;
break;
/* Unknown op code */
default:
@@ -2478,515 +1495,112 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FD__onion_ctl() */
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_archival_index_is_valid
- *
- * Purpose: Determine whether an archival index structure is valid.
- *
- * + Verify page size (power of two).
- * + Verify list exists.
- * + Verify list contents:
- * + Sorted by increasing logical address (no duplicates)
- * + Logical addresses are multiples of page size.
- *
- * Return: TRUE/FALSE
- *-----------------------------------------------------------------------------
- */
-hbool_t
-H5FD_onion_archival_index_is_valid(const H5FD_onion_archival_index_t *aix)
-{
- hbool_t ret_value = TRUE;
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR;
-
- HDassert(aix);
-
- if (H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR != aix->version)
- HGOTO_DONE(FALSE)
- if (NULL == aix->list)
- HGOTO_DONE(FALSE)
-
- /* Ensure list is sorted on logi_page field */
- if (aix->n_entries > 1)
- for (uint64_t i = 1; i < aix->n_entries - 1; i++)
- if (aix->list[i + 1].logi_page <= aix->list[i].logi_page)
- HGOTO_DONE(FALSE)
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_archival_index_is_valid() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_archival_index_find
- *
- * Purpose: Retrieve the archival index entry by logical page ID.
- *
- * The archival index pointer must point to a valid index entry.
- * The entry out pointer-pointer cannot be null.
- *
- * Return: Success: Positive value (1) -- entry found.
- * Entry out pointer-pointer is set to point to entry.
- * Failure: Zero (0) -- entry not found.
- * Entry out pointer-pointer is unmodified.
- *-----------------------------------------------------------------------------
- */
-int
-H5FD_onion_archival_index_find(const H5FD_onion_archival_index_t *aix, uint64_t logi_page,
- const H5FD_onion_index_entry_t **entry_out_p)
-{
- uint64_t low = 0;
- uint64_t high = 0;
- uint64_t n = 0;
- uint64_t range = 0;
- H5FD_onion_index_entry_t *x = NULL;
- int ret_value = 0;
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR;
-
- HDassert(aix);
- HDassert(H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR == aix->version);
- HDassert(entry_out_p);
- if (aix->n_entries != 0)
- HDassert(aix->list);
-
- high = aix->n_entries - 1;
- range = high;
-
- /* Trivial cases */
- if (aix->n_entries == 0 || logi_page > aix->list[high].logi_page || logi_page < aix->list[0].logi_page)
- HGOTO_DONE(0)
-
- /*
- * Binary search on sorted list
- */
-
- /* Winnow down to first of found or one element */
- while (range > 0) {
- HDassert(high < aix->n_entries);
- n = low + (range / 2);
- x = &(aix->list[n]);
- if (x->logi_page == logi_page) {
- *entry_out_p = x; /* element found at fence */
- ret_value = 1;
- goto done;
- }
- else if (x->logi_page < logi_page) {
- low = (n == high) ? high : n + 1;
- }
- else {
- high = (n == low) ? low : n - 1;
- }
- range = high - low;
- }
-
- HDassert(high == low); /* one element */
-
- /* n == low/high check because we may have tested it already above */
- if ((n != low || n != high) && (aix->list[low].logi_page == logi_page)) {
- *entry_out_p = &aix->list[low];
- ret_value = 1;
- }
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_archival_index_find() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_revision_index_destroy
+/*-------------------------------------------------------------------------
+ * Function: H5FDget_onion_revision_count
*
- * Purpose: Release all resources of a revision index.
+ * Purpose: Get the number of revisions in an onion file
*
* Return: SUCCEED/FAIL
- *-----------------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*/
herr_t
-H5FD_onion_revision_index_destroy(H5FD__onion_revision_index_t *rix)
-{
- size_t i = 0;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR;
-
- HDassert(rix);
- HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix->version);
-
- for (i = 0; 0 < rix->_hash_table_n_keys_populated && i < rix->_hash_table_size; i++) {
- H5FD_onion_revision_index_hash_chain_node_t *next_p = NULL;
- H5FD_onion_revision_index_hash_chain_node_t *node_p = rix->_hash_table[i];
-
- if (node_p != NULL)
- rix->_hash_table_n_keys_populated -= 1;
-
- while (node_p != NULL) {
- HDassert(H5FD__ONION_REVISION_INDEX_HASH_CHAIN_NODE_VERSION_CURR == node_p->version);
-
- next_p = node_p->next;
- H5MM_xfree(node_p);
- node_p = next_p;
- }
- }
- H5MM_xfree(rix->_hash_table);
- H5MM_xfree(rix);
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_revision_index_destroy() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_revision_index_init
- *
- * Purpose: Initialize a revision index structure with a default starting
- * size. A new structure is allocated and populated with initial
- * values.
- *
- * Return: Success: Pointer to newly-allocated structure
- * Failure: NULL
- *-----------------------------------------------------------------------------
- */
-H5FD__onion_revision_index_t *
-H5FD_onion_revision_index_init(uint32_t page_size)
+H5FDonion_get_revision_count(const char *filename, hid_t fapl_id, size_t *revision_count /*out*/)
{
- uint64_t table_size = U64_EXP2(H5FD__ONION_REVISION_INDEX_STARTING_SIZE_LOG2);
- H5FD__onion_revision_index_t *rix = NULL;
- H5FD__onion_revision_index_t *ret_value = NULL;
-
- FUNC_ENTER_NOAPI_NOINIT;
+ H5P_genplist_t *plist = NULL;
+ H5FD_t * file = NULL;
+ herr_t ret_value = SUCCEED;
- HDassert(0 != page_size);
- HDassert(POWER_OF_TWO(page_size));
+ FUNC_ENTER_API(FAIL)
+ H5TRACE3("e", "*six", filename, fapl_id, revision_count);
- if (NULL == (rix = H5MM_calloc(sizeof(H5FD__onion_revision_index_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "cannot allocate index")
+ /* Check args */
+ if (!filename || !HDstrcmp(filename, ""))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid file name")
+ if (!revision_count)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "revision count can't be null")
- if (NULL ==
- (rix->_hash_table = H5MM_calloc(table_size * sizeof(H5FD_onion_revision_index_hash_chain_node_t *))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "cannot allocate hash table")
+ /* Make sure using the correct driver */
+ if (NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid FAPL ID")
+ if (H5FD_ONION != H5P_peek_driver(plist))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a Onion VFL driver")
- rix->version = H5FD__ONION_REVISION_INDEX_VERSION_CURR;
- rix->n_entries = 0;
- /* Compute and store log2(page_size) */
- for (rix->page_size_log2 = 0; (((uint32_t)1 << rix->page_size_log2) & page_size) == 0;
- rix->page_size_log2++)
- ;
- rix->_hash_table_size = table_size;
- rix->_hash_table_size_log2 = H5FD__ONION_REVISION_INDEX_STARTING_SIZE_LOG2;
- rix->_hash_table_n_keys_populated = 0;
+ /* Open the file with the driver */
+ if (NULL == (file = H5FD_open(filename, H5F_ACC_RDONLY, fapl_id, HADDR_UNDEF)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTOPENFILE, FAIL, "unable to open file with onion driver")
- ret_value = rix;
+ /* Call the private function */
+ if (H5FD__get_onion_revision_count(file, revision_count) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTGET, FAIL, "failed to get the number of revisions")
done:
- if (NULL == ret_value)
- H5MM_xfree(rix);
+ /* Close H5FD_t structure pointer */
+ if (file && H5FD_close(file) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_revision_index_init() */
+ FUNC_LEAVE_API(ret_value)
+}
-/*-----------------------------------------------------------------------------
- * Function: H5FD__onion_revision_index_resize()
- *
- * Purpose: Replace the hash table in the revision index.
- *
- * Doubles the available number of keys, re-hashes table contents,
- * and updates relevant components in the index structure.
+/*-------------------------------------------------------------------------
+ * Function: H5FD__get_onion_revision_count
*
- * Fails if unable to allocate space for larger hash table.
+ * Purpose: Private version of H5FDget_onion_revision_count()
*
* Return: SUCCEED/FAIL
- *-----------------------------------------------------------------------------
+ *-------------------------------------------------------------------------
*/
static herr_t
-H5FD__onion_revision_index_resize(H5FD__onion_revision_index_t *rix)
-{
- H5FD_onion_revision_index_hash_chain_node_t **new_table = NULL;
- uint64_t i = 0;
- uint64_t new_size_log2 = rix->_hash_table_size_log2 + 1;
- uint64_t new_size = U64_EXP2(new_size_log2);
- uint64_t new_n_keys_populated = 0;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_PACKAGE;
-
- HDassert(rix);
- HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix->version);
- HDassert(rix->_hash_table);
-
- if (NULL == (new_table = H5MM_calloc(new_size * sizeof(H5FD_onion_revision_index_hash_chain_node_t *))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "cannot allocate new hash table")
-
- for (i = 0; i < rix->_hash_table_size; i++) {
- while (rix->_hash_table[i] != NULL) {
- H5FD_onion_revision_index_hash_chain_node_t *node = NULL;
- uint64_t key = 0;
-
- /* Pop entry off of bucket stack and re-hash */
- node = rix->_hash_table[i];
- rix->_hash_table[i] = node->next;
- node->next = NULL;
- key = node->entry_data.logi_page & (new_size - 1);
-
- if (NULL == new_table[key]) {
- new_table[key] = node;
- new_n_keys_populated++;
- }
- else {
- node->next = new_table[i];
- new_table[i] = node;
- }
- }
- }
-
- H5MM_xfree(rix->_hash_table);
- rix->_hash_table_size = new_size;
- rix->_hash_table_size_log2 = new_size_log2;
- rix->_hash_table_n_keys_populated = new_n_keys_populated;
- rix->_hash_table = new_table;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD__onion_revision_index_resize() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_revision_index_insert()
- *
- * Purpose: Add an entry to the revision index, or update an existing
- * entry. Must be used to update entries as well as add --
- * checksum value will change.
- *
- * Entry data is copied into separate memory region; user pointer
- * can be safley re-used or discarded after operation.
- *
- * Return: SUCCEED/FAIL
- *-----------------------------------------------------------------------------
- */
-herr_t
-H5FD_onion_revision_index_insert(H5FD__onion_revision_index_t *rix, const H5FD_onion_index_entry_t *entry)
+H5FD__get_onion_revision_count(H5FD_t *file, size_t *revision_count)
{
- uint64_t key = 0;
- H5FD_onion_revision_index_hash_chain_node_t * node = NULL;
- H5FD_onion_revision_index_hash_chain_node_t **append_dest = NULL;
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER_NOAPI_NOINIT;
-
- HDassert(rix);
- HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix->version);
- HDassert(entry);
-
- /* Resize and re-hash table if necessary */
- if (rix->n_entries >= (rix->_hash_table_size * 2) ||
- rix->_hash_table_n_keys_populated >= (rix->_hash_table_size / 2)) {
- if (H5FD__onion_revision_index_resize(rix) < 0)
- HGOTO_ERROR(H5E_RESOURCE, H5E_NONE_MINOR, FAIL, "unable to resize and hash table")
- }
-
- key = entry->logi_page & (rix->_hash_table_size - 1);
- HDassert(key < rix->_hash_table_size);
+ uint64_t op_code;
+ uint64_t flags;
+ herr_t ret_value = SUCCEED;
- if (NULL == rix->_hash_table[key]) {
- /* Key maps to empty bucket */
+ FUNC_ENTER_PACKAGE
- append_dest = &rix->_hash_table[key];
- rix->_hash_table_n_keys_populated++;
- }
- else {
- /* Key maps to populated bucket */
+ HDassert(file);
+ HDassert(revision_count);
- for (node = rix->_hash_table[key]; node != NULL; node = node->next) {
- append_dest = &node->next; /* look for bucket tail */
- if (entry->logi_page == node->entry_data.logi_page) {
- if (entry->phys_addr != node->entry_data.phys_addr) {
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "physical address mismatch");
- }
- HDmemcpy(&node->entry_data, entry, sizeof(H5FD_onion_index_entry_t));
- append_dest = NULL; /* Node updated, do not append */
- break;
- }
- }
- }
+ op_code = H5FD_CTL__GET_NUM_REVISIONS;
+ flags = H5FD_CTL__FAIL_IF_UNKNOWN_FLAG;
- /* Add new entry to bucket chain */
- if (append_dest != NULL) {
- if (NULL == (node = H5MM_malloc(sizeof(H5FD_onion_revision_index_hash_chain_node_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "cannot allocate new ash chain node")
- node->version = H5FD__ONION_REVISION_INDEX_HASH_CHAIN_NODE_VERSION_CURR;
- node->next = NULL;
- HDmemcpy(&node->entry_data, entry, sizeof(H5FD_onion_index_entry_t));
- *append_dest = node;
- rix->n_entries++;
- }
+ /* Get the number of revisions via the ctl callback */
+ if (H5FD_ctl(file, op_code, flags, NULL, (void **)&revision_count) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_FCNTL, FAIL, "VFD ctl request failed")
done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_revision_index_insert() */
-
-/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_revision_index_find()
- *
- *
- * Purpose: Get pointer to revision index entry with the given page number,
- * if it exists in the index.
- *
- * Return: Success: Positive value (1) -- entry found.
- * Entry out pointer-pointer is set to point to entry.
- * Failure: Zero (0) -- entry not found.
- * Entry out pointer-pointer is unmodified.
- *-----------------------------------------------------------------------------
- */
-int
-H5FD_onion_revision_index_find(const H5FD__onion_revision_index_t *rix_p, uint64_t logi_page,
- const H5FD_onion_index_entry_t **entry_out_p)
-{
- uint64_t key = 0;
- int ret_value = 0;
-
- FUNC_ENTER_NOAPI_NOINIT_NOERR;
-
- HDassert(rix_p);
- HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix_p->version);
- HDassert(rix_p->_hash_table);
- HDassert(entry_out_p);
-
- key = logi_page & (rix_p->_hash_table_size - 1);
- HDassert(key < rix_p->_hash_table_size);
-
- if (rix_p->_hash_table[key] != NULL) {
- H5FD_onion_revision_index_hash_chain_node_t *node = NULL;
-
- for (node = rix_p->_hash_table[key]; node != NULL; node = node->next) {
- if (logi_page == node->entry_data.logi_page) {
- *entry_out_p = &node->entry_data;
- ret_value = 1;
- break;
- }
- }
- }
-
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_revision_index_find() */
-
-/*-----------------------------------------------------------------------------
- * Callback for comparisons in sorting archival index entries by logi_page.
- *-----------------------------------------------------------------------------
- */
-static int
-H5FD__onion_archival_index_list_sort_cmp(const void *_a, const void *_b)
-{
- const H5FD_onion_index_entry_t *a = (const H5FD_onion_index_entry_t *)_a;
- const H5FD_onion_index_entry_t *b = (const H5FD_onion_index_entry_t *)_b;
-
- if (a->logi_page < b->logi_page)
- return -1;
- else if (a->logi_page > b->logi_page)
- return 1;
- return 0;
-} /* end H5FD__onion_archival_index_list_sort_cmp() */
+ FUNC_LEAVE_NOAPI(ret_value)
+}
/*-----------------------------------------------------------------------------
- * Function: H5FD_onion_merge_revision_index_into_archival_index
- *
- * Purpose: Merge index entries from revision index into archival index.
+ * Function: H5FD__onion_write_final_history
*
- * If successful, the archival index is expanded 'behind the
- * scenes' and new entries from the revision index are inserted.
- * The archival index remains sorted in ascending order of logical
- * address.
- *
- * The conversion to archival index changes logical pages in
- * revision index entries to their logical addresses in-file.
+ * Purpose: Write final history to appropriate backing file on file close
*
* Return: SUCCEED/FAIL
*-----------------------------------------------------------------------------
*/
herr_t
-H5FD_onion_merge_revision_index_into_archival_index(const H5FD__onion_revision_index_t *rix,
- H5FD_onion_archival_index_t * aix)
+H5FD__onion_write_final_history(H5FD_onion_t *file)
{
- uint64_t i = 0;
- uint64_t n_kept = 0;
- H5FD_onion_index_entry_t * kept_list = NULL;
- H5FD_onion_archival_index_t new_aix = {
- H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR, 0, /* page_size_log2 tbd */
- 0, /* n_entries */
- NULL, /* list pointer (allocated later) */
- };
+ size_t size = 0;
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT;
-
- HDassert(rix);
- HDassert(aix);
- HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix->version);
- HDassert(H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR == aix->version);
- HDassert(aix->page_size_log2 == rix->page_size_log2);
-
- /* If the revision index is empty there is nothing to archive */
- if (rix->n_entries == 0)
- goto done;
-
- /* Add all revision index entries to new archival list */
- new_aix.page_size_log2 = aix->page_size_log2;
-
- if (NULL == (new_aix.list = H5MM_calloc(rix->n_entries * sizeof(H5FD_onion_index_entry_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to allocate new archival index list")
-
- for (i = 0; i < rix->_hash_table_size; i++) {
- const H5FD_onion_revision_index_hash_chain_node_t *node_p = NULL;
-
- for (node_p = rix->_hash_table[i]; node_p != NULL; node_p = node_p->next) {
- HDmemcpy(&new_aix.list[new_aix.n_entries], &node_p->entry_data, sizeof(H5FD_onion_index_entry_t));
- new_aix.n_entries++;
- }
- }
-
- /* Sort the new archival list */
- HDqsort(new_aix.list, new_aix.n_entries, sizeof(H5FD_onion_index_entry_t),
- H5FD__onion_archival_index_list_sort_cmp);
+ FUNC_ENTER_PACKAGE;
- /* Add the old archival index entries to a 'kept' list containing the
- * old archival list entries that are not also included in the revision
- * list.
- *
- * Note that kept_list will be NULL if there are no entries in the passed-in
- * archival list.
- */
- if (aix->n_entries > 0)
- if (NULL == (kept_list = H5MM_calloc(aix->n_entries * sizeof(H5FD_onion_index_entry_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to allocate larger archival index list")
+ /* TODO: history EOF may not be correct (under what circumstances?) */
+ if (0 == (size = H5FD__onion_write_history(&(file->history), file->backing_onion, file->history_eof,
+ file->history_eof)))
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write final history")
- for (i = 0; i < aix->n_entries; i++) {
- const H5FD_onion_index_entry_t *_p = NULL;
+ if (size != file->header.history_size)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "written history differed from expected size")
- /* Add only if page not already added from revision index */
- if (H5FD_onion_archival_index_find(&new_aix, aix->list[i].logi_page, &_p) == 0) {
- HDmemcpy(&kept_list[n_kept], &aix->list[i], sizeof(H5FD_onion_index_entry_t));
- n_kept++;
- }
- }
-
- /* Destroy the old archival list and replace with a list big enough to hold
- * the revision list entries and the kept list entries
+ /* Is last write operation to history file; no need to extend to page
+ * boundary if set to page-align.
*/
- H5MM_xfree(aix->list);
- if (NULL == (aix->list = H5MM_calloc((new_aix.n_entries + n_kept) * sizeof(H5FD_onion_index_entry_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to allocate exact-size archival index list")
-
- /* Copy (new) revision list entries to replacement list */
- HDmemcpy(aix->list, new_aix.list, sizeof(H5FD_onion_index_entry_t) * new_aix.n_entries);
- aix->n_entries = new_aix.n_entries;
-
- /* Copy (old) kept archival list entries to replacement list */
- if (n_kept > 0) {
- HDmemcpy(&aix->list[aix->n_entries], kept_list, sizeof(H5FD_onion_index_entry_t) * n_kept);
- aix->n_entries += n_kept;
- }
-
- /* Sort this list */
- HDqsort(aix->list, aix->n_entries, sizeof(H5FD_onion_index_entry_t),
- H5FD__onion_archival_index_list_sort_cmp);
+ file->history_eof += size;
done:
- /* Free the temporary lists */
- H5MM_xfree(kept_list);
- H5MM_xfree(new_aix.list);
-
FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FD_onion_merge_revision_index_into_entry_list() */
+} /* end H5FD__onion_write_final_history() */
diff --git a/src/H5FDonion_history.c b/src/H5FDonion_history.c
new file mode 100644
index 0000000..39acbb1
--- /dev/null
+++ b/src/H5FDonion_history.c
@@ -0,0 +1,480 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Onion Virtual File Driver (VFD)
+ *
+ * Purpose: Code for the onion file's history
+ */
+
+/* This source code file is part of the H5FD driver module */
+#include "H5FDdrvr_module.h"
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5FDonion.h" /* Onion file driver */
+#include "H5FDonion_priv.h" /* Onion file driver internals */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD_ingest_history_header
+ *
+ * Purpose: Read and decode the history header information from `raw_file`
+ * at `addr`, and store the decoded information in the structure
+ * at `hdr_out`.
+ *
+ * Return: SUCCEED/FAIL
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5FD__onion_ingest_history_header(H5FD_onion_history_header_t *hdr_out, H5FD_t *raw_file, haddr_t addr)
+{
+ unsigned char *buf = NULL;
+ herr_t ret_value = SUCCEED;
+ haddr_t size = (haddr_t)H5FD__ONION_ENCODED_SIZE_HEADER;
+ uint32_t sum = 0;
+
+ FUNC_ENTER_PACKAGE;
+
+ if (H5FD_get_eof(raw_file, H5FD_MEM_DRAW) < (addr + size))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "header indicates history beyond EOF")
+
+ if (NULL == (buf = H5MM_malloc(sizeof(char) * size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer space")
+
+ if (H5FD_set_eoa(raw_file, H5FD_MEM_DRAW, (addr + size)) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA")
+
+ if (H5FD_read(raw_file, H5FD_MEM_DRAW, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read history header from file")
+
+ if (H5FD__onion_history_header_decode(buf, hdr_out) == 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode history header")
+
+ sum = H5_checksum_fletcher32(buf, size - 4);
+ if (hdr_out->checksum != sum)
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored")
+
+done:
+ H5MM_xfree(buf);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_ingest_history_header() */
+
+/*-----------------------------------------------------------------------------
+ * Read and decode the history information from `raw_file` at
+ * `addr` .. `addr + size` (taken from history header), and store the decoded
+ * information in the structure at `history_out`.
+ *
+ * If successful, `history_out->record_locs` is always allocated, even if
+ * there is zero revisions.
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5FD__onion_ingest_history(H5FD_onion_history_t *history_out, H5FD_t *raw_file, haddr_t addr, haddr_t size)
+{
+ unsigned char *buf = NULL;
+ herr_t ret_value = SUCCEED;
+ uint32_t sum = 0;
+
+ FUNC_ENTER_PACKAGE;
+
+ if (H5FD_get_eof(raw_file, H5FD_MEM_DRAW) < (addr + size))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "header indicates history beyond EOF")
+
+ if (NULL == (buf = H5MM_malloc(sizeof(char) * size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer space");
+
+ if (H5FD_set_eoa(raw_file, H5FD_MEM_DRAW, (addr + size)) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA")
+
+ if (H5FD_read(raw_file, H5FD_MEM_DRAW, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read history from file")
+
+ if (H5FD__onion_history_decode(buf, history_out) != size)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode history (initial)")
+
+ sum = H5_checksum_fletcher32(buf, size - 4);
+ if (history_out->checksum != sum)
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored")
+
+ history_out->record_locs = H5MM_calloc(history_out->n_revisions * sizeof(H5FD_onion_record_loc_t));
+ if (history_out->n_revisions > 0 && NULL == history_out->record_locs)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate record pointer list")
+
+ if (H5FD__onion_history_decode(buf, history_out) != size)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode history (final)")
+
+done:
+ H5MM_xfree(buf);
+ if (ret_value == FAIL)
+ H5MM_xfree(history_out->record_locs);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_ingest_history() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD__onion_write_header
+ *
+ * Purpose: Write in-memory history header to appropriate backing file.
+ * Overwrites existing header data.
+ *
+ * Return: SUCCEED/FAIL
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FD__onion_write_header(H5FD_onion_history_header_t *header, H5FD_t *backing_file)
+{
+ uint32_t sum = 0; /* Not used, but required by the encoder */
+ uint64_t size = 0;
+ unsigned char *buf = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE;
+
+ if (NULL == (buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_HEADER)))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTALLOC, FAIL, "can't allocate buffer for updated history header")
+
+ if (0 == (size = H5FD__onion_history_header_encode(header, buf, &sum)))
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "problem encoding updated history header")
+
+ if (H5FD_write(backing_file, H5FD_MEM_DRAW, 0, (haddr_t)size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, FAIL, "can't write updated history header")
+
+done:
+ H5MM_xfree(buf);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_write_header()*/
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_write_history
+ *
+ * Purpose: Encode and write history to file at the given address.
+ *
+ * Returns: Success: Number of bytes written to destination file (always non-zero)
+ * Failure: 0
+ *-----------------------------------------------------------------------------
+ */
+uint64_t
+H5FD__onion_write_history(H5FD_onion_history_t *history, H5FD_t *file_dest, haddr_t off_start,
+ haddr_t filesize_curr)
+{
+ uint32_t _sum = 0; /* Required by the API call but unused here */
+ uint64_t size = 0;
+ unsigned char *buf = NULL;
+ uint64_t ret_value = 0;
+
+ FUNC_ENTER_PACKAGE;
+
+ if (NULL == (buf = H5MM_malloc(H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY +
+ (H5FD__ONION_ENCODED_SIZE_RECORD_POINTER * history->n_revisions))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, 0, "can't allocate buffer for updated history")
+
+ if (0 == (size = H5FD__onion_history_encode(history, buf, &_sum)))
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, 0, "problem encoding updated history")
+
+ if ((size + off_start > filesize_curr) && (H5FD_set_eoa(file_dest, H5FD_MEM_DRAW, off_start + size) < 0))
+ HGOTO_ERROR(H5E_VFL, H5E_CANTSET, 0, "can't modify EOA for updated history")
+
+ if (H5FD_write(file_dest, H5FD_MEM_DRAW, off_start, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_WRITEERROR, 0, "can't write history as intended")
+
+ ret_value = size;
+
+done:
+ H5MM_xfree(buf);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_write_history() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_history_header_decode
+ *
+ * Purpose: Attempt to read a buffer and store it as a history-header
+ * structure.
+ *
+ * Implementation must correspond with
+ * H5FD__onion_history_header_encode().
+ *
+ * Return: Success: Number of bytes read from buffer
+ * Failure: 0
+ *-----------------------------------------------------------------------------
+ */
+uint64_t
+H5FD__onion_history_header_decode(unsigned char *buf, H5FD_onion_history_header_t *header)
+{
+ uint32_t ui32 = 0;
+ uint32_t sum = 0;
+ uint64_t ui64 = 0;
+ uint8_t * ui8p = NULL;
+ unsigned char *ptr = NULL;
+ uint64_t ret_value = 0;
+
+ FUNC_ENTER_PACKAGE;
+
+ HDassert(buf != NULL);
+ HDassert(header != NULL);
+ HDassert(H5FD__ONION_HEADER_VERSION_CURR == header->version);
+
+ if (HDstrncmp((const char *)buf, H5FD__ONION_HEADER_SIGNATURE, 4))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid header signature")
+
+ if (buf[4] != H5FD__ONION_HEADER_VERSION_CURR)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid header version")
+
+ ptr = buf + 5;
+ ui32 = 0;
+ HDmemcpy(&ui32, ptr, 3);
+ ui8p = (uint8_t *)&ui32;
+ UINT32DECODE(ui8p, header->flags);
+ ptr += 3;
+
+ HDmemcpy(&ui32, ptr, 4);
+ ui8p = (uint8_t *)&ui32;
+ UINT32DECODE(ui8p, header->page_size);
+ ptr += 4;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT32DECODE(ui8p, header->origin_eof);
+ ptr += 8;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT32DECODE(ui8p, header->history_addr);
+ ptr += 8;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT32DECODE(ui8p, header->history_size);
+ ptr += 8;
+
+ sum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
+
+ HDmemcpy(&ui32, ptr, 4);
+ ui8p = (uint8_t *)&ui32;
+ UINT32DECODE(ui8p, header->checksum);
+ ptr += 4;
+
+ if (sum != header->checksum)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "checksum mismatch")
+
+ ret_value = (uint64_t)(ptr - buf);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_history_header_decode() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_history_header_encode
+ *
+ * Purpose: Write history-header structure to the given buffer.
+ * All multi-byte elements are stored in little-endian word order.
+ *
+ * Implementation must correspond with
+ * H5FD__onion_history_header_decode().
+ *
+ * The destination buffer must be sufficiently large to hold the
+ * encoded contents (H5FD__ONION_ENCODED_SIZE_HEADER).
+ *
+ * Return: Number of bytes written to buffer.
+ * The checksum of the generated buffer contents (excluding the
+ * checksum itself) is stored in the pointer `sum_out`).
+ *-----------------------------------------------------------------------------
+ */
+uint64_t
+H5FD__onion_history_header_encode(H5FD_onion_history_header_t *header, unsigned char *buf, uint32_t *sum_out)
+{
+ unsigned char *ptr = buf;
+ uint64_t ret_value = 0;
+
+ FUNC_ENTER_PACKAGE_NOERR;
+
+ HDassert(buf != NULL);
+ HDassert(sum_out != NULL);
+ HDassert(header != NULL);
+ HDassert(H5FD__ONION_HEADER_VERSION_CURR == header->version);
+ HDassert(0 == (header->flags & 0xFF000000)); /* max three bits long */
+
+ HDmemcpy(ptr, H5FD__ONION_HEADER_SIGNATURE, 4);
+ ptr += 4;
+ HDmemcpy(ptr, (unsigned char *)&header->version, 1);
+ ptr += 1;
+ UINT32ENCODE(ptr, header->flags);
+ ptr -= 1; /* truncate to three bytes */
+ UINT32ENCODE(ptr, header->page_size);
+ UINT64ENCODE(ptr, header->origin_eof);
+ UINT64ENCODE(ptr, header->history_addr);
+ UINT64ENCODE(ptr, header->history_size);
+ *sum_out = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
+ UINT32ENCODE(ptr, *sum_out);
+ ret_value = (uint64_t)(ptr - buf);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_history_header_encode() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_history_decode
+ *
+ * Purpose: Attempt to read a buffer and store it as a history
+ * structure.
+ *
+ * Implementation must correspond with
+ * H5FD__onion_history_encode().
+ *
+ * MUST BE CALLED TWICE:
+ * On the first call, n_records in the destination structure must
+ * be zero, and record_locs be NULL.
+ *
+ * If the buffer is well-formed, the destination structure is
+ * tentatively populated with fixed-size values, and the number of
+ * bytes read are returned.
+ *
+ * Prior to the second call, the user must allocate space for
+ * record_locs to hold n_records record-pointer structs.
+ *
+ * Then the decode operation is called a second time, and all
+ * components will be populated (and again number of bytes read is
+ * returned).
+ *
+ * Return: Success: Number of bytes read from buffer
+ * Failure: 0
+ *-----------------------------------------------------------------------------
+ */
+uint64_t
+H5FD__onion_history_decode(unsigned char *buf, H5FD_onion_history_t *history)
+{
+ uint32_t ui32 = 0;
+ uint32_t sum = 0;
+ uint64_t ui64 = 0;
+ uint64_t n_revisions = 0;
+ uint8_t * ui8p = NULL;
+ unsigned char *ptr = NULL;
+ uint64_t ret_value = 0;
+
+ FUNC_ENTER_PACKAGE;
+
+ HDassert(buf != NULL);
+ HDassert(history != NULL);
+ HDassert(H5FD__ONION_WHOLE_HISTORY_VERSION_CURR == history->version);
+
+ if (HDstrncmp((const char *)buf, "OWHS", 4))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid signature")
+
+ if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != buf[4])
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid version")
+
+ ptr = buf + 8;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT64DECODE(ui8p, n_revisions);
+ ptr += 8;
+
+ if (0 == history->n_revisions) {
+ history->n_revisions = n_revisions;
+ ptr += H5FD__ONION_ENCODED_SIZE_RECORD_POINTER * n_revisions;
+ }
+ else {
+ if (history->n_revisions != n_revisions)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0,
+ "history argument suggests different revision count than encoded buffer")
+ if (NULL == history->record_locs)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "list is NULL -- cannot populate")
+
+ for (uint64_t i = 0; i < n_revisions; i++) {
+ H5FD_onion_record_loc_t *rloc = &history->record_locs[i];
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT64DECODE(ui8p, rloc->phys_addr);
+ ptr += 8;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT64DECODE(ui8p, rloc->record_size);
+ ptr += 8;
+
+ HDmemcpy(&ui32, ptr, 4);
+ ui8p = (uint8_t *)&ui32;
+ UINT64DECODE(ui8p, rloc->checksum);
+ ptr += 4;
+ }
+ }
+
+ sum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
+
+ HDmemcpy(&ui32, ptr, 4);
+ ui8p = (uint8_t *)&ui32;
+ UINT32DECODE(ui8p, history->checksum);
+ ptr += 4;
+
+ if (sum != history->checksum)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "checksum mismatch")
+
+ ret_value = (uint64_t)(ptr - buf);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_history_decode() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_history_encode
+ *
+ * Purpose: Write history structure to the given buffer.
+ * All multi-byte elements are stored in little-endian word order.
+ *
+ * Implementation must correspond with
+ * H5FD__onion_history_decode().
+ *
+ * The destination buffer must be sufficiently large to hold the
+ * encoded contents.
+ * (Hint: `sizeof(history struct) +
+ * sizeof(record-pointer-struct) * n_records)` guarantees
+ * ample/excess space.)
+ *
+ * Return: Number of bytes written to buffer.
+ * The checksum of the generated buffer contents (excluding the
+ * checksum itself) is stored in the pointer `sum_out`).
+ *-----------------------------------------------------------------------------
+ */
+uint64_t
+H5FD__onion_history_encode(H5FD_onion_history_t *history, unsigned char *buf, uint32_t *sum_out)
+{
+ unsigned char *ptr = buf;
+ uint32_t vers_u32 = (uint32_t)history->version; /* pad out unused bytes */
+
+ FUNC_ENTER_PACKAGE_NOERR;
+
+ HDassert(history != NULL);
+ HDassert(H5FD__ONION_WHOLE_HISTORY_VERSION_CURR == history->version);
+ HDassert(buf != NULL);
+ HDassert(sum_out != NULL);
+
+ HDmemcpy(ptr, H5FD__ONION_WHOLE_HISTORY_SIGNATURE, 4);
+ ptr += 4;
+ UINT32ENCODE(ptr, vers_u32);
+ UINT64ENCODE(ptr, history->n_revisions);
+ if (history->n_revisions > 0) {
+ HDassert(history->record_locs != NULL); /* TODO: error? */
+ for (uint64_t i = 0; i < history->n_revisions; i++) {
+ UINT64ENCODE(ptr, history->record_locs[i].phys_addr);
+ UINT64ENCODE(ptr, history->record_locs[i].record_size);
+ UINT32ENCODE(ptr, history->record_locs[i].checksum);
+ }
+ }
+ *sum_out = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
+ UINT32ENCODE(ptr, *sum_out);
+
+ FUNC_LEAVE_NOAPI((uint64_t)(ptr - buf));
+} /* end H5FD__onion_history_encode() */
diff --git a/src/H5FDonion_history.h b/src/H5FDonion_history.h
new file mode 100644
index 0000000..e9034a2
--- /dev/null
+++ b/src/H5FDonion_history.h
@@ -0,0 +1,88 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Onion Virtual File Driver (VFD)
+ *
+ * Purpose: Interface for the onion file's history
+ */
+
+#ifndef H5FDonion_history_H
+#define H5FDonion_history_H
+
+/* Number of bytes to encode fixed-size components */
+#define H5FD__ONION_ENCODED_SIZE_HEADER 40
+#define H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY 20
+
+/* Flags must align exactly one per bit, up to 24 bits */
+#define H5FD__ONION_HEADER_FLAG_WRITE_LOCK 0x1
+#define H5FD__ONION_HEADER_FLAG_DIVERGENT_HISTORY 0x2
+#define H5FD__ONION_HEADER_FLAG_PAGE_ALIGNMENT 0x4
+#define H5FD__ONION_HEADER_SIGNATURE "OHDH"
+#define H5FD__ONION_HEADER_VERSION_CURR 1
+
+#define H5FD__ONION_WHOLE_HISTORY_SIGNATURE "OWHS"
+#define H5FD__ONION_WHOLE_HISTORY_VERSION_CURR 1
+
+/* In-memory representation of the on-store onion history file header.
+ */
+typedef struct H5FD_onion_history_header_t {
+ uint8_t version;
+ uint32_t flags; /* At most three bytes used! */
+ uint32_t page_size;
+ uint64_t origin_eof; /* Size of the 'original' canonical file */
+ uint64_t history_addr;
+ uint64_t history_size;
+ uint32_t checksum;
+} H5FD_onion_history_header_t;
+
+/* In-memory representation of the on-store revision record.
+ * Used in the history.
+ */
+typedef struct H5FD_onion_record_loc_t {
+ haddr_t phys_addr;
+ size_t record_size;
+ uint32_t checksum;
+} H5FD_onion_record_loc_t;
+
+/* In-memory representation of the on-store history record/summary.
+ */
+typedef struct H5FD_onion_history_t {
+ uint8_t version;
+ uint64_t n_revisions;
+ H5FD_onion_record_loc_t *record_locs;
+ uint32_t checksum;
+} H5FD_onion_history_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+H5_DLL herr_t H5FD__onion_ingest_history_header(H5FD_onion_history_header_t *hdr_out, H5FD_t *raw_file,
+ haddr_t addr);
+H5_DLL herr_t H5FD__onion_ingest_history(H5FD_onion_history_t *history_out, H5FD_t *raw_file, haddr_t addr,
+ haddr_t size);
+
+H5_DLL herr_t H5FD__onion_write_header(H5FD_onion_history_header_t *header, H5FD_t *backing_file);
+H5_DLL uint64_t H5FD__onion_write_history(H5FD_onion_history_t *history, H5FD_t *backing_file,
+ haddr_t off_start, haddr_t filesize_curr);
+
+H5_DLL uint64_t H5FD__onion_history_header_decode(unsigned char *, H5FD_onion_history_header_t *);
+H5_DLL uint64_t H5FD__onion_history_header_encode(H5FD_onion_history_header_t *, unsigned char *, uint32_t *);
+
+H5_DLL uint64_t H5FD__onion_history_decode(unsigned char *, H5FD_onion_history_t *);
+H5_DLL uint64_t H5FD__onion_history_encode(H5FD_onion_history_t *, unsigned char *, uint32_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H5FDonion_history_H */
diff --git a/src/H5FDonion_index.c b/src/H5FDonion_index.c
new file mode 100644
index 0000000..66af1a1
--- /dev/null
+++ b/src/H5FDonion_index.c
@@ -0,0 +1,934 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Onion Virtual File Driver (VFD)
+ *
+ * Purpose: Code for the archival and revision indexes
+ */
+
+/* This source code file is part of the H5FD driver module */
+#include "H5FDdrvr_module.h"
+
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5FDprivate.h" /* File drivers */
+#include "H5FDonion.h" /* Onion file driver */
+#include "H5FDonion_priv.h" /* Onion file driver internals */
+
+/* 2^n for uint64_t types -- H5_EXP2 unsafe past 32 bits */
+#define U64_EXP2(n) ((uint64_t)1 << (n))
+
+static int H5FD__onion_archival_index_list_sort_cmp(const void *, const void *);
+static herr_t H5FD__onion_revision_index_resize(H5FD_onion_revision_index_t *rix);
+
+/*-----------------------------------------------------------------------------
+ * Read and decode the revision_record information from `raw_file` at
+ * `addr` .. `addr + size` (taken from history), and store the decoded
+ * information in the structure at `r_out`.
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5FD__onion_ingest_revision_record(H5FD_onion_revision_record_t *r_out, H5FD_t *raw_file,
+ const H5FD_onion_history_t *history, uint64_t revision_num)
+{
+ unsigned char *buf = NULL;
+ herr_t ret_value = SUCCEED;
+ uint64_t n = 0;
+ uint64_t high = 0;
+ uint64_t low = 0;
+ uint64_t range = 0;
+ uint32_t sum = 0;
+ haddr_t addr = 0;
+ size_t size = 0;
+
+ FUNC_ENTER_PACKAGE;
+
+ HDassert(r_out);
+ HDassert(raw_file);
+ HDassert(history);
+ HDassert(history->record_locs);
+ HDassert(history->n_revisions > 0);
+
+ high = history->n_revisions - 1;
+ range = high;
+ addr = history->record_locs[high].phys_addr;
+ size = history->record_locs[high].record_size;
+
+ /* Initialize r_out
+ *
+ * TODO: This function should completely initialize r_out. Relying on
+ * other code to some of the work while we just paste over parts
+ * of the struct here is completely bananas.
+ */
+ r_out->comment = H5MM_xfree(r_out->comment);
+ r_out->archival_index.list = H5MM_xfree(r_out->archival_index.list);
+
+ if (H5FD_get_eof(raw_file, H5FD_MEM_DRAW) < (addr + size))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "at least one record extends beyond EOF")
+
+ /* recovery-open may have EOA below revision record */
+ if ((H5FD_get_eoa(raw_file, H5FD_MEM_DRAW) < (addr + size)) &&
+ (H5FD_set_eoa(raw_file, H5FD_MEM_DRAW, (addr + size)) < 0)) {
+ HGOTO_ERROR(H5E_VFL, H5E_CANTSET, FAIL, "can't modify EOA");
+ }
+
+ /* Perform binary search on records to find target revision by ID.
+ * As IDs are added sequentially, they are "guaranteed" to be sorted.
+ */
+ while (range > 0) {
+ n = (range / 2) + low;
+ addr = history->record_locs[n].phys_addr;
+ size = history->record_locs[n].record_size;
+
+ if (NULL == (buf = H5MM_malloc(sizeof(char) * size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer space")
+
+ if (H5FD_read(raw_file, H5FD_MEM_DRAW, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read revision record from file")
+
+ if (H5FD__onion_revision_record_decode(buf, r_out) != size)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode revision record (initial)")
+
+ sum = H5_checksum_fletcher32(buf, size - 4);
+ if (r_out->checksum != sum)
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored")
+
+ if (revision_num == r_out->revision_num)
+ break;
+
+ H5MM_xfree(buf);
+ buf = NULL;
+
+ r_out->archival_index.n_entries = 0;
+ r_out->comment_size = 0;
+
+ if (r_out->revision_num < revision_num)
+ low = (n == high) ? high : n + 1;
+ else
+ high = (n == low) ? low : n - 1;
+ range = high - low;
+ } /* end while 'non-leaf' binary search */
+
+ if (range == 0) {
+ n = low;
+ addr = history->record_locs[n].phys_addr;
+ size = history->record_locs[n].record_size;
+
+ if (NULL == (buf = H5MM_malloc(sizeof(char) * size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate buffer space")
+
+ if (H5FD_read(raw_file, H5FD_MEM_DRAW, addr, size, buf) < 0)
+ HGOTO_ERROR(H5E_VFL, H5E_READERROR, FAIL, "can't read revision record from file")
+
+ if (H5FD__onion_revision_record_decode(buf, r_out) != size)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode revision record (initial)")
+
+ sum = H5_checksum_fletcher32(buf, size - 4);
+ if (r_out->checksum != sum)
+ HGOTO_ERROR(H5E_VFL, H5E_BADVALUE, FAIL, "checksum mismatch between buffer and stored")
+
+ if (revision_num != r_out->revision_num)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL,
+ "could not find target revision!") /* TODO: corrupted? */
+ } /* end if revision ID at 'leaf' in binary search */
+
+ if (r_out->comment_size > 0)
+ if (NULL == (r_out->comment = H5MM_malloc(sizeof(char) * r_out->comment_size)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate comment space")
+
+ if (r_out->archival_index.n_entries > 0)
+ if (NULL == (r_out->archival_index.list =
+ H5MM_calloc(r_out->archival_index.n_entries * sizeof(H5FD_onion_index_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate index entry list")
+
+ if (H5FD__onion_revision_record_decode(buf, r_out) != size)
+ HGOTO_ERROR(H5E_VFL, H5E_CANTDECODE, FAIL, "can't decode revision record (final)")
+
+done:
+ H5MM_xfree(buf);
+ if (ret_value == FAIL) {
+ H5MM_xfree(r_out->comment);
+ H5MM_xfree(r_out->archival_index.list);
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_ingest_revision_record() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_archival_index_is_valid
+ *
+ * Purpose: Determine whether an archival index structure is valid.
+ *
+ * + Verify page size (power of two).
+ * + Verify list exists.
+ * + Verify list contents:
+ * + Sorted by increasing logical address (no duplicates)
+ * + Logical addresses are multiples of page size.
+ *
+ * Return: TRUE/FALSE
+ *-----------------------------------------------------------------------------
+ */
+hbool_t
+H5FD__onion_archival_index_is_valid(const H5FD_onion_archival_index_t *aix)
+{
+ hbool_t ret_value = TRUE;
+
+ FUNC_ENTER_PACKAGE_NOERR;
+
+ HDassert(aix);
+
+ if (H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR != aix->version)
+ HGOTO_DONE(FALSE)
+ if (NULL == aix->list)
+ HGOTO_DONE(FALSE)
+
+ /* Ensure list is sorted on logi_page field */
+ if (aix->n_entries > 1)
+ for (uint64_t i = 1; i < aix->n_entries - 1; i++)
+ if (aix->list[i + 1].logi_page <= aix->list[i].logi_page)
+ HGOTO_DONE(FALSE)
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_archival_index_is_valid() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_archival_index_find
+ *
+ * Purpose: Retrieve the archival index entry by logical page ID.
+ *
+ * The archival index pointer must point to a valid index entry.
+ * The entry out pointer-pointer cannot be null.
+ *
+ * Return: Success: Positive value (1) -- entry found.
+ * Entry out pointer-pointer is set to point to entry.
+ * Failure: Zero (0) -- entry not found.
+ * Entry out pointer-pointer is unmodified.
+ *-----------------------------------------------------------------------------
+ */
+int
+H5FD__onion_archival_index_find(const H5FD_onion_archival_index_t *aix, uint64_t logi_page,
+ const H5FD_onion_index_entry_t **entry_out)
+{
+ uint64_t low = 0;
+ uint64_t high = 0;
+ uint64_t n = 0;
+ uint64_t range = 0;
+ H5FD_onion_index_entry_t *x = NULL;
+ int ret_value = 0;
+
+ FUNC_ENTER_PACKAGE_NOERR;
+
+ HDassert(aix);
+ HDassert(H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR == aix->version);
+ HDassert(entry_out);
+ if (aix->n_entries != 0)
+ HDassert(aix->list);
+
+ high = aix->n_entries - 1;
+ range = high;
+
+ /* Trivial cases */
+ if (aix->n_entries == 0 || logi_page > aix->list[high].logi_page || logi_page < aix->list[0].logi_page)
+ HGOTO_DONE(0)
+
+ /*
+ * Binary search on sorted list
+ */
+
+ /* Winnow down to first of found or one element */
+ while (range > 0) {
+ HDassert(high < aix->n_entries);
+ n = low + (range / 2);
+ x = &(aix->list[n]);
+ if (x->logi_page == logi_page) {
+ *entry_out = x; /* element found at fence */
+ ret_value = 1;
+ goto done;
+ }
+ else if (x->logi_page < logi_page) {
+ low = (n == high) ? high : n + 1;
+ }
+ else {
+ high = (n == low) ? low : n - 1;
+ }
+ range = high - low;
+ }
+
+ HDassert(high == low); /* one element */
+
+ /* n == low/high check because we may have tested it already above */
+ if ((n != low || n != high) && (aix->list[low].logi_page == logi_page)) {
+ *entry_out = &aix->list[low];
+ ret_value = 1;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_archival_index_find() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_revision_index_destroy
+ *
+ * Purpose: Release all resources of a revision index.
+ *
+ * Return: SUCCEED/FAIL
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5FD__onion_revision_index_destroy(H5FD_onion_revision_index_t *rix)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE_NOERR;
+
+ HDassert(rix);
+ HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix->version);
+
+ for (size_t i = 0; 0 < rix->_hash_table_n_keys_populated && i < rix->_hash_table_size; i++) {
+ H5FD_onion_revision_index_hash_chain_node_t *next = NULL;
+ H5FD_onion_revision_index_hash_chain_node_t *node = rix->_hash_table[i];
+
+ if (node != NULL)
+ rix->_hash_table_n_keys_populated -= 1;
+
+ while (node != NULL) {
+ HDassert(H5FD__ONION_REVISION_INDEX_HASH_CHAIN_NODE_VERSION_CURR == node->version);
+
+ next = node->next;
+ H5MM_xfree(node);
+ node = next;
+ }
+ }
+ H5MM_xfree(rix->_hash_table);
+ H5MM_xfree(rix);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_revision_index_destroy() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_revision_index_init
+ *
+ * Purpose: Initialize a revision index structure with a default starting
+ * size. A new structure is allocated and populated with initial
+ * values.
+ *
+ * Return: Success: Pointer to newly-allocated structure
+ * Failure: NULL
+ *-----------------------------------------------------------------------------
+ */
+H5FD_onion_revision_index_t *
+H5FD__onion_revision_index_init(uint32_t page_size)
+{
+ uint64_t table_size = U64_EXP2(H5FD__ONION_REVISION_INDEX_STARTING_SIZE_LOG2);
+ H5FD_onion_revision_index_t *rix = NULL;
+ H5FD_onion_revision_index_t *ret_value = NULL;
+
+ FUNC_ENTER_PACKAGE;
+
+ HDassert(0 != page_size);
+ HDassert(POWER_OF_TWO(page_size));
+
+ if (NULL == (rix = H5MM_calloc(sizeof(H5FD_onion_revision_index_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "cannot allocate index")
+
+ if (NULL ==
+ (rix->_hash_table = H5MM_calloc(table_size * sizeof(H5FD_onion_revision_index_hash_chain_node_t *))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "cannot allocate hash table")
+
+ rix->version = H5FD__ONION_REVISION_INDEX_VERSION_CURR;
+ rix->n_entries = 0;
+ /* Compute and store log2(page_size) */
+ for (rix->page_size_log2 = 0; (((uint32_t)1 << rix->page_size_log2) & page_size) == 0;
+ rix->page_size_log2++)
+ ;
+ rix->_hash_table_size = table_size;
+ rix->_hash_table_size_log2 = H5FD__ONION_REVISION_INDEX_STARTING_SIZE_LOG2;
+ rix->_hash_table_n_keys_populated = 0;
+
+ ret_value = rix;
+
+done:
+ if (NULL == ret_value)
+ H5MM_xfree(rix);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_revision_index_init() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_revision_index_resize()
+ *
+ * Purpose: Replace the hash table in the revision index.
+ *
+ * Doubles the available number of keys, re-hashes table contents,
+ * and updates relevant components in the index structure.
+ *
+ * Fails if unable to allocate space for larger hash table.
+ *
+ * Return: SUCCEED/FAIL
+ *-----------------------------------------------------------------------------
+ */
+static herr_t
+H5FD__onion_revision_index_resize(H5FD_onion_revision_index_t *rix)
+{
+ H5FD_onion_revision_index_hash_chain_node_t **new_table = NULL;
+
+ uint64_t new_size_log2 = rix->_hash_table_size_log2 + 1;
+ uint64_t new_size = U64_EXP2(new_size_log2);
+ uint64_t new_n_keys_populated = 0;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE;
+
+ HDassert(rix);
+ HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix->version);
+ HDassert(rix->_hash_table);
+
+ if (NULL == (new_table = H5MM_calloc(new_size * sizeof(H5FD_onion_revision_index_hash_chain_node_t *))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "cannot allocate new hash table")
+
+ for (uint64_t i = 0; i < rix->_hash_table_size; i++) {
+ while (rix->_hash_table[i] != NULL) {
+ H5FD_onion_revision_index_hash_chain_node_t *node = NULL;
+ uint64_t key = 0;
+
+ /* Pop entry off of bucket stack and re-hash */
+ node = rix->_hash_table[i];
+ rix->_hash_table[i] = node->next;
+ node->next = NULL;
+ key = node->entry_data.logi_page & (new_size - 1);
+
+ if (NULL == new_table[key]) {
+ new_table[key] = node;
+ new_n_keys_populated++;
+ }
+ else {
+ node->next = new_table[i];
+ new_table[i] = node;
+ }
+ }
+ }
+
+ H5MM_xfree(rix->_hash_table);
+ rix->_hash_table_size = new_size;
+ rix->_hash_table_size_log2 = new_size_log2;
+ rix->_hash_table_n_keys_populated = new_n_keys_populated;
+ rix->_hash_table = new_table;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_revision_index_resize() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_revision_index_insert()
+ *
+ * Purpose: Add an entry to the revision index, or update an existing
+ * entry. Must be used to update entries as well as add --
+ * checksum value will change.
+ *
+ * Entry data is copied into separate memory region; user pointer
+ * can be safley re-used or discarded after operation.
+ *
+ * Return: SUCCEED/FAIL
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5FD__onion_revision_index_insert(H5FD_onion_revision_index_t *rix, const H5FD_onion_index_entry_t *entry)
+{
+ uint64_t key = 0;
+ H5FD_onion_revision_index_hash_chain_node_t * node = NULL;
+ H5FD_onion_revision_index_hash_chain_node_t **append_dest = NULL;
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE;
+
+ HDassert(rix);
+ HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix->version);
+ HDassert(entry);
+
+ /* Resize and re-hash table if necessary */
+ if (rix->n_entries >= (rix->_hash_table_size * 2) ||
+ rix->_hash_table_n_keys_populated >= (rix->_hash_table_size / 2)) {
+ if (H5FD__onion_revision_index_resize(rix) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NONE_MINOR, FAIL, "unable to resize and hash table")
+ }
+
+ key = entry->logi_page & (rix->_hash_table_size - 1);
+ HDassert(key < rix->_hash_table_size);
+
+ if (NULL == rix->_hash_table[key]) {
+ /* Key maps to empty bucket */
+
+ append_dest = &rix->_hash_table[key];
+ rix->_hash_table_n_keys_populated++;
+ }
+ else {
+ /* Key maps to populated bucket */
+
+ for (node = rix->_hash_table[key]; node != NULL; node = node->next) {
+ append_dest = &node->next; /* look for bucket tail */
+ if (entry->logi_page == node->entry_data.logi_page) {
+ if (entry->phys_addr != node->entry_data.phys_addr) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "physical address mismatch");
+ }
+ HDmemcpy(&node->entry_data, entry, sizeof(H5FD_onion_index_entry_t));
+ append_dest = NULL; /* Node updated, do not append */
+ break;
+ }
+ }
+ }
+
+ /* Add new entry to bucket chain */
+ if (append_dest != NULL) {
+ if (NULL == (node = H5MM_malloc(sizeof(H5FD_onion_revision_index_hash_chain_node_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "cannot allocate new ash chain node")
+ node->version = H5FD__ONION_REVISION_INDEX_HASH_CHAIN_NODE_VERSION_CURR;
+ node->next = NULL;
+ HDmemcpy(&node->entry_data, entry, sizeof(H5FD_onion_index_entry_t));
+ *append_dest = node;
+ rix->n_entries++;
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_revision_index_insert() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_revision_index_find()
+ *
+ *
+ * Purpose: Get pointer to revision index entry with the given page number,
+ * if it exists in the index.
+ *
+ * Return: Success: Positive value (1) -- entry found.
+ * Entry out pointer-pointer is set to point to entry.
+ * Failure: Zero (0) -- entry not found.
+ * Entry out pointer-pointer is unmodified.
+ *-----------------------------------------------------------------------------
+ */
+int
+H5FD__onion_revision_index_find(const H5FD_onion_revision_index_t *rix, uint64_t logi_page,
+ const H5FD_onion_index_entry_t **entry_out)
+{
+ uint64_t key = 0;
+ int ret_value = 0;
+
+ FUNC_ENTER_PACKAGE_NOERR;
+
+ HDassert(rix);
+ HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix->version);
+ HDassert(rix->_hash_table);
+ HDassert(entry_out);
+
+ key = logi_page & (rix->_hash_table_size - 1);
+ HDassert(key < rix->_hash_table_size);
+
+ if (rix->_hash_table[key] != NULL) {
+ H5FD_onion_revision_index_hash_chain_node_t *node = NULL;
+
+ for (node = rix->_hash_table[key]; node != NULL; node = node->next) {
+ if (logi_page == node->entry_data.logi_page) {
+ *entry_out = &node->entry_data;
+ ret_value = 1;
+ break;
+ }
+ }
+ }
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_revision_index_find() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_revision_record_decode
+ *
+ * Purpose: Attempt to read a buffer and store it as a revision record
+ * structure.
+ *
+ * Implementation must correspond with
+ * H5FD__onion_revision_record_encode().
+ *
+ * MUST BE CALLED TWICE:
+ * On the first call, n_entries and comment_size in the
+ * destination structure must all all be zero, and their
+ * respective variable-length components (index_entry_list,
+ * comment) must all be NULL.
+ *
+ * If the buffer is well-formed, the destination structure is
+ * tentatively populated with fixed-size values, and the number of
+ * bytes read are returned.
+ *
+ * Prior to the second call, the user must allocate space for the
+ * variable-length components, in accordance with the associated
+ * indicators (array of index-entry structures for
+ * index_entry_list, of size n_entries; character arrays for
+ * comment, allocated with the *_size number of bytes -- space
+ * for NULL-terminator is included in _size).
+ *
+ * Then the decode operation is called a second time, and all
+ * components will be populated (and again number of bytes read is
+ * returned).
+ *
+ * Return: Success: Number of bytes read from buffer
+ * Failure: 0
+ *-----------------------------------------------------------------------------
+ */
+uint64_t
+H5FD__onion_revision_record_decode(unsigned char *buf, H5FD_onion_revision_record_t *record)
+{
+ uint32_t ui32 = 0;
+ uint32_t page_size = 0;
+ uint32_t sum = 0;
+ uint64_t ui64 = 0;
+ uint64_t n_entries = 0;
+ uint32_t comment_size = 0;
+ uint8_t * ui8p = NULL;
+ unsigned char *ptr = NULL;
+ uint64_t ret_value = 0;
+
+ FUNC_ENTER_PACKAGE;
+
+ HDassert(buf != NULL);
+ HDassert(record != NULL);
+ HDassert(H5FD__ONION_REVISION_RECORD_VERSION_CURR == record->version);
+ HDassert(H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR == record->archival_index.version);
+
+ if (HDstrncmp((const char *)buf, H5FD__ONION_REVISION_RECORD_SIGNATURE, 4))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid signature")
+
+ if (H5FD__ONION_REVISION_RECORD_VERSION_CURR != buf[4])
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "invalid record version")
+
+ ptr = buf + 8;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT64DECODE(ui8p, record->revision_num);
+ ptr += 8;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT64DECODE(ui8p, record->parent_revision_num);
+ ptr += 8;
+
+ HDmemcpy(record->time_of_creation, ptr, 16);
+ ptr += 16;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT64DECODE(ui8p, record->logi_eof);
+ ptr += 8;
+
+ HDmemcpy(&ui32, ptr, 4);
+ ui8p = (uint8_t *)&ui32;
+ UINT32DECODE(ui8p, page_size);
+ ptr += 4;
+
+ if (page_size == 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "page size is zero")
+ if (!POWER_OF_TWO(page_size))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "page size not power of two")
+
+ for (record->archival_index.page_size_log2 = 0;
+ (((uint32_t)1 << record->archival_index.page_size_log2) & page_size) == 0;
+ record->archival_index.page_size_log2++)
+ ;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT64DECODE(ui8p, n_entries);
+ ptr += 8;
+
+ HDmemcpy(&ui32, ptr, 4);
+ ui8p = (uint8_t *)&ui32;
+ UINT32DECODE(ui8p, comment_size);
+ ptr += 4;
+
+ if (record->archival_index.n_entries == 0) {
+ record->archival_index.n_entries = n_entries;
+ ptr += H5FD__ONION_ENCODED_SIZE_INDEX_ENTRY * n_entries;
+ }
+ else if (n_entries != record->archival_index.n_entries) {
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "n_entries in archival index does not match decoded")
+ }
+ else {
+ H5FD_onion_index_entry_t *entry = NULL;
+
+ if (record->archival_index.list == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "no archival index entry list")
+
+ for (size_t i = 0; i < n_entries; i++) {
+ entry = &record->archival_index.list[i];
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT64DECODE(ui8p, entry->logi_page);
+ ptr += 8;
+
+ /* logi_page actually encoded as address; check and convert */
+ if (entry->logi_page & (page_size - 1))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "logical address does not align with page size")
+
+ entry->logi_page = entry->logi_page >> record->archival_index.page_size_log2;
+
+ HDmemcpy(&ui64, ptr, 8);
+ ui8p = (uint8_t *)&ui64;
+ UINT64DECODE(ui8p, entry->phys_addr);
+ ptr += 8;
+
+ HDmemcpy(&ui32, ptr, 4);
+ ui8p = (uint8_t *)&ui32;
+ UINT32DECODE(ui8p, sum);
+ ptr += 4;
+
+ ui32 = H5_checksum_fletcher32((ptr - 20), 16);
+ if (ui32 != sum)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "index entry checksum mismatch")
+ }
+ }
+
+ if (record->comment_size == 0) {
+ if (record->comment != NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "comment pointer prematurely allocated")
+ record->comment_size = comment_size;
+ }
+ else {
+ if (record->comment == NULL)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "no comment pointer")
+ HDmemcpy(record->comment, ptr, comment_size);
+ }
+ ptr += comment_size;
+
+ sum = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
+
+ HDmemcpy(&ui32, ptr, 4);
+ ui8p = (uint8_t *)&ui32;
+ UINT32DECODE(ui8p, record->checksum);
+ ptr += 4;
+
+ if (sum != record->checksum)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, 0, "checksum mismatch")
+
+ ret_value = (uint64_t)(ptr - buf);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_revision_record_decode() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_revision_record_encode
+ *
+ * Purpose: Write revision-record structure to the given buffer.
+ * All multi-byte elements are stored in little-endian word order.
+ *
+ * Implementation must correspond with
+ * H5FD__onion_revision_record_decode().
+ *
+ * The destination buffer must be sufficiently large to hold the
+ * encoded contents.
+ * (Hint: `sizeof(revision-record-struct) + comment-size +
+ * sizeof(index-entry-struct) * n_entries)`
+ * guarantees ample/excess space.)
+ *
+ * Return: Number of bytes written to buffer.
+ * The checksum of the generated buffer contents (excluding the
+ * checksum itself) is stored in the pointer `sum_out`).
+ *-----------------------------------------------------------------------------
+ */
+uint64_t
+H5FD__onion_revision_record_encode(H5FD_onion_revision_record_t *record, unsigned char *buf,
+ uint32_t *sum_out)
+{
+ unsigned char *ptr = buf; /* original pointer */
+ uint32_t vers_u32 = (uint32_t)record->version; /* pad out unused bytes */
+ uint32_t page_size = 0;
+
+ FUNC_ENTER_PACKAGE_NOERR;
+
+ HDassert(sum_out != NULL);
+ HDassert(buf != NULL);
+ HDassert(record != NULL);
+ HDassert(vers_u32 < 0x100);
+ HDassert(H5FD__ONION_REVISION_RECORD_VERSION_CURR == record->version);
+ HDassert(H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR == record->archival_index.version);
+
+ page_size = (uint32_t)(1 << record->archival_index.page_size_log2);
+
+ HDmemcpy(ptr, H5FD__ONION_REVISION_RECORD_SIGNATURE, 4);
+ ptr += 4;
+ UINT32ENCODE(ptr, vers_u32);
+ UINT64ENCODE(ptr, record->revision_num);
+ UINT64ENCODE(ptr, record->parent_revision_num);
+ HDmemcpy(ptr, record->time_of_creation, 16);
+ ptr += 16;
+ UINT64ENCODE(ptr, record->logi_eof);
+ UINT32ENCODE(ptr, page_size);
+ UINT64ENCODE(ptr, record->archival_index.n_entries);
+ UINT32ENCODE(ptr, record->comment_size);
+
+ if (record->archival_index.n_entries > 0) {
+ uint64_t page_size_log2 = record->archival_index.page_size_log2;
+
+ HDassert(record->archival_index.list != NULL);
+ for (uint64_t i = 0; i < record->archival_index.n_entries; i++) {
+ uint32_t sum = 0;
+ H5FD_onion_index_entry_t *entry = NULL;
+ uint64_t logi_addr = 0;
+
+ entry = &record->archival_index.list[i];
+ logi_addr = entry->logi_page << page_size_log2;
+
+ UINT64ENCODE(ptr, logi_addr);
+ UINT64ENCODE(ptr, entry->phys_addr);
+ sum = H5_checksum_fletcher32((ptr - 16), 16);
+ UINT32ENCODE(ptr, sum);
+ }
+ }
+
+ if (record->comment_size > 0) {
+ HDassert(record->comment != NULL && *record->comment != '\0');
+ HDmemcpy(ptr, record->comment, record->comment_size);
+ ptr += record->comment_size;
+ }
+
+ *sum_out = H5_checksum_fletcher32(buf, (size_t)(ptr - buf));
+ UINT32ENCODE(ptr, *sum_out);
+
+ FUNC_LEAVE_NOAPI((uint64_t)(ptr - buf));
+} /* end H5FD__onion_revision_record_encode() */
+
+/*-----------------------------------------------------------------------------
+ * Callback for comparisons in sorting archival index entries by logi_page.
+ *-----------------------------------------------------------------------------
+ */
+static int
+H5FD__onion_archival_index_list_sort_cmp(const void *_a, const void *_b)
+{
+ const H5FD_onion_index_entry_t *a = (const H5FD_onion_index_entry_t *)_a;
+ const H5FD_onion_index_entry_t *b = (const H5FD_onion_index_entry_t *)_b;
+
+ if (a->logi_page < b->logi_page)
+ return -1;
+ else if (a->logi_page > b->logi_page)
+ return 1;
+ return 0;
+} /* end H5FD__onion_archival_index_list_sort_cmp() */
+
+/*-----------------------------------------------------------------------------
+ * Function: H5FD__onion_merge_revision_index_into_archival_index
+ *
+ * Purpose: Merge index entries from revision index into archival index.
+ *
+ * If successful, the archival index is expanded 'behind the
+ * scenes' and new entries from the revision index are inserted.
+ * The archival index remains sorted in ascending order of logical
+ * address.
+ *
+ * The conversion to archival index changes logical pages in
+ * revision index entries to their logical addresses in-file.
+ *
+ * Return: SUCCEED/FAIL
+ *-----------------------------------------------------------------------------
+ */
+herr_t
+H5FD__onion_merge_revision_index_into_archival_index(const H5FD_onion_revision_index_t *rix,
+ H5FD_onion_archival_index_t * aix)
+{
+ uint64_t n_kept = 0;
+ H5FD_onion_index_entry_t * kept_list = NULL;
+ H5FD_onion_archival_index_t new_aix = {
+ H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR, 0, /* page_size_log2 tbd */
+ 0, /* n_entries */
+ NULL, /* list pointer (allocated later) */
+ };
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_PACKAGE;
+
+ HDassert(rix);
+ HDassert(aix);
+ HDassert(H5FD__ONION_REVISION_INDEX_VERSION_CURR == rix->version);
+ HDassert(H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR == aix->version);
+ HDassert(aix->page_size_log2 == rix->page_size_log2);
+
+ /* If the revision index is empty there is nothing to archive */
+ if (rix->n_entries == 0)
+ goto done;
+
+ /* Add all revision index entries to new archival list */
+ new_aix.page_size_log2 = aix->page_size_log2;
+
+ if (NULL == (new_aix.list = H5MM_calloc(rix->n_entries * sizeof(H5FD_onion_index_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to allocate new archival index list")
+
+ for (uint64_t i = 0; i < rix->_hash_table_size; i++) {
+ const H5FD_onion_revision_index_hash_chain_node_t *node = NULL;
+
+ for (node = rix->_hash_table[i]; node != NULL; node = node->next) {
+ HDmemcpy(&new_aix.list[new_aix.n_entries], &node->entry_data, sizeof(H5FD_onion_index_entry_t));
+ new_aix.n_entries++;
+ }
+ }
+
+ /* Sort the new archival list */
+ HDqsort(new_aix.list, new_aix.n_entries, sizeof(H5FD_onion_index_entry_t),
+ H5FD__onion_archival_index_list_sort_cmp);
+
+ /* Add the old archival index entries to a 'kept' list containing the
+ * old archival list entries that are not also included in the revision
+ * list.
+ *
+ * Note that kept_list will be NULL if there are no entries in the passed-in
+ * archival list.
+ */
+ if (aix->n_entries > 0)
+ if (NULL == (kept_list = H5MM_calloc(aix->n_entries * sizeof(H5FD_onion_index_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to allocate larger archival index list")
+
+ for (uint64_t i = 0; i < aix->n_entries; i++) {
+ const H5FD_onion_index_entry_t *entry = NULL;
+
+ /* Add only if page not already added from revision index */
+ if (H5FD__onion_archival_index_find(&new_aix, aix->list[i].logi_page, &entry) == 0) {
+ HDmemcpy(&kept_list[n_kept], &aix->list[i], sizeof(H5FD_onion_index_entry_t));
+ n_kept++;
+ }
+ }
+
+ /* Destroy the old archival list and replace with a list big enough to hold
+ * the revision list entries and the kept list entries
+ */
+ H5MM_xfree(aix->list);
+ if (NULL == (aix->list = H5MM_calloc((new_aix.n_entries + n_kept) * sizeof(H5FD_onion_index_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "unable to allocate exact-size archival index list")
+
+ /* Copy (new) revision list entries to replacement list */
+ HDmemcpy(aix->list, new_aix.list, sizeof(H5FD_onion_index_entry_t) * new_aix.n_entries);
+ aix->n_entries = new_aix.n_entries;
+
+ /* Copy (old) kept archival list entries to replacement list */
+ if (n_kept > 0) {
+ HDmemcpy(&aix->list[aix->n_entries], kept_list, sizeof(H5FD_onion_index_entry_t) * n_kept);
+ aix->n_entries += n_kept;
+ }
+
+ /* Sort this list */
+ HDqsort(aix->list, aix->n_entries, sizeof(H5FD_onion_index_entry_t),
+ H5FD__onion_archival_index_list_sort_cmp);
+
+done:
+ /* Free the temporary lists */
+ H5MM_xfree(kept_list);
+ H5MM_xfree(new_aix.list);
+
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* end H5FD__onion_merge_revision_index_into_archival_index() */
diff --git a/src/H5FDonion_index.h b/src/H5FDonion_index.h
new file mode 100644
index 0000000..0850537
--- /dev/null
+++ b/src/H5FDonion_index.h
@@ -0,0 +1,146 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifndef H5FDonion_index_H
+#define H5FDonion_index_H
+
+#define H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR 1
+
+/* Number of bytes to encode fixed-size components */
+#define H5FD__ONION_ENCODED_SIZE_INDEX_ENTRY 20
+#define H5FD__ONION_ENCODED_SIZE_RECORD_POINTER 20
+#define H5FD__ONION_ENCODED_SIZE_REVISION_RECORD 68
+
+#define H5FD__ONION_REVISION_INDEX_HASH_CHAIN_NODE_VERSION_CURR 1
+#define H5FD__ONION_REVISION_INDEX_STARTING_SIZE_LOG2 10 /* 2^n slots */
+#define H5FD__ONION_REVISION_INDEX_VERSION_CURR 1
+
+#define H5FD__ONION_REVISION_RECORD_SIGNATURE "ORRS"
+#define H5FD__ONION_REVISION_RECORD_VERSION_CURR 1
+
+/*
+ * Onion Virtual File Driver (VFD)
+ *
+ * Purpose: Interface for the archival and revision indexes
+ */
+
+/*-----------------------------------------------------------------------------
+ *
+ * Structure H5FD__onion_index_entry
+ *
+ * Purpose: Map a page in the logical file to a 'physical address' in the
+ * backing store.
+ *
+ * logi_page: Page 'id' in the logical file.
+ *
+ * phys_addr: Address/offset of start of page in the backing store.
+ *
+ *-----------------------------------------------------------------------------
+ */
+typedef struct H5FD_onion_index_entry_t {
+ uint64_t logi_page;
+ haddr_t phys_addr;
+} H5FD_onion_index_entry_t;
+
+/*-----------------------------------------------------------------------------
+ *
+ * Structure H5FD__onion_archival_index
+ *
+ * Purpose: Encapsulate archival index and associated data.
+ * Convenience structure with sanity-checking components.
+ *
+ * version: Future-proofing identifier. Informs struct membership.
+ * Must equal H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR to be
+ * considered valid.
+ *
+ * page_size: Interval to which the `logi_page` component of each list
+ * entry must align.
+ * Value is taken from the onion history data; must not change
+ * following onionization or file or creation of onion file.
+ *
+ * n_entries: Number of entries in the list.
+ *
+ * list: Pointer to array of archival index entries.
+ * Cannot be NULL.
+ * Entries must be sorted by `logi_page_id` in ascending order.
+ *
+ *-----------------------------------------------------------------------------
+ */
+typedef struct H5FD_onion_archival_index_t {
+ uint8_t version;
+ uint32_t page_size_log2;
+ uint64_t n_entries;
+ H5FD_onion_index_entry_t *list;
+} H5FD_onion_archival_index_t;
+
+/* data structure for storing index entries at a hash key collision */
+/* version 1 implements a singly-linked list */
+typedef struct H5FD_onion_revision_index_hash_chain_node_t H5FD_onion_revision_index_hash_chain_node_t;
+struct H5FD_onion_revision_index_hash_chain_node_t {
+ uint8_t version;
+ H5FD_onion_index_entry_t entry_data;
+ H5FD_onion_revision_index_hash_chain_node_t *next;
+};
+
+typedef struct H5FD_onion_revision_index_t {
+ uint8_t version;
+ uint32_t page_size_log2;
+ uint64_t n_entries; /* count of all entries in table */
+ uint64_t _hash_table_size; /* 'slots' in hash table */
+ uint64_t _hash_table_size_log2; /* 2^(n) -> 'slots' in hash table */
+ uint64_t _hash_table_n_keys_populated; /* count of slots not NULL */
+ H5FD_onion_revision_index_hash_chain_node_t **_hash_table;
+} H5FD_onion_revision_index_t;
+
+/* In-memory representation of the on-store revision record.
+ */
+typedef struct H5FD_onion_revision_record_t {
+ uint8_t version;
+ uint64_t revision_num;
+ uint64_t parent_revision_num;
+ char time_of_creation[16];
+ uint64_t logi_eof;
+ H5FD_onion_archival_index_t archival_index;
+ uint32_t comment_size;
+ char * comment;
+ uint32_t checksum;
+} H5FD_onion_revision_record_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+H5_DLL herr_t H5FD__onion_ingest_revision_record(H5FD_onion_revision_record_t *r_out, H5FD_t *raw_file,
+ const H5FD_onion_history_t *history, uint64_t revision_num);
+
+H5_DLL hbool_t H5FD__onion_archival_index_is_valid(const H5FD_onion_archival_index_t *);
+H5_DLL int H5FD__onion_archival_index_find(const H5FD_onion_archival_index_t *, uint64_t,
+ const H5FD_onion_index_entry_t **);
+
+H5_DLL H5FD_onion_revision_index_t *H5FD__onion_revision_index_init(uint32_t page_size);
+H5_DLL herr_t H5FD__onion_revision_index_destroy(H5FD_onion_revision_index_t *);
+H5_DLL herr_t H5FD__onion_revision_index_insert(H5FD_onion_revision_index_t *,
+ const H5FD_onion_index_entry_t *);
+H5_DLL int H5FD__onion_revision_index_find(const H5FD_onion_revision_index_t *, uint64_t,
+ const H5FD_onion_index_entry_t **);
+
+H5_DLL herr_t H5FD__onion_merge_revision_index_into_archival_index(const H5FD_onion_revision_index_t *,
+ H5FD_onion_archival_index_t *);
+
+H5_DLL uint64_t H5FD__onion_revision_record_decode(unsigned char *, H5FD_onion_revision_record_t *);
+H5_DLL uint64_t H5FD__onion_revision_record_encode(H5FD_onion_revision_record_t *, unsigned char *,
+ uint32_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H5FDonion_index_H */
diff --git a/src/H5FDonion_priv.h b/src/H5FDonion_priv.h
index 63a7049..da4b2d1 100644
--- a/src/H5FDonion_priv.h
+++ b/src/H5FDonion_priv.h
@@ -21,186 +21,7 @@
#ifndef H5FDonion_priv_H
#define H5FDonion_priv_H
-/*
- * INTERNAL MACROS AND DEFINITIONS
- */
-
-#define H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR 1
-
-/* Number of bytes to encode fixed-size components */
-#define H5FD__ONION_ENCODED_SIZE_HEADER 40
-#define H5FD__ONION_ENCODED_SIZE_INDEX_ENTRY 20
-#define H5FD__ONION_ENCODED_SIZE_RECORD_POINTER 20
-#define H5FD__ONION_ENCODED_SIZE_REVISION_RECORD 68
-#define H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY 20
-
-/* Flags must align exactly one per bit, up to 24 bits */
-#define H5FD__ONION_HEADER_FLAG_WRITE_LOCK 0x1
-#define H5FD__ONION_HEADER_FLAG_DIVERGENT_HISTORY 0x2
-#define H5FD__ONION_HEADER_FLAG_PAGE_ALIGNMENT 0x4
-#define H5FD__ONION_HEADER_SIGNATURE "OHDH"
-#define H5FD__ONION_HEADER_VERSION_CURR 1
-
-#define H5FD__ONION_REVISION_INDEX_HASH_CHAIN_NODE_VERSION_CURR 1
-#define H5FD__ONION_REVISION_INDEX_STARTING_SIZE_LOG2 10 /* 2^n slots */
-#define H5FD__ONION_REVISION_INDEX_VERSION_CURR 1
-
-#define H5FD__ONION_REVISION_RECORD_SIGNATURE "ORRS"
-#define H5FD__ONION_REVISION_RECORD_VERSION_CURR 1
-
-#define H5FD__ONION_WHOLE_HISTORY_SIGNATURE "OWHS"
-#define H5FD__ONION_WHOLE_HISTORY_VERSION_CURR 1
-
-/*
- * INTERNAL STRUCTURE DEFINITIONS
- */
-
-/*-----------------------------------------------------------------------------
- *
- * Structure H5FD__onion_index_entry
- *
- * Purpose: Map a page in the logical file to a 'physical address' in the
- * backing store.
- *
- * logi_page: Page 'id' in the logical file.
- *
- * phys_addr: Address/offset of start of page in the backing store.
- *
- *-----------------------------------------------------------------------------
- */
-typedef struct H5FD_onion_index_entry_t {
- uint64_t logi_page;
- uint64_t phys_addr;
-} H5FD_onion_index_entry_t;
-
-/*-----------------------------------------------------------------------------
- *
- * Structure H5FD__onion_archival_index
- *
- * Purpose: Encapsulate archival index and associated data.
- * Convenience structure with sanity-checking components.
- *
- * version: Future-proofing identifier. Informs struct membership.
- * Must equal H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR to be
- * considered valid.
- *
- * page_size: Interval to which the `logi_page` component of each list
- * entry must align.
- * Value is taken from the onion history data; must not change
- * following onionization or file or creation of onion file.
- *
- * n_entries: Number of entries in the list.
- *
- * list: Pointer to array of archival index entries.
- * Cannot be NULL.
- * Entries must be sorted by `logi_page_id` in ascending order.
- *
- *-----------------------------------------------------------------------------
- */
-typedef struct H5FD_onion_archival_index_t {
- uint8_t version;
- uint32_t page_size_log2;
- uint64_t n_entries;
- H5FD_onion_index_entry_t *list;
-} H5FD_onion_archival_index_t;
-
-/* data structure for storing index entries at a hash key collision */
-/* version 1 implements a singly-linked list */
-typedef struct H5FD_onion_revision_index_hash_chain_node_t H5FD_onion_revision_index_hash_chain_node_t;
-struct H5FD_onion_revision_index_hash_chain_node_t {
- uint8_t version;
- H5FD_onion_index_entry_t entry_data;
- H5FD_onion_revision_index_hash_chain_node_t *next;
-};
-
-typedef struct H5FD__onion_revision_index_t {
- uint8_t version;
- uint32_t page_size_log2;
- uint64_t n_entries; /* count of all entries in table */
- uint64_t _hash_table_size; /* 'slots' in hash table */
- uint64_t _hash_table_size_log2; /* 2^(n) -> 'slots' in hash table */
- uint64_t _hash_table_n_keys_populated; /* count of slots not NULL */
- H5FD_onion_revision_index_hash_chain_node_t **_hash_table;
-} H5FD__onion_revision_index_t;
-
-/* In-memory representation of the on-store onion history file header.
- */
-typedef struct H5FD_onion_history_header_t {
- uint8_t version;
- uint32_t flags; /* at most three bytes used! */
- uint32_t page_size;
- uint64_t origin_eof; /* size of the 'original' canonical file */
- uint64_t whole_history_addr;
- uint64_t whole_history_size;
- uint32_t checksum;
-} H5FD_onion_history_header_t;
-
-/* In-memory representation of the on-store revision record.
- */
-typedef struct H5FD_onion_revision_record_t {
- uint8_t version;
- uint64_t revision_num;
- uint64_t parent_revision_num;
- char time_of_creation[16];
- uint64_t logi_eof;
- H5FD_onion_archival_index_t archival_index;
- uint32_t comment_size;
- char * comment;
- uint32_t checksum;
-} H5FD_onion_revision_record_t;
-
-/* In-memory representation of the on-store revision record pointer.
- * Used in the whole-history.
- */
-typedef struct H5FD_onion_record_pointer_t {
- uint64_t phys_addr;
- uint64_t record_size;
- uint32_t checksum;
-} H5FD_onion_record_pointer_t;
-
-/* In-memory representation of the on-store whole-history record/summary.
- */
-typedef struct H5FD_onion_whole_history_t {
- uint8_t version;
- uint64_t n_revisions;
- H5FD_onion_record_pointer_t *record_pointer_list;
- uint32_t checksum;
-} H5FD_onion_whole_history_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * INTERNAL FUNCTION DECLARATIONS
- */
-
-H5_DLL hbool_t H5FD_onion_archival_index_is_valid(const H5FD_onion_archival_index_t *);
-H5_DLL int H5FD_onion_archival_index_find(const H5FD_onion_archival_index_t *, uint64_t,
- const H5FD_onion_index_entry_t **);
-
-H5_DLL H5FD__onion_revision_index_t *H5FD_onion_revision_index_init(uint32_t page_size);
-H5_DLL herr_t H5FD_onion_revision_index_destroy(H5FD__onion_revision_index_t *);
-H5_DLL herr_t H5FD_onion_revision_index_insert(H5FD__onion_revision_index_t *,
- const H5FD_onion_index_entry_t *);
-H5_DLL int H5FD_onion_revision_index_find(const H5FD__onion_revision_index_t *, uint64_t,
- const H5FD_onion_index_entry_t **);
-
-H5_DLL herr_t H5FD_onion_merge_revision_index_into_archival_index(const H5FD__onion_revision_index_t *,
- H5FD_onion_archival_index_t *);
-
-H5_DLL uint64_t H5FD_onion_history_header_decode(unsigned char *, H5FD_onion_history_header_t *);
-H5_DLL uint64_t H5FD_onion_history_header_encode(H5FD_onion_history_header_t *, unsigned char *, uint32_t *);
-
-H5_DLL uint64_t H5FD_onion_revision_record_decode(unsigned char *, H5FD_onion_revision_record_t *);
-H5_DLL uint64_t H5FD_onion_revision_record_encode(H5FD_onion_revision_record_t *, unsigned char *,
- uint32_t *);
-
-H5_DLL uint64_t H5FD_onion_whole_history_decode(unsigned char *, H5FD_onion_whole_history_t *);
-H5_DLL uint64_t H5FD_onion_whole_history_encode(H5FD_onion_whole_history_t *, unsigned char *, uint32_t *);
-
-#ifdef __cplusplus
-}
-#endif
+#include "H5FDonion_history.h"
+#include "H5FDonion_index.h"
#endif /* H5FDonion_priv_H */
diff --git a/src/Makefile.am b/src/Makefile.am
index d289278..fc6ccfd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,8 +61,9 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5lib_settings.c H5system.c \
H5Fsuper.c H5Fsuper_cache.c H5Ftest.c \
H5FA.c H5FAcache.c H5FAdbg.c H5FAdblock.c H5FAdblkpage.c H5FAhdr.c \
H5FAint.c H5FAstat.c H5FAtest.c \
- H5FD.c H5FDcore.c H5FDfamily.c H5FDint.c H5FDlog.c \
- H5FDmulti.c H5FDonion.c H5FDperform.c H5FDsec2.c H5FDspace.c \
+ H5FD.c H5FDcore.c H5FDfamily.c H5FDint.c H5FDlog.c H5FDmulti.c \
+ H5FDonion.c H5FDonion_history.c H5FDonion_index.c \
+ H5FDperform.c H5FDsec2.c H5FDspace.c \
H5FDsplitter.c H5FDstdio.c H5FDtest.c \
H5FL.c H5FO.c H5FS.c H5FScache.c H5FSdbg.c H5FSint.c H5FSsection.c \
H5FSstat.c H5FStest.c \
diff --git a/test/onion.c b/test/onion.c
index f5efcf8..7e2a17d 100644
--- a/test/onion.c
+++ b/test/onion.c
@@ -196,33 +196,33 @@ test_archival_index(void)
/* Invalid version should fail */
aix.version++;
- if (H5FD_onion_archival_index_is_valid(&aix))
+ if (H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
/* Invalid version should fail */
aix.version = 0;
- if (H5FD_onion_archival_index_is_valid(&aix))
+ if (H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
aix.version = H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR;
/* NULL list should fail */
aix.list = NULL;
- if (H5FD_onion_archival_index_is_valid(&aix))
+ if (H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
/* List not full should fail */
aix.list = sorted_incomplete;
- if (H5FD_onion_archival_index_is_valid(&aix))
+ if (H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
/* Unsorted list should fail */
aix.list = unsorted;
- if (H5FD_onion_archival_index_is_valid(&aix))
+ if (H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
/* List with duplicates should fail */
aix.list = sorted_duplicates;
- if (H5FD_onion_archival_index_is_valid(&aix))
+ if (H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
/*
@@ -231,13 +231,13 @@ test_archival_index(void)
/* Sorted list should pass */
aix.list = sorted;
- if (!H5FD_onion_archival_index_is_valid(&aix))
+ if (!H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
/* Extra elements ignored (should pass) */
aix.list = sorted_partial;
aix.n_entries = 4;
- if (!H5FD_onion_archival_index_is_valid(&aix))
+ if (!H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
/*
@@ -248,14 +248,14 @@ test_archival_index(void)
aix.n_entries = 8;
/* Check that address not in array returns zero */
- if (H5FD_onion_archival_index_find(&aix, 3, &entry_out_p) != 0)
+ if (H5FD__onion_archival_index_find(&aix, 3, &entry_out_p) != 0)
TEST_ERROR;
/* Pointer should remain unset */
if (entry_out_p != NULL)
TEST_ERROR;
/* Address found should return 1 */
- if (H5FD_onion_archival_index_find(&aix, 4, &entry_out_p) != 1)
+ if (H5FD__onion_archival_index_find(&aix, 4, &entry_out_p) != 1)
TEST_ERROR;
/* Pointer should be set */
if (NULL == entry_out_p)
@@ -272,11 +272,11 @@ test_archival_index(void)
aix.n_entries = 4;
/* Address not in array should return 0 */
- if (H5FD_onion_archival_index_find(&aix, 1, &entry_out_p) != 0)
+ if (H5FD__onion_archival_index_find(&aix, 1, &entry_out_p) != 0)
TEST_ERROR;
/* Address not in array should return 0 */
- if (H5FD_onion_archival_index_find(&aix, 101, &entry_out_p) != 0)
+ if (H5FD__onion_archival_index_find(&aix, 101, &entry_out_p) != 0)
TEST_ERROR;
/*
@@ -286,7 +286,7 @@ test_archival_index(void)
entry_out_p = NULL;
aix.n_entries = 0; /* actually populated list is irrelevant */
/* Address not in array should return 0 */
- if (H5FD_onion_archival_index_find(&aix, 3, &entry_out_p) != 0)
+ if (H5FD__onion_archival_index_find(&aix, 3, &entry_out_p) != 0)
TEST_ERROR;
/* Pointer should remain unset */
if (entry_out_p != NULL)
@@ -311,8 +311,8 @@ error:
static int
test_revision_index(void)
{
- H5FD__onion_revision_index_t *rix_p = NULL;
- H5FD_onion_index_entry_t entry = {
+ H5FD_onion_revision_index_t *rix_p = NULL;
+ H5FD_onion_index_entry_t entry = {
42, /* logi_page */
111112, /* phys_addr */
};
@@ -322,7 +322,7 @@ test_revision_index(void)
/* Test index creation */
- if (NULL == (rix_p = H5FD_onion_revision_index_init(ONION_TEST_PAGE_SIZE_5)))
+ if (NULL == (rix_p = H5FD__onion_revision_index_init(ONION_TEST_PAGE_SIZE_5)))
TEST_ERROR;
if (H5FD__ONION_REVISION_INDEX_VERSION_CURR != rix_p->version)
TEST_ERROR;
@@ -331,18 +331,18 @@ test_revision_index(void)
/* Test missed search */
- if (H5FD_onion_revision_index_find(rix_p, entry.logi_page, &entry_out_p) != 0)
+ if (H5FD__onion_revision_index_find(rix_p, entry.logi_page, &entry_out_p) != 0)
TEST_ERROR;
/* Test successful insertion and lookup */
/* Insertion failed */
- if (H5FD_onion_revision_index_insert(rix_p, &entry) < 0)
+ if (H5FD__onion_revision_index_insert(rix_p, &entry) < 0)
TEST_ERROR;
if (1 != rix_p->n_entries)
TEST_ERROR;
/* Lookup failed */
- if (H5FD_onion_revision_index_find(rix_p, entry.logi_page, &entry_out_p) < 0)
+ if (H5FD__onion_revision_index_find(rix_p, entry.logi_page, &entry_out_p) < 0)
TEST_ERROR;
/* Failure to set output parameter */
if (NULL == entry_out_p)
@@ -350,20 +350,20 @@ test_revision_index(void)
if (entry.logi_page != entry_out_p->logi_page)
TEST_ERROR;
/* Seeking missing page should miss */
- if (H5FD_onion_revision_index_find(rix_p, entry.logi_page + 1, &entry_out_p) != 0)
+ if (H5FD__onion_revision_index_find(rix_p, entry.logi_page + 1, &entry_out_p) != 0)
TEST_ERROR;
/* Test / demonstrate stored entry independent of user object */
entry.logi_page = 100;
entry.phys_addr = 101;
- if (H5FD_onion_revision_index_insert(rix_p, &entry) < 0)
+ if (H5FD__onion_revision_index_insert(rix_p, &entry) < 0)
TEST_ERROR;
if (2 != rix_p->n_entries)
TEST_ERROR;
entry.logi_page = 500;
entry.phys_addr = 501;
- if (H5FD_onion_revision_index_find(rix_p, 100, &entry_out_p) < 0)
+ if (H5FD__onion_revision_index_find(rix_p, 100, &entry_out_p) < 0)
TEST_ERROR;
if (100 != entry_out_p->logi_page || 101 != entry_out_p->phys_addr)
TEST_ERROR;
@@ -373,7 +373,7 @@ test_revision_index(void)
/* Error cases */
entry.logi_page = 100; /* phys_addr still 501, checksum bbbbbbbb */
- if (H5FD_onion_revision_index_insert(rix_p, &entry) >= 0)
+ if (H5FD__onion_revision_index_insert(rix_p, &entry) >= 0)
TEST_ERROR; /* all components but sum must match */
entry.phys_addr = 101;
@@ -381,18 +381,18 @@ test_revision_index(void)
entry.logi_page = 100;
entry.phys_addr = 101;
- if (H5FD_onion_revision_index_insert(rix_p, &entry) < 0)
+ if (H5FD__onion_revision_index_insert(rix_p, &entry) < 0)
TEST_ERROR;
/* Should still be two unique entries, not three */
if (2 != rix_p->n_entries)
TEST_ERROR;
- if (H5FD_onion_revision_index_find(rix_p, 100, &entry_out_p) < 0)
+ if (H5FD__onion_revision_index_find(rix_p, 100, &entry_out_p) < 0)
TEST_ERROR;
if (100 != entry_out_p->logi_page || 101 != entry_out_p->phys_addr)
TEST_ERROR;
- if (H5FD_onion_revision_index_destroy(rix_p) < 0)
+ if (H5FD__onion_revision_index_destroy(rix_p) < 0)
TEST_ERROR;
PASSED();
@@ -400,7 +400,7 @@ test_revision_index(void)
error:
if (rix_p != NULL)
- (void)H5FD_onion_revision_index_destroy(rix_p);
+ (void)H5FD__onion_revision_index_destroy(rix_p);
return -1;
} /* end test_revision_index() */
@@ -418,8 +418,8 @@ error:
static int
test_revision_index_collisions(void)
{
- H5FD__onion_revision_index_t *rix_p = NULL;
- H5FD_onion_index_entry_t entry = {
+ H5FD_onion_revision_index_t *rix_p = NULL;
+ H5FD_onion_index_entry_t entry = {
0, /* logi_page */
0, /* phys_addr */
};
@@ -429,13 +429,13 @@ test_revision_index_collisions(void)
TESTING("revision index collisions");
- if (NULL == (rix_p = H5FD_onion_revision_index_init(ONION_TEST_PAGE_SIZE_5)))
+ if (NULL == (rix_p = H5FD__onion_revision_index_init(ONION_TEST_PAGE_SIZE_5)))
TEST_ERROR;
for (uint64_t i = 0; i < n_insert; i++) {
entry.phys_addr = i;
entry.logi_page = U64_EXP2(i) + offset_from_power;
- if (H5FD_onion_revision_index_insert(rix_p, &entry) < 0)
+ if (H5FD__onion_revision_index_insert(rix_p, &entry) < 0)
TEST_ERROR;
}
@@ -445,13 +445,13 @@ test_revision_index_collisions(void)
for (uint64_t i = 0; i < n_insert; i++) {
uint64_t page_id = U64_EXP2(i) + offset_from_power;
- if (H5FD_onion_revision_index_find(rix_p, page_id, &entry_out_p) != 1)
+ if (H5FD__onion_revision_index_find(rix_p, page_id, &entry_out_p) != 1)
TEST_ERROR;
if (entry_out_p->phys_addr != i)
TEST_ERROR;
}
- if (H5FD_onion_revision_index_destroy(rix_p) < 0)
+ if (H5FD__onion_revision_index_destroy(rix_p) < 0)
TEST_ERROR;
PASSED();
@@ -459,7 +459,7 @@ test_revision_index_collisions(void)
error:
if (rix_p != NULL)
- (void)H5FD_onion_revision_index_destroy(rix_p);
+ (void)H5FD__onion_revision_index_destroy(rix_p);
return -1;
} /* end test_revision_index_collisions() */
@@ -479,8 +479,8 @@ error:
static int
test_revision_index_resizing(void)
{
- H5FD__onion_revision_index_t *rix_p = NULL;
- H5FD_onion_index_entry_t entry = {
+ H5FD_onion_revision_index_t *rix_p = NULL;
+ H5FD_onion_index_entry_t entry = {
0, /* logi_page */
0, /* phys_addr */
};
@@ -489,13 +489,13 @@ test_revision_index_resizing(void)
TESTING("revision index resizing");
- if (NULL == (rix_p = H5FD_onion_revision_index_init(ONION_TEST_PAGE_SIZE_5)))
+ if (NULL == (rix_p = H5FD__onion_revision_index_init(ONION_TEST_PAGE_SIZE_5)))
TEST_ERROR;
for (uint64_t i = 0; i < n_insert; i++) {
entry.logi_page = i;
entry.phys_addr = ((uint64_t)(-1) - i);
- if (H5FD_onion_revision_index_insert(rix_p, &entry) < 0)
+ if (H5FD__onion_revision_index_insert(rix_p, &entry) < 0)
TEST_ERROR;
}
@@ -505,13 +505,13 @@ test_revision_index_resizing(void)
for (uint64_t i = 0; i < n_insert; i++) {
uint64_t page_id = i;
- if (H5FD_onion_revision_index_find(rix_p, page_id, &entry_out_p) != 1)
+ if (H5FD__onion_revision_index_find(rix_p, page_id, &entry_out_p) != 1)
TEST_ERROR;
if (entry_out_p->phys_addr != ((uint64_t)(-1) - i))
TEST_ERROR;
}
- if (H5FD_onion_revision_index_destroy(rix_p) < 0)
+ if (H5FD__onion_revision_index_destroy(rix_p) < 0)
TEST_ERROR;
PASSED();
@@ -519,7 +519,7 @@ test_revision_index_resizing(void)
error:
if (rix_p != NULL)
- (void)H5FD_onion_revision_index_destroy(rix_p);
+ (void)H5FD__onion_revision_index_destroy(rix_p);
return -1;
} /* end test_revision_index_resizing() */
@@ -536,8 +536,8 @@ error:
static int
test_revision_index_to_archival_index(void)
{
- H5FD__onion_revision_index_t *rix_p = NULL;
- H5FD_onion_index_entry_t rix_entry = {
+ H5FD_onion_revision_index_t *rix_p = NULL;
+ H5FD_onion_index_entry_t rix_entry = {
0, /* logi_page */
0, /* phys_addr */
};
@@ -555,7 +555,7 @@ test_revision_index_to_archival_index(void)
* SETUP
*/
- if (NULL == (rix_p = H5FD_onion_revision_index_init(ONION_TEST_PAGE_SIZE_5)))
+ if (NULL == (rix_p = H5FD__onion_revision_index_init(ONION_TEST_PAGE_SIZE_5)))
TEST_ERROR;
/* Add scattered entries in reverse order. */
@@ -564,7 +564,7 @@ test_revision_index_to_archival_index(void)
rix_entry.logi_page = n;
rix_entry.phys_addr = n * 13;
- if (H5FD_onion_revision_index_insert(rix_p, &rix_entry) < 0)
+ if (H5FD__onion_revision_index_insert(rix_p, &rix_entry) < 0)
TEST_ERROR;
}
@@ -576,10 +576,10 @@ test_revision_index_to_archival_index(void)
/* Successful merge into empty archival index */
- if (H5FD_onion_merge_revision_index_into_archival_index(rix_p, &aix) < 0)
+ if (H5FD__onion_merge_revision_index_into_archival_index(rix_p, &aix) < 0)
TEST_ERROR;
- if (!H5FD_onion_archival_index_is_valid(&aix))
+ if (!H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
if (n_insert != aix.n_entries)
@@ -609,12 +609,12 @@ test_revision_index_to_archival_index(void)
aix.list[1].phys_addr = (2003 * (n_insert + 1) + 47) * 13;
aix.n_entries = 2;
- if (!H5FD_onion_archival_index_is_valid(&aix))
+ if (!H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
- if (H5FD_onion_merge_revision_index_into_archival_index(rix_p, &aix) < 0)
+ if (H5FD__onion_merge_revision_index_into_archival_index(rix_p, &aix) < 0)
TEST_ERROR;
- if (!H5FD_onion_archival_index_is_valid(&aix))
+ if (!H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
if (n_insert + 2 != aix.n_entries)
@@ -645,13 +645,13 @@ test_revision_index_to_archival_index(void)
aix.list[1].phys_addr = 101;
aix.n_entries = 2;
- if (!H5FD_onion_archival_index_is_valid(&aix))
+ if (!H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
- if (H5FD_onion_merge_revision_index_into_archival_index(rix_p, &aix) < 0)
+ if (H5FD__onion_merge_revision_index_into_archival_index(rix_p, &aix) < 0)
TEST_ERROR;
- if (!H5FD_onion_archival_index_is_valid(&aix))
+ if (!H5FD__onion_archival_index_is_valid(&aix))
TEST_ERROR;
if (n_insert != aix.n_entries)
@@ -671,7 +671,7 @@ test_revision_index_to_archival_index(void)
/* CLEANUP */
- if (H5FD_onion_revision_index_destroy(rix_p) < 0)
+ if (H5FD__onion_revision_index_destroy(rix_p) < 0)
TEST_ERROR;
H5MM_xfree(aix.list);
@@ -680,7 +680,7 @@ test_revision_index_to_archival_index(void)
error:
if (rix_p)
- (void)H5FD_onion_revision_index_destroy(rix_p);
+ (void)H5FD__onion_revision_index_destroy(rix_p);
H5MM_xfree(aix.list);
return -1;
@@ -894,8 +894,8 @@ test_header_encode_decode(void)
'O', 'H', 'D', 'H', /* NOTE: match signature define in onion_priv.h */
1, 12, 0, 0, /* NOTE: update version w/ "current" as needed */
0, 16, 0, 0, 0x11, 0x00, 0, 0, 0x02, 0, 0, 0, /* origin_eof */
- 0x40, 0xe2, 0x01, 0, 0, 0, 0, 0, /* whole_history_addr */
- 88, 0, 0, 0, 0, 0, 0, 0, /* whole_history_size */
+ 0x40, 0xe2, 0x01, 0, 0, 0, 0, 0, /* history_addr */
+ 88, 0, 0, 0, 0, 0, 0, 0, /* history_size */
0, 0, 0, 0 /* sum populated below */
};
unsigned char * ptr = NULL;
@@ -915,10 +915,10 @@ test_header_encode_decode(void)
hdr.version = H5FD__ONION_HEADER_VERSION_CURR;
hdr.flags = 12;
hdr.origin_eof = 8589934609ull, hdr.page_size = 4096;
- hdr.whole_history_addr = 123456;
- hdr.whole_history_size = 88;
+ hdr.history_addr = 123456;
+ hdr.history_size = 88;
- if (H5FD_onion_history_header_encode(&hdr, buf, &sum_out) != H5FD__ONION_ENCODED_SIZE_HEADER)
+ if (H5FD__onion_history_header_encode(&hdr, buf, &sum_out) != H5FD__ONION_ENCODED_SIZE_HEADER)
TEST_ERROR;
if (sum != sum_out)
@@ -931,11 +931,11 @@ test_header_encode_decode(void)
}
}
- hdr_out.version = H5FD__ONION_HEADER_VERSION_CURR;
- hdr_out.flags = 0;
- hdr_out.page_size = 0;
- hdr_out.whole_history_addr = 0;
- hdr_out.whole_history_size = 0;
+ hdr_out.version = H5FD__ONION_HEADER_VERSION_CURR;
+ hdr_out.flags = 0;
+ hdr_out.page_size = 0;
+ hdr_out.history_addr = 0;
+ hdr_out.history_size = 0;
/* Invalid header signature prevents decoding.
*/
@@ -943,7 +943,7 @@ test_header_encode_decode(void)
exp[3] = 'X'; /* invalidate encoded signature */
H5E_BEGIN_TRY
{
- size_ret = H5FD_onion_history_header_decode(exp, &hdr_out);
+ size_ret = H5FD__onion_history_header_decode(exp, &hdr_out);
}
H5E_END_TRY;
if (0 != size_ret)
@@ -957,7 +957,7 @@ test_header_encode_decode(void)
exp[4] = 0; /* encoded version 0?!? */
H5E_BEGIN_TRY
{
- size_ret = H5FD_onion_history_header_decode(exp, &hdr_out);
+ size_ret = H5FD__onion_history_header_decode(exp, &hdr_out);
}
H5E_END_TRY;
if (0 != size_ret)
@@ -966,7 +966,7 @@ test_header_encode_decode(void)
exp[4] = H5FD__ONION_HEADER_VERSION_CURR + 1; /* encoded super-version?! */
H5E_BEGIN_TRY
{
- size_ret = H5FD_onion_history_header_decode(exp, &hdr_out);
+ size_ret = H5FD__onion_history_header_decode(exp, &hdr_out);
}
H5E_END_TRY;
if (0 != size_ret)
@@ -977,7 +977,7 @@ test_header_encode_decode(void)
/* Valid header can be decoded */
- if (H5FD_onion_history_header_decode(buf, &hdr_out) != H5FD__ONION_ENCODED_SIZE_HEADER)
+ if (H5FD__onion_history_header_decode(buf, &hdr_out) != H5FD__ONION_ENCODED_SIZE_HEADER)
TEST_ERROR;
if (H5FD__ONION_HEADER_VERSION_CURR != hdr_out.version)
TEST_ERROR;
@@ -985,9 +985,9 @@ test_header_encode_decode(void)
TEST_ERROR;
if (hdr.page_size != hdr_out.page_size)
TEST_ERROR;
- if (hdr.whole_history_addr != hdr_out.whole_history_addr)
+ if (hdr.history_addr != hdr_out.history_addr)
TEST_ERROR;
- if (hdr.whole_history_size != hdr_out.whole_history_size)
+ if (hdr.history_size != hdr_out.history_size)
TEST_ERROR;
PASSED();
@@ -998,10 +998,10 @@ error:
} /* end test_header_encode_decode() */
/*-----------------------------------------------------------------------------
- * Function: test_whole_history_encode_decode_empty()
+ * Function: test_history_encode_decode_empty()
*
- * Purpose: Verify onion whole-history encoding and decoding behavior.
- * Tests the case of the "empty" whole-history.
+ * Purpose: Verify onion history encoding and decoding behavior.
+ * Tests the case of the "empty" history.
* Verifies behavior in standard error cases.
*
* Return: PASSED : 0
@@ -1009,7 +1009,7 @@ error:
*-----------------------------------------------------------------------------
*/
static int
-test_whole_history_encode_decode_empty(void)
+test_history_encode_decode_empty(void)
{
unsigned char buf[32];
unsigned char exp[32] = {
@@ -1017,30 +1017,30 @@ test_whole_history_encode_decode_empty(void)
1, 0, 0, 0, /* NOTE: update version w/ "current" as needed */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* sum populated below */
};
- unsigned char * ptr = NULL;
- uint32_t sum = 0;
- uint32_t sum_out = 0;
- size_t i = 0;
- uint64_t size_ret = 0;
- H5FD_onion_whole_history_t whs = {
+ unsigned char * ptr = NULL;
+ uint32_t sum = 0;
+ uint32_t sum_out = 0;
+ size_t i = 0;
+ uint64_t size_ret = 0;
+ H5FD_onion_history_t history = {
H5FD__ONION_WHOLE_HISTORY_VERSION_CURR, 0, /* n_revisions */
NULL, /* list */
0, /* checksum */
};
- H5FD_onion_whole_history_t whs_out = {
+ H5FD_onion_history_t history_out = {
H5FD__ONION_WHOLE_HISTORY_VERSION_CURR, 0, /* n_revisions */
NULL, /* list */
0, /* checksum */
};
- TESTING("encode/decode whole-history (empty and failures)");
+ TESTING("encode/decode history (empty and failures)");
/* Generage checksum but don't store it yet */
sum = H5_checksum_fletcher32(exp, H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY - 4);
ptr = exp + H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY - 4;
UINT32ENCODE(ptr, sum);
- if (H5FD_onion_whole_history_encode(&whs, buf, &sum_out) != H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY)
+ if (H5FD__onion_history_encode(&history, buf, &sum_out) != H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY)
TEST_ERROR;
for (i = 0; i < 20; i++) {
if (exp[i] != buf[i]) {
@@ -1050,14 +1050,14 @@ test_whole_history_encode_decode_empty(void)
}
if (sum != sum_out)
TEST_ERROR;
- whs.checksum = sum; /* set to compare later */
+ history.checksum = sum; /* set to compare later */
/* Invalid signature prevents decoding */
exp[3] = 'X'; /* invalidate encoded signature */
H5E_BEGIN_TRY
{
- size_ret = H5FD_onion_whole_history_decode(exp, &whs_out);
+ size_ret = H5FD__onion_history_decode(exp, &history_out);
}
H5E_END_TRY;
if (0 != size_ret)
@@ -1070,7 +1070,7 @@ test_whole_history_encode_decode_empty(void)
exp[4] = 0; /* encoded version 0?!? */
H5E_BEGIN_TRY
{
- size_ret = H5FD_onion_whole_history_decode(exp, &whs_out);
+ size_ret = H5FD__onion_history_decode(exp, &history_out);
}
H5E_END_TRY;
if (0 != size_ret)
@@ -1079,7 +1079,7 @@ test_whole_history_encode_decode_empty(void)
exp[4] = H5FD__ONION_WHOLE_HISTORY_VERSION_CURR + 1;
H5E_BEGIN_TRY
{
- size_ret = H5FD_onion_whole_history_decode(exp, &whs_out);
+ size_ret = H5FD__onion_history_decode(exp, &history_out);
}
H5E_END_TRY;
if (0 != size_ret)
@@ -1089,15 +1089,15 @@ test_whole_history_encode_decode_empty(void)
/* Valid summary can be decoded */
- if (H5FD_onion_whole_history_decode(buf, &whs_out) != H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY)
+ if (H5FD__onion_history_decode(buf, &history_out) != H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY)
TEST_ERROR;
- if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != whs_out.version)
+ if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != history_out.version)
TEST_ERROR;
- if (whs.n_revisions != whs_out.n_revisions)
+ if (history.n_revisions != history_out.n_revisions)
TEST_ERROR;
- if (whs.checksum != whs_out.checksum)
+ if (history.checksum != history_out.checksum)
TEST_ERROR;
- if (NULL != whs_out.record_pointer_list)
+ if (NULL != history_out.record_locs)
TEST_ERROR;
PASSED();
@@ -1105,12 +1105,12 @@ test_whole_history_encode_decode_empty(void)
error:
return -1;
-} /* end test_whole_history_encode_decode_empty() */
+} /* end test_history_encode_decode_empty() */
/*-----------------------------------------------------------------------------
- * Function: test_whole_history_encode_decode()
+ * Function: test_history_encode_decode()
*
- * Purpose: Verify onion whole-history encoding and decoding behavior.
+ * Purpose: Verify onion history encoding and decoding behavior.
* Encode/decode with some set of revision record pointers.
*
* Return: PASSED : 0
@@ -1118,7 +1118,7 @@ error:
*-----------------------------------------------------------------------------
*/
static int
-test_whole_history_encode_decode(void)
+test_history_encode_decode(void)
{
unsigned char *buf = NULL;
unsigned char exp[80] = {
@@ -1134,100 +1134,100 @@ test_whole_history_encode_decode(void)
/* final checksum */
0, 0, 0, 0 /* sum populated below */
};
- unsigned char * buf_p = NULL;
- uint32_t sum_out = 0;
- size_t i = 0;
- H5FD_onion_whole_history_t whs = {
+ unsigned char * buf_p = NULL;
+ uint32_t sum_out = 0;
+ size_t i = 0;
+ H5FD_onion_history_t history = {
H5FD__ONION_WHOLE_HISTORY_VERSION_CURR, 3, /* n_revisions */
NULL, /* list set below */
0, /* checksum not set by us */
};
- H5FD_onion_whole_history_t whs_out = {
+ H5FD_onion_history_t history_out = {
H5FD__ONION_WHOLE_HISTORY_VERSION_CURR, 0, /* n_revisions must start as zero */
NULL, /* list */
0, /* checksum */
};
- uint64_t exp_size =
- H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY + H5FD__ONION_ENCODED_SIZE_RECORD_POINTER * whs.n_revisions;
+ uint64_t exp_size = H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY +
+ H5FD__ONION_ENCODED_SIZE_RECORD_POINTER * history.n_revisions;
- TESTING("encode/decode whole-history");
+ TESTING("encode/decode history");
if (80 != exp_size)
TEST_ERROR;
- whs.record_pointer_list = HDcalloc(whs.n_revisions, sizeof(H5FD_onion_record_pointer_t));
- if (NULL == whs.record_pointer_list)
+ history.record_locs = HDcalloc(history.n_revisions, sizeof(H5FD_onion_record_loc_t));
+ if (NULL == history.record_locs)
TEST_ERROR;
- /* must match values in exp */
- whs.record_pointer_list[0].phys_addr = 568ull;
- whs.record_pointer_list[0].record_size = 238ull;
- whs.record_pointer_list[1].phys_addr = 241017ull;
- whs.record_pointer_list[1].record_size = 4555ull;
- whs.record_pointer_list[2].phys_addr = 918153371232ull;
- whs.record_pointer_list[2].record_size = 240ull;
+ /* Must match values in exp */
+ history.record_locs[0].phys_addr = 568ull;
+ history.record_locs[0].record_size = 238ull;
+ history.record_locs[1].phys_addr = 241017ull;
+ history.record_locs[1].record_size = 4555ull;
+ history.record_locs[2].phys_addr = 918153371232ull;
+ history.record_locs[2].record_size = 240ull;
/* Populate revision pointer sums in exp */
- for (i = 0; i < whs.n_revisions; i++) {
- uint64_t whs_pre = H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY - 4;
- uint64_t ptr_pre = H5FD__ONION_ENCODED_SIZE_RECORD_POINTER - 4;
- uint64_t ptr_size = H5FD__ONION_ENCODED_SIZE_RECORD_POINTER;
+ for (i = 0; i < history.n_revisions; i++) {
+ uint64_t history_pre = H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY - 4;
+ uint64_t ptr_pre = H5FD__ONION_ENCODED_SIZE_RECORD_POINTER - 4;
+ uint64_t ptr_size = H5FD__ONION_ENCODED_SIZE_RECORD_POINTER;
- buf_p = exp + whs_pre + ptr_size * i;
- whs.record_pointer_list[i].checksum = H5_checksum_fletcher32(buf_p, ptr_pre);
+ buf_p = exp + history_pre + ptr_size * i;
+ history.record_locs[i].checksum = H5_checksum_fletcher32(buf_p, ptr_pre);
buf_p += ptr_pre;
- UINT32ENCODE(buf_p, whs.record_pointer_list[i].checksum);
+ UINT32ENCODE(buf_p, history.record_locs[i].checksum);
}
/* Compute, populate, and store exp final sum */
- whs.checksum = H5_checksum_fletcher32(exp, exp_size - 4);
- buf_p = exp + exp_size - 4;
- UINT32ENCODE(buf_p, whs.checksum);
+ history.checksum = H5_checksum_fletcher32(exp, exp_size - 4);
+ buf_p = exp + exp_size - 4;
+ UINT32ENCODE(buf_p, history.checksum);
if (NULL == (buf = HDmalloc(exp_size)))
TEST_ERROR;
- if (H5FD_onion_whole_history_encode(&whs, buf, &sum_out) != exp_size)
+ if (H5FD__onion_history_encode(&history, buf, &sum_out) != exp_size)
TEST_ERROR;
for (i = 0; i < exp_size; i++) {
if (exp[i] != buf[i])
TEST_ERROR;
}
- if (whs.checksum != sum_out)
+ if (history.checksum != sum_out)
TEST_ERROR;
/* Initial decode, gets always-present components */
- whs_out.n_revisions = 0; /* must be initialized to 0 */
- if (H5FD_onion_whole_history_decode(exp, &whs_out) != exp_size)
+ history_out.n_revisions = 0; /* must be initialized to 0 */
+ if (H5FD__onion_history_decode(exp, &history_out) != exp_size)
TEST_ERROR;
- if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != whs_out.version)
+ if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != history_out.version)
TEST_ERROR;
- if (whs.n_revisions != whs_out.n_revisions)
+ if (history.n_revisions != history_out.n_revisions)
TEST_ERROR;
/* Must be created by us */
- if (NULL != whs_out.record_pointer_list)
+ if (NULL != history_out.record_locs)
TEST_ERROR;
/* True decode requires allocating space for record pointers */
- whs_out.record_pointer_list = HDcalloc(whs_out.n_revisions, sizeof(H5FD_onion_record_pointer_t));
- if (NULL == whs_out.record_pointer_list)
+ history_out.record_locs = HDcalloc(history_out.n_revisions, sizeof(H5FD_onion_record_loc_t));
+ if (NULL == history_out.record_locs)
TEST_ERROR;
- if (H5FD_onion_whole_history_decode(exp, &whs_out) != exp_size)
+ if (H5FD__onion_history_decode(exp, &history_out) != exp_size)
TEST_ERROR;
- if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != whs_out.version)
+ if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != history_out.version)
TEST_ERROR;
- if (whs.n_revisions != whs_out.n_revisions)
+ if (history.n_revisions != history_out.n_revisions)
TEST_ERROR;
- if (whs.checksum != whs_out.checksum)
+ if (history.checksum != history_out.checksum)
TEST_ERROR;
- if (NULL == whs_out.record_pointer_list)
+ if (NULL == history_out.record_locs)
TEST_ERROR;
- for (i = 0; i < whs.n_revisions; i++) {
- H5FD_onion_record_pointer_t exp_rp = whs.record_pointer_list[i];
- H5FD_onion_record_pointer_t act_rp = whs_out.record_pointer_list[i];
+ for (i = 0; i < history.n_revisions; i++) {
+ H5FD_onion_record_loc_t exp_rp = history.record_locs[i];
+ H5FD_onion_record_loc_t act_rp = history_out.record_locs[i];
if (exp_rp.phys_addr != act_rp.phys_addr)
TEST_ERROR;
@@ -1237,20 +1237,20 @@ test_whole_history_encode_decode(void)
TEST_ERROR;
}
- HDfree(whs_out.record_pointer_list);
+ HDfree(history_out.record_locs);
HDfree(buf);
- HDfree(whs.record_pointer_list);
+ HDfree(history.record_locs);
PASSED();
return 0;
error:
- HDfree(whs_out.record_pointer_list);
+ HDfree(history_out.record_locs);
HDfree(buf);
- HDfree(whs.record_pointer_list);
+ HDfree(history.record_locs);
return -1;
-} /* end test_whole_history_encode_decode() */
+} /* end test_history_encode_decode() */
/*-----------------------------------------------------------------------------
*
@@ -1380,7 +1380,7 @@ test_revision_record_encode_decode(void)
/* Test encode */
- if (H5FD_onion_revision_record_encode(&record, buf, &sum_out) != exp_size)
+ if (H5FD__onion_revision_record_encode(&record, buf, &sum_out) != exp_size)
TEST_ERROR;
hbool_t badness = FALSE;
@@ -1419,7 +1419,7 @@ test_revision_record_encode_decode(void)
exp[2] = 'Y';
H5E_BEGIN_TRY
{
- size_ret = H5FD_onion_revision_record_decode(exp, &r_out);
+ size_ret = H5FD__onion_revision_record_decode(exp, &r_out);
}
H5E_END_TRY;
if (0 != size_ret)
@@ -1430,7 +1430,7 @@ test_revision_record_encode_decode(void)
exp[4] = 0;
H5E_BEGIN_TRY
{
- size_ret = H5FD_onion_revision_record_decode(exp, &r_out);
+ size_ret = H5FD__onion_revision_record_decode(exp, &r_out);
}
H5E_END_TRY;
if (0 != size_ret)
@@ -1440,7 +1440,7 @@ test_revision_record_encode_decode(void)
exp[4] = H5FD__ONION_REVISION_RECORD_VERSION_CURR + 1;
H5E_BEGIN_TRY
{
- size_ret = H5FD_onion_revision_record_decode(exp, &r_out);
+ size_ret = H5FD__onion_revision_record_decode(exp, &r_out);
}
H5E_END_TRY;
if (0 != size_ret)
@@ -1450,7 +1450,7 @@ test_revision_record_encode_decode(void)
/* Test successful decode */
/* Initial decode; get variable-length component sizes */
- if (H5FD_onion_revision_record_decode(exp, &r_out) != exp_size)
+ if (H5FD__onion_revision_record_decode(exp, &r_out) != exp_size)
TEST_ERROR;
if (record.comment_size != r_out.comment_size)
TEST_ERROR;
@@ -1466,7 +1466,7 @@ test_revision_record_encode_decode(void)
TEST_ERROR;
/* Decode into all components */
- if (H5FD_onion_revision_record_decode(exp, &r_out) != exp_size)
+ if (H5FD__onion_revision_record_decode(exp, &r_out) != exp_size)
TEST_ERROR;
if (H5FD__ONION_REVISION_RECORD_VERSION_CURR != r_out.version)
TEST_ERROR;
@@ -1590,7 +1590,7 @@ verify_history_as_expected_onion(H5FD_t *raw_file, struct expected_history *filt
{
unsigned char * buf = NULL; /* allocated area for actual file bytes */
H5FD_onion_history_header_t hdr_out;
- H5FD_onion_whole_history_t whs_out;
+ H5FD_onion_history_t history_out;
H5FD_onion_revision_record_t rev_out;
uint64_t filesize = 0;
uint64_t readsize = 0;
@@ -1598,9 +1598,9 @@ verify_history_as_expected_onion(H5FD_t *raw_file, struct expected_history *filt
hdr_out.version = H5FD__ONION_HEADER_VERSION_CURR;
- whs_out.version = H5FD__ONION_WHOLE_HISTORY_VERSION_CURR;
- whs_out.n_revisions = 0;
- whs_out.record_pointer_list = NULL;
+ history_out.version = H5FD__ONION_WHOLE_HISTORY_VERSION_CURR;
+ history_out.n_revisions = 0;
+ history_out.record_locs = NULL;
rev_out.version = H5FD__ONION_REVISION_RECORD_VERSION_CURR;
rev_out.archival_index.version = H5FD__ONION_ARCHIVAL_INDEX_VERSION_CURR;
@@ -1617,7 +1617,7 @@ verify_history_as_expected_onion(H5FD_t *raw_file, struct expected_history *filt
if (H5FDread(raw_file, H5FD_MEM_DRAW, H5P_DEFAULT, 0, readsize, buf) < 0)
TEST_ERROR;
- readsize = H5FD_onion_history_header_decode(buf, &hdr_out);
+ readsize = H5FD__onion_history_header_decode(buf, &hdr_out);
if (0 == readsize)
TEST_ERROR;
if (H5FD__ONION_HEADER_VERSION_CURR != hdr_out.version)
@@ -1628,7 +1628,7 @@ verify_history_as_expected_onion(H5FD_t *raw_file, struct expected_history *filt
TEST_ERROR;
if (filter->page_size != hdr_out.page_size)
TEST_ERROR;
- if (hdr_out.whole_history_addr + hdr_out.whole_history_size != filesize)
+ if (hdr_out.history_addr + hdr_out.history_size != filesize)
TEST_ERROR;
if (filter->origin_eof != hdr_out.origin_eof)
TEST_ERROR;
@@ -1636,42 +1636,42 @@ verify_history_as_expected_onion(H5FD_t *raw_file, struct expected_history *filt
HDfree(buf);
buf = NULL;
- /* Ingest whole-history */
+ /* Ingest history */
- readsize = hdr_out.whole_history_size;
+ readsize = hdr_out.history_size;
if (NULL == (buf = HDmalloc(readsize * sizeof(unsigned char))))
TEST_ERROR;
- if (H5FDread(raw_file, H5FD_MEM_DRAW, H5P_DEFAULT, hdr_out.whole_history_addr, readsize, buf) < 0)
+ if (H5FDread(raw_file, H5FD_MEM_DRAW, H5P_DEFAULT, hdr_out.history_addr, readsize, buf) < 0)
TEST_ERROR;
/* Initial read, get count of revisions */
- readsize = H5FD_onion_whole_history_decode(buf, &whs_out);
+ readsize = H5FD__onion_history_decode(buf, &history_out);
if (0 == readsize)
TEST_ERROR;
- if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != whs_out.version)
+ if (H5FD__ONION_WHOLE_HISTORY_VERSION_CURR != history_out.version)
TEST_ERROR;
- if (HDmemcmp(&whs_out.checksum, &buf[readsize - 4], 4) != 0)
+ if (HDmemcmp(&history_out.checksum, &buf[readsize - 4], 4) != 0)
TEST_ERROR;
- if (whs_out.checksum != H5_checksum_fletcher32(buf, readsize - 4))
+ if (history_out.checksum != H5_checksum_fletcher32(buf, readsize - 4))
TEST_ERROR;
- if (filter->n_revisions != whs_out.n_revisions)
+ if (filter->n_revisions != history_out.n_revisions)
TEST_ERROR;
/* Final read, populate pointers to revision records */
- whs_out.record_pointer_list = HDcalloc(whs_out.n_revisions, sizeof(H5FD_onion_record_pointer_t));
- if (NULL == whs_out.record_pointer_list)
+ history_out.record_locs = HDcalloc(history_out.n_revisions, sizeof(H5FD_onion_record_loc_t));
+ if (NULL == history_out.record_locs)
TEST_ERROR;
- if (H5FD_onion_whole_history_decode(buf, &whs_out) != readsize)
+ if (H5FD__onion_history_decode(buf, &history_out) != readsize)
TEST_ERROR;
/* Re-use buffer space to sanity-check checksum for record pointer(s). */
- HDassert(readsize >= sizeof(H5FD_onion_record_pointer_t));
- for (i = 0; i < whs_out.n_revisions; i++) {
+ HDassert(readsize >= sizeof(H5FD_onion_record_loc_t));
+ for (i = 0; i < history_out.n_revisions; i++) {
- HDmemcpy(buf, &whs_out.record_pointer_list[i].phys_addr, 8);
- HDmemcpy(buf + 8, &whs_out.record_pointer_list[i].record_size, 8);
+ HDmemcpy(buf, &history_out.record_locs[i].phys_addr, 8);
+ HDmemcpy(buf + 8, &history_out.record_locs[i].record_size, 8);
- if (whs_out.record_pointer_list[i].checksum != H5_checksum_fletcher32(buf, 16))
+ if (history_out.record_locs[i].checksum != H5_checksum_fletcher32(buf, 16))
TEST_ERROR;
}
@@ -1680,9 +1680,9 @@ verify_history_as_expected_onion(H5FD_t *raw_file, struct expected_history *filt
/* Ingest revision(s) */
- for (i = 0; i < whs_out.n_revisions; i++) {
- H5FD_onion_record_pointer_t *rpp = &whs_out.record_pointer_list[i];
- struct expected_revision * erp = &filter->revisions[i];
+ for (i = 0; i < history_out.n_revisions; i++) {
+ H5FD_onion_record_loc_t * rpp = &history_out.record_locs[i];
+ struct expected_revision *erp = &filter->revisions[i];
rev_out.archival_index.list = NULL;
rev_out.archival_index.n_entries = 0;
@@ -1697,7 +1697,7 @@ verify_history_as_expected_onion(H5FD_t *raw_file, struct expected_history *filt
TEST_ERROR;
/* Initial revision read -- get fixed components */
- readsize = H5FD_onion_revision_record_decode(buf, &rev_out);
+ readsize = H5FD__onion_revision_record_decode(buf, &rev_out);
if (0 == readsize)
TEST_ERROR;
if (rpp->record_size != readsize)
@@ -1723,7 +1723,7 @@ verify_history_as_expected_onion(H5FD_t *raw_file, struct expected_history *filt
if (NULL == rev_out.archival_index.list)
TEST_ERROR;
- readsize = H5FD_onion_revision_record_decode(buf, &rev_out);
+ readsize = H5FD__onion_revision_record_decode(buf, &rev_out);
if (rpp->record_size != readsize)
TEST_ERROR;
@@ -1747,8 +1747,8 @@ verify_history_as_expected_onion(H5FD_t *raw_file, struct expected_history *filt
HDfree(rev_out.archival_index.list);
}
- HDfree(whs_out.record_pointer_list);
- whs_out.record_pointer_list = NULL;
+ HDfree(history_out.record_locs);
+ history_out.record_locs = NULL;
return 0;
@@ -1756,7 +1756,7 @@ error:
HDfree(buf);
HDfree(rev_out.comment);
HDfree(rev_out.archival_index.list);
- HDfree(whs_out.record_pointer_list);
+ HDfree(history_out.record_locs);
return -1;
@@ -1770,7 +1770,7 @@ error:
* + open (not yet written)
* + "Empty" .h5 file created
* + .onion file created w/ only header (0 whole-hist addr)
- * + .onion.recovery created w/ "empty" whole-history
+ * + .onion.recovery created w/ "empty" history
* + Cannot open onionized canonical file (incomplete history, no rev)
*
* Inspect file contents on backing store.
@@ -1789,8 +1789,8 @@ verify_stored_onion_create_0_open(struct onion_filepaths *paths, H5FD_onion_fapl
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* checksum encoded below */
};
- size_t whs_exp_bytes_size = 20;
- unsigned char whs_exp_bytes[] = {
+ size_t history_exp_bytes_size = 20;
+ unsigned char history_exp_bytes[] = {
'O', 'W', 'H', 'S', 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* checksum encoded below */
};
unsigned char *ptr = NULL;
@@ -1811,9 +1811,9 @@ verify_stored_onion_create_0_open(struct onion_filepaths *paths, H5FD_onion_fapl
UINT32ENCODE(ptr, sum);
ptr = NULL;
- /* Finish populating expected whole-history bytes */
- sum = H5_checksum_fletcher32(whs_exp_bytes, H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY - 4);
- ptr = whs_exp_bytes + H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY - 4;
+ /* Finish populating expected history bytes */
+ sum = H5_checksum_fletcher32(history_exp_bytes, H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY - 4);
+ ptr = history_exp_bytes + H5FD__ONION_ENCODED_SIZE_WHOLE_HISTORY - 4;
UINT32ENCODE(ptr, sum);
ptr = NULL;
@@ -1847,8 +1847,8 @@ verify_stored_onion_create_0_open(struct onion_filepaths *paths, H5FD_onion_fapl
if (compare_file_bytes_exactly(paths->onion, fapl_id, H5FD__ONION_ENCODED_SIZE_HEADER, hdr_exp_bytes) < 0)
TEST_ERROR;
- /* Look at history backing file: should have nascent whole-history */
- if (compare_file_bytes_exactly(paths->recovery, fapl_id, whs_exp_bytes_size, whs_exp_bytes) < 0)
+ /* Look at history backing file: should have nascent history */
+ if (compare_file_bytes_exactly(paths->recovery, fapl_id, history_exp_bytes_size, history_exp_bytes) < 0)
TEST_ERROR;
/* Inspect .h5 file contents */
@@ -2213,15 +2213,15 @@ test_several_revisions_with_logical_gaps(void)
0, /* flags */
"first" /* comment */
};
- H5FD_t * file = NULL; /* Onion virtual file for read/write */
- struct expected_history filter;
- unsigned char * buf = NULL;
- struct revise_revision about[4];
- H5FD_onion_whole_history_t whs_out;
- size_t i = 0;
- haddr_t size = 0;
- uint64_t a_off = ONION_TEST_PAGE_SIZE_5 + 7; /* 39 */
- uint64_t b_off = (((a_off + a_list_size_s + ONION_TEST_PAGE_SIZE_5 - 1) >> 5) << 5) +
+ H5FD_t * file = NULL; /* Onion virtual file for read/write */
+ struct expected_history filter;
+ unsigned char * buf = NULL;
+ struct revise_revision about[4];
+ H5FD_onion_history_t history_out;
+ size_t i = 0;
+ haddr_t size = 0;
+ uint64_t a_off = ONION_TEST_PAGE_SIZE_5 + 7; /* 39 */
+ uint64_t b_off = (((a_off + a_list_size_s + ONION_TEST_PAGE_SIZE_5 - 1) >> 5) << 5) +
ONION_TEST_PAGE_SIZE_5 + 7; /* full page between */
TESTING("multiple revisions with gaps and overlap");
@@ -2230,9 +2230,9 @@ test_several_revisions_with_logical_gaps(void)
* SETUP *
*********/
- whs_out.version = H5FD__ONION_WHOLE_HISTORY_VERSION_CURR;
- whs_out.n_revisions = 0;
- whs_out.record_pointer_list = NULL;
+ history_out.version = H5FD__ONION_WHOLE_HISTORY_VERSION_CURR;
+ history_out.n_revisions = 0;
+ history_out.record_locs = NULL;
onion_info.backing_fapl_id = h5_fileaccess();
@@ -2516,7 +2516,7 @@ error:
onion_filepaths_destroy(paths);
}
- HDfree(whs_out.record_pointer_list);
+ HDfree(history_out.record_locs);
HDfree(buf);
if (file != NULL)
@@ -2662,7 +2662,7 @@ test_page_aligned_history_create(void)
unsigned char * buf = NULL;
struct revise_revision about[2];
H5FD_onion_history_header_t hdr_out;
- H5FD_onion_whole_history_t whs_out;
+ H5FD_onion_history_t history_out;
size_t i = 0;
uint64_t a_off = b_list_size_s - a_list_size_s;
@@ -2672,10 +2672,10 @@ test_page_aligned_history_create(void)
* SETUP *
*********/
- hdr_out.version = H5FD__ONION_HEADER_VERSION_CURR;
- whs_out.version = H5FD__ONION_WHOLE_HISTORY_VERSION_CURR;
- whs_out.n_revisions = 0;
- whs_out.record_pointer_list = NULL;
+ hdr_out.version = H5FD__ONION_HEADER_VERSION_CURR;
+ history_out.version = H5FD__ONION_WHOLE_HISTORY_VERSION_CURR;
+ history_out.n_revisions = 0;
+ history_out.record_locs = NULL;
onion_info.backing_fapl_id = h5_fileaccess();
fapl_id = H5Pcreate(H5P_FILE_ACCESS);
@@ -2760,39 +2760,38 @@ test_page_aligned_history_create(void)
TEST_ERROR;
if (H5FDread(file, H5FD_MEM_DRAW, H5P_DEFAULT, 0, H5FD__ONION_ENCODED_SIZE_HEADER, buf) < 0)
TEST_ERROR;
- if (H5FD_onion_history_header_decode(buf, &hdr_out) != H5FD__ONION_ENCODED_SIZE_HEADER)
+ if (H5FD__onion_history_header_decode(buf, &hdr_out) != H5FD__ONION_ENCODED_SIZE_HEADER)
TEST_ERROR;
- if (hdr_out.whole_history_addr & ((1 << 5) - 1)) /* 5::PAGE_SIZE_5 */
+ if (hdr_out.history_addr & ((1 << 5) - 1)) /* 5::PAGE_SIZE_5 */
TEST_ERROR;
HDfree(buf);
buf = NULL;
- if (NULL == (buf = HDmalloc(hdr_out.whole_history_size)))
+ if (NULL == (buf = HDmalloc(hdr_out.history_size)))
TEST_ERROR;
- if (H5FDread(file, H5FD_MEM_DRAW, H5P_DEFAULT, hdr_out.whole_history_addr, hdr_out.whole_history_size,
- buf) < 0)
+ if (H5FDread(file, H5FD_MEM_DRAW, H5P_DEFAULT, hdr_out.history_addr, hdr_out.history_size, buf) < 0)
TEST_ERROR;
- if (H5FD_onion_whole_history_decode(buf, &whs_out) != hdr_out.whole_history_size)
+ if (H5FD__onion_history_decode(buf, &history_out) != hdr_out.history_size)
TEST_ERROR;
- if (whs_out.n_revisions != 2)
+ if (history_out.n_revisions != 2)
TEST_ERROR;
- whs_out.record_pointer_list = HDcalloc(whs_out.n_revisions, sizeof(H5FD_onion_record_pointer_t));
- if (NULL == whs_out.record_pointer_list)
+ history_out.record_locs = HDcalloc(history_out.n_revisions, sizeof(H5FD_onion_record_loc_t));
+ if (NULL == history_out.record_locs)
TEST_ERROR;
- if (H5FD_onion_whole_history_decode(buf, &whs_out) != hdr_out.whole_history_size)
+ if (H5FD__onion_history_decode(buf, &history_out) != hdr_out.history_size)
TEST_ERROR;
HDfree(buf);
buf = NULL;
- for (i = 0; i < whs_out.n_revisions; i++) {
- H5FD_onion_record_pointer_t *rr_p = &whs_out.record_pointer_list[i];
- if (rr_p->phys_addr & ((1 << 5) - 1)) /* 5::PAGE_SIZE_5 */
+ for (i = 0; i < history_out.n_revisions; i++) {
+ H5FD_onion_record_loc_t *rloc = &history_out.record_locs[i];
+ if (rloc->phys_addr & ((1 << 5) - 1)) /* 5::PAGE_SIZE_5 */
TEST_ERROR;
/* TODO: check phys_addr of each page entry? */
}
- HDfree(whs_out.record_pointer_list);
- whs_out.record_pointer_list = NULL;
+ HDfree(history_out.record_locs);
+ history_out.record_locs = NULL;
if (H5FDclose(file) < 0)
TEST_ERROR;
@@ -2823,7 +2822,7 @@ error:
onion_filepaths_destroy(paths);
}
- HDfree(whs_out.record_pointer_list);
+ HDfree(history_out.record_locs);
HDfree(buf);
if (file != NULL)
@@ -4631,8 +4630,8 @@ main(void)
nerrors -= test_revision_index_to_archival_index();
nerrors -= test_fapl();
nerrors -= test_header_encode_decode();
- nerrors -= test_whole_history_encode_decode_empty();
- nerrors -= test_whole_history_encode_decode();
+ nerrors -= test_history_encode_decode_empty();
+ nerrors -= test_history_encode_decode();
nerrors -= test_revision_record_encode_decode();
nerrors -= test_create_oniontarget(FALSE, FALSE);
nerrors -= test_create_oniontarget(TRUE, FALSE);