diff options
author | kyang2014 <kyang2014@users.noreply.github.com> | 2021-04-30 14:13:03 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-30 14:13:03 (GMT) |
commit | 4042f4c2d4b5bf824fdcfc313d906e466c88ddb7 (patch) | |
tree | ab3536e454d3e0f35cd7d46eb07e9aca0d45fa31 | |
parent | 41ab0ced0b232af9fa0fe196e2e1f29d97566bfe (diff) | |
parent | 16b2b76b263afe59bb001df80b04222471ee9cc1 (diff) | |
download | hdf5-4042f4c2d4b5bf824fdcfc313d906e466c88ddb7.zip hdf5-4042f4c2d4b5bf824fdcfc313d906e466c88ddb7.tar.gz hdf5-4042f4c2d4b5bf824fdcfc313d906e466c88ddb7.tar.bz2 |
Merge pull request #571 from kyang2014/feature/vfd_swmr
Add group attribute tests for VFD SWMR
-rw-r--r-- | test/testvfdswmr.sh.in | 155 | ||||
-rw-r--r-- | test/vfd_swmr_common.c | 4 | ||||
-rw-r--r-- | test/vfd_swmr_group_writer.c | 2847 |
3 files changed, 2858 insertions, 148 deletions
diff --git a/test/testvfdswmr.sh.in b/test/testvfdswmr.sh.in index c64f9de..979f5a9 100644 --- a/test/testvfdswmr.sh.in +++ b/test/testvfdswmr.sh.in @@ -54,17 +54,20 @@ fi BIGSET_n=25 # -n option: # of iterations BIGSET_few_s=20 # -s option: # of datasets (for few_big test) BIGSET_many_s=500 # -s option: # of datasets (for many_small test) -GROUP_n=100 # -n option: # of groups (for vfd_swmr_group_writer.c) +GROUP_n=40 # -n option: # of groups (for group test) +GROUP_attr_n=1 # -n option: # of groups (for group attribute test) + if [[ "$HDF5TestExpress" -eq 0 ]] ; then # Setting for exhaustive run BIGSET_n=50 BIGSET_few_s=40 BIGSET_many_s=1000 GROUP_n=400 + GROUP_attr_n=4 elif [[ "$HDF5TestExpress" -gt 1 ]]; then # Setting for quick run BIGSET_n=10 BIGSET_few_s=10 BIGSET_many_s=100 - GROUP_n=40 + GROUP_n=20 fi ############################################################################### @@ -153,7 +156,7 @@ if [ $rc -ne 0 ] ; then fi all_tests="generator expand shrink expand_shrink sparse vlstr_null vlstr_oob zoo groups attrdset" -all_tests="${all_tests} few_big many_small" +all_tests="${all_tests} groups_attrs os_groups_attrs few_big many_small" tests=${all_tests} if [ $# -gt 0 ]; then @@ -668,7 +671,7 @@ for options in "-p -g -a 10 -v -m -d 10 -c 3 -u 5" "-k -a 20 -v -m -d 5"; do done # -# Make sure that we can create GROUP_n groups (40, 100, or 400 depending on the HDF5TestExpress level) +# Make sure that we can create GROUP_n groups (20, 40, or 400 depending on the HDF5TestExpress level) # while a reader waits for each to appear. # if [ ${do_groups:-no} = yes ]; then @@ -705,6 +708,150 @@ if [ ${do_groups:-no} = yes ]; then rm -f vfd_swmr_group_reader.*.{out,rc} fi +# The group attribute test takes longer. +# So for standard run and quick run, we +# shorten the number of tests. The standard +# run covers all the features we need to +# test. The quick run doesn't cover the +# attribute storage change between dense and +# compact. +# The exhaustive run tries to test a feature +# per test from scratch. +# +grp_attr_list=( + "compact" + "dense" + "compact-del" + "dense-del" + "compact-add-to-dense" + "dense-del-to-compact" + "modify" + "add-vstr" + "remove-vstr" + "modify-vstr" + ) +grp_sub_attr_list=( + "dense-del-to-compact" + "modify" + "remove-vstr" + "modify-vstr" + ) + +grp_short_sub_attr_list=( + "dense" + "modify" + "remove-vstr" + "modify-vstr" + ) + +if [[ "$HDF5TestExpress" -eq 1 ]] ; then #Setting for standard run + grp_attr_list=("${grp_sub_attr_list[@]}") +elif [[ "$HDF5TestExpress" -gt 1 ]] ; then #Setting for quick run + grp_attr_list=("${grp_short_sub_attr_list[@]}") +fi + +for options in ${grp_attr_list[*]}; do + if [ ${do_groups_attrs:-no} = no ]; then + continue + fi + echo launch vfd_swmr_group attribute: $options + catch_out_err_and_rc vfd_swmr_group_writer \ + ../vfd_swmr_group_writer -q -c 1 -n $GROUP_attr_n -a 1 -A $options & + pid_writer=$! + + catch_out_err_and_rc vfd_swmr_group_reader \ + ../vfd_swmr_group_reader -q -c 1 -n $GROUP_attr_n -a 1 -A $options & + pid_reader=$! + + # Wait for the reader to finish before signalling the + # writer to quit: the writer holds the file open so that the + # reader will find the shadow file when it opens + # the .h5 file. + wait $pid_reader + wait $pid_writer + + # Collect exit code of the reader + if [ $(cat vfd_swmr_group_reader.rc) -ne 0 ]; then + echo reader had error + nerrors=$((nerrors + 1)) + fi + + # Collect exit code of the writer + if [ $(cat vfd_swmr_group_writer.rc) -ne 0 ]; then + echo writer had error + nerrors=$((nerrors + 1)) + fi + + # Clean up output files + rm -f vfd_swmr_group_writer.{out,rc} + rm -f vfd_swmr_group_reader.*.{out,rc} +done + +# The following tests are for add/del/modify attributes for +# groups created with the old-style. +# Check https://portal.hdfgroup.org/display/HDF5/Groups for +# the detailed group implementation note. +# The 'compact' and 'compact-del' are the attribute addition +# and deletion tests. Other test names have the same meaning +# as those of the new-style group tests. +# +os_grp_attr_list=( + "compact" + "compact-del" + "modify" + "add-vstr" + "remove-vstr" + "modify-vstr" + ) +os_grp_sub_attr_list=( + "modify" + "remove-vstr" + "modify-vstr" + ) +if [[ "$HDF5TestExpress" -gt 0 ]] ; then #Setting for standard run + os_grp_attr_list=("${os_grp_sub_attr_list[@]}") +fi + +for options in ${os_grp_attr_list[*]}; do + if [ ${do_os_groups_attrs:-no} = no ]; then + continue + fi + echo launch vfd_swmr_group attribute with old-style group: $options + catch_out_err_and_rc vfd_swmr_group_writer \ + ../vfd_swmr_group_writer -q -G -c 1 -n $GROUP_attr_n -a 1 -A $options & + pid_writer=$! + + catch_out_err_and_rc vfd_swmr_group_reader \ + ../vfd_swmr_group_reader -q -G -c 1 -n $GROUP_attr_n -a 1 -A $options & + pid_reader=$! + + # Wait for the reader to finish before signalling the + # writer to quit: the writer holds the file open so that the + # reader will find the shadow file when it opens + # the .h5 file. + wait $pid_reader + wait $pid_writer + + # Collect exit code of the reader + if [ $(cat vfd_swmr_group_reader.rc) -ne 0 ]; then + echo reader had error + nerrors=$((nerrors + 1)) + fi + + # Collect exit code of the writer + if [ $(cat vfd_swmr_group_writer.rc) -ne 0 ]; then + echo writer had error + nerrors=$((nerrors + 1)) + fi + + # Clean up output files + rm -f vfd_swmr_group_writer.{out,rc} + rm -f vfd_swmr_group_reader.*.{out,rc} +done + + + + for options in "-d 1" "-d 1 -F" "-d 2" "-d 2 -F" "-d 1 -V" "-d 1 -M" "-d 1 -V -F" "-d 1 -M -F"; do if [ ${do_many_small:-no} = no ]; then continue diff --git a/test/vfd_swmr_common.c b/test/vfd_swmr_common.c index 68e0b9c..aed9cbe 100644 --- a/test/vfd_swmr_common.c +++ b/test/vfd_swmr_common.c @@ -391,6 +391,10 @@ vfd_swmr_create_fapl(bool use_latest_format, bool use_vfd_swmr, bool only_meta_p if (H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) return H5I_INVALID_HID; } + else {/* Currently this is used only for old-styled group implementation tests.*/ + if (H5Pset_libver_bounds(fapl, H5F_LIBVER_EARLIEST, H5F_LIBVER_LATEST) < 0) + return H5I_INVALID_HID; + } /* Enable page buffering */ if (H5Pset_page_buffer_size(fapl, 4096, only_meta_pages ? 100 : 0, 0) < 0) diff --git a/test/vfd_swmr_group_writer.c b/test/vfd_swmr_group_writer.c index 25ee8c5..7f083c8 100644 --- a/test/vfd_swmr_group_writer.c +++ b/test/vfd_swmr_group_writer.c @@ -24,17 +24,27 @@ #ifndef H5_HAVE_WIN32_API #define READER_WAIT_TICKS 3 +#define VS_ATTR_NAME_LEN 21 typedef struct { - hid_t file, filetype, one_by_one_sid; - char filename[PATH_MAX]; - char progname[PATH_MAX]; - unsigned int asteps; - unsigned int csteps; - unsigned int nsteps; - unsigned int update_interval; - bool use_vfd_swmr; - bool use_named_pipes; + hid_t file, filetype, one_by_one_sid; + char filename[PATH_MAX]; + char progname[PATH_MAX]; + unsigned int asteps; + unsigned int csteps; + unsigned int nsteps; + unsigned int update_interval; + bool use_vfd_swmr; + bool old_style_grp; + bool use_named_pipes; + char at_pattern; + bool attr_test; + uint32_t max_lag; + uint32_t tick_len; + int np_fd_w_to_r; + int np_fd_r_to_w; + int np_notify; + int np_verify; } state_t; #define ALL_HID_INITIALIZER \ @@ -43,26 +53,58 @@ typedef struct { .file = H5I_INVALID_HID, .one_by_one_sid = H5I_INVALID_HID, .filename = "", \ .filetype = H5T_NATIVE_UINT32, .asteps = 10, .csteps = 10, .nsteps = 100, .update_interval = READER_WAIT_TICKS, \ .use_vfd_swmr = true, \ + .old_style_grp = false, \ .use_named_pipes = true \ - } + , .at_pattern = ' ' \ + , .attr_test = false \ + , .tick_len = 4 \ + , .max_lag = 7 \ + , .np_fd_w_to_r = -1 \ + , .np_fd_r_to_w = -1 \ + , .np_notify = 0 \ + , .np_verify = 0 } + static void usage(const char *progname) { - fprintf(stderr, "usage: %s [-S] [-a steps] [-b] [-c]\n" - " [-n iterations] [-N] [-q] [-u numb_ticks]\n" - "\n" - "-S: do not use VFD SWMR\n" - "-a steps: `steps` between adding attributes\n" - "-b: write data in big-endian byte order\n" - "-c steps: `steps` between communication between the writer and reader\n" - "-n ngroups: the number of groups\n" - "-N: do not use named pipes, mainly for running the writer and reader seperately\n" - "-u numb_tcks: `numb_ticks` for the reader to wait before verification\n" - "-q: silence printouts, few messages\n" - "\n", - progname); - exit(EXIT_FAILURE); + fprintf(stderr, "usage: %s [-S] [-G] [-a steps] [-b] [-c]\n" + " [-n iterations] [-N] [-q] [-u numb_ticks] [-A at_pattern]\n" + "\n" + "-S: do not use VFD SWMR\n" + "-G: old-style type of group\n" + "-a steps: `steps` between adding attributes\n" + "-b: write data in big-endian byte order\n" + "-c steps: `steps` between communication between the writer and reader\n" + "-n ngroups: the number of groups\n" + "-N: do not use named pipes, \n" + " mainly for running the writer and reader seperately\n" + "-u numb_ticks: `numb_ticks` for the reader to wait before verification\n" + "-A at_pattern: `at_pattern' for different attribute tests\n" + " The value of `at_pattern` is one of the following:\n" + " `compact` - Attributes added in compact storage\n" + " `dense` - An attribute added in dense storage\n" + " `compact-del` - Attributes added and then one\n" + " attribute deleted, in compact \n" + " `dense-del` - Attributes added until the storage\n" + " is dense then an attribute deleted\n" + " the storge still in dense\n" + " `compact-add-to-dense` - Attributes added first in compact\n" + " then in dense storage\n" + " `dense-del-to-compact` - Attributes added until the storage\n" + " is dense, then several attributes \n" + " deleted, the storage changed to\n" + " compact\n" + " `modify` - An attribute added then modified\n" + " `add-vstr` - A VL string attribute added\n" + " `remove-vstr` - A VL string attribute added then\n" + " deleted\n" + " `modify-vstr` - A VL string attribute added then \n" + " modified \n" + "-q: silence printouts, few messages\n" + "\n", + progname); + exit(EXIT_FAILURE); } static bool @@ -87,17 +129,20 @@ state_init(state_t *s, int argc, char **argv) if (tfile) HDfree(tfile); - while ((ch = getopt(argc, argv, "Sa:bc:n:Nqu:")) != -1) { + while ((ch = getopt(argc, argv, "SGa:bc:n:Nqu:A:")) != -1) { switch (ch) { case 'S': s->use_vfd_swmr = false; break; + case 'G': + s->old_style_grp = true; + break; case 'a': case 'c': case 'n': case 'u': errno = 0; - tmp = strtoul(optarg, &end, 0); + tmp = HDstrtoul(optarg, &end, 0); if (end == optarg || *end != '\0') { H5_FAILED(); AT(); printf("couldn't parse `-%c` argument `%s`\n", ch, optarg); @@ -127,6 +172,33 @@ state_init(state_t *s, int argc, char **argv) case 'N': s->use_named_pipes = false; break; + case 'A': + if (HDstrcmp(optarg, "compact") == 0) + s->at_pattern = 'c'; + else if (HDstrcmp(optarg, "dense") == 0) + s->at_pattern = 'd'; + else if (HDstrcmp(optarg, "compact-add-to-dense") == 0) + s->at_pattern = 't'; + else if (HDstrcmp(optarg, "compact-del") == 0) + s->at_pattern = 'C'; + else if (HDstrcmp(optarg, "dense-del") == 0) + s->at_pattern = 'D'; + else if (HDstrcmp(optarg, "dense-del-to-compact") == 0) + s->at_pattern = 'T'; + else if (HDstrcmp(optarg, "modify") == 0) + s->at_pattern = 'M'; + else if (HDstrcmp(optarg,"add-vstr") ==0) + s->at_pattern = 'v'; + else if (HDstrcmp(optarg, "remove-vstr") == 0) + s->at_pattern = 'r'; + else if (HDstrcmp(optarg, "modify-vstr") == 0) + s->at_pattern = 'm'; + else { + H5_FAILED(); AT(); + printf("Invalid -A argument \"%s\"", optarg); + goto error; + } + break; case 'q': verbosity = 0; break; @@ -171,72 +243,1428 @@ state_init(state_t *s, int argc, char **argv) error: if (tfile) HDfree(tfile); + return false; +} + +/* Named Pipe Subroutine: np_wr_send_receive + * Description: + * The writer sends a message to the reader, + * then waits for max_lag ticks, + * then checks the returned message from the reader. + * Return: + * True if succeed + * False if an error occurs in any step above. + * An error is mostly caused by an unexpected + * notification number from the message sent + * by the reader. + */ +static bool np_wr_send_receive(state_t *s) { + + unsigned int i; + /* Bump up the value of notify to notice the reader to start to read */ + s->np_notify++; + if (HDwrite(s->np_fd_w_to_r, &(s->np_notify), sizeof(int)) < 0) { + H5_FAILED(); AT(); + printf("HDwrite failed\n"); + goto error; + } + + /* During the wait, writer makes repeated HDF5 API calls + * to trigger EOT at approximately the correct time */ + for(i = 0; i < s->max_lag + 1; i++) { + decisleep(s->tick_len); + H5E_BEGIN_TRY { + H5Aexists(s->file, "nonexistent"); + } H5E_END_TRY; + } + /* Receive the same value from the reader and verify it before + * going to the next step */ + (s->np_verify)++; + if (HDread(s->np_fd_r_to_w, &(s->np_notify), sizeof(int)) < 0){ + H5_FAILED(); AT(); + printf("HDread failed\n"); + goto error; + } + + if (s->np_notify == -1) { + H5_FAILED(); AT(); + printf("reader failed to verify group or attribute operation.\n"); + goto error; + } + + if (s->np_notify != s->np_verify) { + H5_FAILED(); AT(); + printf("received message %d, expecting %d\n", s->np_notify, s->np_verify); + goto error; + } + + return true; + +error: return false; + } -static bool -add_group_attribute(const state_t *s, hid_t g, hid_t sid, unsigned int which) -{ - hid_t aid; - char name[sizeof("attr-9999999999")]; +/* Named Pipe Subroutine: np_rd_receive + * Description: + * The reader receives a message from the writer, + * then checks if the notification number from + * the writer is expected. + * Return: + * True if succeed + * False if an error occurs in any step above. + * An error is mostly caused by an unexpected + * notification number from the message sent + * by the writer. + */ +static bool np_rd_receive(state_t *s) { + + /* The writer should have bumped up the value of notify. + * Do the same with verify and confirm it */ + s->np_verify++; + + /* Receive the notify that the writer bumped up the value */ + if (HDread(s->np_fd_w_to_r, &(s->np_notify), sizeof(int)) < 0) { + H5_FAILED(); AT(); + printf("HDread failed\n"); + goto error; + } + + if (s->np_notify == -1) { + H5_FAILED(); AT(); + printf("writer failed to create group or carry out an attribute operation.\n"); + goto error; + } + + if (s->np_notify != s->np_verify) { + H5_FAILED(); AT(); + printf("received message %d, expecting %d\n", s->np_notify, s->np_verify); + goto error; + } + + return true; + +error: + return false; +} + +/* Named Pipe Subroutine: np_rd_send + * Description: + * The reader sends an acknowledgement to the writer + * Return: + * True if succeed + * False if an error occurs in sending the message. + */ +static bool np_rd_send(state_t *s) { + + if (HDwrite(s->np_fd_r_to_w, &(s->np_notify), sizeof(int)) < 0) { + H5_FAILED(); AT(); + printf("HDwrite failed\n"); + return false; + } + else + return true; +} + +/* Named Pipe Subroutine: np_send_error + * Description: + * An error (notification number is 1) message is sent + * either from the reader or the writer. + * A boolean input parameter is used to choose + * either reader or writer. + * Return: + * None + */ +static void np_send_error(state_t *s,bool writer) { + s->np_notify = -1; + if(writer) + HDwrite(s->np_fd_w_to_r, &(s->np_notify), sizeof(int)); + else + HDwrite(s->np_fd_r_to_w, &(s->np_notify), sizeof(int)); +} + +/*------------------------------------------------------------------------- + * Function: add_attr + * + * Purpose: Add attributes to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t oid + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group name. The group name is "group-which". + * + * unsigned num_attrs + * The number of attributes to be created + * + * const char*aname_fmt + * The attribute name template used to create unique attribute names. + * + * unsigned int g_which + * This parameter is used to generate correct group name in a key + * debugging message. + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- +*/ + +static bool +add_attr(state_t *s, + hid_t oid, + unsigned int which, + unsigned num_attrs, + const char*aname_fmt, + unsigned int g_which) { + + char attrname[VS_ATTR_NAME_LEN]; + unsigned u; + unsigned attr_value; + hid_t aid = H5I_INVALID_HID; + hid_t amtype = H5I_INVALID_HID; + hid_t atype = s->filetype; + hid_t sid = s->one_by_one_sid; + + /* Need to obtain native datatype for H5Aread */ + if((amtype = H5Tget_native_type(atype,H5T_DIR_ASCEND)) <0) { + H5_FAILED(); AT(); + printf("H5Tget_native_type failed\n"); + goto error; + } + + for (u = 0; u < num_attrs; u++) { + + /* Create attribute */ + /* Construct attribute name like attr-0-0 */ + HDsprintf(attrname, aname_fmt, which,u); + if((aid = H5Acreate2(oid, attrname, atype, sid, H5P_DEFAULT, + H5P_DEFAULT)) < 0) { + H5_FAILED(); AT(); + printf("H5Acreate2 failed\n"); + goto error; + } + + attr_value = u+which; +#if 0 + // Just for debugging to check if error handling works. + attr_value = u+which+1; +#endif + + dbgf(1, "setting attribute %s on group %u to %u\n", attrname, g_which, u+which); + + /* Write data into the attribute */ + if (H5Awrite(aid, amtype, &attr_value) < 0) { + H5_FAILED(); AT(); + printf("H5Awrite failed\n"); + goto error; + } + + /* Close attribute */ + if(H5Aclose(aid) < 0) { + H5_FAILED(); AT(); + printf("H5Aclose failed\n"); + goto error; + } + + /* Writer sends a message to reader: an attribute is successfully generated. + then wait for the reader to verify and send an acknowledgement message back.*/ + if (s->use_named_pipes && s->attr_test == true) { + dbgf(2, "writer: write attr - ready to send/receive message: %d\n", s->np_notify+1); + if(np_wr_send_receive(s) == false) { + H5_FAILED(); AT(); + dbgf(2, "writer: write attr - verification failed.\n"); + /* Note: This is (mostly) because the verification failure message + * from the reader. So don't send the error message back to + * the reader. Just stop the test. */ + goto error2; + } + } + + } /* end for */ + + if(H5Tclose(amtype) < 0) { + H5_FAILED(); AT(); + goto error; + } + return true; + +error: + /* Writer needs to send an error message to the reader to stop the test*/ + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); + +error2: + H5E_BEGIN_TRY { + H5Aclose(aid); + H5Tclose(amtype); + } H5E_END_TRY; + + return false; + +} + +/*------------------------------------------------------------------------- + * Function: add_default_group_attr + * + * Purpose: Add an attribute to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used for the "dense" storage test. + * It is also used by the group-only test. + *------------------------------------------------------------------------- +*/ + +static bool +add_default_group_attr(state_t *s, hid_t g, unsigned int which) { + + const char* aname_format ="attr-%u"; + + /* Note: Since we only add one attribute, the parameter for + * the number of attributes is 1. */ + return add_attr(s,g,which,1,aname_format,which); + +} + +/*------------------------------------------------------------------------- + * Function: add_vlstr_attr + * + * Purpose: Add a variable length string attribute to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "vstr" test. + *------------------------------------------------------------------------- +*/ + + +static bool +add_vlstr_attr(state_t*s, hid_t g, unsigned int which) { + + hid_t aid = H5I_INVALID_HID; + hid_t atype = H5I_INVALID_HID; + char name[VS_ATTR_NAME_LEN]; + char *astr_val = NULL; + hid_t sid = s->one_by_one_sid; + + /* Allocate buffer for the VL string value */ + astr_val = HDmalloc(VS_ATTR_NAME_LEN); + if (astr_val == NULL) { + H5_FAILED(); AT(); + printf("Allocate memory for VL string failed.\n"); + goto error; + } + + /* Assign the VL string value and the attribute name.. */ + HDsprintf(astr_val,"%u",which); esnprintf(name, sizeof(name), "attr-%u", which); dbgf(1, "setting attribute %s on group %u to %u\n", name, which, which); - if ((aid = H5Acreate2(g, name, s->filetype, sid, H5P_DEFAULT, - H5P_DEFAULT)) < 0) { + /* Create a datatype to refer to. */ + if ((atype = H5Tcopy(H5T_C_S1)) < 0) { H5_FAILED(); AT(); - printf("H5Acreate2 failed\n"); + printf("Cannot create variable length datatype.\n"); + goto error; + } + + if (H5Tset_size(atype, H5T_VARIABLE) < 0) { + H5_FAILED(); AT(); + printf("Cannot set variable length datatype.\n"); + goto error; + } + + /* Generate the VL string attribute.*/ + if ((aid = H5Acreate2(g, name, atype, sid, H5P_DEFAULT, + H5P_DEFAULT)) < 0) { + H5_FAILED(); AT(); + printf("H5Acreate2 failed.\n"); + goto error; + } + + if (H5Awrite(aid, atype, &astr_val) < 0) { + H5_FAILED(); AT(); + printf("H5Awrite failed.\n"); + goto error; + } + + if (H5Tclose(atype) < 0) { + H5_FAILED(); AT(); + printf("H5Tclose() failed\n"); + goto error; + } + if (H5Aclose(aid) < 0) { + H5_FAILED(); AT(); + printf("H5Aclose() failed\n"); + goto error; + } + + HDfree(astr_val); + + /* Writer sends a message to reader: a VL string attribute is successfully generated. + then wait for the reader to verify and send an acknowledgement message back. */ + if (s->use_named_pipes && s->attr_test == true) { + dbgf(2, "writer: write attr - ready to send the message: %d\n", s->np_notify+1); + if(np_wr_send_receive(s) == false) { + H5_FAILED(); AT(); + dbgf(2, "writer: write attr - verification failed.\n"); + goto error2; + } + } + + return true; + +error: + /* Writer needs to send an error message to the reader to stop the test*/ + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); + H5E_BEGIN_TRY { + H5Aclose(aid); + H5Tclose(atype); + } H5E_END_TRY; + + if(astr_val) + HDfree(astr_val); + +error2: + return false; +} + +/*------------------------------------------------------------------------- + * Function: del_one_attr + * + * Purpose: delete one attribute in a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t obj_id + * HDF5 object ID (in this file: means group ID) + * + * bool is_dense + * if the deleted attribute is for checking the dense storage + * + * bool is_vl + * if the deleted attribute is a VL string + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute names + * according to if this attribute is a VL string or for checking + * the dense storage or the storage transition from dense to + * compact. + * + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- +*/ + +static bool +del_one_attr(state_t *s, hid_t obj_id,bool is_dense,bool is_vl,unsigned int which) { + + char attrname[VS_ATTR_NAME_LEN]; + + /*attribute name template for the dense storage related deletion operation */ + const char* aname_format_d = "attr-d-%u-%u"; + + /*attribute name template used for general attribute deletion operation */ + const char* aname_format = "attr-%u-%u"; + + /*attribute name template used for VL string attribute deletion operation */ + const char* aname_format_vl="attr-%u"; + + dbgf(2, "writer: coming to delete the attribute.\n"); + + /* Construct the attribute name */ + if(is_dense == true) + HDsprintf(attrname, aname_format_d, which,0); + else if(is_vl == true) + HDsprintf(attrname, aname_format_vl, which,0); + else + HDsprintf(attrname, aname_format, which,0); + + /* Delete the attribute */ + if(H5Adelete(obj_id, attrname) <0) { + H5_FAILED(); AT(); + printf("H5Adelete() failed\n"); + goto error; + } + + /* Writer sends a message to reader: an attribute is successfully generated. + then wait for the reader to verify and send an acknowledgement message back. */ + if(s->use_named_pipes && s->attr_test == true) { + dbgf(2, "writer: delete attr - ready to send the message: %d\n", s->np_notify+1); + if(np_wr_send_receive(s) == false) { + H5_FAILED(); AT(); + dbgf(2, "writer: delete attr - verification failed.\n"); + goto error2; + } + } + + return true; + +error: + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); + +error2: + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_del_vlstr_attr + * + * Purpose: Add a variable length string attribute + * then delete this attribute in this a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "remove-vstr" test. + *------------------------------------------------------------------------- +*/ + + +static bool +add_del_vlstr_attr(state_t *s, hid_t g, unsigned int which) { + + bool ret_value = false; + + /* Add a VL string attribute then delete it. */ + ret_value = add_vlstr_attr(s,g,which); + if(ret_value == true) + ret_value = del_one_attr(s,g,false,true,which); + + return ret_value; + +} + +/*------------------------------------------------------------------------- + * Function: modify_attr + * + * Purpose: Modify the value of an attribute in a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * const char*aname_fmt + * The attribute name template used to create unique attribute names. + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group name. The group name is "group-which". + * + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- +*/ + + +static bool +modify_attr(state_t *s, hid_t g, const char* aname_fmt,unsigned int which) { + + char attrname[VS_ATTR_NAME_LEN]; + hid_t aid = H5I_INVALID_HID; + hid_t amtype = H5I_INVALID_HID; + unsigned int modify_value; + + HDsprintf(attrname,aname_fmt,which,0); + if((aid = H5Aopen(g,attrname,H5P_DEFAULT))<0) { + H5_FAILED(); AT(); + printf("H5Aopen failed\n"); goto error; } - if (H5Awrite(aid, H5T_NATIVE_UINT, &which) < 0) { + if((amtype = H5Tget_native_type(s->filetype,H5T_DIR_ASCEND))<0) { + H5_FAILED(); AT(); + printf("H5Tget_native_type failed\n"); + goto error; + } + + /* Make a large number to verify the change easily */ + modify_value = which+10000; + + if (H5Awrite(aid,amtype,&modify_value) <0) { H5_FAILED(); AT(); printf("H5Awrite failed\n"); goto error; } + if (H5Tclose(amtype) < 0) { + H5_FAILED(); AT(); + goto error; + } + if (H5Aclose(aid) < 0) { + H5_FAILED(); AT(); + goto error; + } + + /* Writer sends a message to reader: an attribute is successfully modified. + then wait for the reader to verify and send an acknowledgement message back.*/ + if (s->use_named_pipes && s->attr_test == true) { + dbgf(2, "writer: modify attr - ready to send the message: %d\n", s->np_notify+1); + if(np_wr_send_receive(s) == false) { + H5_FAILED(); AT(); + dbgf(2, "writer: write attr - verification failed.\n"); + /* Note: This is (mostly) because the verification failure message + * from the reader. So don't send the error message back to + * the reader. Just stop the test. */ + goto error2; + } + } + + return true; +error: + /* Writer needs to send an error message to the reader to stop the test*/ + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); + H5E_BEGIN_TRY { + H5Aclose(aid); + H5Tclose(aid); + } H5E_END_TRY; + +error2: + return false; + +} + +/*------------------------------------------------------------------------- + * Function: modify_vlstr_attr + * + * Purpose: Modify the value of an VL string attribute in a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group name. The group name is "group-which". + * + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- +*/ + + + +static bool +modify_vlstr_attr(state_t*s,hid_t g, unsigned int which) { + + hid_t aid = H5I_INVALID_HID; + hid_t atype = H5I_INVALID_HID; + char name[VS_ATTR_NAME_LEN]; + char *astr_val = NULL; + + astr_val = HDmalloc(VS_ATTR_NAME_LEN); + if (astr_val == NULL) { + H5_FAILED(); AT(); + printf("Allocate memory for VL string failed.\n"); + goto error; + } + + /* Change the VL string value and create the attribute name. */ + HDsprintf(astr_val,"%u%c",which,'A'); + esnprintf(name, sizeof(name), "attr-%u", which); + + dbgf(1, "setting attribute %s on group %u to %u\n", name, which, which); + + /* Create a datatype to refer to. */ + if ((atype = H5Tcopy(H5T_C_S1)) < 0) { + H5_FAILED(); AT(); + printf("Cannot create variable length datatype.\n"); + goto error; + } + + if (H5Tset_size(atype, H5T_VARIABLE) < 0) { + H5_FAILED(); AT(); + printf("Cannot set variable length datatype.\n"); + goto error; + } + + /* Open this attribute. */ + if ((aid = H5Aopen(g, name, H5P_DEFAULT))<0) { + H5_FAILED(); AT(); + printf("H5Aopen failed.\n"); + goto error; + } + + dbgf(1, "The modified VL string value is %s \n", astr_val); + + if (H5Awrite(aid, atype, &astr_val) < 0) { + H5_FAILED(); AT(); + printf("H5Awrite failed.\n"); + goto error; + } + + if (H5Tclose(atype) < 0) { + H5_FAILED(); AT(); + printf("H5Tclose() failed\n"); + goto error; + } if (H5Aclose(aid) < 0) { H5_FAILED(); AT(); - printf("H5Aclose failed\n"); + printf("H5Aclose() failed\n"); goto error; } + HDfree(astr_val); + + /* Writer sends a message to reader: a VL string attribute is successfully generated. + then wait for the reader to verify and send an acknowledgement message back. */ + if (s->use_named_pipes && s->attr_test == true) { + dbgf(2, "writer: modify vl attr - ready to send the message: %d\n", s->np_notify+1); + if(np_wr_send_receive(s) == false) { + H5_FAILED(); AT(); + dbgf(2, "writer: write attr - verification failed.\n"); + goto error2; + } + } + return true; error: H5E_BEGIN_TRY { H5Aclose(aid); + H5Tclose(atype); } H5E_END_TRY; + if(astr_val) + HDfree(astr_val); + + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); + +error2: + return false; + +} + +/*------------------------------------------------------------------------- + * Function: add_modify_vlstr_attr + * + * Purpose: Add a variable length string attribute + * then modify this attribute in this a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "modify-vstr" test. + *------------------------------------------------------------------------- +*/ + +static bool +add_modify_vlstr_attr(state_t *s, hid_t g, unsigned int which) { + + bool ret_value = false; + ret_value = add_vlstr_attr(s,g,which); + if (true == ret_value) + ret_value = modify_vlstr_attr(s,g,which); + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: add_attrs_compact + * + * Purpose: Add some attributes to the group. + * the number of attributes should be the maximal number of + * attributes that the compact storage can hold + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "modify-vstr" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- +*/ + +static bool +add_attrs_compact(state_t *s, hid_t g, hid_t gcpl, unsigned int which) { + + unsigned max_compact = 0; + unsigned min_dense = 0; + const char* aname_format="attr-%u-%u"; + + if(s->old_style_grp) + max_compact = 2; + else { + /* Obtain the maximal number of attributes to be stored in compact + * storage and the minimal number of attributes to be stored in + * dense storage. */ + if(H5Pget_attr_phase_change(gcpl, &max_compact, &min_dense)<0) { + H5_FAILED(); AT(); + printf("H5Pget_attr_phase_change() failed\n"); + goto error; + } + } + + /* Add max_compact attributes, these attributes are stored in + * compact storage. */ + return add_attr(s,g,which,max_compact,aname_format,which); + +error: + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_attrs_compact_dense + * + * Purpose: Add some attributes to the group. + * First, the number of attributes should be the maximal number + * of attributes that the compact storage can hold. + * Then, add another atribute, the storage becomes dense. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "compact-to-dense" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- +*/ + +static bool +add_attrs_compact_dense(state_t *s, hid_t g, hid_t gcpl, unsigned int which) { + + unsigned max_compact = 0; + unsigned min_dense = 0; + const char* aname_format="attr-d-%u-%u"; + bool ret_value = false; + + if(H5Pget_attr_phase_change(gcpl, &max_compact, &min_dense) < 0) { + H5_FAILED(); AT(); + printf("H5Pget_attr_phase_change failed\n"); + goto error; + } + + /* Add attributes, until just before converting to dense storage */ + ret_value = add_attrs_compact(s, g, gcpl, which); + + /* Add another attribute, the storage becomes dense. */ + if(ret_value == true) + ret_value = add_attr(s,g,which+max_compact,1,aname_format,which); + + return ret_value; + +error: + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); return false; } +/*------------------------------------------------------------------------- + * Function: del_attrs_compact_dense_compact + * + * Purpose: delete some attributes in the group. + * The number of attributes are deleted in such a way + * that the attribute storage changes from compact to + * dense then to compact again. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is an internal function used by the + * "dense-del-to-compact" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- +*/ + +static bool +del_attrs_compact_dense_compact(state_t *s, + hid_t obj_id, + hid_t gcpl, + unsigned int which) { + + unsigned max_compact = 0; + unsigned min_dense = 0; + unsigned u = 0; + + char attrname[VS_ATTR_NAME_LEN]; + const char* aname_format="attr-%u-%u"; + const char* adname_format="attr-d-%u-%u"; + + /* Obtain the maximal number of attributes to be stored in compact + * storage and the minimal number of attributes to be stored in + * dense storage. */ + if (H5Pget_attr_phase_change(gcpl, &max_compact, &min_dense) < 0) { + H5_FAILED(); AT(); + printf("H5Pget_attr_phase_change failed\n"); + goto error; + } + u= max_compact +1; + + + /* delete a number of attributes so that the attribute storage just becomes dense.*/ + for(u--;u>=(min_dense-1);u--) { + HDsprintf(attrname, aname_format, which,max_compact-u); + if (H5Adelete(obj_id,attrname) < 0) { + H5_FAILED(); AT(); + printf("H5Adelete failed\n"); + goto error; + } + + /* For each attribute deletion, we want to ensure the verification + * from the reader. + * So writer sends a message to reader: an attribute is successfully deleted. + then wait for reader to verify and send an acknowledgement message back. */ + if(s->use_named_pipes && s->attr_test == true) { + dbgf(2, "writer: delete attr - ready to send the message: %d\n", s->np_notify+1); + if(np_wr_send_receive(s) == false) { + H5_FAILED(); AT(); + dbgf(2, "writer: delete attr - verification failed.\n"); + goto error2; + } + } + } + + /* The writer deletes another attribute, the storage is + * still dense. However, the attribute to be deleted + * doesn't follow the previous for loop. It may be + * in different location in the object header. Just add + * a litter variation to check if this operation is successful. + * The attribute name to be deleted is attr-max_compact+which-0 + */ + + HDsprintf(attrname,adname_format,max_compact+which,0); + if (H5Adelete(obj_id,attrname) < 0) { + H5_FAILED(); AT(); + printf("H5Adelete failed\n"); + goto error; + } + /* Again we need to notify the reader via Named pipe. */ + if(s->use_named_pipes && s->attr_test == true) { + dbgf(2, "writer: delete attr - ready to send the message: %d\n", s->np_notify+1); + if(np_wr_send_receive(s) == false) { + H5_FAILED(); AT(); + dbgf(2, "writer: delete attr - verification failed.\n"); + goto error2; + } + } + + /* The following comments are left here in case in the future we want to + * use HDF5 function to verify the attribute storage */ +#if 0 + // May H5Oget_info3 -- obtain the number of attributes. + //Check the number of attributes >=min_dense. + //We may use the internal function + //is_dense = H5O__is_attr_dense_test(dataset) to check if it is dense in the future. + // +#endif + + return true; + +error: + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); + +error2: + return false; +} + +/*------------------------------------------------------------------------- + * Function: add_del_attrs_compact + * + * Purpose: Add some attributes to the group and then delete one attribute. + * First, the number of attributes to be added should be the + * maximal number of attributes that the compact storage can hold. + * Then, delete one atribute, the storage is still compact. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "compact-del" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- +*/ + +static bool +add_del_attrs_compact(state_t *s, hid_t g, hid_t gcpl, unsigned int which) { + + bool ret_value = false; + ret_value = add_attrs_compact(s, g, gcpl, which); + if(ret_value == true) { + dbgf(2, "writer: before deleting the attribute.\n"); + ret_value = del_one_attr(s,g,false,false,which); + } + + return ret_value; + +} + +/*------------------------------------------------------------------------- + * Function: add_del_attrs_compact_dense + * + * Purpose: Add some attributes to the group and then delete one attribute. + * First, the number of attributes to be added exceeds + * the maximal number of attributes that the compact storage can hold. + * The storage changes from compact to dense. + * Then, delete one atribute, the storage is still dense. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "dense-del" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- +*/ + + +static bool +add_del_attrs_compact_dense(state_t *s, hid_t g, hid_t gcpl, unsigned int which) { + + bool ret_value = false; + unsigned max_compact = 0; + unsigned min_dense = 0; + + if( H5Pget_attr_phase_change(gcpl, &max_compact, &min_dense) < 0) { + H5_FAILED(); AT(); + printf("H5Pget_attr_phase_change failed\n"); + goto error; + } + + ret_value = add_attrs_compact_dense(s,g,gcpl,which); + if(ret_value == true) + ret_value = del_one_attr(s,g,true,false,which+max_compact); + + return ret_value; + +error: + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); + return false; + +} + + +/*------------------------------------------------------------------------- + * Function: add_del_attrs_compact_dense_compact + * + * Purpose: Add attributes to the group and then delete some of them. + * First, the number of attributes to be added exceeds + * the maximal number of attributes that the compact storage can hold. + * The storage changes from compact to dense. + * Then, delete some attributes, the storage changes from + * dense to compact again. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * Return: Success: true + * Failure: false + * + * Note: This is for the "dense-del-to-compact" test. + * For attribute compact/dense storage, check the reference + * manual of H5Pget_attr_phase_change. + *------------------------------------------------------------------------- +*/ + + +static bool +add_del_attrs_compact_dense_compact(state_t *s, + hid_t g, + hid_t gcpl, + unsigned int which) { + + bool ret_value = false; + ret_value = add_attrs_compact_dense(s,g,gcpl,which); + if(ret_value == true) + ret_value = del_attrs_compact_dense_compact(s,g,gcpl,which); + + return ret_value; +} + +/*------------------------------------------------------------------------- + * Function: add_modify_default_group_attr + * + * Purpose: Add an attribute then modify the value to a group. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * The group name is "group-which" and the attribute name + * is "attr-which". + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used for the "modify" storage test. + *------------------------------------------------------------------------- +*/ + + +static bool +add_modify_default_group_attr(state_t *s, hid_t g, unsigned int which) { + + bool ret_value = false; + const char* aname_format ="attr-%u"; + ret_value = add_default_group_attr(s,g,which); + if(ret_value == true) + ret_value = modify_attr(s,g,aname_format,which); + return ret_value; + +} + +/*------------------------------------------------------------------------- + * Function: add_group_attribute + * + * Purpose: Check the attribute test pattern and then call the + * correponding test function.. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * hid_t gcpl + * Object creation property list ID + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group and attribute names. + * + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the write_group() function. + *------------------------------------------------------------------------- +*/ + +static bool +add_group_attribute(state_t *s, hid_t g, hid_t gcpl, unsigned int which) +{ + + bool ret_value = false; + char test_pattern = s->at_pattern; + + switch (test_pattern) { + case 'c': + ret_value = add_attrs_compact(s, g, gcpl, which); + break; + case 't': + ret_value = add_attrs_compact_dense(s, g, gcpl, which); + break; + case 'C': + ret_value = add_del_attrs_compact(s, g, gcpl, which); + break; + case 'D': + ret_value = add_del_attrs_compact_dense(s, g, gcpl, which); + break; + case 'T': + ret_value = add_del_attrs_compact_dense_compact(s, g, gcpl, which); + break; + case 'M': + ret_value = add_modify_default_group_attr(s, g, which); + break; + case 'v': + ret_value = add_vlstr_attr(s,g, which); + break; + case 'r': + ret_value = add_del_vlstr_attr(s, g, which); + break; + case 'm': + ret_value = add_modify_vlstr_attr(s,g, which); + break; + case 'd': + case ' ': + default: + ret_value = add_default_group_attr(s, g, which); + break; + } + return ret_value; + +} + +/*------------------------------------------------------------------------- + * Function: write_group + * + * Purpose: Create a group and carry out attribute operations(add,delete etc.) + * according to the attribute test pattern. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations for group creation + * + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the main() function. + *------------------------------------------------------------------------- +*/ + static bool write_group(state_t *s, unsigned int which) { char name[sizeof("/group-9999999999")]; hid_t g = H5I_INVALID_HID; + hid_t gcpl = H5I_INVALID_HID; bool result = true; + H5G_info_t group_info; if (which >= s->nsteps) { H5_FAILED(); AT(); - printf("group order is out of bounds\n"); + printf("Number of created groups is out of bounds\n"); goto error; } esnprintf(name, sizeof(name), "/group-%d", which); - if ((g = H5Gcreate2(s->file, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) { + if(s->old_style_grp) + gcpl = H5P_DEFAULT; + else { + gcpl = H5Pcreate(H5P_GROUP_CREATE); + if(gcpl <0) { + H5_FAILED(); AT(); + printf("H5Pcreate failed\n"); + goto error; + } + + /* If we test the dense storage, change the attribute phase. */ + if(s->at_pattern =='d') { + if(H5Pset_attr_phase_change(gcpl, 0, 0) <0) { + H5_FAILED(); AT(); + printf("H5Pset_attr_phase_change failed for the dense storage.\n"); + goto error; + } + } + } + + if ((g = H5Gcreate2(s->file, name, H5P_DEFAULT, gcpl, + H5P_DEFAULT)) < 0) { H5_FAILED(); AT(); printf("H5Gcreate2 failed\n"); goto error; } - if (s->asteps != 0 && which % s->asteps == 0) - result = add_group_attribute(s, g, s->one_by_one_sid, which); + if(H5Gget_info(g,&group_info) <0) { + H5_FAILED(); AT(); + printf("H5Gget_info failed\n"); + goto error; + } + + if(s->old_style_grp) { + if(group_info.storage_type != H5G_STORAGE_TYPE_SYMBOL_TABLE) { + H5_FAILED(); AT(); + printf("Old-styled group test: but the group is not in old-style. \n"); + goto error; + } + dbgf(2,"Writer: group is created with the old-style.\n"); + } + else { + if(group_info.storage_type == H5G_STORAGE_TYPE_SYMBOL_TABLE) { + H5_FAILED(); AT(); + printf("The created group should NOT be in old-style . \n"); + goto error; + } + dbgf(2,"Writer: group is created with the new-style.\n"); + + } + /* If an attribute test is turned on and named pipes are used, + * the writer should send and receive messages after the group creation. + * This will distinguish an attribute operation error from an + * group creation error. + * Writer sends a message to reader: an attribute is successfully generated. + * then wait for the reader to verify and send an acknowledgement message back.*/ + if (s->use_named_pipes && s->attr_test == true) { + dbgf(2, "writer: ready to send the message: %d\n", s->np_notify+1); + if(np_wr_send_receive(s) == false) { + H5_FAILED(); AT(); + /* Note: This is (mostly) because the verification failure message + * from the reader. So don't send the error message back to + * the reader. Just stop the test. */ + goto error2; + } + } + + /* Then carry out the attribute operation. */ + if (s->asteps != 0 && which % s->asteps == 0) + result = add_group_attribute(s, g, gcpl,which); if (H5Gclose(g) < 0) { H5_FAILED(); AT(); @@ -244,26 +1672,454 @@ write_group(state_t *s, unsigned int which) goto error; } + if(!s->old_style_grp && H5Pclose(gcpl) <0) { + H5_FAILED(); AT(); + printf("H5Pclose failed\n"); + goto error; + } + return result; error: + /* Writer needs to send an error message to the reader to stop the test*/ + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,true); + +error2: + H5E_BEGIN_TRY { H5Gclose(g); + if(!s->old_style_grp) + H5Pclose(gcpl); + } H5E_END_TRY; + + return false; + +} +/*------------------------------------------------------------------------- + * Function: check_attr_storage_type + * + * Purpose: Check if the attribute storage type is correct + * + * Parameters: hid_t oid + * HDF5 object ID (in this file: means group ID) + * + * bool is_compact + * true if the attribute is stored in compact storage + * false if the attribute is stored in dense storage + * + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- +*/ + +static bool +check_attr_storage_type(hid_t g, + bool is_compact) { + + H5O_native_info_t ninfo; + + /* Get the object information */ + if(H5Oget_native_info(g, &ninfo, H5O_NATIVE_INFO_HDR|H5O_NATIVE_INFO_META_SIZE) < 0) { + H5_FAILED(); AT(); + printf("H5Oget_native_info failed\n"); + goto error; + } + + if(is_compact) { + if(ninfo.meta_size.attr.index_size != 0 || + ninfo.meta_size.attr.heap_size != 0) { + H5_FAILED(); AT(); + printf("Should be in compact storage,but it is not.\n"); + goto error; + } + } + else { + if(ninfo.meta_size.attr.index_size == 0 || + ninfo.meta_size.attr.heap_size == 0) { + H5_FAILED(); AT(); + printf("Should be in dense storage,but it is not.\n"); + goto error; + } + } + + return true; + +error: + return false; + +} + + +/*------------------------------------------------------------------------- + * Function: vrfy_attr + * + * Purpose: Verify is a group attribute value is as expected. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t oid + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * newly created group name. The group name is "group-which". + * + * const char*aname + * The attribute name + * + * unsigned int g_which + * This parameter is used to generate correct group name in a key + * debugging message. + * + * bool check_storage + * a flag to indicate if the storage check is on + * + * bool is_compact + * true if the attribute is stored in compact storage + * false if the attribute is stored in dense storage + * Note: this parameter is not used if the check_storage + * is set to false. + * + * + * Return: Success: true + * Failure: false + * + *------------------------------------------------------------------------- +*/ + +static bool +vrfy_attr(state_t *s, + hid_t g, + unsigned int which, + const char* aname, + unsigned int g_which, + bool check_storage, + bool is_compact) { + + unsigned int read_which; + hid_t aid = H5I_INVALID_HID; + hid_t amtype = H5I_INVALID_HID; + + /* The reader receives a message from the writer.Then sleep + * for a few ticks or stop the test if receiving an error + * message. + */ + if(s->use_named_pipes && true == s->attr_test) { + if(false == np_rd_receive(s)) { + H5_FAILED(); AT(); + /* Since receiving the error message from the writer, + * just stop the test. */ + goto error2; + } + decisleep(s->tick_len * s->update_interval); + dbgf(1, "Reader: finish reading the message: %d\n",s->np_notify); + } + + /* Go ahead to read the attribute. */ + dbgf(1, "verifying attribute %s on group %u equals %u\n", aname, g_which, + which); + + if ((amtype = H5Tget_native_type(s->filetype,H5T_DIR_ASCEND)) <0) { + H5_FAILED(); AT(); + printf("H5Tget_native_type failed\n"); + goto error; + } + + if ((aid = H5Aopen(g, aname, H5P_DEFAULT)) < 0) { + H5_FAILED(); AT(); + printf("H5Aopen failed\n"); + goto error; + } + + if (H5Aread(aid, amtype, &read_which) < 0) { + H5_FAILED(); AT(); + printf("H5Aread failed\n"); + goto error; + } + + if (H5Aclose(aid) < 0) { + H5_FAILED(); AT(); + printf("H5Aclose failed\n"); + goto error; + } + + if(read_which != which) { + H5_FAILED(); AT(); + dbgf(2, "reader: the add_attribute verfication failed,expected value is %d\n", which); + dbgf(2, "reader: the add_attribute verfication failed, the value is %d\n", read_which); + printf("The add_attribute verification failed\n"); + goto error; + } + + + if(!s->old_style_grp && check_storage == true) { + if(false == check_attr_storage_type(g,is_compact)) { + H5_FAILED(); AT(); + printf("The attribute storage type is wrong. \n"); + goto error; + } + dbgf(2, "reader: finish checking the storage type: %d\n", s->np_notify); + + } + + /* If the read value is expected, send back an OK message to the writer. */ + if(s->use_named_pipes && s->attr_test == true) { + if(np_rd_send(s)==false) + goto error; + dbgf(2, "reader: finish sending back the message: %d\n", s->np_notify); + } + return true; + +error: + H5E_BEGIN_TRY { + H5Tclose(amtype); + H5Aclose(aid); } H5E_END_TRY; + /* Send back an error message to the writer so that the writer can stop. */ + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,false); +error2: return false; + } +/*------------------------------------------------------------------------- + * Function: verify_default_group_attr + * + * Purpose: Check if the reader can retrieve the correct value of a + * group attribute corrected by the writer. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The expected attribute value. It is also used to construct the + * group name. + * + * Return: Success: true + * Failure: false + * + * Note: This function is used for the "dense" storage test. + * It is also used by the group-only test. + *------------------------------------------------------------------------- +*/ + static bool -verify_group_attribute(hid_t g, unsigned int which) +verify_default_group_attr(state_t*s,hid_t g, unsigned int which) { + char attrname[VS_ATTR_NAME_LEN]; + const char* aname_format = "attr-%u"; + HDsprintf(attrname, aname_format, which); + return vrfy_attr(s,g,which,attrname,which,false,true); + +} + +/*------------------------------------------------------------------------- + * Function: verify_modify_attr + * + * Purpose: Check if the reader can retrieve the correct value of + * an attribute in a group, first the original value then + * the modified value. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The expected attribute value. It is also used to construct the + * group name. The modified attribute value can be derived from + * the expected attribute value. + * + * Return: Success: true + * Failure: false + * + * Note: This function is used for the "modified" test. + *------------------------------------------------------------------------- +*/ + +static bool +verify_modify_attr(state_t *s, hid_t g, unsigned int which) { + + bool ret = false; + const char* aname_fmt ="attr-%u"; unsigned int read_which; - hid_t aid; - char name[sizeof("attr-9999999999")]; + hid_t aid = H5I_INVALID_HID; + hid_t amtype = H5I_INVALID_HID; + char attrname[VS_ATTR_NAME_LEN]; + + /* First verify the original attribute value */ + ret = verify_default_group_attr(s,g,which); + + /* Then the modified value */ + if(ret == true) { + + /* The reader receives a message from the writer.Then sleep + * for a few ticks or stop the test if receiving an error + * message. + */ + if(s->use_named_pipes && true == s->attr_test) { + if(false == np_rd_receive(s)) { + H5_FAILED(); AT(); + goto error2; + } + decisleep(s->tick_len * s->update_interval); + dbgf(1, "Reader: finish reading the message: %d\n",s->np_notify); + } + + /* Go ahead to read the attribute. */ + esnprintf(attrname, sizeof(attrname), aname_fmt, which); + if ((amtype = H5Tget_native_type(s->filetype,H5T_DIR_ASCEND)) < 0) { + H5_FAILED(); AT(); + printf("H5Tget_native_type failed\n"); + goto error; + } + + if ((aid = H5Aopen(g, attrname, H5P_DEFAULT)) < 0) { + H5_FAILED(); AT(); + printf("H5Aopen failed\n"); + goto error; + } + + if (H5Aread(aid, amtype, &read_which) < 0) { + H5_FAILED(); AT(); + printf("H5Aread failed\n"); + goto error; + } + + if(H5Tclose(amtype) <0) { + H5_FAILED(); AT(); + printf("H5Tclose failed.\n"); + goto error; + } + + if (H5Aclose(aid) < 0) { + H5_FAILED(); AT(); + printf("H5Aclose failed\n"); + goto error; + } + + /* verify the modified value */ + if(read_which != (which+10000)) { + H5_FAILED(); AT(); + dbgf(2, "reader: the modified_attr() expected value is %d\n", (-1)*(int)which); + dbgf(2, "reader: the modified_attr() actual value is %d\n", read_which); + printf("The modify_attribute verification failed.\n"); + goto error; + } + + /* The reader sends an OK message back to the writer. */ + if(s->use_named_pipes && s->attr_test == true) { + if(np_rd_send(s)==false) + goto error2; + dbgf(2, "reader: modify_attr finish sending back the message: %d\n", s->np_notify); + } + return true; + + } + return false; + +error: + H5E_BEGIN_TRY { + H5Aclose(aid); + H5Tclose(amtype); + } H5E_END_TRY; + + /* The reader needs to send an error message back to the writer to stop the test.*/ + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,false); + +error2: + + return false; +} + +/*------------------------------------------------------------------------- + * Function: verify_group_vlstr_attr + * + * Purpose: Check if the reader can retrieve the correct value of + * a variable length string attribute created by the writer. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * Use to derieve the expected attribute value. It is also used + * to construct the group name. + * + * bool vrfy_mod + * true if this function is used for the modified VL string test. + * false if this function is just used for the VL string test. + * + * Return: Success: true + * Failure: false + * + * Note: This function is an internal function used by + * both the "vlstr" and the "modify-vstr" tests. + *------------------------------------------------------------------------- +*/ + + +static bool +verify_group_vlstr_attr(state_t*s, hid_t g, unsigned int which, bool vrfy_mod) +{ + hid_t aid = H5I_INVALID_HID; + hid_t atype = H5I_INVALID_HID; + char name[VS_ATTR_NAME_LEN]; + + char *astr_val_exp; + char * astr_val; + + /* The reader receives a message from the writer.Then sleep + * for a few ticks or stop the test if the received message + * is an error message. + */ + if(s->use_named_pipes && true == s->attr_test) { + if(false == np_rd_receive(s)) { + H5_FAILED(); AT(); + goto error2; + } + decisleep(s->tick_len * s->update_interval); + dbgf(1, "Reader: finish reading the message: %d\n",s->np_notify); + } + + /* Go ahead to read the VL string attribute. */ + astr_val_exp = HDmalloc(VS_ATTR_NAME_LEN); + if (astr_val_exp == NULL) { + H5_FAILED(); AT(); + printf("Allocate memory for expected buffer failed.\n"); + goto error; + } esnprintf(name, sizeof(name), "attr-%u", which); - dbgf(1, "verifying attribute %s on group %u equals %u\n", name, which, which); + /* Construct the expected VL string value,depending if + * it is the modified value or the original value. */ + if(vrfy_mod == true) + HDsprintf(astr_val_exp,"%u%c",which,'A'); + else + HDsprintf(astr_val_exp,"%u",which); + + dbgf(1, "verifying attribute %s on group %u equals %u\n", name, which, + which); + + dbgf(1,"expected vl attr is= %s\n",astr_val_exp); if ((aid = H5Aopen(g, name, H5P_DEFAULT)) < 0) { H5_FAILED(); AT(); @@ -271,57 +2127,766 @@ verify_group_attribute(hid_t g, unsigned int which) goto error; } - if (H5Aread(aid, H5T_NATIVE_UINT, &read_which) < 0) { + /* Create a VL string datatype */ + if ((atype = H5Tcopy(H5T_C_S1)) < 0) { H5_FAILED(); AT(); - printf("H5Aread failed\n"); + printf("Cannot create variable length datatype.\n"); goto error; } - if (read_which != which) { + if (H5Tset_size(atype, H5T_VARIABLE) < 0) { H5_FAILED(); AT(); - printf("H5Aread wrong value\n"); + printf("Cannot set variable length datatype.\n"); goto error; } + if (H5Aread(aid, atype, &astr_val) < 0) { + H5_FAILED(); AT(); + printf("Cannot read the attribute.\n"); + goto error; + } + + dbgf(1,"read attr is= %s\n",astr_val); + if (HDstrcmp(astr_val, astr_val_exp) != 0) { + H5_FAILED(); AT(); + dbgf(2, "reader: the vl add_attribute verfication failed,expected value is %s\n", astr_val_exp); + dbgf(2, "reader: the vl add_attribute verfication failed, the value is %s\n", astr_val); + printf("The vl add_attribute verification failed\n"); + goto error; + } + + if(H5Tclose(atype) <0) { + H5_FAILED(); AT(); + printf("H5Tclose failed.\n"); + goto error; + } + if (H5Aclose(aid) < 0) { H5_FAILED(); AT(); - printf("H5Aread failed\n"); + printf("H5Aclose failed.\n"); goto error; } + H5free_memory(astr_val); + HDfree(astr_val_exp); + + /* Reader sends an OK message back to the reader */ + if(s->use_named_pipes && s->attr_test == true) { + if(np_rd_send(s)==false) + goto error2; + dbgf(2, "reader: finish sending back the message: %d\n", s->np_notify); + } + return true; error: H5E_BEGIN_TRY { H5Aclose(aid); + H5Tclose(atype); } H5E_END_TRY; + if(astr_val) + H5free_memory(astr_val); + if(astr_val_exp) + HDfree(astr_val_exp); + /* The reader sends an error message to the writer to stop the test.*/ + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,false); + +error2: + + return false; + +} + +/*------------------------------------------------------------------------- + * Function: verify_del_one_attr + * + * Purpose: verify if an attribute is successfully deleted. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * const char* aname + * The name of the attribute to be deleted. + * + * Return: Success: true + * Failure: false + * + * Note: This is an internal function used by "remove-vlstr", + * "compact-del","dense-del",dense-del-to-compact" tests. + *------------------------------------------------------------------------- +*/ + + +static bool +verify_del_one_attr(state_t *s, + hid_t g, + const char *aname, + bool check_storage, + bool is_compact) { + + + htri_t attr_exists = FALSE; + + /* The reader receives a message from the writer.Then sleep + * for a few ticks or stop the test if the received message + * is an error message. + */ + if(s->use_named_pipes && true == s->attr_test) { + if(false == np_rd_receive(s)) { + H5_FAILED(); AT(); + goto error2; + } + decisleep(s->tick_len * s->update_interval); + dbgf(1, "Reader: finish reading the message: %d\n",s->np_notify); + } + + /* Check if the deleted attribute still exists. */ + attr_exists = H5Aexists_by_name(g,".",aname,H5P_DEFAULT); + if(attr_exists == FALSE) { + dbgf(1,"verify_del_attrs_compact() test: \n"); + dbgf(1," attribute %s is successfully deleted. \n",aname); + } + else if(attr_exists == TRUE) { + dbgf(1,"verify_del_attrs_compact() test failed \n"); + goto error; + } + else{ + dbgf(1,"H5Aexists_by_name failed \n"); + goto error; + } + + if(!s->old_style_grp && check_storage == true) { + if(false == check_attr_storage_type(g,is_compact)) { + H5_FAILED(); AT(); + printf("The attribute storage type is wrong. \n"); + goto error; + } + dbgf(2, "reader: finish checking the storage type: %d\n", s->np_notify); + + } + + /* Reader sends an OK message back to the reader */ + if(s->use_named_pipes && s->attr_test == true) { + if(np_rd_send(s)==false) + goto error; + dbgf(2, "reader: finish sending back the message: %d\n", s->np_notify); + } + + return true; +error: + /* The reader sends an error message to the writer to stop the test.*/ + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,false); + +error2: + return false; +} + +/*------------------------------------------------------------------------- + * Function: verify_remove_vlstr_attr + * + * Purpose: Verify if an variable length string attribute is + * successfully deleted by the writer. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * Use to derieve the expected attribute value added + * by the writer. It is also used to construct + * the attribute name. + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is for the "remove-vstr" test. + * Also note this function first verifies if + * a variable length attribute is added then + * it verifies if it is deleted successfully. + *------------------------------------------------------------------------- +*/ + +static bool +verify_remove_vlstr_attr(state_t* s,hid_t g, unsigned int which) +{ + bool ret = false; + char attrname[VS_ATTR_NAME_LEN]; + const char* aname_format = "attr-%u"; + + ret = verify_group_vlstr_attr(s,g,which,false); + if(ret == true) { + HDsprintf(attrname,aname_format,which); + ret = verify_del_one_attr(s,g,attrname,false,false); + } + return ret; +} + +/*------------------------------------------------------------------------- + * Function: verify_modify_vlstr_attr + * + * Purpose: Verify if an variable length string attribute is + * successfully modified by the writer. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * Use to derieve the expected attribute value added + * by the writer. It is also used to construct + * the attribute name. + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is for the "modify-vstr" test. + * Also note this function first verifies if + * a variable length attribute is added then + * it verifies if it is modified successfully. + *------------------------------------------------------------------------- +*/ + +static bool +verify_modify_vlstr_attr(state_t *s, hid_t g, unsigned int which){ + + bool ret = false; + + ret = verify_group_vlstr_attr(s,g,which,false); + if(ret == true) + ret = verify_group_vlstr_attr(s,g,which,true); + return ret; + +} + +/*------------------------------------------------------------------------- + * Function: verify_attrs_compact + * + * Purpose: verify if attributes are successfully added for the compact + * storage. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigend max_c + * The maximal number of attributes the compact storage + * can hold + * + * unsigned int which + * Use to derieve the expected attribute value added + * by the writer. It is also used to construct the + * attribute names. + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used by the "compact" test. + *------------------------------------------------------------------------- +*/ + +static bool +verify_attrs_compact(state_t *s, hid_t g, unsigned max_c, unsigned int which) { + + unsigned u; + bool ret = true; + const char* aname_format = "attr-%u-%u"; + char attrname[VS_ATTR_NAME_LEN]; + + /* Need to verify the added attribute one by one. */ + for (u = 0; u < max_c; u++) { + + HDsprintf(attrname, aname_format, which,u); + if(false == vrfy_attr(s,g,u+which,attrname,which,true,true)) { + ret = false; + break; + } + + } + return ret; + +} + +/*------------------------------------------------------------------------- + * Function: verify_attrs_compact_dense + * + * Purpose: verify if attributes are successfully added first in the + * compact storage then in the dense storage. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigend max_c + * The maximal number of attributes the compact storage + * can hold + * + * unsigned int which + * Use to derieve the expected attribute value added + * by the writer. It is also used to construct + * attribute names. + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used by the "compact-dense" test. + *------------------------------------------------------------------------- +*/ + + +static bool +verify_attrs_compact_dense(state_t *s, hid_t g, unsigned max_c, unsigned int which) { + + const char* aname_format = "attr-d-%u-%u"; + char attrname[VS_ATTR_NAME_LEN]; + + bool ret = verify_attrs_compact(s,g,max_c,which); + + if(ret == true) { + + /* Now the storage is in dense. Verify if the + * retrieved value is correct. */ + HDsprintf(attrname, aname_format, max_c+which,0); + ret = vrfy_attr(s,g,which+max_c,attrname,which,true,false); + if(ret == false) + dbgf(1,"verify_attrs_compact_dense failed \n"); + + } + return ret; +} + +/*------------------------------------------------------------------------- + * Function: verify_del_attrs_compact + * + * Purpose: verify if an attribute in compact storage is successfully + * deleted. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigend max_c + * The maximal number of attributes the compact storage + * can hold + * + * unsigned int which + * Use to derieve the expected attribute value added + * by the writer. It is also used to construct + * attribute names. + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used by the "compact-del" test. + * Also note this function first verifies if + * attributes are successfully added in compact storage then + * it verifies if one added attribute is deleted successfully. + *------------------------------------------------------------------------- +*/ + +static bool +verify_del_attrs_compact(state_t *s, hid_t g, unsigned max_c, unsigned int which) { + + const char* aname_format = "attr-%u-%u"; + char attrname[VS_ATTR_NAME_LEN]; + + bool ret = verify_attrs_compact(s,g,max_c,which); + + if(ret == true) { + /* The writer only deletes the attribute attr-which-0 */ + HDsprintf(attrname,aname_format,which,0); + ret = verify_del_one_attr(s,g,attrname,true,true); + } + + return ret; +} + +/*------------------------------------------------------------------------- + * Function: verify_del_attrs_compact_dense + * + * Purpose: verify if an attribute in dense storage is successfully + * deleted. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigend max_c + * The maximal number of attributes the compact storage + * can hold + * + * unsigned int which + * Use to derieve the expected attribute value added + * by the writer. It is also used to construct + * attribute names. + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used by the "dense-del" test. + * Also note this function first verifies if + * attributes are successfully added in compact storage then + * in dense storage. Afterwards, + * it verifies if one added attribute is deleted successfully. + *------------------------------------------------------------------------- +*/ + + +static bool +verify_del_attrs_compact_dense(state_t *s, + hid_t g, + unsigned max_c, + unsigned int which) { + + const char* aname_format = "attr-d-%u-%u"; + char attrname[VS_ATTR_NAME_LEN]; + + bool ret = verify_attrs_compact_dense(s,g,max_c,which); + + if(ret == true) { + /* The writer only deletes the attribute attr-d-which-0 */ + HDsprintf(attrname,aname_format,max_c+which,0); + ret = verify_del_one_attr(s,g,attrname,true,false); + } + + return ret; + +} + +/*------------------------------------------------------------------------- + * Function: verify_del_attrs_compact_dense_compact + * + * Purpose: verify that the attributes are deleted successfully + * even the attribute storage changes from dense to + * compact. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigend max_c + * The maximal number of attributes the compact storage + * can hold + * + * unsigend min_d + * The minimal number of attributes to be stored in + * dense storage + * + * unsigned int which + * Use to derieve the expected attribute value added + * by the writer. It is also used to construct + * attribute names. + * + * + * Return: Success: true + * Failure: false + * + * Note: This function is used by the "dense-del-to-compact" test. + * Also note this function first verifies if + * attributes are successfully added in compact storage then + * in dense storage. Afterwards, + * it verifies if some added attributes are deleted successfully + * until the storage changes from dense to compact. + *------------------------------------------------------------------------- +*/ + + +static bool +verify_del_attrs_compact_dense_compact(state_t *s, + hid_t g, + unsigned max_c, + unsigned min_d, + unsigned int which) { + + unsigned u; + const char* aname_format = "attr-%u-%u"; + char attrname[VS_ATTR_NAME_LEN]; + + /* Verify the attributes are added correctly from + * compact to dense storage*/ + bool ret = verify_attrs_compact_dense(s,g,max_c,which); + + if(ret == true) { + + /* Then verify the deletion of attributes + * from dense to compact. + */ + u = max_c + 1; + for(u--;u>=(min_d-1);u--) { + HDsprintf(attrname, aname_format, which,max_c-u); + if(u==(min_d-1)) + ret = verify_del_one_attr(s,g,attrname,true,true); + else + ret = verify_del_one_attr(s,g,attrname,true,false); + } + + /* Just verify one more deleted attribute by the writer. + The storage is still compact. */ + HDsprintf(attrname,aname_format,max_c+which,0); + ret = verify_del_one_attr(s,g,attrname,true,true); + } + + return ret; + +} + +/*------------------------------------------------------------------------- + * Function: verify_group_attribute + * + * Purpose: Check the attribute test pattern and then call the + * correponding verification function. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * hid_t g + * HDF5 object ID (in this file: means group ID) + * + * unsigned int which + * The number of iterations for group creation, use to generate + * group and attribute names. + * + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the verify_group() function. + *------------------------------------------------------------------------- +*/ + + +static bool +verify_group_attribute(state_t *s, hid_t g, unsigned int which) +{ + char test_pattern = s->at_pattern; + bool ret = false; + unsigned max_compact = 0; + unsigned min_dense = 0; + hid_t gcpl = H5I_INVALID_HID; + + /* For tests "compact","compact-to-dense","compact-del", + * "dense-del", "dense-del-to-compact", + * the maximal number of attributes for the compact storage + * and the minimal number of attributes for the dense storage + * are needed. So obtain them here + * When testing the old-style group creation case, only max_compact + * matters. To reduce the testing time, we set max_compact to 2.*/ + switch (test_pattern) { + case 'c': + case 't': + case 'C': + case 'D': + case 'T': + if(s->old_style_grp) + max_compact = 2; + else { + if((gcpl = H5Gget_create_plist(g)) < 0) { + H5_FAILED(); AT(); + printf("H5Gget_create_plist failed\n"); + goto error; + } + if (H5Pget_attr_phase_change(gcpl,&max_compact,&min_dense) < 0) { + H5_FAILED(); AT(); + printf("H5Pget_attr_phase_change failed\n"); + goto error; + } + if(H5Pclose(gcpl) < 0) { + H5_FAILED(); AT(); + printf("H5Pclose failed\n"); + goto error; + } + } + break; + case 'v': + case 'd': + case 'M': + case 'm': + case 'r': + case ' ': + default: + break; + } + + /* Distribute the verification test. */ + switch (test_pattern) { + case 'c': + ret = verify_attrs_compact(s, g, max_compact, which); + break; + case 't': + ret = verify_attrs_compact_dense(s, g, max_compact, which); + break; + case 'C': + ret = verify_del_attrs_compact(s, g, max_compact, which); + break; + case 'D': + ret = verify_del_attrs_compact_dense(s, g, max_compact, which); + break; + case 'T': + ret = verify_del_attrs_compact_dense_compact(s, g, max_compact, min_dense, which); + break; + case 'M': + ret = verify_modify_attr(s, g, which); + break; + case 'v': + ret = verify_group_vlstr_attr(s,g, which,false); + break; + case 'r': + ret = verify_remove_vlstr_attr(s,g, which); + break; + case 'm': + ret = verify_modify_vlstr_attr(s,g, which); + break; + case 'd': + case ' ': + default: + ret = verify_default_group_attr(s, g, which); + break; + } + + return ret; + +error: + /* Still to finish the handshaking */ + if(s->use_named_pipes && s->attr_test == true) { + np_rd_receive(s); + np_send_error(s,false); + } return false; } +/*------------------------------------------------------------------------- + * Function: verify_group + * + * Purpose: verify the success of group creation and + * carry out the test for attribute operations(add,delete etc.) + * according to the attribute test pattern. + * + * Parameters: state_t *s + * The struct that stores information of HDF5 file, named pipe + * and some VFD SWMR configuration parameters + * + * unsigned int which + * The number of iterations for group creation + * + * + * Return: Success: true + * Failure: false + * + * Note: This is called by the main() function. + *------------------------------------------------------------------------- +*/ + + + static bool verify_group(state_t *s, unsigned int which) { char name[sizeof("/group-9999999999")]; hid_t g = H5I_INVALID_HID; bool result = true; + H5G_info_t group_info; + + /* The reader receives a message from the writer.Then sleep + * for a few ticks or stop the test if the received message + * is an error message. + */ + if(s->use_named_pipes && true == s->attr_test) { + + if(false == np_rd_receive(s)) { + H5_FAILED(); AT(); + goto error2; + } + decisleep(s->tick_len * s->update_interval); + dbgf(1, "reader: finish reading the message: %d\n",s->np_notify); + + } if (which >= s->nsteps) { H5_FAILED(); AT(); - printf("Group order is out of bounds\n"); + printf("Number of created groups is out of bounds\n"); goto error; } esnprintf(name, sizeof(name), "/group-%d", which); - if ((g = H5Gopen(s->file, name, H5P_DEFAULT)) < 0) { + + if((g = H5Gopen(s->file, name, H5P_DEFAULT)) <0) { H5_FAILED(); AT(); printf("H5Gopen failed\n"); goto error; } + if(H5Gget_info(g,&group_info) <0) { + H5_FAILED(); AT(); + printf("H5Gget_info failed\n"); + goto error; + } + + dbgf(2,"Storage info is %d\n",group_info.storage_type); + if(s->old_style_grp) { + if(group_info.storage_type != H5G_STORAGE_TYPE_SYMBOL_TABLE) { + H5_FAILED(); AT(); + printf("Reader - Old-styled group: but the group is not in old-style. \n"); + goto error; + } + dbgf(2,"Reader: verify that the group is created with the old-style.\n"); + } + else { + if(group_info.storage_type == H5G_STORAGE_TYPE_SYMBOL_TABLE) { + H5_FAILED(); AT(); + printf("Reader - The created group should NOT be in old-style . \n"); + goto error; + } + dbgf(2,"Reader: verify that the group is created with the new-style.\n"); + + } + + /* Reader sends an OK message back to the reader */ + if(s->use_named_pipes && s->attr_test == true) { + + if(np_rd_send(s)==false) + goto error; + dbgf(1, "Reader: finish sending back the message: %d\n",s->np_notify); + + } + + /* Check if we need to skip the attribute test for this group. */ if (s->asteps != 0 && which % s->asteps == 0) - result = verify_group_attribute(g, which); + result = verify_group_attribute(s, g, which); else result = true; @@ -334,11 +2899,19 @@ verify_group(state_t *s, unsigned int which) return result; error: + H5E_BEGIN_TRY { H5Gclose(g); } H5E_END_TRY; + /* The reader sends an error message to the writer to stop the test.*/ + if(s->use_named_pipes && s->attr_test == true) + np_send_error(s,false); + +error2: + return false; + } int @@ -354,7 +2927,8 @@ main(int argc, char **argv) const char *fifo_reader_to_writer = "./fifo_group_reader_to_writer"; int fd_writer_to_reader = -1, fd_reader_to_writer = -1; int notify = 0, verify = 0; - unsigned int i; + bool wg_ret = false; + bool vg_ret = false; if (!state_init(&s, argc, argv)) { H5_FAILED(); AT(); @@ -362,11 +2936,13 @@ main(int argc, char **argv) goto error; } - personality = strstr(s.progname, "vfd_swmr_group_"); + personality = HDstrstr(s.progname, "vfd_swmr_group_"); - if (personality != NULL && strcmp(personality, "vfd_swmr_group_writer") == 0) + if (personality != NULL && + HDstrcmp(personality, "vfd_swmr_group_writer") == 0) writer = true; - else if (personality != NULL && strcmp(personality, "vfd_swmr_group_reader") == 0) + else if (personality != NULL && + HDstrcmp(personality, "vfd_swmr_group_reader") == 0) writer = false; else { H5_FAILED(); AT(); @@ -377,8 +2953,12 @@ main(int argc, char **argv) /* config, tick_len, max_lag, writer, flush_raw_data, md_pages_reserved, md_file_path */ init_vfd_swmr_config(&config, 4, 7, writer, FALSE, 128, "./group-shadow"); - /* use_latest_format, use_vfd_swmr, only_meta_page, config */ - if ((fapl = vfd_swmr_create_fapl(true, s.use_vfd_swmr, true, &config)) < 0) { + /* If old-style option is chosen, use the earliest file format(H5F_LIBVER_EARLIEST) + * as the second parameter of H5Pset_libver_bound() that is called by + * vfd_swmr_create_fapl. Otherwise, the latest file format(H5F_LIBVER_LATEST) + * should be used as the second parameter of H5Pset_libver_bound(). + * Also pass the use_vfd_swmr, only_meta_page, config to vfd_swmr_create_fapl().*/ + if ((fapl = vfd_swmr_create_fapl(!s.old_style_grp, s.use_vfd_swmr, true, &config)) < 0) { H5_FAILED(); AT(); printf("vfd_swmr_create_fapl failed\n"); goto error; @@ -440,123 +3020,94 @@ main(int argc, char **argv) goto error; } + /* Pass the named pipe information to the struct of state_t s, for attribute tests.*/ + if(s.use_named_pipes) { + s.np_fd_w_to_r = fd_writer_to_reader; + s.np_fd_r_to_w = fd_reader_to_writer; + s.np_notify = notify; + s.np_verify = verify; + s.tick_len = config.tick_len; + s.max_lag = config.max_lag; + } + + /* For attribute test, force the named pipe to communicate in every step. + * This will avoid the fake verification error from the reader when using the named pipe. + * If the named pipe is not forced to communicate in every step, the reader may go ahead + * to verify the group and the attribute operations before the writer has a chance to + * carry out the corresponding operations. */ + if (s.at_pattern != ' ') { + s.attr_test = true; + if(s.use_named_pipes) + s.csteps = 1; + } + if (writer) { for (step = 0; step < s.nsteps; step++) { dbgf(2, "writer: step %d\n", step); - if (!write_group(&s, step)) { + wg_ret = write_group(&s, step); + + if(wg_ret == false) { H5_FAILED(); AT(); - printf("write_group failed\n"); + printf("write_group failed at step %d\n",step); /* At communication interval, notifies the reader about the failture and quit */ - if (s.use_named_pipes && (step % s.csteps == 0)) { - notify = -1; - HDwrite(fd_writer_to_reader, ¬ify, sizeof(int)); - } - + if (s.use_named_pipes && s.attr_test !=true && step % s.csteps == 0) + np_send_error(&s,true); goto error; - } else { - /* At communication interval, notifies the reader and waits for its response */ - if (s.use_named_pipes && (step % s.csteps == 0)) { - /* Bump up the value of notify to notice the reader to start to read */ - notify++; - if (HDwrite(fd_writer_to_reader, ¬ify, sizeof(int)) < 0) { - H5_FAILED(); AT(); - printf("HDwrite failed\n"); - goto error; - } - - /* During the wait, writer makes repeated HDF5 API calls - * to trigger EOT at approximately the correct time */ - for(i = 0; i < config.max_lag + 1; i++) { - decisleep(config.tick_len); - H5E_BEGIN_TRY { - H5Aexists(s.file, "nonexistent"); - } H5E_END_TRY; - } - - /* Receive the same value from the reader and verify it before - * going to the next step */ - verify++; - if (HDread(fd_reader_to_writer, ¬ify, sizeof(int)) < 0) { - H5_FAILED(); AT(); - printf("HDread failed\n"); - goto error; - } + } + else { - if (notify == -1) { - H5_FAILED(); AT(); - printf("reader failed to verify group\n"); - goto error; - } + /* At communication interval, notifies the reader and waits for its response */ + if (s.use_named_pipes && s.attr_test != true && step % s.csteps == 0) { - if (notify != verify) { + if(np_wr_send_receive(&s) == false) { H5_FAILED(); AT(); - printf("received message %d, expecting %d\n", notify, verify); + dbgf(2, "writer: write group - verification failed.\n"); goto error; } } } } - } - else { - for (step = 0; step < s.nsteps; step++) { - dbgf(2, "reader: step %d\n", step); - - /* At communication interval, waits for the writer to finish creation before starting verification - */ - if (s.use_named_pipes && (step % s.csteps == 0)) { - /* The writer should have bumped up the value of notify. - * Do the same with verify and confirm it */ - verify++; - - /* Receive the notify that the writer bumped up the value */ - if (HDread(fd_writer_to_reader, ¬ify, sizeof(int)) < 0) { - H5_FAILED(); AT(); - printf("HDread failed\n"); - goto error; - } - - if (notify == -1) { - H5_FAILED(); AT(); - printf("writer failed to create group\n"); - goto error; - } + } else { + for (step = 0; step < s.nsteps;step++) { + dbgf(1, "reader: step %d\n", step); - if (notify != verify) { + /* At communication interval, waits for the writer to finish creation before starting verification */ + if (s.use_named_pipes && s.attr_test != true && step % s.csteps == 0) { + if(false == np_rd_receive(&s)) { H5_FAILED(); AT(); - printf("received message %d, expecting %d\n", notify, verify); goto error; } } - /* Wait for a few ticks for the update to happen */ - if (s.use_named_pipes) + /* For the default test, wait for a few ticks for the update to happen */ + if(s.use_named_pipes && s.attr_test== false) decisleep(config.tick_len * s.update_interval); - /* Start to verify group */ - if (!verify_group(&s, step)) { - H5_FAILED(); AT(); + vg_ret = verify_group(&s, step); + + if (vg_ret == false) { + printf("verify_group failed\n"); + H5_FAILED(); AT(); /* At communication interval, tell the writer about the failure and exit */ - if (s.use_named_pipes && (step % s.csteps == 0)) { - notify = -1; - HDwrite(fd_reader_to_writer, ¬ify, sizeof(int)); - } - + if (s.use_named_pipes && s.attr_test != true && step % s.csteps == 0) + np_send_error(&s,false); goto error; - } else { - if (s.use_named_pipes && (step % s.csteps == 0)) { - /* Send back the same nofity value for acknowledgement to tell the writer - * move to the next step */ - if (HDwrite(fd_reader_to_writer, ¬ify, sizeof(int)) < 0) { - H5_FAILED(); AT(); - printf("HDwrite failed\n"); + + } + else { + + /* Send back the same nofity value for acknowledgement to tell the writer + * move to the next step. */ + if (s.use_named_pipes && s.attr_test!=true && step % s.csteps == 0) { + if(np_rd_send(&s)==false) goto error; - } } } + } } @@ -572,6 +3123,12 @@ main(int argc, char **argv) goto error; } + if (H5Sclose(s.one_by_one_sid) < 0) { + H5_FAILED(); AT(); + printf("H5Sclose failed\n"); + goto error; + } + if (H5Fclose(s.file) < 0) { H5_FAILED(); AT(); printf("H5Fclose failed\n"); @@ -612,6 +3169,7 @@ error: H5E_BEGIN_TRY { H5Pclose(fapl); H5Pclose(fcpl); + H5Sclose(s.one_by_one_sid); H5Fclose(s.file); } H5E_END_TRY; @@ -627,6 +3185,7 @@ error: } return EXIT_FAILURE; + } #else /* H5_HAVE_WIN32_API */ |