summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMohamad Chaarawi <chaarawi@hdfgroup.org>2013-06-14 00:30:20 (GMT)
committerMohamad Chaarawi <chaarawi@hdfgroup.org>2013-06-14 00:30:20 (GMT)
commit373038013ea82651f9fe587a0439cab710ede0b8 (patch)
treee61a32d511c5c6c3f56fbfccf0840ea244c2a308 /src
parent07ccc1ab5a7c1de2b2a49ff1890ee8153663a47e (diff)
downloadhdf5-373038013ea82651f9fe587a0439cab710ede0b8.zip
hdf5-373038013ea82651f9fe587a0439cab710ede0b8.tar.gz
hdf5-373038013ea82651f9fe587a0439cab710ede0b8.tar.bz2
[svn-r23769] add property to indicate append
add a new version of checksum algorithm to correctly save the state other updates...
Diffstat (limited to 'src')
-rw-r--r--src/H5Pdxpl.c16
-rw-r--r--src/H5Sprivate.h2
-rw-r--r--src/H5Sselect.c75
-rw-r--r--src/H5VLiod.c53
-rw-r--r--src/H5VLiod.h3
-rw-r--r--src/H5VLiod_client.c14
-rw-r--r--src/H5VLiod_client.h4
-rw-r--r--src/H5VLiod_server.c19
-rw-r--r--src/H5checksum.c169
-rw-r--r--src/H5private.h1
-rw-r--r--src/H5public.h9
11 files changed, 351 insertions, 14 deletions
diff --git a/src/H5Pdxpl.c b/src/H5Pdxpl.c
index e5578f9..146ae96 100644
--- a/src/H5Pdxpl.c
+++ b/src/H5Pdxpl.c
@@ -48,6 +48,7 @@
/****************/
#ifdef H5_HAVE_EFF
+
#define H5D_XFER_INJECT_BAD_CHECKSUM_SIZE sizeof(hbool_t)
#define H5D_XFER_INJECT_BAD_CHECKSUM_DEF FALSE
#define H5D_XFER_INJECT_BAD_CHECKSUM_ENC H5P__encode_hbool_t
@@ -57,6 +58,12 @@
#define H5D_XFER_CHECKSUM_DEF 0
#define H5D_XFER_CHECKSUM_ENC H5P__encode_unsigned
#define H5D_XFER_CHECKSUM_DEC H5P__decode_unsigned
+
+#define H5D_XFER_APPEND_ONLY_SIZE sizeof(hbool_t)
+#define H5D_XFER_APPEND_ONLY_DEF FALSE
+#define H5D_XFER_APPEND_ONLY_ENC H5P__encode_hbool_t
+#define H5D_XFER_APPEND_ONLY_DEC H5P__decode_hbool_t
+
#endif /* H5_HAVE_EFF */
/* ======== Data transfer properties ======== */
@@ -252,6 +259,7 @@ const H5P_libclass_t H5P_CLS_DXFR[1] = {{
#ifdef H5_HAVE_EFF
static const hbool_t H5D_def_inject_bad_checksum_g = H5D_XFER_INJECT_BAD_CHECKSUM_DEF;
static const uint32_t H5D_def_checksum_g = H5D_XFER_CHECKSUM_DEF;
+static const hbool_t H5D_def_append_only_g = H5D_XFER_APPEND_ONLY_DEF;
#endif /* H5_HAVE_EFF */
/* Property value defaults */
@@ -307,6 +315,7 @@ H5P__dxfr_reg_prop(H5P_genclass_t *pclass)
FUNC_ENTER_STATIC
#ifdef H5_HAVE_EFF
+
if(H5P_register_real(pclass, H5D_XFER_INJECT_BAD_CHECKSUM_NAME, H5D_XFER_INJECT_BAD_CHECKSUM_SIZE,
&H5D_def_inject_bad_checksum_g,
NULL, NULL, NULL, H5D_XFER_INJECT_BAD_CHECKSUM_ENC, H5D_XFER_INJECT_BAD_CHECKSUM_DEC,
@@ -318,6 +327,13 @@ H5P__dxfr_reg_prop(H5P_genclass_t *pclass)
NULL, NULL, NULL, H5D_XFER_CHECKSUM_ENC, H5D_XFER_CHECKSUM_DEC,
NULL, NULL, NULL, NULL) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
+ if(H5P_register_real(pclass, H5D_XFER_APPEND_ONLY_NAME, H5D_XFER_APPEND_ONLY_SIZE,
+ &H5D_def_append_only_g,
+ NULL, NULL, NULL, H5D_XFER_APPEND_ONLY_ENC, H5D_XFER_APPEND_ONLY_DEC,
+ NULL, NULL, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTINSERT, FAIL, "can't insert property into class")
+
#endif /* H5_HAVE_EFF */
/* Register the max. temp buffer size property */
diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h
index 63b31bc..34fc07f 100644
--- a/src/H5Sprivate.h
+++ b/src/H5Sprivate.h
@@ -272,6 +272,8 @@ H5_DLL H5S_t *H5S_decode(const unsigned char *buf);
H5_DLL herr_t H5S_get_offsets(const H5S_t *space, size_t elmt_size, size_t nelmts,
hsize_t **_off, size_t **_len, size_t *_num_entries);
+H5_DLL uint32_t H5S_checksum(const void *buf, size_t elmt_size, size_t nelmts,
+ const H5S_t *space);
#ifdef H5_HAVE_PARALLEL
/* Global vars whose value comes from environment variable */
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index 23f87b1..1d6c63d 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -2143,3 +2143,78 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_get_offsets() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5S_checksum
+ *
+ * Purpose: Computes a checksum for a buffer with a dataspace
+ * selection using the HDF5 fletcher checksume routines.
+ *
+ * Return: Returns a 32-bit value. Every bit of the key affects every bit of
+ * the return value. Two keys differing by one or two bits will have
+ * totally different hash values.
+ *
+ * Programmer: Mohamad Chaarawi
+ * June 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+uint32_t
+H5S_checksum(const void *buf, size_t elmt_size, size_t nelmts, const H5S_t *space)
+{
+ hsize_t _off[H5D_IO_VECTOR_SIZE]; /* Array to store sequence offsets in memory */
+ hsize_t *off = NULL; /* Pointer to sequence offsets in memory */
+ size_t _len[H5D_IO_VECTOR_SIZE]; /* Array to store sequence lengths in memory */
+ size_t *len = NULL; /* Pointer to sequence lengths in memory */
+ H5S_sel_iter_t iter; /* Memory selection iteration info */
+ hbool_t iter_init = 0; /* Memory selection iteration info has been initialized */
+ size_t nseq; /* Number of sequences generated */
+ uint32_t ret_value = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ len = _len;
+ off = _off;
+
+ /* Check for only one element in selection */
+ if(nelmts == 1) {
+ size_t buf_size = elmt_size * nelmts;
+
+ if(H5S_SELECT_OFFSET(space, off) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, 0, "can't retrieve memory selection offset");
+
+ ret_value = H5_checksum_lookup3(buf, buf_size, ret_value);
+ } /* end if */
+ else {
+ size_t nelem; /* Number of elements used in sequences */
+ size_t i;
+
+ /* Initialize iterator */
+ if(H5S_select_iter_init(&iter, space, elmt_size) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, 0, "unable to initialize selection iterator")
+ iter_init = 1;
+
+ nseq = 0;
+
+ /* Loop, until all bytes are processed */
+ while(nelmts > 0) {
+ /* Get sequences for selection */
+ if(H5S_SELECT_GET_SEQ_LIST(space, 0, &iter, H5D_IO_VECTOR_SIZE, nelmts, &nseq,
+ &nelem, off, len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, 0, "sequence length generation failed");
+
+ for(i=0 ; i<nseq ; i++) {
+ ret_value = H5_checksum_lookup3(&((char *)buf)[0]+off[i], len[i], ret_value);
+ }
+ nelmts -= nelem;
+ } /* end while */
+ } /* end else */
+
+done:
+ /* Release memory selection iterator */
+ if(iter_init)
+ if(H5S_SELECT_ITER_RELEASE(&iter) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, 0, "unable to release selection iterator")
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_checksum */
diff --git a/src/H5VLiod.c b/src/H5VLiod.c
index a8562e9..d479676 100644
--- a/src/H5VLiod.c
+++ b/src/H5VLiod.c
@@ -683,6 +683,48 @@ done:
FUNC_LEAVE_API(ret_value)
} /* end H5Pget_dxpl_inject_bad_checksum() */
+herr_t
+H5Pset_dxpl_append_only(hid_t dxpl_id, hbool_t flag)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+
+ if(dxpl_id == H5P_DEFAULT)
+ HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "can't set values in default property list")
+
+ /* Check arguments */
+ if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
+
+ /* Set the transfer mode */
+ if(H5P_set(plist, H5D_XFER_APPEND_ONLY_NAME, &flag) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pset_dxpl_append_only() */
+
+herr_t
+H5Pget_dxpl_append_only(hid_t dxpl_id, hbool_t *flag/*out*/)
+{
+ H5P_genplist_t *plist; /* Property list pointer */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+
+ if(NULL == (plist = H5P_object_verify(dxpl_id, H5P_DATASET_XFER)))
+ HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a dxpl")
+
+ /* Get the transfer mode */
+ if(flag)
+ if(H5P_get(plist, H5D_XFER_APPEND_ONLY_NAME, flag) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to get value")
+
+done:
+ FUNC_LEAVE_API(ret_value)
+} /* end H5Pget_dxpl_append_only() */
/*-------------------------------------------------------------------------
@@ -2304,12 +2346,15 @@ H5VL_iod_dataset_read(void *_dset, hid_t mem_type_id, hid_t mem_space_id,
/* setup info struct for I/O request.
This is to manage the I/O operation once the wait is called. */
- if(NULL == (info = (H5VL_iod_io_info_t *)H5MM_malloc(sizeof(H5VL_iod_io_info_t))))
+ if(NULL == (info = (H5VL_iod_io_info_t *)H5MM_calloc(sizeof(H5VL_iod_io_info_t))))
HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a request");
info->status = status;
info->bulk_handle = bulk_handle;
info->buf_ptr = buf;
- info->buf_size = buf_size;
+ info->nelmts = nelmts;
+ info->type_size = type_size;
+ if(NULL == (info->space = H5S_copy(mem_space, FALSE, TRUE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace")
/* Get async request for operation */
if(do_async) {
@@ -2451,7 +2496,7 @@ H5VL_iod_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id,
buf_size = nelmts * type_size;
/* calculate a checksum for the data */
- internal_cs = H5_checksum_fletcher32(buf, buf_size);
+ internal_cs = H5S_checksum(buf, type_size, nelmts, mem_space);
/* Verify the checksum value if the dxpl contains a user defined checksum */
if(H5P_DATASET_XFER_DEFAULT != dxpl_id) {
@@ -2552,7 +2597,7 @@ H5VL_iod_dataset_write(void *_dset, hid_t mem_type_id, hid_t mem_space_id,
/* setup info struct for I/O request
This is to manage the I/O operation once the wait is called. */
- if(NULL == (info = (H5VL_iod_io_info_t *)H5MM_malloc(sizeof(H5VL_iod_io_info_t))))
+ if(NULL == (info = (H5VL_iod_io_info_t *)H5MM_calloc(sizeof(H5VL_iod_io_info_t))))
HGOTO_ERROR(H5E_DATASET, H5E_NOSPACE, FAIL, "can't allocate a request");
info->status = status;
info->bulk_handle = bulk_handle;
diff --git a/src/H5VLiod.h b/src/H5VLiod.h
index 773f51b..a813f59 100644
--- a/src/H5VLiod.h
+++ b/src/H5VLiod.h
@@ -51,6 +51,7 @@ extern "C" {
#define H5D_XFER_INJECT_BAD_CHECKSUM_NAME "inject_bad_checksum"
#define H5D_XFER_CHECKSUM_NAME "checksum"
+#define H5D_XFER_APPEND_ONLY_NAME "append_only"
H5_DLL H5VL_class_t *H5VL_iod_init(void);
H5_DLL herr_t H5Pset_fapl_iod(hid_t fapl_id, MPI_Comm comm, MPI_Info info);
@@ -61,6 +62,8 @@ H5_DLL herr_t H5Pset_dxpl_checksum(hid_t dxpl_id, uint32_t flag);
H5_DLL herr_t H5Pget_dxpl_checksum(hid_t dxpl_id, uint32_t *flag);
H5_DLL herr_t H5Pset_dxpl_inject_bad_checksum(hid_t dxpl_id, hbool_t flag);
H5_DLL herr_t H5Pget_dxpl_inject_bad_checksum(hid_t dxpl_id, hbool_t *flag);
+H5_DLL herr_t H5Pset_dxpl_append_only(hid_t dxpl_id, hbool_t flag);
+H5_DLL herr_t H5Pget_dxpl_append_only(hid_t dxpl_id, hbool_t *flag);
#endif /* H5_HAVE_EFF */
#ifdef __cplusplus
diff --git a/src/H5VLiod_client.c b/src/H5VLiod_client.c
index 022f5ab..a34521c 100644
--- a/src/H5VLiod_client.c
+++ b/src/H5VLiod_client.c
@@ -26,6 +26,7 @@
#include "H5Iprivate.h" /* IDs */
#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
+#include "H5Sprivate.h" /* Dataspaces */
#include "H5VLprivate.h" /* VOL plugins */
#include "H5VLiod.h" /* Iod VOL plugin */
#include "H5VLiod_common.h"
@@ -346,7 +347,7 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req)
req->state = H5VL_IOD_COMPLETED;
}
if(HG_DSET_WRITE == req->type && SUCCEED != *((int *)info->status)) {
- fprintf(stderr, "write failed %d\n", *((int *)info->status));
+ fprintf(stderr, "Errrr! Dataset Write Failure Reported from Server\n");
req->status = H5AO_FAILED;
req->state = H5VL_IOD_COMPLETED;
}
@@ -354,7 +355,7 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req)
H5VL_iod_read_status_t *read_status = (H5VL_iod_read_status_t *)info->status;
if(SUCCEED != read_status->ret) {
- fprintf(stderr, "read failed\n");
+ fprintf(stderr, "Errrr! Dataset Read Failure Reported from Server\n");
req->status = H5AO_FAILED;
req->state = H5VL_IOD_COMPLETED;
}
@@ -362,15 +363,18 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req)
uint32_t internal_cs;
/* calculate a checksum for the data recieved */
- internal_cs = H5_checksum_fletcher32(info->buf_ptr, info->buf_size);
+ internal_cs = H5S_checksum(info->buf_ptr, info->type_size,
+ info->nelmts, info->space);
/* verify data integrity */
if(internal_cs != read_status->cs) {
- fprintf(stderr, "Errrrr! Data integrity failure (expecting %u got %u).\n",
+ fprintf(stderr, "Errrrr! Dataset Read integrity failure (expecting %u got %u).\n",
read_status->cs, internal_cs);
req->status = H5AO_FAILED;
req->state = H5VL_IOD_COMPLETED;
}
+ if(info->space && H5S_close(info->space) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
}
}
@@ -394,7 +398,7 @@ H5VL_iod_request_complete(H5VL_iod_file_t *file, H5VL_iod_request_t *req)
req->state = H5VL_IOD_COMPLETED;
}
if(SUCCEED != *((int *)info->status)) {
- fprintf(stderr, "write failed %d\n", *((int *)info->status));
+ fprintf(stderr, "Attribute I/O Failure Reported from Server\n");
req->status = H5AO_FAILED;
req->state = H5VL_IOD_COMPLETED;
}
diff --git a/src/H5VLiod_client.h b/src/H5VLiod_client.h
index 1722690..9e10328 100644
--- a/src/H5VLiod_client.h
+++ b/src/H5VLiod_client.h
@@ -196,7 +196,9 @@ typedef struct H5VL_iod_io_info_t {
void *status;
hg_bulk_t *bulk_handle;
void *buf_ptr;
- size_t buf_size;
+ size_t nelmts;
+ size_t type_size;
+ struct H5S_t *space;
} H5VL_iod_io_info_t;
H5_DLL herr_t H5VL_iod_request_delete(H5VL_iod_file_t *file, H5VL_iod_request_t *request);
diff --git a/src/H5VLiod_server.c b/src/H5VLiod_server.c
index dfd3516..63c60c1 100644
--- a/src/H5VLiod_server.c
+++ b/src/H5VLiod_server.c
@@ -3368,11 +3368,14 @@ H5VL_iod_server_dset_read_cb(AXE_engine_t UNUSED axe_engine,
if(H5Tconvert(src_id, dst_id, nelmts, buf, NULL, dxpl_id) < 0)
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "data type conversion failed");
- cs = H5_checksum_fletcher32(buf, size);
+ /* calculate a checksum for the data to be sent */
+ cs = H5_checksum_lookup3(buf, size, 0);
+
+ /* MSC - check if client requested to corrupt data */
if(dxpl_id != H5P_DEFAULT && H5Pget_dxpl_inject_bad_checksum(dxpl_id, &flag) < 0)
HGOTO_ERROR(H5E_SYM, H5E_READERROR, FAIL, "can't read property list");
if(flag) {
- fprintf(stderr, "Injecting a bad data value to generate a bad checksum \n");
+ fprintf(stderr, "Injecting a bad data value to cause corruption \n");
buf_ptr[0] = 10;
}
}
@@ -3391,7 +3394,7 @@ done:
output.ret = ret_value;
output.cs = cs;
- fprintf(stderr, "Done with dset read, sending response to client\n");
+ fprintf(stderr, "Done with dset read, checksum %u, sending response to client\n", cs);
if(HG_SUCCESS != HG_Handler_start_output(op_data->hg_handle, &output))
HDONE_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "can't send result of write to client");
@@ -3444,6 +3447,7 @@ H5VL_iod_server_dset_write_cb(AXE_engine_t UNUSED axe_engine,
size_t size, buf_size, src_size, dst_size;
void *buf;
size_t nelmts;
+ hbool_t flag = FALSE;
na_addr_t source = HG_Handler_get_addr(op_data->hg_handle);
herr_t ret_value = SUCCEED;
@@ -3495,11 +3499,18 @@ H5VL_iod_server_dset_write_cb(AXE_engine_t UNUSED axe_engine,
if(HG_SUCCESS != HG_Bulk_block_handle_free(bulk_block_handle))
HGOTO_ERROR(H5E_SYM, H5E_WRITEERROR, FAIL, "can't free bds block handle");
+ /* MSC - check if client requested to corrupt data */
+ if(dxpl_id != H5P_DEFAULT && H5Pget_dxpl_inject_bad_checksum(dxpl_id, &flag) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_READERROR, FAIL, "can't read property list");
+ if(flag) {
+ ((int *)buf)[0] = 10;
+ }
+
/* If client specified a checksum, verify it */
if(dxpl_id != H5P_DEFAULT && H5Pget_dxpl_checksum(dxpl_id, &data_cs) < 0)
HGOTO_ERROR(H5E_SYM, H5E_READERROR, FAIL, "can't read property list");
if(data_cs != 0) {
- cs = H5_checksum_fletcher32(buf, size);
+ cs = H5_checksum_lookup3(buf, size, 0);
if(cs != data_cs) {
fprintf(stderr, "Errrr.. Network transfer Data corruption. expecting %u, got %u\n",
data_cs, cs);
diff --git a/src/H5checksum.c b/src/H5checksum.c
index ec8b2b0..de1e491 100644
--- a/src/H5checksum.c
+++ b/src/H5checksum.c
@@ -430,6 +430,175 @@ done:
FUNC_LEAVE_NOAPI(c)
} /* end H5_checksum_lookup3() */
+uint32_t
+H5_checksum_lookup4(const void *key, size_t length, H5_checksum_seed_t *cs)
+{
+ const uint8_t *k = (const uint8_t *)key;
+ uint32_t position = 0;
+ uint32_t a, b, c; /* internal state */
+ int pos = 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOERR
+
+ /* Sanity check */
+ HDassert(key);
+ HDassert(length > 0);
+
+ /* Set up the internal state */
+ if(cs) {
+ if(!cs->a && !cs->b && !cs->c) {
+ a = b = c = 0xdeadbeef + ((uint32_t)cs->total_length);
+ /* Compute new State */
+ cs->state = 12 - (length % 12);
+ }
+ else {
+ a = cs->a;
+ b = cs->b;
+ c = cs->c;
+
+ /* determine position to start up on */
+ if(cs->state) {
+ position = 12 - cs->state + 1;
+ }
+
+ /* Compute new State */
+ cs->state = cs->state - (length % 12);
+ if(cs->state < 0) {
+ H5_lookup3_mix(a, b, c);
+ cs->state = 12 + cs->state;
+ }
+
+ /* Move towards mod 12 */
+ switch(position) /* all the case statements fall through */
+ {
+ case 0 :
+ break;
+ case 1 :
+ a+=k[pos++];
+ length --;
+ if(0 == length)
+ break;
+ case 2 :
+ a+=((uint32_t)k[pos++])<<8;
+ length --;
+ if(0 == length)
+ break;
+ case 3 :
+ a+=((uint32_t)k[pos++])<<16;
+ length --;
+ if(0 == length)
+ break;
+ case 4 :
+ a+=((uint32_t)k[pos++])<<24;
+ length --;
+ if(0 == length)
+ break;
+ case 5 :
+ b+=k[pos++];
+ length --;
+ if(0 == length)
+ break;
+ case 6 :
+ b+=((uint32_t)k[pos++])<<8;
+ length --;
+ if(0 == length)
+ break;
+ case 7 :
+ b+=((uint32_t)k[pos++])<<16;
+ length --;
+ if(0 == length)
+ break;
+ case 8 :
+ b+=((uint32_t)k[pos++])<<24;
+ length --;
+ if(0 == length)
+ break;
+ case 9 :
+ c+=k[pos++];
+ length --;
+ if(0 == length)
+ break;
+ case 10:
+ c+=((uint32_t)k[pos++])<<8;
+ length --;
+ if(0 == length)
+ break;
+ case 11:
+ c+=((uint32_t)k[pos++])<<16;
+ length --;
+ if(0 == length)
+ break;
+ case 12:
+ c+=((uint32_t)k[pos++])<<24;
+ length --;
+ H5_lookup3_mix(a, b, c);
+ break;
+ }
+ }
+ /* capture internal state if we are done at this stage */
+ if(0 == length) {
+ cs->a = a;
+ cs->b = b;
+ cs->c = c;
+ H5_lookup3_final(a, b, c);
+ goto done;
+ }
+ }
+ else
+ a = b = c = 0xdeadbeef + ((uint32_t)length);
+
+ /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+ while (length > 12)
+ {
+ a += k[0+pos];
+ a += ((uint32_t)k[1+pos])<<8;
+ a += ((uint32_t)k[2+pos])<<16;
+ a += ((uint32_t)k[3+pos])<<24;
+ b += k[4+pos];
+ b += ((uint32_t)k[5+pos])<<8;
+ b += ((uint32_t)k[6+pos])<<16;
+ b += ((uint32_t)k[7+pos])<<24;
+ c += k[8+pos];
+ c += ((uint32_t)k[9+pos])<<8;
+ c += ((uint32_t)k[10+pos])<<16;
+ c += ((uint32_t)k[11+pos])<<24;
+ H5_lookup3_mix(a, b, c);
+ length -= 12;
+ k += 12;
+ }
+
+ /*-------------------------------- last block: affect all 32 bits of (c) */
+ switch(length) /* all the case statements fall through */
+ {
+ case 12: c+=((uint32_t)k[11+pos])<<24;
+ case 11: c+=((uint32_t)k[10+pos])<<16;
+ case 10: c+=((uint32_t)k[9+pos])<<8;
+ case 9 : c+=k[8+pos];
+ case 8 : b+=((uint32_t)k[7+pos])<<24;
+ case 7 : b+=((uint32_t)k[6+pos])<<16;
+ case 6 : b+=((uint32_t)k[5+pos])<<8;
+ case 5 : b+=k[4+pos];
+ case 4 : a+=((uint32_t)k[3+pos])<<24;
+ case 3 : a+=((uint32_t)k[2+pos])<<16;
+ case 2 : a+=((uint32_t)k[1+pos])<<8;
+ case 1 : a+=k[pos];
+ break;
+ case 0 : goto done;
+ }
+
+ /* capture internal state */
+ if(cs) {
+ cs->a = a;
+ cs->b = b;
+ cs->c = c;
+ }
+
+ H5_lookup3_final(a, b, c);
+
+done:
+ FUNC_LEAVE_NOAPI(c)
+} /* end H5_checksum_lookup3() */
+
/*-------------------------------------------------------------------------
* Function: H5_checksum_metadata
diff --git a/src/H5private.h b/src/H5private.h
index 46c02e7..42ea519 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -2361,6 +2361,7 @@ H5_DLL int H5Z_term_interface(void);
H5_DLL uint32_t H5_checksum_fletcher32(const void *data, size_t len);
H5_DLL uint32_t H5_checksum_crc(const void *data, size_t len);
H5_DLL uint32_t H5_checksum_lookup3(const void *data, size_t len, uint32_t initval);
+H5_DLL uint32_t H5_checksum_lookup4(const void *data, size_t len, H5_checksum_seed_t *cs);
H5_DLL uint32_t H5_checksum_metadata(const void *data, size_t len, uint32_t initval);
H5_DLL uint32_t H5_hash_string(const char *str);
diff --git a/src/H5public.h b/src/H5public.h
index deb4587..d0f3e78 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -301,6 +301,15 @@ typedef struct H5_ih_info_t {
hsize_t heap_size;
} H5_ih_info_t;
+/* Internal Checksum state */
+typedef struct H5_checksum_seed_t {
+ uint32_t a;
+ uint32_t b;
+ uint32_t c;
+ int32_t state;
+ size_t total_length;
+} H5_checksum_seed_t;
+
/* Functions in H5.c */
H5_DLL herr_t H5open(void);
H5_DLL herr_t H5close(void);