summaryrefslogtreecommitdiffstats
path: root/test/tsohm.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/tsohm.c')
-rw-r--r--test/tsohm.c324
1 files changed, 323 insertions, 1 deletions
diff --git a/test/tsohm.c b/test/tsohm.c
index 9274ed4..6585f0e 100644
--- a/test/tsohm.c
+++ b/test/tsohm.c
@@ -142,6 +142,11 @@ typedef struct size2_helper_struct {
h5_stat_size_t attrs2;
} size2_helper_struct;
+/* Number of distinct messages for the sohm_delete test */
+#define DELETE_NUM_MESGS 7
+#define HALF_DELETE_NUM_MESGS 3
+#define DELETE_DIMS {1,1,1,1,1,1,1}
+
/****************************************************************
**
** check_fcpl_values(): Helper function for test_sohm_fcpl.
@@ -2429,6 +2434,320 @@ static void test_sohm_size2(int close_reopen)
+/*-------------------------------------------------------------------------
+ * Function: delete_helper_write
+ *
+ * Purpose: Creates a dataset and attribute in file FILE_ID using value X
+ * in the DSPACE_ID and DCPL_ID arrays.
+ *
+ * Programmer: James Laird
+ * Tuesday, December 19, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void delete_helper_write(hid_t file_id, hid_t *dspace_id, hid_t *dcpl_id, int x)
+{
+ hid_t dset_id = -1;
+ hid_t attr_id = -1;
+ char wdata;
+ herr_t ret;
+
+ /* Create dataset */
+ dset_id = H5Dcreate(file_id, DSETNAME[x], H5T_NATIVE_CHAR, dspace_id[x], dcpl_id[x]);
+ CHECK_I(dset_id, "H5Dcreate");
+
+ /* Write data to dataset */
+ wdata = x + 'a';
+ ret = H5Dwrite(dset_id, H5T_NATIVE_CHAR, dspace_id[x], dspace_id[x], H5P_DEFAULT, &wdata);
+ CHECK_I(ret, "H5Dwrite");
+
+ /* Create an attribute on the dataset. */
+ attr_id = H5Acreate(dset_id, "attr_name", H5T_NATIVE_CHAR, dspace_id[x], H5P_DEFAULT);
+ CHECK_I(attr_id, "H5Acreate");
+
+ /* Write to attribute */
+ ret = H5Awrite(attr_id, H5T_NATIVE_CHAR, &wdata);
+ CHECK_I(ret, "H5Awrite");
+
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+}
+
+/*-------------------------------------------------------------------------
+ * Function: delete_helper_read
+ *
+ * Purpose: Checks the value of the dataset and attribute created by
+ * delete_helper_write.
+ *
+ * Programmer: James Laird
+ * Tuesday, December 19, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void delete_helper_read(hid_t file_id, hid_t *dspace_id, int x)
+{
+ hid_t dset_id = -1;
+ hid_t attr_id = -1;
+ char rdata;
+ herr_t ret;
+
+ /* Open dataset */
+ dset_id = H5Dopen(file_id, DSETNAME[x]);
+ CHECK_I(dset_id, "H5Dcreate");
+
+ /* Read */
+ rdata = '\0';
+ ret = H5Dread(dset_id, H5T_NATIVE_CHAR, dspace_id[x], dspace_id[x], H5P_DEFAULT, &rdata);
+ CHECK_I(ret, "H5Dread");
+ VERIFY(rdata, (x + 'a'), "H5Dread");
+
+ /* Open attribute */
+ attr_id = H5Aopen_name(dset_id, "attr_name");
+ CHECK_I(attr_id, "H5Aopen");
+
+ /* Read */
+ rdata = '\0';
+ ret = H5Aread(attr_id, H5T_NATIVE_CHAR, &rdata);
+ CHECK_I(ret, "H5Dread");
+ VERIFY(rdata, (x + 'a'), "H5Dread");
+
+ /* Cleanup */
+ ret = H5Aclose(attr_id);
+ CHECK_I(ret, "H5Aclose");
+ ret = H5Dclose(dset_id);
+ CHECK_I(ret, "H5Dclose");
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: delete_helper
+ *
+ * Purpose: Creates some shared messages, deletes them, and creates some
+ * more messages. The second batch of messages should use the
+ * space freed by the first batch, so should be about the same
+ * size as a file that never had the first batch of messages
+ * created.
+ *
+ * FCPL_ID is the file creation property list to use.
+ * DSPACE_ID and DCPL_ID are arrays of different dataspaces
+ * and property lists with filter pipelines used to create the
+ * messages.
+ *
+ * Programmer: James Laird
+ * Tuesday, December 19, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void delete_helper(hid_t fcpl_id, hid_t *dspace_id, hid_t *dcpl_id)
+{
+ hid_t file_id=-1;
+ int x;
+ h5_stat_size_t norm_filesize;
+ h5_stat_size_t deleted_filesize;
+ herr_t ret;
+
+ /* Get the size of a "normal" file with no deleted messages */
+ file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fcreate");
+
+ /* Create batch of messages in the file starting at message 2 */
+ for(x=HALF_DELETE_NUM_MESGS; x<DELETE_NUM_MESGS; ++x) {
+ delete_helper_write(file_id, dspace_id, dcpl_id, x);
+ }
+
+ /* Check that messages can be read */
+ for(x=HALF_DELETE_NUM_MESGS; x<DELETE_NUM_MESGS; ++x) {
+ delete_helper_read(file_id, dspace_id, x);
+ }
+
+ /* Close file and get filesize */
+ ret = H5Fclose(file_id);
+ CHECK_I(ret, "H5Fclose");
+ norm_filesize = h5_get_file_size(FILENAME);
+
+
+ /* Create a new file with messages 0 to (HALF_DELETE_NUM_MESGS - 1) */
+ file_id = H5Fcreate(FILENAME, H5F_ACC_TRUNC, fcpl_id, H5P_DEFAULT);
+ CHECK_I(file_id, "H5Fcreate");
+
+ for(x=0; x<HALF_DELETE_NUM_MESGS; ++x) {
+ delete_helper_write(file_id, dspace_id, dcpl_id, x);
+ }
+
+ /* Verify each dataset, then delete it (which should delete
+ * its shared messages as well
+ */
+ for(x=0; x<HALF_DELETE_NUM_MESGS; ++x) {
+ delete_helper_read(file_id, dspace_id, x);
+ ret = H5Ldelete(file_id, DSETNAME[x], H5P_DEFAULT);
+ CHECK_I(ret, "H5Ldelete");
+ }
+
+ /* The file is now empty. Write and verify the second batch of messages
+ * again.
+ */
+ for(x=HALF_DELETE_NUM_MESGS; x<DELETE_NUM_MESGS; ++x) {
+ delete_helper_write(file_id, dspace_id, dcpl_id, x);
+ }
+ for(x=HALF_DELETE_NUM_MESGS; x<DELETE_NUM_MESGS; ++x) {
+ delete_helper_read(file_id, dspace_id, x);
+ }
+
+ /* Close file and get filesize */
+ ret = H5Fclose(file_id);
+ CHECK_I(ret, "H5Fclose");
+ deleted_filesize = h5_get_file_size(FILENAME);
+
+ /* The two filesizes should be almost the same */
+ if(norm_filesize > deleted_filesize * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+ if(deleted_filesize > norm_filesize * OVERHEAD_ALLOWED)
+ VERIFY(0, 1, "h5_get_file_size");
+
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_delete
+ *
+ * Purpose: Tests shared object header message deletion.
+ *
+ * Creates lots of shared messages, then ensures that they
+ * can be deleted without corrupting the remaining messages.
+ * Also checks that indexes convert from B-trees back into
+ * lists.
+ *
+ * Programmer: James Laird
+ * Tuesday, December 19, 2006
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void test_sohm_delete()
+{
+ hid_t fcpl_id;
+ /* We'll use dataspaces, filter pipelines, and attributes for this
+ * test. Create a number of distinct messages of each type.
+ */
+ hid_t dspace_id[DELETE_NUM_MESGS] = {0};
+ hid_t dcpl_id[DELETE_NUM_MESGS] = {0};
+ int x;
+ hsize_t dims[] = DELETE_DIMS;
+ herr_t ret;
+
+ /* Create a number of different dataspaces.
+ * For simplicity, each dataspace has only one element.
+ */
+ for(x=0; x<DELETE_NUM_MESGS; ++x) {
+ dspace_id[x] = H5Screate_simple(x + 1, dims, dims);
+ CHECK_I(dspace_id[x], "H5Screate_simple");
+ }
+
+ /* Create a number of different filter pipelines. */
+ dcpl_id[0] = H5Pcreate(H5P_DATASET_CREATE);
+ CHECK_I(dcpl_id[0], "H5Pcreate");
+
+ ret = H5Pset_chunk(dcpl_id[0], 1, dims);
+ CHECK_I(ret, "H5Pset_chunk");
+ ret = H5Pset_shuffle(dcpl_id[0]);
+ CHECK_I(ret, "H5Pset_shuffle");
+
+ for(x=1; x<DELETE_NUM_MESGS; x+=2) {
+ dcpl_id[x] = H5Pcopy(dcpl_id[x-1]);
+ CHECK_I(dcpl_id[x], "H5Pcopy");
+ ret = H5Pset_chunk(dcpl_id[x], x+1, dims);
+ CHECK_I(ret, "H5Pset_chunk");
+ ret = H5Pset_deflate(dcpl_id[x], 1);
+ CHECK_I(ret, "H5Pset_deflate");
+
+ dcpl_id[x+1] = H5Pcopy(dcpl_id[x]);
+ CHECK_I(dcpl_id[x+1], "H5Pcopy");
+ ret = H5Pset_chunk(dcpl_id[x+1], x+2, dims);
+ CHECK_I(ret, "H5Pset_chunk");
+ ret = H5Pset_shuffle(dcpl_id[x+1]);
+ CHECK_I(ret, "H5Pset_shuffle");
+ }
+
+ /* Create an fcpl where all messages are shared in the same index */
+ fcpl_id = H5Pcreate(H5P_FILE_CREATE);
+ CHECK_I(fcpl_id, "H5Pcreate");
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 1);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_ALL_FLAG, 16);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+
+
+ /* Use big list indexes */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 4 * DELETE_NUM_MESGS, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ /* Test that messages can be created and deleted properly */
+ delete_helper(fcpl_id, dspace_id, dcpl_id);
+
+
+ /* Use B-tree indexes */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ delete_helper(fcpl_id, dspace_id, dcpl_id);
+
+
+ /* Use small list indexes that will convert from lists to B-trees and back */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, HALF_DELETE_NUM_MESGS, HALF_DELETE_NUM_MESGS - 1);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ delete_helper(fcpl_id, dspace_id, dcpl_id);
+
+
+ /* Use two indexes */
+ ret = H5Pset_shared_mesg_nindexes(fcpl_id, 2);
+ CHECK_I(ret, "H5Pset_shared_mesg_nindexes");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 1, H5O_MESG_SDSPACE_FLAG | H5O_MESG_ATTR_FLAG, 16);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+ ret = H5Pset_shared_mesg_index(fcpl_id, 2, H5O_MESG_DTYPE_FLAG, 16);
+ CHECK_I(ret, "H5Pset_shared_mesg_index");
+
+ /* Use big list indexes */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 4 * DELETE_NUM_MESGS, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+
+ /* Use B-tree indexes */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, 0, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ delete_helper(fcpl_id, dspace_id, dcpl_id);
+
+
+ /* Set phase change values so that one index converts to a B-tree and one doesn't */
+ ret = H5Pset_shared_mesg_phase_change(fcpl_id, HALF_DELETE_NUM_MESGS + 1, 0);
+ CHECK_I(ret, "H5Pset_shared_mesg_phase_change");
+
+ delete_helper(fcpl_id, dspace_id, dcpl_id);
+
+ /* Cleanup */
+ ret = H5Pclose(fcpl_id);
+ CHECK_I(ret, "H5Pclose");
+
+ for(x=DELETE_NUM_MESGS - 1; x>=0; --x) {
+ ret = H5Sclose(dspace_id[x]);
+ CHECK_I(ret, "H5Sclose");
+ ret = H5Pclose(dcpl_id[x]);
+ CHECK_I(ret, "H5Pclose");
+ }
+}
+
+
/****************************************************************
**
** test_sohm(): Main Shared Object Header Message testing routine.
@@ -2444,7 +2763,10 @@ test_sohm(void)
test_sohm_size1(); /* Tests the sizes of files with one SOHM */
test_sohm_attrs(); /* Tests shared messages in attributes */
test_sohm_size2(0); /* Tests the sizes of files with multiple SOHMs */
- test_sohm_size2(1); /* Tests the sizes of files with multiple SOHMs */
+ test_sohm_size2(1); /* Tests the sizes of files with multiple
+ * SOHMs, closing and reopening file after
+ * each write. */
+ test_sohm_delete(); /* Test deleting shared messages */
} /* test_sohm() */