summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlrknox <lrknox>2016-12-23 20:05:04 (GMT)
committerlrknox <lrknox>2016-12-23 20:05:04 (GMT)
commitc2492712037dcf7353601410cb4a83776de92441 (patch)
tree386c291c03cbd61b6b7d5b68c9203fcbce6f7c15
parenta659d6ed5aaf658f08da621c0dee078e894cc9d3 (diff)
parent96c28287935c50693e19d473537b4f58692a30f8 (diff)
downloadhdf5-c2492712037dcf7353601410cb4a83776de92441.zip
hdf5-c2492712037dcf7353601410cb4a83776de92441.tar.gz
hdf5-c2492712037dcf7353601410cb4a83776de92441.tar.bz2
Merge branch 'develop' of https://bitbucket.hdfgroup.org/scm/~lrknox/hdf5_lrk into develop
-rw-r--r--MANIFEST4
-rw-r--r--configure.ac1
-rw-r--r--hl/tools/h5watch/Makefile.am8
-rw-r--r--hl/tools/h5watch/extend_dset.c62
-rw-r--r--java/src/hdf/hdf5lib/H5.java11
-rw-r--r--java/src/hdf/hdf5lib/HDF5Constants.java6
-rw-r--r--java/src/jni/h5Constants.c4
-rw-r--r--java/src/jni/h5fImp.c13
-rw-r--r--java/src/jni/h5fImp.h9
-rw-r--r--java/test/CMakeLists.txt1
-rw-r--r--java/test/JUnit-interface.txt4
-rw-r--r--java/test/Makefile.am1
-rw-r--r--java/test/TestAll.java2
-rw-r--r--java/test/TestH5Fswmr.java118
-rw-r--r--src/H5Ocache.c6
-rw-r--r--src/H5Opkg.h6
-rw-r--r--test/CMakeLists.txt19
-rw-r--r--test/CMakeTests.cmake34
-rw-r--r--test/Makefile.am24
-rw-r--r--test/accum.c224
-rw-r--r--test/accum_swmr_reader.c99
-rw-r--r--test/cork.c165
-rw-r--r--test/dsets.c2
-rw-r--r--test/flush1.c61
-rw-r--r--test/flush2.c173
-rw-r--r--test/flushrefresh.c1151
-rw-r--r--test/h5test.c121
-rw-r--r--test/h5test.h3
-rw-r--r--test/links.c101
-rw-r--r--test/ohdr.c155
-rw-r--r--test/testflushrefresh.sh.in200
-rw-r--r--test/tfile.c6
-rw-r--r--tools/test/h5ls/CMakeTests.cmake21
-rw-r--r--tools/test/h5ls/testh5ls.sh.in59
34 files changed, 2698 insertions, 176 deletions
diff --git a/MANIFEST b/MANIFEST
index ae8e0a3..0c0c4fd 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -884,6 +884,7 @@
./test/H5srcdir_str.h.in
./test/Makefile.am
./test/accum.c
+./test/accum_swmr_reader.c
./test/app_ref.c
./test/bad_compound.h5
./test/be_data.h5
@@ -942,6 +943,7 @@
./test/filter_fail.c
./test/flush1.c
./test/flush2.c
+./test/flushrefresh.c
./test/gen_bad_ohdr.c
./test/gen_bad_compound.c
./test/gen_bogus.c
@@ -1009,6 +1011,7 @@
./test/testcheck_version.sh.in
./test/testerror.sh.in
./test/testlinks_env.sh.in
+./test/testflushrefresh.sh.in
./test/testframe.c
./test/testhdf5.c
./test/testhdf5.h
@@ -2882,6 +2885,7 @@
./java/test/TestH5Fparams.java
./java/test/TestH5Fbasic.java
./java/test/TestH5F.java
+./java/test/TestH5Fswmr.java
./java/test/TestH5Gbasic.java
./java/test/TestH5G.java
./java/test/TestH5Giterate.java
diff --git a/configure.ac b/configure.ac
index f4c5855..82ad020 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3317,6 +3317,7 @@ AC_CONFIG_FILES([src/libhdf5.settings
test/Makefile
test/testcheck_version.sh
test/testerror.sh
+ test/testflushrefresh.sh
test/H5srcdir_str.h
test/testlibinfo.sh
test/testlinks_env.sh
diff --git a/hl/tools/h5watch/Makefile.am b/hl/tools/h5watch/Makefile.am
index a5891ef..35a08e6 100644
--- a/hl/tools/h5watch/Makefile.am
+++ b/hl/tools/h5watch/Makefile.am
@@ -37,6 +37,14 @@ h5watch_LDFLAGS = $(LT_STATIC_EXEC) $(AM_LDFLAGS)
# Programs all depend on the hdf5 library, the tools library, and the HL
# library.
LDADD=$(LIBH5_HL) $(LIBH5TOOLS) $(LIBHDF5)
+
+# Add extend_dset specific preprocessor flags here
+# (add the main test subdirectory to the include file path)
+extend_dset_CPPFLAGS=$(AM_CPPFLAGS) -I$(top_srcdir)/test
+# Add extend_dset specific library flags here
+# (add the main test library to the list of libraries)
+extend_dset_LDADD=$(LDADD) $(LIBH5TEST)
+
#
CHECK_CLEANFILES+=*.h5
DISTCLEANFILES=testh5watch.sh
diff --git a/hl/tools/h5watch/extend_dset.c b/hl/tools/h5watch/extend_dset.c
index 023e201..4038a4f 100644
--- a/hl/tools/h5watch/extend_dset.c
+++ b/hl/tools/h5watch/extend_dset.c
@@ -14,6 +14,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "H5HLprivate2.h"
+#include "h5test.h"
/*
* Extending datasets in WATCH.h5 generated by h5watchgentest.c
@@ -30,8 +31,6 @@
#define WRITER_MESSAGE "writer_message"
/* The message received from the test script to start extending dataset */
#define READER_MESSAGE "reader_message"
-/* Message timeout in seconds */
-#define MESSAGE_TIMEOUT 300
/* Size of data buffer */
#define TEST_BUF_SIZE 100
@@ -57,8 +56,6 @@ int two_tests[TWO_NTESTS][2] = { {2, 2}, {2, -11}, {2, 0},
static herr_t extend_dset_two(const char *file, char *dname);
static herr_t extend_dset_one(const char *file, char *dname);
-void send_message(const char *file);
-static herr_t wait_message(const char *file);
/* Data structures for datasets with compound data type */
@@ -87,55 +84,6 @@ typedef struct set_t {
} set_t;
/*
- * To send a message by creating the file.
- */
-void
-send_message(const char *file)
-{
- FILE *id;
-
- id = HDfopen(file, "w+");
- HDfclose(id);
-} /* end send_message() */
-
-/*
- *
- * Repeatedly check for the message file.
- * It will stop when the file exists or exceeds the timeout limit.
- */
-static herr_t
-wait_message(const char *file)
-{
- FILE *id; /* File pointer */
- time_t t0, t1; /* Time info */
-
- /* Start timer */
- HDtime(&t0);
-
- /* Wait for message from test script to start work */
- while((id = HDfopen(file, "r")) == NULL) {
- /* Get current time */
- HDtime(&t1);
- /*
- * Determine time difference--
- * if waiting too long for the message, then it is
- * unlikely the message will get sent, then fail rather
- * than loop forever.
- */
- if(HDdifftime(t1, t0) > MESSAGE_TIMEOUT)
- goto error;
- } /* end while */
-
- HDfclose(id);
- HDunlink(file);
-
- return SUCCEED;
-
-error:
- return FAIL;
-} /* end wait_message() */
-
-/*
***********************************************************************
*
* Extending a two-dimensional dataset:
@@ -198,7 +146,7 @@ extend_dset_two(const char *file, char *dname)
goto error;
/* Send message to the test script to start "h5watch" */
- send_message(WRITER_MESSAGE);
+ h5_send_message(WRITER_MESSAGE, NULL, NULL);
if((sid = H5Dget_space(did)) < 0)
goto error;
@@ -215,7 +163,7 @@ extend_dset_two(const char *file, char *dname)
goto error;
/* Wait for message from the test script to start extending dataset */
- if(wait_message(READER_MESSAGE) < 0)
+ if(h5_wait_message(READER_MESSAGE) < 0)
goto error;
/* Loop through different variations of extending the dataset */
@@ -355,7 +303,7 @@ extend_dset_one(const char *file, char *dname)
goto error;
/* Send message to the test script to start "h5watch" */
- send_message(WRITER_MESSAGE);
+ h5_send_message(WRITER_MESSAGE, NULL, NULL);
if((did = H5Dopen2(fid, dname, H5P_DEFAULT)) < 0)
goto error;
@@ -369,7 +317,7 @@ extend_dset_one(const char *file, char *dname)
goto error;
/* Wait for message from the test script to start extending dataset */
- if(wait_message(READER_MESSAGE) < 0)
+ if(h5_wait_message(READER_MESSAGE) < 0)
goto error;
/* Loop through different variations of extending the dataset */
diff --git a/java/src/hdf/hdf5lib/H5.java b/java/src/hdf/hdf5lib/H5.java
index cd5793d..6b2af4b 100644
--- a/java/src/hdf/hdf5lib/H5.java
+++ b/java/src/hdf/hdf5lib/H5.java
@@ -2853,6 +2853,17 @@ public class H5 implements java.io.Serializable {
public synchronized static native void H5Fclear_elink_file_cache(long file_id) throws HDF5LibraryException;
/**
+ * H5Fstart_swmr_write will activate SWMR writing mode for a file associated with file_id. This routine will
+ * prepare and ensure the file is safe for SWMR writing.
+ *
+ * @param file_id
+ * IN: Identifier of the target file.
+ *
+ * @exception HDF5LibraryException
+ * - Error from the HDF-5 Library.
+ **/
+ public synchronized static native void H5Fstart_swmr_write(long file_id) throws HDF5LibraryException;
+
/**
* H5Fstart_mdc_logging starts logging metadata cache events if logging was previously enabled.
*
diff --git a/java/src/hdf/hdf5lib/HDF5Constants.java b/java/src/hdf/hdf5lib/HDF5Constants.java
index 8089544..acd3eb5 100644
--- a/java/src/hdf/hdf5lib/HDF5Constants.java
+++ b/java/src/hdf/hdf5lib/HDF5Constants.java
@@ -201,6 +201,8 @@ public class HDF5Constants {
public static final int H5F_ACC_RDWR = H5F_ACC_RDWR();
public static final int H5F_ACC_TRUNC = H5F_ACC_TRUNC();
public static final int H5F_ACC_DEFAULT = H5F_ACC_DEFAULT();
+ public static final int H5F_ACC_SWMR_READ = H5F_ACC_SWMR_READ();
+ public static final int H5F_ACC_SWMR_WRITE = H5F_ACC_SWMR_WRITE();
public static final int H5F_CLOSE_DEFAULT = H5F_CLOSE_DEFAULT();
public static final int H5F_CLOSE_SEMI = H5F_CLOSE_SEMI();
public static final int H5F_CLOSE_STRONG = H5F_CLOSE_STRONG();
@@ -984,6 +986,10 @@ public class HDF5Constants {
private static native final int H5F_ACC_DEFAULT();
+ private static native final int H5F_ACC_SWMR_READ();
+
+ private static native final int H5F_ACC_SWMR_WRITE();
+
private static native final int H5F_CLOSE_DEFAULT();
private static native final int H5F_CLOSE_SEMI();
diff --git a/java/src/jni/h5Constants.c b/java/src/jni/h5Constants.c
index ffde130..976a224 100644
--- a/java/src/jni/h5Constants.c
+++ b/java/src/jni/h5Constants.c
@@ -363,6 +363,10 @@ JNIEXPORT jint JNICALL
Java_hdf_hdf5lib_HDF5Constants_H5F_1ACC_1TRUNC(JNIEnv *env, jclass cls) { return H5F_ACC_TRUNC; }
JNIEXPORT jint JNICALL
Java_hdf_hdf5lib_HDF5Constants_H5F_1ACC_1DEFAULT(JNIEnv *env, jclass cls) { return H5F_ACC_DEFAULT; }
+JNIEXPORT jint JNICALL
+Java_hdf_hdf5lib_HDF5Constants_H5F_1ACC_1SWMR_1READ(JNIEnv *env, jclass cls) { return H5F_ACC_SWMR_READ; }
+JNIEXPORT jint JNICALL
+Java_hdf_hdf5lib_HDF5Constants_H5F_1ACC_1SWMR_1WRITE(JNIEnv *env, jclass cls) { return H5F_ACC_SWMR_WRITE; }
#pragma GCC diagnostic pop
JNIEXPORT jint JNICALL
diff --git a/java/src/jni/h5fImp.c b/java/src/jni/h5fImp.c
index d4b3a3c..058ba26 100644
--- a/java/src/jni/h5fImp.c
+++ b/java/src/jni/h5fImp.c
@@ -538,6 +538,19 @@ Java_hdf_hdf5lib_H5_H5Fclear_1elink_1file_1cache
/*
* Class: hdf_hdf5lib_H5
+ * Method: H5Fstart_swmr_write
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_hdf_hdf5lib_H5_H5Fstart_1swmr_1write
+ (JNIEnv *env, jclass cls, jlong file_id)
+{
+ if (H5Fstart_swmr_write((hid_t)file_id) < 0)
+ h5libraryError(env);
+} /* end Java_hdf_hdf5lib_H5_H5Fstart_1swmr_1write */
+
+/*
+ * Class: hdf_hdf5lib_H5
* Method: H5Fstart_mdc_logging
* Signature: (J)V
*/
diff --git a/java/src/jni/h5fImp.h b/java/src/jni/h5fImp.h
index b88e491..7aff835 100644
--- a/java/src/jni/h5fImp.h
+++ b/java/src/jni/h5fImp.h
@@ -214,6 +214,15 @@ Java_hdf_hdf5lib_H5_H5Fclear_1elink_1file_1cache
/*
* Class: hdf_hdf5lib_H5
+ * Method: H5Fstart_swmr_write
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL
+Java_hdf_hdf5lib_H5_H5Fstart_1swmr_1write
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: hdf_hdf5lib_H5
* Method: H5Fstart_mdc_logging
* Signature: (J)V
*/
diff --git a/java/test/CMakeLists.txt b/java/test/CMakeLists.txt
index 8cb41f7..b3a996b 100644
--- a/java/test/CMakeLists.txt
+++ b/java/test/CMakeLists.txt
@@ -16,6 +16,7 @@ set (HDF5_JAVA_TEST_SOURCES
TestH5Fparams.java
TestH5Fbasic.java
TestH5F.java
+ TestH5Fswmr.java
TestH5Gbasic.java
TestH5G.java
TestH5Giterate.java
diff --git a/java/test/JUnit-interface.txt b/java/test/JUnit-interface.txt
index 05814cd..7fd80f8 100644
--- a/java/test/JUnit-interface.txt
+++ b/java/test/JUnit-interface.txt
@@ -93,6 +93,8 @@ JUnit version 4.11
.testH5Fget_intent_rdonly
.testH5Fget_create_plist
.testH5Fget_obj_count
+.testH5Fstart_swmr_write
+.testH5Fswmr_read_attempts
.testH5Gget_info_by_name_not_exists
.testH5Gget_info_by_idx_not_exists
.testH5Gget_info_by_name
@@ -635,7 +637,7 @@ JUnit version 4.11
Time: XXXX
-OK (633 tests)
+OK (635 tests)
HDF5-DIAG: Error detected in HDF5 (version (number)) thread (IDs):
#000: (file name) line (number) in H5Fopen(): can't set access and transfer property lists
diff --git a/java/test/Makefile.am b/java/test/Makefile.am
index 9f29f1c..92ac12d 100644
--- a/java/test/Makefile.am
+++ b/java/test/Makefile.am
@@ -43,6 +43,7 @@ noinst_JAVA = \
TestH5Fparams.java \
TestH5Fbasic.java \
TestH5F.java \
+ TestH5Fswmr.java \
TestH5Gbasic.java \
TestH5G.java \
TestH5Giterate.java \
diff --git a/java/test/TestAll.java b/java/test/TestAll.java
index e3abe21..a4b44c3 100644
--- a/java/test/TestAll.java
+++ b/java/test/TestAll.java
@@ -23,7 +23,7 @@ import org.junit.runners.Suite;
TestH5Eregister.class,
TestH5Edefault.class,
TestH5E.class,
- TestH5Fparams.class, TestH5Fbasic.class, TestH5F.class,
+ TestH5Fparams.class, TestH5Fbasic.class, TestH5F.class, TestH5Fswmr.class,
TestH5Gbasic.class, TestH5G.class, TestH5Giterate.class,
TestH5Sbasic.class, TestH5S.class,
TestH5Tparams.class, TestH5Tbasic.class, TestH5T.class,
diff --git a/java/test/TestH5Fswmr.java b/java/test/TestH5Fswmr.java
new file mode 100644
index 0000000..b65ebf2
--- /dev/null
+++ b/java/test/TestH5Fswmr.java
@@ -0,0 +1,118 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+package test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+
+import hdf.hdf5lib.H5;
+import hdf.hdf5lib.HDF5Constants;
+import hdf.hdf5lib.exceptions.HDF5LibraryException;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+public class TestH5Fswmr {
+ @Rule public TestName testname = new TestName();
+ private static final String H5_FILE = "testswmr.h5";
+
+ long H5fid = -1;
+ long H5fapl = -1;
+ long H5fcpl = -1;
+
+ private final void _deleteFile(String filename) {
+ File file = new File(filename);
+
+ if (file.exists()) {
+ try {file.delete();} catch (SecurityException e) {}
+ }
+ }
+
+ @Before
+ public void createH5file()
+ throws HDF5LibraryException, NullPointerException {
+ assertTrue("H5 open ids is 0",H5.getOpenIDCount()==0);
+ System.out.print(testname.getMethodName());
+
+ H5fapl = H5.H5Pcreate(HDF5Constants.H5P_FILE_ACCESS);
+ H5fcpl = H5.H5Pcreate(HDF5Constants.H5P_FILE_CREATE);
+ H5.H5Pset_libver_bounds(H5fapl, HDF5Constants.H5F_LIBVER_LATEST, HDF5Constants.H5F_LIBVER_LATEST);
+
+ H5fid = H5.H5Fcreate(H5_FILE, HDF5Constants.H5F_ACC_TRUNC, H5fcpl, H5fapl);
+ H5.H5Fflush(H5fid, HDF5Constants.H5F_SCOPE_LOCAL);
+ }
+
+ @After
+ public void deleteH5file() throws HDF5LibraryException {
+ if (H5fapl > 0) {
+ try {H5.H5Pclose(H5fapl);} catch (Exception ex) {}
+ H5fapl = -1;
+ }
+ if (H5fcpl > 0) {
+ try {H5.H5Pclose(H5fcpl);} catch (Exception ex) {}
+ H5fcpl = -1;
+ }
+ if (H5fid > 0) {
+ try {H5.H5Fclose(H5fid);} catch (Exception ex) {}
+ H5fid = -1;
+ }
+ _deleteFile(H5_FILE);
+ System.out.println();
+ }
+
+ @Test
+ public void testH5Fstart_swmr_write() {
+ try {
+ H5.H5Fstart_swmr_write(H5fid);
+ }
+ catch (Throwable err) {
+ fail("H5.H5Fstart_swmr_write: " + err);
+ }
+ }
+
+ @Test
+ public void testH5Fswmr_read_attempts() {
+ long read_attempts = 0;
+
+ try {
+ read_attempts = H5.H5Pget_metadata_read_attempts(H5fapl);
+ }
+ catch (Throwable err) {
+ fail("H5.testH5Fswmr_read_attempts: " + err);
+ }
+ assertTrue(read_attempts == 1);
+
+ try {
+ H5.H5Pset_metadata_read_attempts(H5fapl, 20);
+ }
+ catch (Throwable err) {
+ fail("H5.testH5Fswmr_read_attempts: " + err);
+ }
+ try {
+ read_attempts = H5.H5Pget_metadata_read_attempts(H5fapl);
+ }
+ catch (Throwable err) {
+ fail("H5.testH5Fswmr_read_attempts: " + err);
+ }
+ assertTrue(read_attempts == 20);
+ }
+}
diff --git a/src/H5Ocache.c b/src/H5Ocache.c
index 94498ee..d398e41 100644
--- a/src/H5Ocache.c
+++ b/src/H5Ocache.c
@@ -46,12 +46,6 @@
/* Local Macros */
/****************/
-/* Set the object header size to speculatively read in */
-/* (needs to be more than the object header prefix size to work at all and
- * should be larger than the largest object type's default object header
- * size to save the extra I/O operations) */
-#define H5O_SPEC_READ_SIZE 512
-
/******************/
/* Local Typedefs */
diff --git a/src/H5Opkg.h b/src/H5Opkg.h
index e778f90..ef49535 100644
--- a/src/H5Opkg.h
+++ b/src/H5Opkg.h
@@ -217,6 +217,12 @@
#define H5O_SHARE_IS_SHARABLE 0x01
#define H5O_SHARE_IN_OHDR 0x02
+/* Set the object header size to speculatively read in */
+/* (needs to be more than the object header prefix size to work at all and
+ * should be larger than the largest object type's default object header
+ * size to save the extra I/O operations) */
+#define H5O_SPEC_READ_SIZE 512
+
/* The "message class" type */
struct H5O_msg_class_t {
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5a55616..35884d0 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -196,7 +196,6 @@ MACRO (ADD_H5_EXE file)
ENDMACRO (ADD_H5_EXE file)
set (H5_TESTS
- #testhdf5
cache
cache_api
cache_tagging
@@ -211,7 +210,6 @@ set (H5_TESTS
fheap
pool
accum
- #hyperslab
istore
bittests
dt_arith
@@ -234,7 +232,6 @@ set (H5_TESTS
app_ref
enum
set_extent
- #ttsafe
enc_dec_plist
enc_dec_plist_cross_platform
getname
@@ -322,12 +319,28 @@ set (H5_CHECK_TESTS
tcheck_version
testmeta
links_env
+ flushrefresh
)
foreach (test ${H5_CHECK_TESTS})
ADD_H5_EXE(${test})
endforeach (test ${H5_CHECK_TESTS})
+#-- Adding test for accum_swmr_reader
+# This has to be copied to the test directory for execve() to find it
+# and it can't be renamed (i.e., no <foo>-shared).
+add_executable (accum_swmr_reader ${HDF5_TEST_SOURCE_DIR}/accum_swmr_reader.c)
+TARGET_NAMING (accum_swmr_reader STATIC)
+TARGET_C_PROPERTIES (accum_swmr_reader STATIC " " " ")
+target_link_libraries (accum_swmr_reader ${HDF5_LIB_TARGET} ${HDF5_TEST_LIB_TARGET})
+set_target_properties (accum_swmr_reader PROPERTIES FOLDER test)
+
+#-- Set accum dependencies
+set_target_properties (accum PROPERTIES DEPENDS accum_swmr_reader)
+if (BUILD_SHARED_LIBS)
+ set_target_properties (accum-shared PROPERTIES DEPENDS accum_swmr_reader)
+endif (BUILD_SHARED_LIBS)
+
#-- Adding test for libinfo
set (GREP_RUNNER ${PROJECT_BINARY_DIR}/GrepRunner.cmake)
file (WRITE ${GREP_RUNNER}
diff --git a/test/CMakeTests.cmake b/test/CMakeTests.cmake
index 3fc0fb6..5b3d0bf 100644
--- a/test/CMakeTests.cmake
+++ b/test/CMakeTests.cmake
@@ -43,6 +43,21 @@ set (HDF5_TEST_FILES
tnullspace.h5
)
+add_custom_command (
+ TARGET accum_swmr_reader
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy_if_different "$<TARGET_FILE:accum_swmr_reader>" "${PROJECT_BINARY_DIR}/H5TEST/accum_swmr_reader"
+)
+if (BUILD_SHARED_LIBS)
+ add_custom_command (
+ TARGET accum_swmr_reader
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy_if_different "$<TARGET_FILE:accum_swmr_reader>" "${PROJECT_BINARY_DIR}/H5TEST-shared/accum_swmr_reader"
+ )
+endif (BUILD_SHARED_LIBS)
+
foreach (h5_tfile ${HDF5_TEST_FILES})
HDFTEST_COPY_FILE("${HDF5_TOOLS_DIR}/testfiles/${h5_tfile}" "${PROJECT_BINARY_DIR}/H5TEST/${h5_tfile}" "HDF5_TEST_LIB_files")
if (BUILD_SHARED_LIBS)
@@ -425,6 +440,13 @@ set (test_CLEANFILES
tvlstr.h5
tvlstr2.h5
flush.h5
+ flush-swmr.h5
+ noflush.h5
+ noflush-swmr.h5
+ flush_extend.h5
+ flush_extend-swmr.h5
+ noflush_extend.h5
+ noflush_extend-swmr.h5
enum1.h5
titerate.h5
ttsafe.h5
@@ -493,6 +515,13 @@ set (test_CLEANFILES
vds_src_0.h5
vds_src_1.h5
tbogus.h5.copy
+ flushrefresh.h5
+ flushrefresh_VERIFICATION_START
+ flushrefresh_VERIFICATION_CHECKPOINT1
+ flushrefresh_VERIFICATION_CHECKPOINT2
+ flushrefresh_VERIFICATION_DONE
+ accum_swmr_big.h5
+ ohdr_swmr.h5
cache_logging.h5
cache_logging.out
)
@@ -854,6 +883,11 @@ set_tests_properties (H5PLUGIN-plugin PROPERTIES
)
##############################################################################
+### S W M R T E S T S
+##############################################################################
+# testflushrefresh.sh: flushrefresh
+
+##############################################################################
##############################################################################
### V F D T E S T S ###
##############################################################################
diff --git a/test/Makefile.am b/test/Makefile.am
index 380043a..da89b22 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -28,8 +28,11 @@ AM_CPPFLAGS+=-I$(top_srcdir)/src -I$(top_builddir)/src
# testlibinfo.sh:
# testcheck_version.sh: tcheck_version
# tetlinks_env.sh: links_env
-TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh
-SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT)
+# testflushrefresh.sh: flushrefresh
+TEST_SCRIPT = testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh \
+ testflushrefresh.sh
+SCRIPT_DEPEND = error_test$(EXEEXT) err_compat$(EXEEXT) links_env$(EXEEXT) \
+ testflushrefresh.sh
if HAVE_SHARED_CONDITIONAL
TEST_SCRIPT += test_plugin.sh
SCRIPT_DEPEND += plugin$(EXEEXT)
@@ -53,13 +56,15 @@ TEST_PROG= testhdf5 cache cache_api cache_tagging lheap ohdr stab gheap \
# List programs to be built when testing here.
# error_test and err_compat are built at the same time as the other tests, but executed by testerror.sh.
# tcheck_version is used by testcheck_version.sh.
+# accum_swmr_reader is used by accum.c.
# links_env is used by testlinks_env.sh
+# flushrefresh is used by testflushrefresh.sh.
# 'make check' doesn't run them directly, so they are not included in TEST_PROG.
# Also build testmeta, which is used for timings test. It builds quickly,
# and this lets automake keep all its test programs in one place.
check_PROGRAMS=$(TEST_PROG) error_test err_compat tcheck_version \
- testmeta \
- links_env
+ testmeta accum_swmr_reader \
+ links_env flushrefresh
if HAVE_SHARED_CONDITIONAL
check_PROGRAMS+= plugin
endif
@@ -147,7 +152,9 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse
stdio.h5 sec2.h5 dtypes[0-9].h5 dtypes1[0].h5 dt_arith[1-2].h5 tattr.h5 \
tselect.h5 mtime.h5 unlink.h5 unicode.h5 coord.h5 \
fillval_[0-9].h5 fillval.raw mount_[0-9].h5 testmeta.h5 ttime.h5 \
- trefer[1-3].h5 tvltypes.h5 tvlstr.h5 tvlstr2.h5 flush.h5 \
+ trefer[1-3].h5 tvltypes.h5 tvlstr.h5 tvlstr2.h5 \
+ flush.h5 flush-swmr.h5 noflush.h5 noflush-swmr.h5 flush_extend.h5 \
+ flush_extend-swmr.h5 noflush_extend.h5 noflush_extend-swmr.h5 \
enum1.h5 titerate.h5 ttsafe.h5 tarray1.h5 tgenprop.h5 \
tmisc[0-9]*.h5 set_extent[1-5].h5 ext[12].bin \
getname.h5 getname[1-3].h5 sec2_file.h5 direct_file.h5 \
@@ -162,6 +169,9 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse
split_get_file_image_test-m.h5 split_get_file_image_test-r.h5 \
file_image_core_test.h5.copy unregister_filter_1.h5 unregister_filter_2.h5 \
vds_virt.h5 vds_dapl.h5 vds_src_[0-1].h5 \
+ flushrefresh.h5 flushrefresh_VERIFICATION_START \
+ flushrefresh_VERIFICATION_CHECKPOINT1 flushrefresh_VERIFICATION_CHECKPOINT2 \
+ flushrefresh_VERIFICATION_DONE accum_swmr_big.h5 ohdr_swmr.h5 \
cache_logging.h5 cache_logging.out \
swmr[0-2].h5
# Sources for testhdf5 executable
@@ -171,5 +181,7 @@ testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \
tvlstr.c tvltypes.c
# Temporary files.
-DISTCLEANFILES=testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh test_plugin.sh
+DISTCLEANFILES=testerror.sh testlibinfo.sh testcheck_version.sh testlinks_env.sh test_plugin.sh \
+ testflushrefresh.sh
+
include $(top_srcdir)/config/conclude.am
diff --git a/test/accum.c b/test/accum.c
index 3b9f9e6..1fcd051 100644
--- a/test/accum.c
+++ b/test/accum.c
@@ -18,13 +18,20 @@
#include "h5test.h"
#define H5F_FRIEND /*suppress error about including H5Fpkg */
+#define H5FD_FRIEND /*suppress error about including H5FDpkg */
+#define H5FD_TESTING
#include "H5Fpkg.h"
-#include "H5FDprivate.h"
+#include "H5FDpkg.h"
#include "H5Iprivate.h"
/* Filename */
#define FILENAME "accum.h5"
+/* The file name is the same as the define in accum_swmr_reader.c */
+#define SWMR_FILENAME "accum_swmr_big.h5"
+/* The reader forked by test_swmr_write_big() */
+#define SWMR_READER "accum_swmr_reader"
+
/* "big" I/O test values */
#define BIG_BUF_SIZE (6 * 1024 * 1024)
@@ -50,6 +57,7 @@ unsigned test_read_after(const H5F_io_info_t *fio_info);
unsigned test_free(const H5F_io_info_t *fio_info);
unsigned test_big(const H5F_io_info_t *fio_info);
unsigned test_random_write(const H5F_io_info_t *fio_info);
+unsigned test_swmr_write_big(hbool_t newest_format);
/* Helper Function Prototypes */
void accum_printf(void);
@@ -124,6 +132,10 @@ main(void)
if(H5Fclose(fid) < 0) TEST_ERROR
HDremove(FILENAME);
+ /* This test uses a different file */
+ nerrors += test_swmr_write_big(TRUE);
+ nerrors += test_swmr_write_big(FALSE);
+
if(nerrors)
goto error;
puts("All metadata accumulator tests passed.");
@@ -1777,6 +1789,216 @@ error:
return 1;
} /* end test_random_write() */
+/*-------------------------------------------------------------------------
+ * Function: test_swmr_write_big
+ *
+ * Purpose: A SWMR test: verifies that writing "large" metadata to a file
+ * opened with SWMR_WRITE will flush the existing metadata in the
+ * accumulator to disk first before writing the "large" metadata
+ * to disk.
+ * This test will fork and exec a reader "accum_swmr_reader" which
+ * opens the same file with SWMR_READ and verifies that the correct
+ * metadata is read from disk.
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi; April 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+test_swmr_write_big(hbool_t newest_format)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fapl = -1; /* File access property list */
+ H5F_t *rf = NULL; /* File pointer */
+ uint8_t *wbuf2 = NULL, *rbuf = NULL; /* Buffers for reading & writing */
+ uint8_t wbuf[1024]; /* Buffer for reading & writing */
+ unsigned u; /* Local index variable */
+#ifdef H5_HAVE_UNISTD_H
+ pid_t pid; /* Process ID */
+#endif /* H5_HAVE_UNISTD_H */
+ int status; /* Status returned from child process */
+ H5F_io_info_t fio_info; /* I/O info for operation */
+ char *new_argv[] = {NULL};
+ char *driver = NULL; /* VFD string (from env variable) */
+
+ if(newest_format) {
+ TESTING("SWMR write of large metadata: with latest format");
+ } else {
+ TESTING("SWMR write of large metadata: with non-latest-format");
+ } /* end if */
+
+#if !(defined(H5_HAVE_FORK) && defined(H5_HAVE_WAITPID))
+
+ SKIPPED();
+ HDputs(" Test skipped due to fork or waitpid not defined.");
+ return 0;
+
+#else /* defined(H5_HAVE_FORK && defined(H5_HAVE_WAITPID) */
+
+ /* Skip this test if SWMR I/O is not supported for the VFD specified
+ * by the environment variable.
+ */
+ driver = HDgetenv("HDF5_DRIVER");
+ if (!H5FD_supports_swmr_test(driver)) {
+ SKIPPED();
+ HDputs(" Test skipped due to VFD not supporting SWMR I/O.");
+ return 0;
+ } /* end if */
+
+ /* File access property list */
+ if((fapl = h5_fileaccess()) < 0)
+ FAIL_STACK_ERROR
+
+ /* Both cases will result in v3 superblock and version 2 object header for SWMR */
+ if(newest_format) { /* latest format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ if((fid = H5Fcreate(SWMR_FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+ } else { /* non-latest-format */
+ if((fid = H5Fcreate(SWMR_FILENAME, H5F_ACC_TRUNC|H5F_ACC_SWMR_WRITE, H5P_DEFAULT, fapl)) < 0)
+ FAIL_STACK_ERROR
+ } /* end if */
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Open the file with SWMR_WRITE */
+ if((fid = H5Fopen(SWMR_FILENAME, H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get H5F_t * to internal file structure */
+ if(NULL == (rf = (H5F_t *)H5I_object(fid))) FAIL_STACK_ERROR
+
+ /* Set up I/O info for operation */
+ fio_info.f = rf;
+ if(NULL == (fio_info.dxpl = (H5P_genplist_t *)H5I_object(H5AC_ind_read_dxpl_id)))
+ FAIL_STACK_ERROR
+
+ /* We'll be writing lots of garbage data, so extend the
+ file a ways. 10MB should do. */
+ if(H5FD_set_eoa(rf->shared->lf, H5FD_MEM_DEFAULT, (haddr_t)(1024*1024*10)) < 0)
+ FAIL_STACK_ERROR
+
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Reset metadata accumulator for the file */
+ if(accum_reset(&fio_info) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Allocate space for the write & read buffers */
+ if((wbuf2 = (uint8_t *)HDmalloc((size_t)BIG_BUF_SIZE)) == NULL)
+ FAIL_STACK_ERROR;
+ if((rbuf = (uint8_t *)HDmalloc((size_t)BIG_BUF_SIZE)) == NULL)
+ FAIL_STACK_ERROR;
+
+ /* Initialize wbuf with "0, 1, 2...1024"*/
+ for(u = 0; u < 1024; u++)
+ wbuf[u] = (uint8_t)u;
+
+ /* Write [1024, 1024] bytes with wbuf */
+ if(H5F_block_write(rf, H5FD_MEM_DEFAULT, (haddr_t)1024, (size_t)1024, H5AC_ind_read_dxpl_id, wbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Read the data */
+ if(H5F_block_read(rf, H5FD_MEM_DEFAULT, (haddr_t)1024, (size_t)1024, H5AC_ind_read_dxpl_id, rbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Verify the data read is correct */
+ if(HDmemcmp(wbuf, rbuf, (size_t)1024) != 0)
+ TEST_ERROR;
+ /* Flush the data to disk */
+ if(accum_reset(&fio_info) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Initialize wbuf with all 1s */
+ for(u = 0; u < 1024; u++)
+ wbuf[u] = (uint8_t)1;
+
+ /* Initialize wbuf2 */
+ for(u = 0; u < BIG_BUF_SIZE; u++)
+ wbuf2[u] = (uint8_t)(u + 1);
+
+ /* Write [1024,1024] with wbuf--all 1s */
+ if(H5F_block_write(rf, H5FD_MEM_DEFAULT, (haddr_t)1024, (size_t)1024, H5AC_ind_read_dxpl_id, wbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Read the data */
+ if(H5F_block_read(rf, H5FD_MEM_DEFAULT, (haddr_t)1024, (size_t)1024, H5AC_ind_read_dxpl_id, rbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Verify the data read is correct */
+ if(HDmemcmp(wbuf, rbuf, (size_t)1024) != 0)
+ TEST_ERROR;
+ /* The data stays in the accumulator */
+
+ /* Write a large piece of metadata [2048, BIG_BUF_SIZE] with wbuf2 */
+ if(H5F_block_write(rf, H5FD_MEM_DEFAULT, (haddr_t)2048, (size_t)BIG_BUF_SIZE, H5AC_ind_read_dxpl_id, wbuf2) < 0)
+ FAIL_STACK_ERROR;
+ /* Read the data */
+ if(H5F_block_read(rf, H5FD_MEM_DEFAULT, (haddr_t)2048, (size_t)BIG_BUF_SIZE, H5AC_ind_read_dxpl_id, rbuf) < 0)
+ FAIL_STACK_ERROR;
+ /* Verify the data read is correct */
+ if(HDmemcmp(wbuf2, rbuf, (size_t)BIG_BUF_SIZE) != 0)
+ TEST_ERROR;
+
+ /* Fork child process to verify that the data at [1024, 2014] does get written to disk */
+ if((pid = HDfork()) < 0) {
+ HDperror("fork");
+ FAIL_STACK_ERROR;
+ } else if(0 == pid) { /* Child process */
+ /* Run the reader */
+ status = HDexecv(SWMR_READER, new_argv);
+ printf("errno from execv = %s\n", strerror(errno));
+ FAIL_STACK_ERROR;
+ } /* end if */
+
+ /* Parent process -- wait for the child process to complete */
+ while(pid != HDwaitpid(pid, &status, 0))
+ /*void*/;
+
+ /* Check if child process terminates normally and its return value */
+ if(WIFEXITED(status) && !WEXITSTATUS(status)) {
+ /* Flush the accumulator */
+ if(accum_reset(&fio_info) < 0)
+ FAIL_STACK_ERROR;
+ /* Close the property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close and remove the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+ HDremove(SWMR_FILENAME);
+
+ /* Release memory */
+ if(wbuf2)
+ HDfree(wbuf2);
+ if(rbuf)
+ HDfree(rbuf);
+ PASSED();
+ return 0;
+ } /* end if */
+
+error:
+ /* Closing and remove the file */
+ H5Pclose(fapl);
+ H5Fclose(fid);
+ HDremove(SWMR_FILENAME);
+ /* Release memory */
+ if(wbuf2)
+ HDfree(wbuf2);
+ if(rbuf)
+ HDfree(rbuf);
+
+ return 1;
+
+#endif
+
+} /* end test_swmr_write_big() */
+
/*-------------------------------------------------------------------------
* Function: accum_printf
diff --git a/test/accum_swmr_reader.c b/test/accum_swmr_reader.c
new file mode 100644
index 0000000..d98fe70
--- /dev/null
+++ b/test/accum_swmr_reader.c
@@ -0,0 +1,99 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#include "h5test.h"
+
+#define H5F_FRIEND /*suppress error about including H5Fpkg */
+#define H5FD_FRIEND /*suppress error about including H5FDpkg */
+#define H5FD_TESTING
+
+#include "H5Fpkg.h"
+#include "H5FDpkg.h"
+#include "H5Iprivate.h"
+
+/* Filename: this is the same as the define in accum.c used by test_swmr_write_big() */
+#define SWMR_FILENAME "accum_swmr_big.h5"
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: This is the reader forked/execved by "test_swmr_write_big()"
+ * test in accum.c. The reader reads at address 1024 from the file
+ * and verifies that the metadata in the accumulator at address
+ * 1024 does get written to disk.
+ *
+ * Return: Success: EXIT_SUCCESS
+ * Failure: EXIT_FAILURE
+ *
+ * Programmer: Vailin Choi; June 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main(void)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fapl = -1; /* file access property list ID */
+ H5F_t *f = NULL; /* File pointer */
+ unsigned u; /* Local index variable */
+ uint8_t rbuf[1024]; /* Buffer for reading */
+ uint8_t buf[1024]; /* Buffer for holding the expected data */
+ char *driver = NULL; /* VFD string (from env variable) */
+
+ /* Skip this test if SWMR I/O is not supported for the VFD specified
+ * by the environment variable.
+ */
+ driver = HDgetenv("HDF5_DRIVER");
+ if(!H5FD_supports_swmr_test(driver)) {
+ return EXIT_SUCCESS;
+ }
+
+ /* Initialize buffers */
+ for(u = 0; u < 1024; u++) {
+ rbuf[u] = 0; /* The buffer for reading */
+ buf[u] = 1; /* The expected data should be all 1s */
+ }
+
+ if((fapl = h5_fileaccess()) < 0)
+ FAIL_STACK_ERROR
+
+ /* Open the file with SWMR_READ */
+ if((fid = H5Fopen(SWMR_FILENAME, H5F_ACC_RDONLY | H5F_ACC_SWMR_READ, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get H5F_t * to internal file structure */
+ if(NULL == (f = (H5F_t *)H5I_object(fid)))
+ FAIL_STACK_ERROR
+
+ /* Should read in [1024, 2024] with buf data */
+ if(H5F_block_read(f, H5FD_MEM_DEFAULT, (haddr_t)1024, (size_t)1024, H5AC_ind_read_dxpl_id, rbuf) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Verify the data read is correct */
+ if(HDmemcmp(buf, rbuf, (size_t)1024) != 0)
+ TEST_ERROR;
+
+ /* CLose the file */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR;
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ return EXIT_SUCCESS;
+
+error:
+ H5Fclose(fid);
+ return EXIT_FAILURE;
+} /* end main() */
+
diff --git a/test/cork.c b/test/cork.c
index 95f08b5..6cca163 100644
--- a/test/cork.c
+++ b/test/cork.c
@@ -66,14 +66,14 @@
/* ===================== */
/* Tests */
-static unsigned test_objs_cork(hbool_t new_format);
-static unsigned test_dset_cork(hbool_t new_format);
+static unsigned test_objs_cork(hbool_t swmr, hbool_t new_format);
+static unsigned test_dset_cork(hbool_t swmr, hbool_t new_format);
static unsigned verify_old_dset_cork(void);
-static unsigned verify_obj_dset_cork(void);
-static unsigned verify_dset_cork(hbool_t new_format);
-static unsigned verify_group_cork(void);
-static unsigned verify_named_cork(void);
-static unsigned verify_multiple_cork(void);
+static unsigned verify_obj_dset_cork(hbool_t swmr);
+static unsigned verify_dset_cork(hbool_t swmr, hbool_t new_format);
+static unsigned verify_group_cork(hbool_t swmr);
+static unsigned verify_named_cork(hbool_t swmr);
+static unsigned verify_multiple_cork(hbool_t swmr);
/*-------------------------------------------------------------------------
@@ -284,7 +284,7 @@ error:
*-------------------------------------------------------------------------
*/
static unsigned
-verify_obj_dset_cork(void)
+verify_obj_dset_cork(hbool_t swmr)
{
/* Variable Declarations */
hid_t fid = -1; /* File ID */
@@ -301,7 +301,11 @@ verify_obj_dset_cork(void)
char attrname[500]; /* Name of attribute */
unsigned flags; /* File access flags */
- TESTING("cork status for dataset objects with attributes");
+ if(swmr) {
+ TESTING("cork status for dataset objects with attributes (SWMR)");
+ } else {
+ TESTING("cork status for dataset objects with attributes");
+ }
/* Create fapl */
if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
@@ -312,6 +316,8 @@ verify_obj_dset_cork(void)
/* Create the file with/without SWMR access */
flags = H5F_ACC_TRUNC;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid = H5Fcreate(FILENAME, flags, H5P_DEFAULT, fapl)) < 0)
TEST_ERROR
@@ -405,6 +411,8 @@ verify_obj_dset_cork(void)
/* Re-open the file */
flags = H5F_ACC_RDWR;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid = H5Fopen(FILENAME, flags, fapl)) < 0)
TEST_ERROR
@@ -478,7 +486,7 @@ error:
*-------------------------------------------------------------------------
*/
static unsigned
-verify_dset_cork(hbool_t new_format)
+verify_dset_cork(hbool_t swmr, hbool_t new_format)
{
/* Variable Declarations */
hid_t fid = -1; /* File ID */
@@ -494,10 +502,18 @@ verify_dset_cork(hbool_t new_format)
unsigned flags; /* File access flags */
/* Testing Macro */
- if(new_format) {
- TESTING("cork status for chunked datasets with different indexing types (latest)");
+ if(swmr) {
+ if(new_format) {
+ TESTING("cork status for chunked datasets with different indexing types (SWMR & latest)");
+ } else {
+ TESTING("cork status for chunked datasets with different indexing types (SWMR & non-latest)");
+ } /* end if */
} else {
- TESTING("cork status for chunked datasets with different indexing types (non-latest)");
+ if(new_format) {
+ TESTING("cork status for chunked datasets with different indexing types (non-SWMR & latest)");
+ } else {
+ TESTING("cork status for chunked datasets with different indexing types (non-SWMR & non-latest)");
+ } /* end if */
} /* end if */
/* Create fapl */
@@ -511,6 +527,8 @@ verify_dset_cork(hbool_t new_format)
/* Create the file */
flags = H5F_ACC_TRUNC;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid = H5Fcreate(FILENAME, flags, H5P_DEFAULT, fapl)) < 0)
TEST_ERROR
@@ -608,6 +626,8 @@ verify_dset_cork(hbool_t new_format)
/* Reopen the file */
flags = H5F_ACC_RDWR;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid = H5Fopen(FILENAME, flags, fapl)) < 0)
TEST_ERROR
@@ -704,7 +724,7 @@ error:
*-------------------------------------------------------------------------
*/
static unsigned
-verify_group_cork(void)
+verify_group_cork(hbool_t swmr)
{
/* Variable Declarations */
hid_t fid = -1; /* File ID */
@@ -718,7 +738,11 @@ verify_group_cork(void)
int i = 0; /* Local index variable */
/* Testing Macro */
- TESTING("cork status for groups");
+ if(swmr) {
+ TESTING("cork status for groups (SWMR)");
+ } else {
+ TESTING("cork status for groups");
+ }
/* Create fapl */
if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
@@ -729,6 +753,8 @@ verify_group_cork(void)
/* Create the file */
flags = H5F_ACC_TRUNC;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid = H5Fcreate(FILENAME, flags, H5P_DEFAULT, fapl)) < 0)
TEST_ERROR
@@ -784,6 +810,8 @@ verify_group_cork(void)
/* Re-open the file and the three groups */
flags = H5F_ACC_RDWR;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid = H5Fopen(FILENAME, flags, fapl)) < 0)
FAIL_STACK_ERROR
if((gid = H5Gopen2(fid, GRP, H5P_DEFAULT)) < 0)
@@ -863,7 +891,7 @@ error:
*-------------------------------------------------------------------------
*/
static unsigned
-verify_named_cork(void)
+verify_named_cork(hbool_t swmr)
{
/* Variable Declarations */
hid_t fid = -1; /* File ID */
@@ -879,7 +907,11 @@ verify_named_cork(void)
int i = 0; /* Local index variable */
/* Testing Macro */
- TESTING("cork status for named datatypes");
+ if(swmr) {
+ TESTING("cork status for named datatypes (SWMR)");
+ } else {
+ TESTING("cork status for named datatypes");
+ }
/* Create fapl */
if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
@@ -890,6 +922,8 @@ verify_named_cork(void)
/* Create the file */
flags = H5F_ACC_TRUNC;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid = H5Fcreate(FILENAME, flags, H5P_DEFAULT, fapl)) < 0)
TEST_ERROR
@@ -982,6 +1016,8 @@ verify_named_cork(void)
/* Re-open the file and the three groups */
flags = H5F_ACC_RDWR;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid = H5Fopen(FILENAME, flags, fapl)) < 0)
FAIL_STACK_ERROR
if((gid = H5Gopen2(fid, GRP, H5P_DEFAULT)) < 0)
@@ -1131,7 +1167,7 @@ error:
*-------------------------------------------------------------------------
*/
static unsigned
-verify_multiple_cork(void)
+verify_multiple_cork(hbool_t swmr)
{
/* Variable Declarations */
hid_t fid1 = -1, fid2 = -1; /* File ID */
@@ -1150,7 +1186,11 @@ verify_multiple_cork(void)
herr_t ret; /* Return value */
/* Testing Macro */
- TESTING("cork status for multiple opens");
+ if(swmr) {
+ TESTING("cork status for multiple opens (SWMR)");
+ } else {
+ TESTING("cork status for multiple opens");
+ }
/* Create fapl */
if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
@@ -1161,6 +1201,8 @@ verify_multiple_cork(void)
/* Create the file */
flags = H5F_ACC_TRUNC;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid1 = H5Fcreate(FILENAME, flags, H5P_DEFAULT, fapl)) < 0)
TEST_ERROR
@@ -1212,6 +1254,8 @@ verify_multiple_cork(void)
/* Open the file twice: fid1, fid2 */
flags = H5F_ACC_RDWR;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
if((fid1 = H5Fopen(FILENAME, flags, fapl)) < 0)
TEST_ERROR
if((fid2 = H5Fopen(FILENAME, flags, fapl)) < 0)
@@ -1484,7 +1528,7 @@ error:
*-------------------------------------------------------------------------
*/
static unsigned
-test_objs_cork(hbool_t new_format)
+test_objs_cork(hbool_t swmr, hbool_t new_format)
{
hid_t fid; /* HDF5 File ID */
hid_t fapl; /* File access property list */
@@ -1493,14 +1537,25 @@ test_objs_cork(hbool_t new_format)
hid_t aid; /* Attribute ID */
hsize_t dims[RANK]; /* Dataset dimension sizes */
hbool_t corked; /* Cork status of an object */
+ unsigned flags; /* File access flags */
herr_t ret; /* Return value */
/* Testing Macro */
if(new_format) {
- TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled (new library format)");
+ if(swmr) {
+ TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled (new library format) (SWMR)");
+ } /* end if */
+ else {
+ TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled (new library format)");
+ } /* end else */
} else {
- TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled (old library format)");
- } /* end if */
+ if(swmr) {
+ TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled (old library format) (SWMR)");
+ } /* end if */
+ else {
+ TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled (old library format)");
+ } /* end else */
+ } /* end else */
/* Create fapl */
if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
@@ -1512,8 +1567,11 @@ test_objs_cork(hbool_t new_format)
TEST_ERROR
} /* end if */
- /* Create an HDF5 file */
- if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ /* Create the file with/without SWMR access */
+ flags = H5F_ACC_TRUNC;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
+ if((fid = H5Fcreate(FILENAME, flags, H5P_DEFAULT, fapl)) < 0)
TEST_ERROR
/* Create group */
@@ -1753,7 +1811,7 @@ error:
*-------------------------------------------------------------------------
*/
static unsigned
-test_dset_cork(hbool_t new_format)
+test_dset_cork(hbool_t swmr, hbool_t new_format)
{
hid_t fid; /* File ID */
hid_t fapl; /* File access property list */
@@ -1770,12 +1828,23 @@ test_dset_cork(hbool_t new_format)
int data[DIMS0][DIMS1]; /* Data buffer */
int rbuf[DIMS0][DIMS1]; /* Data buffer */
hbool_t corked; /* Cork status of an object */
+ unsigned flags; /* File access flags */
/* Testing Macro */
if(new_format) {
- TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled on datasets (new library format)");
+ if(swmr) {
+ TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled on datasets (new library format) (SWMR)");
+ } /* end if */
+ else {
+ TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled on datasets (new library format)");
+ } /* end else */
} else {
- TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled on datasets (old library format)");
+ if(swmr) {
+ TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled on datasets (old library format) (SWMR)");
+ } /* end if */
+ else {
+ TESTING("H5Odisable_mdc_flushes/H5Oenable_mdc_flushes/H5Oare_mdc_flushes_disabled on datasets (old library format)");
+ } /* end else */
} /* end if */
/* Create fapl */
@@ -1788,8 +1857,11 @@ test_dset_cork(hbool_t new_format)
TEST_ERROR
} /* end if */
- /* Create a new HDF5 file */
- if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ /* Create the file with/without SWMR access */
+ flags = H5F_ACC_TRUNC;
+ if(swmr)
+ flags |= H5F_ACC_SWMR_WRITE;
+ if((fid = H5Fcreate(FILENAME, flags, H5P_DEFAULT, fapl)) < 0)
TEST_ERROR
/* Create a group */
@@ -2070,26 +2142,29 @@ error:
int
main(void)
{
+ unsigned swmr; /* Loop over SWMR/non-SWMR */
unsigned nerrs = 0; /* Error Encountered */
/* Test for dataset created with old library format */
nerrs += verify_old_dset_cork();
- /* Tests with new/old library format */
- /* This is the test moved from th5o.c: test_h5o_cork() */
- nerrs += test_objs_cork(TRUE);
- nerrs += test_objs_cork(FALSE);
- /* This is the test moved from th5o.c: test_h5o_cork_dataset() */
- nerrs += test_dset_cork(TRUE);
- nerrs += test_dset_cork(FALSE);
-
- /* Tests with/without SWMR access */
- nerrs += verify_obj_dset_cork();
- nerrs += verify_dset_cork(TRUE);
- nerrs += verify_dset_cork(FALSE);
- nerrs += verify_group_cork();
- nerrs += verify_named_cork();
- nerrs += verify_multiple_cork();
+ for(swmr = 0; swmr <= 1; swmr++) {
+ /* Tests with new/old library format */
+ /* This is the test moved from th5o.c: test_h5o_cork() */
+ nerrs += test_objs_cork(swmr, TRUE);
+ nerrs += test_objs_cork(swmr, FALSE);
+ /* This is the test moved from th5o.c: test_h5o_cork_dataset() */
+ nerrs += test_dset_cork(swmr, TRUE);
+ nerrs += test_dset_cork(swmr, FALSE);
+
+ /* Tests with/without SWMR access */
+ nerrs += verify_obj_dset_cork(swmr);
+ nerrs += verify_dset_cork(swmr, TRUE);
+ nerrs += verify_dset_cork(swmr, FALSE);
+ nerrs += verify_group_cork(swmr);
+ nerrs += verify_named_cork(swmr);
+ nerrs += verify_multiple_cork(swmr);
+ } /* end for */
/* Delete test files */
HDremove(FILENAME);
diff --git a/test/dsets.c b/test/dsets.c
index 31ef88a..d086c58 100644
--- a/test/dsets.c
+++ b/test/dsets.c
@@ -12667,7 +12667,7 @@ main(void)
/* Don't run this test using certain file drivers */
envval = HDgetenv("HDF5_DRIVER");
if(envval == NULL)
- envval = "nomatch";
+ envval = "sec2";
/* Set the random # seed */
HDsrandom((unsigned)HDtime(NULL));
diff --git a/test/flush1.c b/test/flush1.c
index 64d072a..0e53f2b 100644
--- a/test/flush1.c
+++ b/test/flush1.c
@@ -27,8 +27,13 @@
const char *FILENAME[] = {
"flush",
+ "flush-swmr",
"noflush",
+ "noflush-swmr",
+ "flush_extend",
+ "flush_extend-swmr",
"noflush_extend",
+ "noflush_extend-swmr",
NULL
};
@@ -51,14 +56,17 @@ static double the_data[100][100];
*-------------------------------------------------------------------------
*/
static hid_t
-create_file(char* name, hid_t fapl)
+create_file(char* name, hid_t fapl, hbool_t swmr)
{
hid_t file, dcpl, space, dset, groups, grp;
hsize_t ds_size[2] = {100, 100};
hsize_t ch_size[2] = {5, 5};
+ unsigned flags;
size_t i, j;
- if((file = H5Fcreate(name, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) FAIL_STACK_ERROR
+ flags = H5F_ACC_TRUNC | (swmr ? H5F_ACC_SWMR_WRITE : 0);
+
+ if((file = H5Fcreate(name, flags, H5P_DEFAULT, fapl)) < 0) FAIL_STACK_ERROR
/* Create a chunked dataset */
if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) FAIL_STACK_ERROR
@@ -156,30 +164,43 @@ main(void)
{
hid_t file, fapl;
char name[1024];
+ unsigned swmr;
h5_reset();
fapl = h5_fileaccess();
TESTING("H5Fflush (part1)");
- /* Create the file */
- h5_fixname(FILENAME[0], fapl, name, sizeof name);
- file = create_file(name, fapl);
- /* Flush and exit without closing the library */
- if (H5Fflush(file, H5F_SCOPE_GLOBAL) < 0) goto error;
-
- /* Create the file */
- h5_fixname(FILENAME[2], fapl, name, sizeof name);
- file = create_file(name, fapl);
- /* Flush and exit without closing the library */
- if(H5Fflush(file, H5F_SCOPE_GLOBAL) < 0) goto error;
- /* Add a bit to the file and don't flush the new part */
- extend_file(file);
-
- /* Create the other file which will not be flushed */
- h5_fixname(FILENAME[1], fapl, name, sizeof name);
- file = create_file(name, fapl);
-
+ /* Loop over SWMR & non-SWMR opens for the file */
+ for(swmr = 0; swmr <= 1; swmr++) {
+ /* Create the file */
+ h5_fixname(FILENAME[0 + swmr], fapl, name, sizeof name);
+ file = create_file(name, fapl, swmr);
+ /* Flush and exit without closing the library */
+ if (H5Fflush(file, H5F_SCOPE_GLOBAL) < 0) goto error;
+
+ /* Create the other file which will not be flushed */
+ h5_fixname(FILENAME[2 + swmr], fapl, name, sizeof name);
+ file = create_file(name, fapl, swmr);
+
+ /* Create the file */
+ h5_fixname(FILENAME[4 + swmr], fapl, name, sizeof name);
+ file = create_file(name, fapl, swmr);
+ /* Flush and exit without closing the library */
+ if(H5Fflush(file, H5F_SCOPE_GLOBAL) < 0) goto error;
+ /* Add a bit to the file and don't flush the new part */
+ extend_file(file);
+ /* Flush and exit without closing the library */
+ if (H5Fflush(file, H5F_SCOPE_GLOBAL) < 0) goto error;
+
+ /* Create the file */
+ h5_fixname(FILENAME[6 + swmr], fapl, name, sizeof name);
+ file = create_file(name, fapl, swmr);
+ /* Flush and exit without closing the library */
+ if(H5Fflush(file, H5F_SCOPE_GLOBAL) < 0) goto error;
+ /* Add a bit to the file and don't flush the new part */
+ extend_file(file);
+ } /* end for */
PASSED();
fflush(stdout);
diff --git a/test/flush2.c b/test/flush2.c
index 7dc45be..3f4328a 100644
--- a/test/flush2.c
+++ b/test/flush2.c
@@ -24,10 +24,20 @@
*/
#include "h5test.h"
+/* Make this private property (defined in H5Fprivate.h) available */
+/* This is used in the helper routine clear_status_flags() */
+#define H5F_ACS_CLEAR_STATUS_FLAGS_NAME "clear_status_flags"
+
+
const char *FILENAME[] = {
"flush",
+ "flush-swmr",
"noflush",
+ "noflush-swmr",
+ "flush_extend",
+ "flush_extend-swmr",
"noflush_extend",
+ "noflush_extend-swmr",
NULL
};
@@ -134,6 +144,53 @@ error:
return 1;
} /* end check_file() */
+/*-------------------------------------------------------------------------
+ * Function: clear_status_flags
+ *
+ * Purpose: To clear the status_flags in the superblock of the file.
+ * It is smilar to the tool "h5clear".
+ *
+ * Return: Success: 0
+ * Failure: 1
+ *
+ * Programmer: Vailin Choi
+ * July 2013
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+clear_status_flags(char *name, hid_t fapl)
+{
+ hid_t new_fapl = -1;
+ hid_t fid = -1;
+ hbool_t clear = TRUE;
+
+ /* Get a copy of fapl */
+ if((new_fapl = H5Pcopy(fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Set this private property */
+ if(H5Pset(new_fapl, H5F_ACS_CLEAR_STATUS_FLAGS_NAME, &clear) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Has to open rw */
+ if((fid = H5Fopen(name, H5F_ACC_RDWR, new_fapl)) < 0)
+ FAIL_STACK_ERROR;
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR;
+
+ /* CLose the property list */
+ if(H5Pclose(new_fapl) < 0)
+ FAIL_STACK_ERROR;
+
+ return 0;
+
+error:
+ return 1;
+} /* clear_status_flags() */
+
/*-------------------------------------------------------------------------
* Function: main
@@ -166,6 +223,26 @@ main(void)
/* Check the case where the file was flushed */
h5_fixname(FILENAME[0], fapl, name, sizeof name);
+
+ if(check_file(name, fapl, FALSE)) {
+ H5_FAILED()
+ goto error;
+ }
+ else
+ PASSED();
+
+
+ TESTING("H5Fflush (part2 with flush + SWMR)");
+
+ /* Check the case where the file was flushed w/SWMR */
+ h5_fixname(FILENAME[1], fapl, name, sizeof name);
+
+ /* Clear the status_flags of the file which is flushed and exited in flush1.c */
+ if(clear_status_flags(name, fapl) < 0) {
+ H5_FAILED()
+ goto error;
+ }
+
if(check_file(name, fapl, FALSE)) {
H5_FAILED()
goto error;
@@ -180,7 +257,31 @@ main(void)
H5Eget_auto2(H5E_DEFAULT,&func,NULL);
H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
- h5_fixname(FILENAME[1], fapl, name, sizeof name);
+ h5_fixname(FILENAME[2], fapl, name, sizeof name);
+ /* No need to clear the status_flags because this file is not flushed in flush1.c */
+ /* H5Fopen() in check_file() will just return error */
+ if(check_file(name, fapl, FALSE))
+ PASSED()
+ else {
+#if defined H5_HAVE_WIN32_API && !defined (hdf5_EXPORTS)
+ SKIPPED();
+ puts(" DLL will flush the file even when calling _exit, skip this test temporarily");
+#else
+ H5_FAILED()
+ goto error;
+#endif
+ }
+ H5Eset_auto2(H5E_DEFAULT, func, NULL);
+
+ /* Check the case where the file was not flushed. This should give an error
+ * so we turn off the error stack temporarily */
+ TESTING("H5Fflush (part2 without flush + SWMR)");
+ H5Eget_auto2(H5E_DEFAULT,&func,NULL);
+ H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
+
+ h5_fixname(FILENAME[3], fapl, name, sizeof name);
+ /* No need to clear the status_flags because this file is not flushed in flush1.c */
+ /* H5Fopen() in check_file() will just return error */
if(check_file(name, fapl, FALSE))
PASSED()
else {
@@ -196,11 +297,79 @@ main(void)
/* Check the case where the file was flushed, but more data was added afterward. This should give an error
* so we turn off the error stack temporarily */
+ TESTING("H5Fflush (part2 with flush and later addition and another flush)");
+ H5Eget_auto2(H5E_DEFAULT,&func,NULL);
+ H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
+
+ h5_fixname(FILENAME[4], fapl, name, sizeof name);
+
+ /* Clear the status_flags of the file which is flushed and exited in flush1.c */
+ if(clear_status_flags(name, fapl) < 0) {
+ H5_FAILED()
+ goto error;
+ }
+
+ if(check_file(name, fapl, TRUE)) {
+ H5_FAILED()
+ goto error;
+ }
+ else
+ PASSED();
+
+ H5Eset_auto2(H5E_DEFAULT, func, NULL);
+
+ /* Check the case where the file was flushed, but more data was added afterward. This should give an error
+ * so we turn off the error stack temporarily */
+ TESTING("H5Fflush (part2 with flush and later addition and another flush + SWMR)");
+ H5Eget_auto2(H5E_DEFAULT,&func,NULL);
+ H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
+
+ h5_fixname(FILENAME[5], fapl, name, sizeof name);
+
+ if(check_file(name, fapl, TRUE))
+ PASSED()
+ else {
+#if defined H5_HAVE_WIN32_API && !defined (hdf5_EXPORTS)
+ SKIPPED();
+ puts(" DLL will flush the file even when calling _exit, skip this test temporarily");
+#else
+ H5_FAILED()
+ goto error;
+#endif
+ }
+
+ H5Eset_auto2(H5E_DEFAULT, func, NULL);
+
+ /* Check the case where the file was flushed, but more data was added afterward. This should give an error
+ * so we turn off the error stack temporarily */
TESTING("H5Fflush (part2 with flush and later addition)");
H5Eget_auto2(H5E_DEFAULT,&func,NULL);
H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
- h5_fixname(FILENAME[2], fapl, name, sizeof name);
+ h5_fixname(FILENAME[6], fapl, name, sizeof name);
+
+ if(check_file(name, fapl, TRUE))
+ PASSED()
+ else {
+#if defined H5_HAVE_WIN32_API && !defined (hdf5_EXPORTS)
+ SKIPPED();
+ puts(" DLL will flush the file even when calling _exit, skip this test temporarily");
+#else
+ H5_FAILED()
+ goto error;
+#endif
+ }
+
+ H5Eset_auto2(H5E_DEFAULT, func, NULL);
+
+ /* Check the case where the file was flushed, but more data was added afterward. This should give an error
+ * so we turn off the error stack temporarily */
+ TESTING("H5Fflush (part2 with flush and later addition + SWMR)");
+ H5Eget_auto2(H5E_DEFAULT,&func,NULL);
+ H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
+
+ h5_fixname(FILENAME[7], fapl, name, sizeof name);
+
if(check_file(name, fapl, TRUE))
PASSED()
else {
diff --git a/test/flushrefresh.c b/test/flushrefresh.c
new file mode 100644
index 0000000..e0a7484
--- /dev/null
+++ b/test/flushrefresh.c
@@ -0,0 +1,1151 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+/*
+ * Programmer: Mike McGreevy
+ * June 30, 2010
+ *
+ * Purpose: This test file contains routines used to test flushing and
+ * refreshing individual objects' metadata from the cache.
+ *
+ * Note: This file should NOT be run manually. Instead, invoke it
+ * via its associated test script, testflushrefresh.sh
+ *
+ */
+
+#define H5FD_FRIEND /*suppress error about including H5FDpkg */
+#define H5FD_TESTING
+
+/* ======== */
+/* Includes */
+/* ======== */
+
+#include "testhdf5.h"
+#include "H5FDpkg.h" /* File Drivers */
+
+/* ======= */
+/* Defines */
+/* ======= */
+
+/* Name of Test File */
+#define FILENAME "flushrefresh.h5"
+
+/* Names of Signal Files */
+#define SIGNAL_TO_SCRIPT "flushrefresh_VERIFICATION_START"
+#define SIGNAL_BETWEEN_PROCESSES_1 "flushrefresh_VERIFICATION_CHECKPOINT1"
+#define SIGNAL_BETWEEN_PROCESSES_2 "flushrefresh_VERIFICATION_CHECKPOINT2"
+#define SIGNAL_FROM_SCRIPT "flushrefresh_VERIFICATION_DONE"
+
+/* Paths to Various Objects in the Testfile */
+#define RG "/"
+#define D1 "/Dataset1"
+#define D2 "/Group1/Dataset2"
+#define D3 "/Group3/Dataset3"
+#define G1 "/Group1"
+#define G2 "/Group1/Group2"
+#define G3 "/Group3"
+#define T1 "/CommittedDatatype1"
+#define T2 "/Group1/Group2/CommittedDatatype2"
+#define T3 "/Group3/CommittedDatatype3"
+
+/* Flushed States */
+#define FLUSHED "FLUSHED"
+#define NOT_FLUSHED "NOT_FLUSHED"
+
+/* Error Handling */
+/* For errors occuring in the main process, use the standard TEST_ERROR macro.
+ For errors occurring in the spawned process (from the test script), use
+ the PROCESS_ERROR macro, which will send a signal to the main process so the
+ main process can propogate errors correctly. */
+FILE * errorfile;
+#define ERRFILE "flushrefresh_ERROR"
+#define PROCESS_ERROR \
+ { \
+ errorfile = HDfopen(ERRFILE, "w+"); \
+ HDfprintf(errorfile, "Error occurred in flushrefresh.\n"); \
+ HDfflush(errorfile); \
+ HDfclose(errorfile); \
+ TEST_ERROR; \
+ }
+
+#define CLEANUP_FILES \
+ { \
+ HDremove(ERRFILE); \
+ HDremove(FILENAME); \
+ HDremove(SIGNAL_TO_SCRIPT); \
+ HDremove(SIGNAL_BETWEEN_PROCESSES_1); \
+ HDremove(SIGNAL_BETWEEN_PROCESSES_2); \
+ HDremove(SIGNAL_FROM_SCRIPT); \
+ } \
+
+/* ===================== */
+/* Function Declarations */
+/* ===================== */
+
+/* Main */
+int main(int argc, const char *argv[]);
+
+/* Flush Test Framework */
+herr_t test_flush(void);
+herr_t flush_verification(const char * obj_pathname, const char * expected);
+herr_t run_flush_verification_process(const char * obj_pathname, const char * expected);
+
+/* Refresh Test Framework */
+herr_t test_refresh(void);
+herr_t refresh_verification(const char * obj_pathname);
+herr_t start_refresh_verification_process(const char * obj_pathname);
+herr_t end_refresh_verification_process(void);
+
+/* Other Helper Functions */
+herr_t check_for_errors(void);
+herr_t end_verification(void);
+
+/* ========= */
+/* Functions */
+/* ========= */
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: This function coordinates the test of flush/refresh
+ * functionality verification. It accepts either one, two or
+ * no command line parameters. The main test routine runs
+ * with no command line parameters specified, while verification
+ * routines run with one or two command line parameters.
+ *
+ * Note: This program should not be run manually, as the
+ * test is controlled by the testflushrefresh.sh script. Running
+ * the flushrefresh program manually will result in failure, as
+ * it will time out waiting for a signal from the test script
+ * which will never come.
+ *
+ * Return: 0 on Success, 1 on Failure
+ *
+ * Programmer: Mike McGreevy
+ * July 1, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+int main(int argc, const char *argv[])
+{
+ /* Variables */
+ const char *envval = NULL;
+
+ /* Initialize library */
+ if(H5open() < 0)
+ TEST_ERROR;
+
+ /* Parse command line options */
+ if(argc == 1) {
+ /* No arguments supplied. Run main test routines if
+ * using sec2 or stdio driver, otherwise don't run
+ * anything. */
+
+ /* Determine driver being used */
+ envval = HDgetenv("HDF5_DRIVER");
+
+ if(envval == NULL || H5FD_supports_swmr_test(envval)) {
+ if(test_flush() != SUCCEED) TEST_ERROR;
+ if(test_refresh() != SUCCEED) TEST_ERROR;
+ } /* end if */
+ else {
+ HDfprintf(stdout, "Skipping all flush/refresh tests (only run with SWMR-enabled file drivers).\n");
+
+ /* Test script is expecting some signals, so send them out to end it. */
+ if(end_verification() < 0) TEST_ERROR;
+ if(end_verification() < 0) TEST_ERROR;
+ } /* end else */
+ } else if(argc == 3) {
+ /* Two arguments supplied. Pass them to flush verification routine. */
+ if(flush_verification(argv[1], argv[2]) != 0) PROCESS_ERROR;
+ } else if(argc == 2) {
+ /* One argument supplied. Pass it to refresh verification routine. */
+ if(refresh_verification(argv[1]) != 0) PROCESS_ERROR;
+ } else {
+ /* Illegal number of arguments supplied. Error. */
+ HDfprintf(stderr, "Error. %d is an Invalid number of arguments to main().\n", argc);
+ PROCESS_ERROR
+ } /* end if */
+
+ return SUCCEED;
+
+error:
+ /* Return */
+ return FAIL;
+} /* main */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_flush
+ *
+ * Purpose: This function tests flushing individual objects' metadata
+ * from the metadata cache.
+ *
+ * Return: 0 on Success, 1 on Failure
+ *
+ * Programmer: Mike McGreevy
+ * July 1, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t test_flush(void)
+{
+ /**************************************************************************
+ *
+ * Test Description:
+ *
+ * This test will build an HDF5 file with several objects in a varying
+ * hierarchical layout. It will then attempt to flush the objects
+ * in the file one by one, individually, using the four H5*flush
+ * routines (D,G,T, and O). After each call to either create or flush an
+ * object, a series of verifications will occur on each object in the file.
+ *
+ * Each verification consists of spawning off a new process and determining
+ * if the object can be opened and its information retreived in said
+ * alternate process. It reports the results, which are compared to an
+ * expected value (either that the object can be found on disk, or that it
+ * cannot).
+ *
+ * Note that to spawn a verification, this program sends a signal (by creating
+ * a file on disk) to the test script controlling it, indicating how to
+ * run the verification.
+ *
+ * Implementation is funky, but basically, an example:
+ *
+ * Step 1. Dataset is created.
+ * Step 2. Verify that dataset can't be opened by separate process, as
+ * it should not have been flushed to disk yet.
+ * Step 3. Group is created.
+ * Step 4. Verify that group can't be opened by separate process.
+ * Step 5. H5Gflush is called on the group.
+ * Step 6. Verify that group CAN be opened, but dataset still has
+ * yet to hit disk, and CANNOT be opened. Success! Only the group
+ * was flushed.
+ *
+ **************************************************************************/
+
+ /**************************************************************************
+ * Generated Test File will look like this:
+ *
+ * GROUP "/"
+ * DATASET "Dataset1"
+ * GROUP "Group1" {
+ * DATASET "Dataset2"
+ * GROUP "Group2" {
+ * DATATYPE "CommittedDatatype3"
+ * }
+ * }
+ * GROUP "Group3" {
+ * DATASET "Dataset3"
+ * DATATYPE "CommittedDatatype2"
+ * }
+ * DATATYPE "CommittedDatatype1"
+ **************************************************************************/
+
+ /* Variables */
+ hid_t fid,gid,gid2,gid3,sid,tid1,tid2,tid3,did,did2,did3,rid,fapl,status = 0;
+ hsize_t dims[2] = {3,5};
+
+ /* Testing Message */
+ HDfprintf(stdout, "Testing individual object flush behavior:\n");
+
+ /* Cleanup any old error or signal files */
+ CLEANUP_FILES;
+
+ /* ================ */
+ /* CREATE TEST FILE */
+ /* ================ */
+
+ /* Create file, open root group - have to use latest file format for SWMR */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) TEST_ERROR;
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) TEST_ERROR;
+ if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC|H5F_ACC_SWMR_WRITE, H5P_DEFAULT, fapl)) < 0) TEST_ERROR;
+ if((rid = H5Gopen2(fid, "/", H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create data space and types */
+ if((sid = H5Screate_simple(2, dims, dims)) < 0) TEST_ERROR;
+ if((tid1 = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR;
+ if((tid2 = H5Tcopy(H5T_NATIVE_CHAR)) < 0) TEST_ERROR;
+ if((tid3 = H5Tcopy(H5T_NATIVE_LONG)) < 0) TEST_ERROR;
+
+ /* Create Group1 */
+ if((gid = H5Gcreate2(fid, "Group1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Group2 */
+ if((gid2 = H5Gcreate2(gid, "Group2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Group3 */
+ if((gid3 = H5Gcreate2(fid, "Group3", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Dataset1 */
+ if((did = H5Dcreate2(fid, "Dataset1", tid1, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Dataset2 */
+ if((did2 = H5Dcreate2(gid, "Dataset2", tid3, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Dataset3 */
+ if((did3 = H5Dcreate2(gid3, "Dataset3", tid2, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create CommittedDatatype1 */
+ if((status = H5Tcommit2(fid, "CommittedDatatype1", tid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create CommittedDatatype2 */
+ if((status = H5Tcommit2(gid2, "CommittedDatatype2", tid2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create CommittedDatatype3 */
+ if((status = H5Tcommit2(gid3, "CommittedDatatype3", tid3, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* ============ */
+ /* FLUSH GROUPS */
+ /* ============ */
+
+ /* Test */
+ TESTING("to ensure H5Gflush correctly flushes single groups");
+
+ /* First, let's verify that nothing is currently flushed. */
+ if(run_flush_verification_process(RG, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ /* Then, flush the root group and verify it's the only thing on disk */
+ if((status = H5Gflush(rid)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ /* Flush Group1 and Verify it is recently flushed, and nothing
+ * else has changed. */
+ if((status = H5Gflush(gid)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ /* Flush Group2 and Verify it is recently flushed, and nothing
+ * else has changed. */
+ if((status = H5Gflush(gid2)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ PASSED();
+
+ /* ============== */
+ /* FLUSH DATASETS */
+ /* ============== */
+
+ /* Test */
+ TESTING("to ensure H5Dflush correctly flushes single datasets");
+
+ /* Flush Dataset1 and verify it's the only thing that hits disk. */
+ if((status = H5Dflush(did)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ /* Flush Dataset2 and verify it's the only thing that hits disk. */
+ if((status = H5Dflush(did2)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ PASSED();
+
+ /* =============== */
+ /* FLUSH DATATYPES */
+ /* =============== */
+
+ /* Test */
+ TESTING("to ensure H5Tflush correctly flushes single datatypes");
+
+ /* Flush Datatype 1 and verify it's the only thing that hits disk. */
+ if((status = H5Tflush(tid1)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ /* Flush Datatype 2 and verify it's the only thing that hits disk. */
+ if((status = H5Tflush(tid2)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ PASSED();
+
+ /* ============= */
+ /* FLUSH OBJECTS */
+ /* ============= */
+
+ /* Test */
+ TESTING("to ensure H5Oflush correctly flushes single objects");
+
+ /* Flush Group3 and verify it's the only thing that hits disk. */
+ if((status = H5Oflush(gid3)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, NOT_FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ /* Flush Dataset3 and verify it's the only thing that hits disk. */
+ if((status = H5Oflush(did3)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, NOT_FLUSHED) != 0) TEST_ERROR;
+
+ /* Flush CommittedDatatype3 and verify it's the only thing that hits disk. */
+ if((status = H5Oflush(tid3)) < 0) TEST_ERROR;
+ if(run_flush_verification_process(RG, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(G3, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(D3, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T1, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T2, FLUSHED) != 0) TEST_ERROR;
+ if(run_flush_verification_process(T3, FLUSHED) != 0) TEST_ERROR;
+
+ PASSED();
+
+ /* ================== */
+ /* Cleanup and Return */
+ /* ================== */
+ if(H5Pclose(fapl) < 0) TEST_ERROR;
+ if(H5Gclose(gid) < 0) TEST_ERROR;
+ if(H5Gclose(gid2) < 0) TEST_ERROR;
+ if(H5Dclose(did) < 0) TEST_ERROR;
+ if(H5Dclose(did2) < 0) TEST_ERROR;
+ if(H5Gclose(rid) < 0) TEST_ERROR;
+ if(H5Fclose(fid) < 0) TEST_ERROR;
+
+ /* Delete test file */
+ HDremove(FILENAME);
+
+ if(end_verification() < 0) TEST_ERROR;
+
+ return SUCCEED;
+
+error:
+ return FAIL;
+} /* end test_flush */
+
+
+/*-------------------------------------------------------------------------
+ * Function: test_refresh
+ *
+ * Purpose: This function tests refresh (evict/reload) of individual
+ * objects' metadata from the metadata cache.
+ *
+ * Return: 0 on Success, 1 on Failure
+ *
+ * Programmer: Mike McGreevy
+ * August 17, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t test_refresh(void)
+{
+ /**************************************************************************
+ *
+ * Test Description:
+ *
+ * This test will build an HDF5 file with several objects in a varying
+ * hierarchical layout. It will then flush the entire file to disk. Then,
+ * an attribute will be added to each object in the file.
+ *
+ * One by one, this process will flush each object to disk, individually.
+ * It will also be coordinating with another process, which will open
+ * the object before it is flushed by this process, and then refresh the
+ * object after it's been flushed, comparing the before and after object
+ * information to ensure that they are as expected. (i.e., most notably,
+ * that an attribute has been added, and is only visible after a
+ * successful call to a H5*refresh function).
+ *
+ * As with the flush case, the implemention is a bit tricky as it's
+ * dealing with signals going back and forth between the two processes
+ * to ensure the timing is correct, but basically, an example:
+ *
+ * Step 1. Dataset is created.
+ * Step 2. Dataset is flushed.
+ * Step 3. Attribute on Dataset is created.
+ * Step 4. Another process opens the dataset and verifies that it does
+ * not see an attribute (as the attribute hasn't been flushed yet).
+ * Step 5. This process flushes the dataset again (with Attribute attached).
+ * Step 6. The other process calls H5Drefresh, which should evict/reload
+ * the object's metadata, and thus pick up the attribute that's
+ * attached to it. Most other before/after object information is
+ * compared for sanity as well.
+ * Step 7. Rinse and Repeat for each object in the file.
+ *
+ **************************************************************************/
+
+ /**************************************************************************
+ * Generated Test File will look like this:
+ *
+ * GROUP "/"
+ * DATASET "Dataset1"
+ * GROUP "Group1" {
+ * DATASET "Dataset2"
+ * GROUP "Group2" {
+ * DATATYPE "CommittedDatatype3"
+ * }
+ * }
+ * GROUP "Group3" {
+ * DATASET "Dataset3"
+ * DATATYPE "CommittedDatatype2"
+ * }
+ * DATATYPE "CommittedDatatype1"
+ **************************************************************************/
+
+ /* Variables */
+ hid_t aid,fid,sid,tid1,did,dcpl,fapl = 0;
+ hid_t gid,gid2,gid3,tid2,tid3,did2,did3;
+ herr_t status = 0;
+ hsize_t dims[2] = {50,50};
+ hsize_t cdims[2] = {1,1};
+ int fillval = 2;
+
+ /* Testing Message */
+ HDfprintf(stdout, "Testing individual object refresh behavior:\n");
+
+ /* Cleanup any old error or signal files */
+ CLEANUP_FILES;
+
+ /* ================ */
+ /* CREATE TEST FILE */
+ /* ================ */
+
+ /* Create File */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0) TEST_ERROR;
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) TEST_ERROR;
+ if((fid = H5Fcreate(FILENAME, H5F_ACC_TRUNC|H5F_ACC_SWMR_WRITE, H5P_DEFAULT, fapl)) < 0) TEST_ERROR;
+
+ /* Create data space and types */
+ if((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR;
+ if(H5Pset_chunk(dcpl, 2, cdims) < 0) TEST_ERROR;
+ if(H5Pset_fill_value(dcpl, H5T_NATIVE_INT, &fillval) < 0) TEST_ERROR;
+ if((sid = H5Screate_simple(2, dims, dims)) < 0) TEST_ERROR;
+ if((tid1 = H5Tcopy(H5T_NATIVE_INT)) < 0) TEST_ERROR;
+ if((tid2 = H5Tcopy(H5T_NATIVE_CHAR)) < 0) TEST_ERROR;
+ if((tid3 = H5Tcopy(H5T_NATIVE_LONG)) < 0) TEST_ERROR;
+
+ /* Create Group1 */
+ if((gid = H5Gcreate2(fid, "Group1", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Group2 */
+ if((gid2 = H5Gcreate2(gid, "Group2", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Group3 */
+ if((gid3 = H5Gcreate2(fid, "Group3", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Dataset1 */
+ if((did = H5Dcreate2(fid, "Dataset1", tid1, sid, H5P_DEFAULT, dcpl, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Dataset2 */
+ if((did2 = H5Dcreate2(gid, "Dataset2", tid3, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create Dataset3 */
+ if((did3 = H5Dcreate2(gid3, "Dataset3", tid2, sid, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create CommittedDatatype1 */
+ if((status = H5Tcommit2(fid, "CommittedDatatype1", tid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create CommittedDatatype2 */
+ if((status = H5Tcommit2(gid2, "CommittedDatatype2", tid2, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Create CommittedDatatype3 */
+ if((status = H5Tcommit2(gid3, "CommittedDatatype3", tid3, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+
+ /* Flush File to Disk */
+ if(H5Fflush(fid, H5F_SCOPE_GLOBAL) < 0) TEST_ERROR;
+
+ /* ================ */
+ /* Refresh Datasets */
+ /* ================ */
+
+ TESTING("to ensure that H5Drefresh correctly refreshes single datasets");
+
+ /* Create an attribute on each object before flush. */
+
+ /* Verify First Dataset can be refreshed with H5Drefresh */
+ if(start_refresh_verification_process(D1) != 0) TEST_ERROR;
+
+ if((aid = H5Acreate2(did, "Attribute", tid1, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+ if(H5Aclose(aid) < 0) TEST_ERROR;
+ if(H5Oflush(did) < 0) TEST_ERROR;
+
+ if(end_refresh_verification_process() != 0) TEST_ERROR;
+
+ /* Verify Second Dataset can be refreshed with H5Drefresh */
+ if(start_refresh_verification_process(D2) != 0) TEST_ERROR;
+
+ if((aid = H5Acreate2(did2, "Attribute", tid1, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+ if(H5Aclose(aid) < 0) TEST_ERROR;
+ if(H5Oflush(did2) < 0) TEST_ERROR;
+
+ if(end_refresh_verification_process() != 0) TEST_ERROR;
+
+ PASSED();
+
+ /* ============== */
+ /* Refresh Groups */
+ /* ============== */
+
+ TESTING("to ensure that H5Grefresh correctly refreshes single groups");
+
+ /* Verify First Group can be refreshed with H5Grefresh */
+ if(start_refresh_verification_process(G1) != 0) TEST_ERROR;
+
+ if((aid = H5Acreate2(gid, "Attribute", tid1, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+ if(H5Aclose(aid) < 0) TEST_ERROR;
+ if(H5Oflush(gid) < 0) TEST_ERROR;
+
+ if(end_refresh_verification_process() != 0) TEST_ERROR;
+
+ /* Verify Second Group can be refreshed with H5Grefresh */
+ if(start_refresh_verification_process(G2) != 0) TEST_ERROR;
+
+ if((aid = H5Acreate2(gid2, "Attribute", tid1, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+ if(H5Aclose(aid) < 0) TEST_ERROR;
+ if(H5Oflush(gid2) < 0) TEST_ERROR;
+
+ if(end_refresh_verification_process() != 0) TEST_ERROR;
+
+ PASSED();
+
+ /* ================= */
+ /* Refresh Datatypes */
+ /* ================= */
+
+ TESTING("to ensure that H5Trefresh correctly refreshes single datatypes");
+
+ /* Verify First Committed Datatype can be refreshed with H5Trefresh */
+ if(start_refresh_verification_process(T1) != 0) TEST_ERROR;
+
+ if((aid = H5Acreate2(tid1, "Attribute", tid1, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+ if(H5Aclose(aid) < 0) TEST_ERROR;
+ if(H5Oflush(tid1) < 0) TEST_ERROR;
+
+ if(end_refresh_verification_process() != 0) TEST_ERROR;
+
+ /* Verify Second Committed Datatype can be refreshed with H5Trefresh */
+ if(start_refresh_verification_process(T2) != 0) TEST_ERROR;
+
+ if((aid = H5Acreate2(tid2, "Attribute", tid1, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+ if(H5Aclose(aid) < 0) TEST_ERROR;
+ if(H5Oflush(tid2) < 0) TEST_ERROR;
+
+ if(end_refresh_verification_process() != 0) TEST_ERROR;
+
+ PASSED();
+
+ /* =============== */
+ /* Refresh Objects */
+ /* =============== */
+
+ TESTING("to ensure that H5Orefresh correctly refreshes single objects");
+
+ /* Verify Third Dataset can be refreshed with H5Orefresh */
+ if(start_refresh_verification_process(D3) != 0) TEST_ERROR;
+
+ if((aid = H5Acreate2(did3, "Attribute", tid1, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+ if(H5Aclose(aid) < 0) TEST_ERROR;
+ if(H5Oflush(did3) < 0) TEST_ERROR;
+
+ if(end_refresh_verification_process() != 0) TEST_ERROR;
+
+ /* Verify Third Group can be refreshed with H5Orefresh */
+ if(start_refresh_verification_process(G3) != 0) TEST_ERROR;
+
+ if((aid = H5Acreate2(gid3, "Attribute", tid1, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+ if(H5Aclose(aid) < 0) TEST_ERROR;
+ if(H5Oflush(gid3) < 0) TEST_ERROR;
+
+ if(end_refresh_verification_process() != 0) TEST_ERROR;
+
+ /* Verify Third Committed Datatype can be refreshed with H5Orefresh */
+ if(start_refresh_verification_process(T3) != 0) TEST_ERROR;
+
+ if((aid = H5Acreate2(tid3, "Attribute", tid1, sid, H5P_DEFAULT, H5P_DEFAULT)) < 0) TEST_ERROR;
+ if(H5Aclose(aid) < 0) TEST_ERROR;
+ if(H5Oflush(tid3) < 0) TEST_ERROR;
+
+ if(end_refresh_verification_process() != 0) TEST_ERROR;
+
+ PASSED();
+
+ /* ================== */
+ /* Cleanup and Return */
+ /* ================== */
+
+ /* Close Stuff */
+ if(H5Pclose(fapl) < 0) TEST_ERROR;
+ if(H5Pclose(dcpl) < 0) TEST_ERROR;
+ if(H5Tclose(tid1) < 0) TEST_ERROR;
+ if(H5Tclose(tid2) < 0) TEST_ERROR;
+ if(H5Tclose(tid3) < 0) TEST_ERROR;
+ if(H5Dclose(did) < 0) TEST_ERROR;
+ if(H5Dclose(did2) < 0) TEST_ERROR;
+ if(H5Dclose(did3) < 0) TEST_ERROR;
+ if(H5Gclose(gid) < 0) TEST_ERROR;
+ if(H5Gclose(gid2) < 0) TEST_ERROR;
+ if(H5Gclose(gid3) < 0) TEST_ERROR;
+ if(H5Sclose(sid) < 0) TEST_ERROR;
+ if(H5Fclose(fid) < 0) TEST_ERROR;
+
+ /* Delete Test File */
+ HDremove(FILENAME);
+
+ if(end_verification() < 0) TEST_ERROR;
+
+ return SUCCEED;
+
+error:
+ /* Return */
+ return FAIL;
+} /* test_refresh() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: run_flush_verification_process
+ *
+ * Purpose: This function is used to communicate with the test script
+ * in order to spawn off a process to verify that a flush
+ * of an individual object was successful.
+ *
+ * Return: 0 on Success, 1 on Failure
+ *
+ * Programmer: Mike McGreevy
+ * July 16, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t run_flush_verification_process(const char * obj_pathname, const char * expected)
+{
+ HDremove(SIGNAL_FROM_SCRIPT);
+
+ /* Send Signal to SCRIPT indicating that it should kick off a verification process. */
+ h5_send_message(SIGNAL_TO_SCRIPT, obj_pathname, expected);
+
+ /* Wait for Signal from SCRIPT indicating that verification process has completed. */
+ if(h5_wait_message(SIGNAL_FROM_SCRIPT) < 0) TEST_ERROR;
+
+ /* Check to see if any errors occurred */
+ if(check_for_errors() < 0) TEST_ERROR;
+
+ /* Return */
+ return SUCCEED;
+
+error:
+ return FAIL;
+} /* run_flush_verification_process */
+
+
+/*-------------------------------------------------------------------------
+ * Function: flush_verification
+ *
+ * Purpose: This function tries to open target object in the test file.
+ * It compares the success of the open function to the expected
+ * value, and succeeds if they are equal and fails if they differ.
+ *
+ * Note that full path to the object must be provided as the
+ * obj_pathname argument.
+ *
+ * Return: 0 on Success, 1 on Failure
+ *
+ * Programmer: Mike McGreevy
+ * July 16, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t flush_verification(const char * obj_pathname, const char * expected)
+{
+ /* Variables */
+ hid_t oid = -1, fid = -1;
+ herr_t status = 0;
+ H5O_info_t oinfo;
+
+ /* Try to open the testfile and then obj_pathname within the file */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILENAME, H5F_ACC_SWMR_READ, H5P_DEFAULT);
+ oid = H5Oopen(fid, obj_pathname, H5P_DEFAULT);
+ status = H5Oget_info(oid, &oinfo);
+ } H5E_END_TRY;
+
+ /* Compare to expected result */
+ if(HDstrcmp(expected, FLUSHED) == 0) {
+ if((oid < 0) || (status < 0)) {
+ HDfprintf(stderr, "Error! %s should be on disk, but was NOT!\n", obj_pathname);
+ PROCESS_ERROR;
+ } /* end if */
+ } else if(HDstrcmp(expected, NOT_FLUSHED) == 0) {
+ if((oid > 0) || (status > 0)) {
+ HDfprintf(stderr, "Error! %s not expected to be flushed, but it was found on disk!\n", obj_pathname);
+ PROCESS_ERROR;
+ } /* end if */
+ } else {
+ HDfprintf(stderr, "Error! Bad verification parameters. %s is an invalid expected outcome.\n", expected);
+ PROCESS_ERROR;
+ } /* end if */
+
+ /* Cleanup */
+ H5E_BEGIN_TRY {
+ H5Oclose(oid);
+ H5Fclose(fid);
+ } H5E_END_TRY;
+
+ return SUCCEED;
+
+error:
+ return FAIL;
+} /* flush_verification */
+
+
+/*-------------------------------------------------------------------------
+ * Function: start_refresh_verification_process
+ *
+ * Purpose: This function is used to communicate with the test script
+ * in order to spawn off a process which will test the
+ * H5*refresh routine.
+ *
+ * Return: 0 on Success, 1 on Failure
+ *
+ * Programmer: Mike McGreevy
+ * July 16, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t start_refresh_verification_process(const char * obj_pathname)
+{
+ HDremove(SIGNAL_BETWEEN_PROCESSES_1);
+
+ /* Send Signal to SCRIPT indicating that it should kick off a refresh
+ verification process */
+ h5_send_message(SIGNAL_TO_SCRIPT, obj_pathname, NULL);
+
+ /* Wait for Signal from VERIFICATION PROCESS indicating that it's opened the
+ target object and ready for MAIN PROCESS to modify it */
+ if(h5_wait_message(SIGNAL_BETWEEN_PROCESSES_1) < 0) TEST_ERROR;
+
+ /* Check to see if any errors occurred */
+ if(check_for_errors() < 0) TEST_ERROR;
+
+ /* Return */
+ return SUCCEED;
+
+error:
+ return FAIL;
+} /* start_refresh_verification_process */
+
+
+/*-------------------------------------------------------------------------
+ * Function: end_refresh_verification_process
+ *
+ * Purpose: This function is used to communicate with the verification
+ * process spawned by the start_refresh_verification_process
+ * function. It gives it the go-ahead to call H5*refresh
+ * on an object and conlcude the refresh verification.
+ *
+ * Return: 0 on Success, 1 on Failure
+ *
+ * Programmer: Mike McGreevy
+ * July 16, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t end_refresh_verification_process(void)
+{
+ HDremove(SIGNAL_FROM_SCRIPT);
+
+ /* Send Signal to REFRESH VERIFICATION PROCESS indicating that the object
+ has been modified and it should now attempt to refresh its metadata,
+ and verify the results. */
+ h5_send_message(SIGNAL_BETWEEN_PROCESSES_2, NULL, NULL);
+
+ /* Wait for Signal from SCRIPT indicating that the refresh verification
+ process has completed. */
+ if(h5_wait_message(SIGNAL_FROM_SCRIPT) < 0) TEST_ERROR;
+
+ /* Check to see if any errors occurred */
+ if(check_for_errors() < 0) TEST_ERROR;
+
+ /* Return */
+ return SUCCEED;
+
+error:
+ return FAIL;
+} /* end_refresh_verification_process */
+
+
+/*-------------------------------------------------------------------------
+ * Function: refresh_verification
+ *
+ * Purpose: This function opens the specified object, and checks to see
+ * that is does not have any attributes on it. It then sends
+ * a signal to the main process, which will flush the object
+ * (putting an attribute on the object on disk). This function
+ * will then refresh the object, and verify that it has picked
+ * up the new metadata reflective of the added attribute.
+ *
+ * Return: 0 on Success, 1 on Failure
+ *
+ * Programmer: Mike McGreevy
+ * July 16, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t refresh_verification(const char * obj_pathname)
+{
+ /* Variables */
+ hid_t oid,fid,status = 0;
+ H5O_info_t flushed_oinfo;
+ H5O_info_t refreshed_oinfo;
+ int tries = 800, sleep_tries = 400;
+ hbool_t ok = FALSE;
+
+ HDremove(SIGNAL_BETWEEN_PROCESSES_2);
+
+ /* Open Object */
+ if((fid = H5Fopen(FILENAME, H5F_ACC_SWMR_READ, H5P_DEFAULT)) < 0) PROCESS_ERROR;
+ if((oid = H5Oopen(fid, obj_pathname, H5P_DEFAULT)) < 0) PROCESS_ERROR;
+
+ /* Get Object info */
+ if((status = H5Oget_info(oid, &flushed_oinfo)) < 0) PROCESS_ERROR;
+
+ /* Make sure there are no attributes on the object. This is just a sanity
+ check to ensure we didn't erroneously flush the attribute before
+ starting the verification. */
+ if(flushed_oinfo.num_attrs != 0)
+ PROCESS_ERROR;
+
+ /* Send Signal to MAIN PROCESS indicating that it can go ahead and modify the
+ object. */
+ h5_send_message(SIGNAL_BETWEEN_PROCESSES_1, obj_pathname, NULL);
+
+ /* Wait for Signal from MAIN PROCESS indicating that it's modified the
+ object and we can run verification now. */
+ if(h5_wait_message(SIGNAL_BETWEEN_PROCESSES_2) < 0) PROCESS_ERROR;
+
+ /* Get object info again. This will NOT reflect what's on disk, only what's
+ in the cache. Thus, all values will be unchanged from above, despite
+ newer information being on disk. */
+ if((status = H5Oget_info(oid, &refreshed_oinfo)) < 0) PROCESS_ERROR;
+
+ /* Verify that before doing a refresh, getting the object info returns stale
+ information. (i.e., unchanged from above, despite new info on disk). */
+ if(flushed_oinfo.addr != refreshed_oinfo.addr) PROCESS_ERROR;
+ if(flushed_oinfo.type != refreshed_oinfo.type) PROCESS_ERROR;
+ if(flushed_oinfo.hdr.version != refreshed_oinfo.hdr.version) PROCESS_ERROR;
+ if(flushed_oinfo.hdr.flags != refreshed_oinfo.hdr.flags) PROCESS_ERROR;
+ if(flushed_oinfo.num_attrs != refreshed_oinfo.num_attrs) PROCESS_ERROR;
+ if(flushed_oinfo.hdr.nmesgs != refreshed_oinfo.hdr.nmesgs) PROCESS_ERROR;
+ if(flushed_oinfo.hdr.nchunks != refreshed_oinfo.hdr.nchunks) PROCESS_ERROR;
+ if(flushed_oinfo.hdr.space.total != refreshed_oinfo.hdr.space.total) PROCESS_ERROR;
+
+ /* Refresh object */
+ /* The H5*refresh function called depends on which object we are trying
+ * to refresh. (MIKE: add desired refresh call as parameter so adding new
+ * test cases is easy). */
+ do {
+
+ if((HDstrcmp(obj_pathname, D1) == 0) || (HDstrcmp(obj_pathname, D2) == 0)) {
+ if(H5Drefresh(oid) < 0) PROCESS_ERROR;
+ } /* end if */
+ else if((HDstrcmp(obj_pathname, G1) == 0) || (HDstrcmp(obj_pathname, G2) == 0)) {
+ if(H5Grefresh(oid) < 0) PROCESS_ERROR;
+ } /* end if */
+ else if((HDstrcmp(obj_pathname, T1) == 0) || (HDstrcmp(obj_pathname, T2) == 0)) {
+ if(H5Trefresh(oid) < 0) PROCESS_ERROR;
+ } /* end if */
+ else if((HDstrcmp(obj_pathname, D3) == 0) || (HDstrcmp(obj_pathname, G3) == 0) ||
+ (HDstrcmp(obj_pathname, T3) == 0)) {
+ if(H5Orefresh(oid) < 0) PROCESS_ERROR;
+ } /* end if */
+ else {
+ HDfprintf(stdout, "Error. %s is an unrecognized object.\n", obj_pathname);
+ PROCESS_ERROR;
+ } /* end else */
+
+ /* Get object info. This should now accurately reflect the refreshed object on disk. */
+ if((status = H5Oget_info(oid, &refreshed_oinfo)) < 0) PROCESS_ERROR;
+
+ /* Confirm following (first 4) attributes are the same: */
+ /* Confirm following (last 4) attributes are different */
+ if( (flushed_oinfo.addr == refreshed_oinfo.addr) &&
+ (flushed_oinfo.type == refreshed_oinfo.type) &&
+ (flushed_oinfo.hdr.version == refreshed_oinfo.hdr.version) &&
+ (flushed_oinfo.hdr.flags == refreshed_oinfo.hdr.flags) &&
+ (flushed_oinfo.num_attrs != refreshed_oinfo.num_attrs) &&
+ (flushed_oinfo.hdr.nmesgs != refreshed_oinfo.hdr.nmesgs) &&
+ (flushed_oinfo.hdr.nchunks != refreshed_oinfo.hdr.nchunks) &&
+ (flushed_oinfo.hdr.space.total != refreshed_oinfo.hdr.space.total) ) {
+ ok = TRUE;
+ break;
+ }
+ if(tries == sleep_tries)
+ HDsleep(1);
+
+ } while(--tries);
+
+ if(!ok) {
+ printf("FLUSHED: num_attrs=%d, nmesgs=%d, nchunks=%d, total=%d\n",
+ (int)flushed_oinfo.num_attrs, (int)flushed_oinfo.hdr.nmesgs,
+ (int)flushed_oinfo.hdr.nchunks, (int)flushed_oinfo.hdr.space.total);
+ printf("REFRESHED: num_attrs=%d, nmesgs=%d, nchunks=%d, total=%d\n",
+ (int)refreshed_oinfo.num_attrs, (int)refreshed_oinfo.hdr.nmesgs,
+ (int)refreshed_oinfo.hdr.nchunks, (int)refreshed_oinfo.hdr.space.total);
+ PROCESS_ERROR;
+ }
+
+ /* Close objects */
+ if(H5Oclose(oid) < 0) PROCESS_ERROR;
+ if(H5Fclose(fid) < 0) PROCESS_ERROR;
+
+ /* Return */
+ return SUCCEED;
+
+error:
+ return FAIL;
+} /* refresh_verification */
+
+
+/*-------------------------------------------------------------------------
+ * Function: check_for_errors()
+ *
+ * Purpose: This function checks the status of external verification
+ * processes to see if they've succeeded. It checks for the
+ * existance of flushrefresh_ERROR file. If present, that indicates
+ * an external verification process has failed, and this function
+ * thus fails as well. If not present, then nothing else has
+ * failed, and this function succeeds.
+ *
+ * Return: 0 on Success, 1 on Failure
+ *
+ * Programmer: Mike McGreevy
+ * July 1, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t check_for_errors(void)
+{
+ FILE * file;
+
+ if((file = HDfopen(ERRFILE, "r"))) {
+ HDfclose(file);
+ HDremove(ERRFILE);
+ return FAIL;
+ } /* end if */
+
+ return SUCCEED;
+} /* check_for_errors */
+
+
+/*-------------------------------------------------------------------------
+ * Function: end_verification
+ *
+ * Purpose: Tells test script that verification routines are completed and
+ * that the test can wrap up.
+ *
+ * Return: void
+ *
+ * Programmer: Mike McGreevy
+ * July 16, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t end_verification(void)
+{
+ HDremove(SIGNAL_FROM_SCRIPT);
+
+ /* Send Signal to SCRIPT to indicate that we're done with verification. */
+ h5_send_message(SIGNAL_TO_SCRIPT, "VERIFICATION_DONE", "VERIFICATION_DONE");
+
+ /* Wait for Signal from SCRIPT indicating that we can continue. */
+ if(h5_wait_message(SIGNAL_FROM_SCRIPT) < 0) TEST_ERROR;
+
+ return SUCCEED;
+
+error:
+ return FAIL;
+} /* end_verification */
+
diff --git a/test/h5test.c b/test/h5test.c
index f85e96c..9759fa8 100644
--- a/test/h5test.c
+++ b/test/h5test.c
@@ -93,6 +93,12 @@ static const char *multi_letters = "msbrglo";
/* Length of multi-file VFD filename buffers */
#define H5TEST_MULTI_FILENAME_LEN 1024
+/* Temporary file for sending signal messages */
+#define TMP_SIGNAL_FILE "tmp_signal_file"
+
+/* The # of seconds to wait for the message file--used by h5_wait_message() */
+#define MESSAGE_TIMEOUT 300 /* Timeout in seconds */
+
/* Previous error reporting function */
static H5E_auto2_t err_func = NULL;
@@ -1711,3 +1717,118 @@ error:
return -1;
}
+/*-------------------------------------------------------------------------
+ * Function: h5_send_message
+ *
+ * Purpose: Sends the specified signal.
+ *
+ * In terms of this test framework, a signal consists of a file
+ * on disk. Since there are multiple processes that need to
+ * communicate with each other, they do so by writing and
+ * reading signal files on disk, the names and contents of
+ * which are used to inform a process about when it can
+ * proceed and what it should do next.
+ *
+ * This function writes a signal file. The first argument is
+ * the name of the signal file, and the second and third
+ * arguments are the contents of the first two lines of the
+ * signal file. The last two arguments may be NULL.
+ *
+ * Return: void
+ *
+ * Programmer: Mike McGreevy
+ * August 18, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+h5_send_message(const char *send, const char *arg1, const char *arg2)
+{
+ FILE *signalfile;
+
+ HDremove(TMP_SIGNAL_FILE);
+
+ /* Create signal file (which will send signal to some other process) */
+ signalfile = HDfopen(TMP_SIGNAL_FILE, "w+");
+
+ /* Write messages to signal file, if provided */
+ if(arg2 != NULL) {
+ HDassert(arg1);
+ HDfprintf(signalfile, "%s\n%s\n", arg1, arg2);
+ } /* end if */
+ else if(arg1 != NULL) {
+ HDassert(arg2 == NULL);
+ HDfprintf(signalfile, "%s\n", arg1);
+ } /* end if */
+ else {
+ HDassert(arg1 == NULL);
+ HDassert(arg2 == NULL);
+ }/* end else */
+
+ HDfclose(signalfile);
+
+ HDrename(TMP_SIGNAL_FILE, send);
+} /* h5_send_message() */
+
+/*-------------------------------------------------------------------------
+ * Function: h5_wait_message
+ *
+ * Purpose: Waits for the specified signal.
+ *
+ * In terms of this test framework, a signal consists of a file
+ * on disk. Since there are multiple processes that need to
+ * communicate with each other, they do so by writing and
+ * reading signal files on disk, the names and contents of
+ * which are used to inform a process about when it can
+ * proceed and what it should do next.
+ *
+ * This function continuously attempts to read the specified
+ * signal file from disk, and only continues once it has
+ * successfully done so (i.e., only after another process has
+ * called the "h5_send_message" function to write the signal file).
+ * This functon will then immediately remove the file (i.e.,
+ * to indicate that it has been received and can be reused),
+ * and then exits, allowing the calling function to continue.
+ *
+ * Return: void
+ *
+ * Programmer: Mike McGreevy
+ * August 18, 2010
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+h5_wait_message(const char *waitfor)
+{
+ FILE *returnfile;
+ time_t t0,t1;
+
+ /* Start timer. If this function runs for too long (i.e.,
+ expected signal is never received), it will
+ return failure */
+ HDtime(&t0);
+
+ /* Wait for return signal from some other process */
+ while ((returnfile = HDfopen(waitfor, "r")) == NULL) {
+
+ /* make note of current time. */
+ HDtime(&t1);
+
+ /* If we've been waiting for a signal for too long, then
+ it was likely never sent and we should fail rather
+ than loop infinitely */
+ if(HDdifftime(t1, t0) > MESSAGE_TIMEOUT) {
+ HDfprintf(stdout, "Error communicating between processes. Make sure test script is running.\n");
+ TEST_ERROR;
+ } /* end if */
+ } /* end while */
+
+ HDfclose(returnfile);
+ HDunlink(waitfor);
+
+ return SUCCEED;
+
+error:
+ return FAIL;
+} /* h5_wait_message() */
+
diff --git a/test/h5test.h b/test/h5test.h
index 6806e8f..e79f2b1 100644
--- a/test/h5test.h
+++ b/test/h5test.h
@@ -197,6 +197,9 @@ H5TEST_DLL char* getenv_all(MPI_Comm comm, int root, const char* name);
/* Extern global variables */
H5TEST_DLLVAR int TestVerbosity;
+H5TEST_DLL void h5_send_message(const char *file, const char *arg1, const char *arg2);
+H5TEST_DLL herr_t h5_wait_message(const char *file);
+
#ifdef __cplusplus
}
#endif
diff --git a/test/links.c b/test/links.c
index 2c841f0..182eb6c 100644
--- a/test/links.c
+++ b/test/links.c
@@ -27,8 +27,12 @@
#define H5G_FRIEND /*suppress error about including H5Gpkg */
#define H5G_TESTING
+#define H5FD_FRIEND /*suppress error about including H5FDpkg */
+#define H5FD_TESTING
+
#include "h5test.h"
#include "H5srcdir.h"
+#include "H5FDpkg.h" /* File drivers */
#include "H5Gpkg.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
#include "H5Lprivate.h" /* Links */
@@ -3951,7 +3955,7 @@ external_set_elink_fapl3(hbool_t new_format)
*-------------------------------------------------------------------------
*/
static int
-external_set_elink_acc_flags(hid_t fapl, hbool_t new_format)
+external_set_elink_acc_flags(const char *env_h5_drvr, hid_t fapl, hbool_t new_format)
{
hid_t file1 = -1, file2 = -1, group = -1, subgroup = -1, gapl = -1;
char filename1[NAME_BUF_SIZE],
@@ -4010,6 +4014,15 @@ external_set_elink_acc_flags(hid_t fapl, hbool_t new_format)
} H5E_END_TRY;
if(subgroup != FAIL) TEST_ERROR
+ /* Attempt to set SWMR flags on gapl.
+ * This is just a smoke check of the flags. The actual external link
+ * functionality is tested in the SWMR tests.
+ */
+ /* Set SWMR reader flags on gapl */
+ if(H5Pset_elink_acc_flags(gapl, H5F_ACC_RDONLY | H5F_ACC_SWMR_READ) < 0) TEST_ERROR
+ /* Set SWMR writer flags on gapl */
+ if(H5Pset_elink_acc_flags(gapl, H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE) < 0) TEST_ERROR
+
/* Attempt to set invalid flags on gapl */
H5E_BEGIN_TRY {
ret = H5Pset_elink_acc_flags(gapl, H5F_ACC_TRUNC);
@@ -4023,10 +4036,94 @@ external_set_elink_acc_flags(hid_t fapl, hbool_t new_format)
ret = H5Pset_elink_acc_flags(gapl, H5F_ACC_CREAT);
} H5E_END_TRY;
if(ret != FAIL) TEST_ERROR
+ /* SWMR reader with write access */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_elink_acc_flags(gapl, H5F_ACC_RDWR | H5F_ACC_SWMR_READ);
+ } H5E_END_TRY;
+ if(ret != FAIL) TEST_ERROR
+ /* SWMR writer with read-only access */
+ H5E_BEGIN_TRY {
+ ret = H5Pset_elink_acc_flags(gapl, H5F_ACC_RDONLY | H5F_ACC_SWMR_WRITE);
+ } H5E_END_TRY;
+ if(ret != FAIL) TEST_ERROR
/* Close file1 */
if(H5Fclose(file1) < 0) TEST_ERROR
+ /* Only run this part with VFDs that support SWMR */
+ if(H5FD_supports_swmr_test(env_h5_drvr)) {
+
+ /* Reopen file1, with read-write and SWMR-write access */
+ /* Only supported under the latest file format */
+ if(new_format) {
+ if((file1 = H5Fopen(filename1, H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE, fapl)) < 0) FAIL_STACK_ERROR
+
+ /* Open a group through the external link using default gapl */
+ if((group = H5Gopen2(file1, "/ext_link/group", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
+
+ /* Verify that the correct parameters have been set on file2 */
+ if((file2 = H5Iget_file_id(group)) < 0) FAIL_STACK_ERROR
+ if(H5Fget_intent(file2, &flags) < 0) FAIL_STACK_ERROR
+ if(flags != (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE)) TEST_ERROR
+
+ /* Close file2 and group */
+ if(H5Gclose(group) < 0) FAIL_STACK_ERROR
+ if(H5Fclose(file2) < 0) FAIL_STACK_ERROR
+
+ /* Set elink access flags on gapl to be H5F_ACC_RDWR (dropping SWMR_WRITE) */
+ if(H5Pset_elink_acc_flags(gapl, H5F_ACC_RDWR) < 0) FAIL_STACK_ERROR
+
+ /* Open a group through the external link using gapl */
+ if((group = H5Gopen2(file1, "/ext_link/group", gapl)) < 0) FAIL_STACK_ERROR
+
+ /* Verify that the correct parameters have been set on file2 */
+ if((file2 = H5Iget_file_id(group)) < 0) FAIL_STACK_ERROR
+ if(H5Fget_intent(file2, &flags) < 0) FAIL_STACK_ERROR
+ if(flags != H5F_ACC_RDWR) TEST_ERROR
+
+ /* Close file2 and group */
+ if(H5Gclose(group) < 0) FAIL_STACK_ERROR
+ if(H5Fclose(file2) < 0) FAIL_STACK_ERROR
+
+ /* Close file1 */
+ if(H5Fclose(file1) < 0) TEST_ERROR
+ }
+
+ /* Reopen file1, with read-only and SWMR-read access */
+ if((file1 = H5Fopen(filename1, H5F_ACC_RDONLY | H5F_ACC_SWMR_READ, fapl)) < 0) FAIL_STACK_ERROR
+
+ /* Open a group through the external link using default gapl */
+ if((group = H5Gopen2(file1, "/ext_link/group", H5P_DEFAULT)) < 0) FAIL_STACK_ERROR
+
+ /* Verify that the correct parameters have been set on file2 */
+ if((file2 = H5Iget_file_id(group)) < 0) FAIL_STACK_ERROR
+ if(H5Fget_intent(file2, &flags) < 0) FAIL_STACK_ERROR
+ if(flags != (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ)) TEST_ERROR
+
+ /* Close file2 and group */
+ if(H5Gclose(group) < 0) FAIL_STACK_ERROR
+ if(H5Fclose(file2) < 0) FAIL_STACK_ERROR
+
+ /* Set elink access flags on gapl to be H5F_ACC_RDWR (dropping SWMR_WRITE) */
+ if(H5Pset_elink_acc_flags(gapl, H5F_ACC_RDONLY) < 0) FAIL_STACK_ERROR
+
+ /* Open a group through the external link using gapl */
+ if((group = H5Gopen2(file1, "/ext_link/group", gapl)) < 0) FAIL_STACK_ERROR
+
+ /* Verify that the correct parameters have been set on file2 */
+ if((file2 = H5Iget_file_id(group)) < 0) FAIL_STACK_ERROR
+ if(H5Fget_intent(file2, &flags) < 0) FAIL_STACK_ERROR
+ if(flags != H5F_ACC_RDONLY) TEST_ERROR
+
+ /* Close file2 and group */
+ if(H5Gclose(group) < 0) FAIL_STACK_ERROR
+ if(H5Fclose(file2) < 0) FAIL_STACK_ERROR
+
+ /* Close file1 */
+ if(H5Fclose(file1) < 0) TEST_ERROR
+ } /* end if */
+
+
/* Verify that H5Fcreate and H5Fopen reject H5F_ACC_DEFAULT */
H5E_BEGIN_TRY {
file1 = H5Fcreate(filename1, H5F_ACC_DEFAULT, H5P_DEFAULT, fapl);
@@ -14840,7 +14937,7 @@ main(void)
/* This test cannot run with the EFC because the EFC cannot currently
* reopen a cached file with a different intent */
- nerrors += external_set_elink_acc_flags(my_fapl, new_format) < 0 ? 1 : 0;
+ nerrors += external_set_elink_acc_flags(env_h5_drvr, my_fapl, new_format) < 0 ? 1 : 0;
/* Try external link tests both with and without the external file cache
*/
diff --git a/test/ohdr.c b/test/ohdr.c
index f06dc71..2ac9866 100644
--- a/test/ohdr.c
+++ b/test/ohdr.c
@@ -44,6 +44,11 @@ const char *FILENAME[] = {
*/
#define FILE_BOGUS "tbogus.h5"
+/* */
+#define FILE_OHDR_SWMR "ohdr_swmr.h5"
+#define DSET_NAME "COMPACT_DSET"
+#define OBJ_VERSION_LATEST 2
+
/*
* Verify that messages are moved forward into a "continuation message":
* Create an object header with several continuation chunks
@@ -297,6 +302,152 @@ error:
} /* test_ohdr_cache() */
/*
+ * To exercise the coding for the re-read of the object header for SWMR access.
+ * When the object header is read in H5O_load() of H5Ocache.c, the library initially reads
+ * H5O_SPEC_READ_SIZE (512, currently) bytes for decoding, then reads the
+ * remaining bytes later if the object header is greater than H5O_SPEC_READ_SIZE
+ * bytes. For SWMR access, the read should be done all at one time.
+ */
+static herr_t
+test_ohdr_swmr(hbool_t new_format)
+{
+ hid_t fid = -1; /* File ID */
+ hid_t fapl = -1; /* File access property list */
+ hid_t did = -1; /* Dataset ID */
+ hid_t sid = -1; /* Dataspace ID */
+ hid_t plist = -1; /* Dataset creation property list */
+ size_t compact_size = 1024; /* The size of compact dataset */
+ int *wbuf = NULL; /* Buffer for writing */
+ hsize_t dims[1]; /* Dimension sizes */
+ size_t u; /* Iterator */
+ int n; /* Data variable */
+ H5O_info_t obj_info; /* Information for the object */
+
+ if(new_format) {
+ TESTING("exercise the coding for the re-read of the object header for SWMR access: latest-format");
+ } else {
+ TESTING("exercise the coding for the re-read of the object header for SWMR access: non-latest-format");
+ } /* end if */
+
+ /* File access property list */
+ if((fapl = H5Pcreate(H5P_FILE_ACCESS)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create the file with/without latest format: ensure version 2 object header for SWMR */
+ if(new_format) {
+ /* Set to use latest library format */
+ if(H5Pset_libver_bounds(fapl, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0)
+ FAIL_STACK_ERROR
+
+ if((fid = H5Fcreate(FILE_OHDR_SWMR, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end if */
+ else {
+ if((fid = H5Fcreate(FILE_OHDR_SWMR, H5F_ACC_TRUNC|H5F_ACC_SWMR_WRITE, H5P_DEFAULT, fapl)) < 0)
+ TEST_ERROR
+ } /* end else */
+
+ /* Initialize data */
+ wbuf = (int *)HDcalloc(compact_size, sizeof(int));
+ n = 0;
+ for(u = 0; u < compact_size; u++)
+ wbuf[u] = n++;
+
+ /* Create a small data space for compact dataset */
+ dims[0] = (hsize_t)compact_size;
+ if((sid = H5Screate_simple(1, dims, NULL)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create property list for compact dataset creation */
+ if((plist = H5Pcreate(H5P_DATASET_CREATE)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Set the layout for the compact dataset */
+ if(H5Pset_layout(plist, H5D_COMPACT) < 0)
+ FAIL_STACK_ERROR
+
+ /* Create a compact dataset */
+ if((did = H5Dcreate2(fid, DSET_NAME, H5T_NATIVE_INT, sid, H5P_DEFAULT, plist, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Write to the compact dataset */
+ if(H5Dwrite(did, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, wbuf) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Open the file for SWMR write with/without latest format */
+ if((fid = H5Fopen(FILE_OHDR_SWMR, H5F_ACC_RDWR|H5F_ACC_SWMR_WRITE, fapl)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Open the compact dataset */
+ if((did = H5Dopen2(fid, DSET_NAME, H5P_DEFAULT)) < 0)
+ FAIL_STACK_ERROR
+
+ /* Get the object information */
+ if(H5Oget_info(did, &obj_info) < 0)
+ FAIL_STACK_ERROR
+
+ if(obj_info.hdr.version != OBJ_VERSION_LATEST)
+ FAIL_STACK_ERROR
+
+ /* The size of object header should be greater than the speculative read size of H5O_SPEC_READ_SIZE */
+ /* This will exercise the coding for the re-read of the object header for SWMR access */
+ if(obj_info.hdr.space.total < H5O_SPEC_READ_SIZE)
+ TEST_ERROR;
+
+ /* Close the dataset */
+ if(H5Dclose(did) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the file */
+ if(H5Fclose(fid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataspace */
+ if(H5Sclose(sid) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the dataset creation property list */
+ if(H5Pclose(plist) < 0)
+ FAIL_STACK_ERROR
+
+ /* Close the file access property list */
+ if(H5Pclose(fapl) < 0)
+ FAIL_STACK_ERROR
+
+ /* Remove the test file */
+ if(HDremove(FILE_OHDR_SWMR) < 0)
+ FAIL_STACK_ERROR
+
+ /* Free the buffer */
+ HDfree(wbuf);
+
+ PASSED();
+
+ return SUCCEED;
+
+error:
+ H5E_BEGIN_TRY {
+ H5Fclose(fid);
+ H5Dclose(did);
+ H5Sclose(sid);
+ H5Pclose(plist);
+ H5Pclose(fapl);
+ HDremove(FILE_OHDR_SWMR);
+ HDfree(wbuf);
+ } H5E_END_TRY;
+
+ return FAIL;
+} /* test_ohdr_swmr() */
+
+/*
* To test objects with unknown messages in a file with:
* a) H5O_BOGUS_VALID_ID:
* --the bogus_id is within the range of H5O_msg_class_g[]
@@ -832,6 +983,10 @@ main(void)
/* Verify symbol table messages are cached */
if(h5_verify_cached_stabs(FILENAME, fapl) < 0) TEST_ERROR
+ /* A test to exercise the re-read of the object header for SWMR access */
+ if(test_ohdr_swmr(TRUE) < 0) TEST_ERROR
+ if(test_ohdr_swmr(FALSE) < 0) TEST_ERROR
+
HDputs("All object header tests passed.");
h5_cleanup(FILENAME, fapl);
return 0;
diff --git a/test/testflushrefresh.sh.in b/test/testflushrefresh.sh.in
new file mode 100644
index 0000000..7bfeb60
--- /dev/null
+++ b/test/testflushrefresh.sh.in
@@ -0,0 +1,200 @@
+#! /bin/sh
+#
+# Copyright by The HDF Group.
+# Copyright by the Board of Trustees of the University of Illinois.
+# All rights reserved.
+#
+# This file is part of HDF5. The full HDF5 copyright notice, including
+# terms governing use, modification, and redistribution, is contained in
+# the files COPYING and Copyright.html. COPYING can be found at the root
+# of the source code distribution tree; Copyright.html can be found at the
+# root level of an installed copy of the electronic HDF5 document set and
+# is linked from the top-level documents page. It can also be found at
+# http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have
+# access to either file, you may request a copy from help@hdfgroup.org.
+#
+#
+# Test script for the flush/evict single objects feature.
+#
+# This test file doesn't actually perform any tests, rather, it acts
+# as a process manager for the 'flushrefresh' test file, which is where
+# the tests are actually housed. The reason this script exists is because
+# the verification of this feature needs to occur in separate processes
+# from the one in which the file is being manipulated in. (i.e., we have
+# a single writer process, and various reader processes spawning off
+# and doing the verification that individual objects are being
+# correctly flushed).
+#
+# Programmer:
+# Mike McGreevy
+# Tuesday, July 20, 2010
+
+###############################################################################
+## test variables
+###############################################################################
+
+# Number of errors encountered during test run.
+nerrors=0
+
+# Set up a function to check the current time since the epoch - ideally, we'd
+# like to use Perl. If it wasn't detected by configure, then use date, though
+# this is less portable and might cause problems on machines that don't
+# recognize the +%s option (like Solaris).
+#
+# Note that PERL will resolve to true or false, not a path.
+PERL=@PERL@
+if test -n "$PERL"; then
+ TimeStamp()
+ {
+ time=`perl -e 'print int(time)'`
+ echo "$time"
+ }
+else
+ TimeStamp()
+ {
+ time=`date +%s`
+ echo "$time"
+ }
+fi
+
+###############################################################################
+## Main
+###############################################################################
+# The build (current) directory might be different than the source directory.
+if test -z "$srcdir"; then
+ srcdir=.
+fi
+
+# Check to see if the VFD specified by the HDF5_DRIVER environment variable
+# supports SWMR.
+./swmr_check_compat_vfd
+rc=$?
+if [ $rc -ne 0 ] ; then
+ echo
+ echo "The VFD specified by the HDF5_DRIVER environment variable"
+ echo "does not support SWMR."
+ echo
+ echo "flush/refresh tests skipped"
+ echo
+ exit 0
+fi
+
+# ========================
+# Launch the Test Program.
+# ========================
+./flushrefresh &
+pid_main=$!
+
+# =================================================
+# Set up/initialize some variables to be used later
+# =================================================
+testfile=flushrefresh.h5
+startsignal=flushrefresh_VERIFICATION_START
+endsignal=flushrefresh_VERIFICATION_DONE
+timeout_length=300
+timedout=0
+verification_done=0
+if [ -e $testfile ]; then
+ rm $testfile
+fi
+
+# =======================================
+# Run flush verification on test program.
+# =======================================
+
+until [ $verification_done -eq 1 ]; do
+
+ # Wait for signal from test program that verification routine can run.
+ before=`TimeStamp`
+ until [ -s $startsignal ]; do
+ after=`TimeStamp`
+ timediff=`expr $after - $before`
+ if [ $timediff -gt $timeout_length ]; then
+ nerrors=`expr $nerrors + 1`
+ timedout=1
+ break
+ fi
+ done
+
+ # Check to see if we timed out looking for the signal before continuing.
+ if [ $timedout -gt 0 ]; then
+ echo timed out waiting for signal from test program.
+ break
+ fi
+
+ # Read in test routine parameters from signal file, then delete signal file.
+ param1=`head -1 $startsignal`
+ param2=`tail -1 $startsignal`
+ rm $startsignal
+
+ # Check if we're done with verifications, otherwise run the specified verification.
+ if [ "$param1" = "VERIFICATION_DONE" ]; then
+ verification_done=1
+ echo "all flush verification complete" > $endsignal
+ else
+ ./flushrefresh $param1 $param2
+ echo "verification flush process done" > $endsignal
+ fi
+
+done
+
+# =========================================
+# Run refresh verification on test program.
+# =========================================
+if [ $timedout -eq 0 ]; then
+ until [ $verification_done -eq 2 ]; do
+
+ # Wait for signal from test program that verification routine can run.
+ before=`TimeStamp`
+ until [ -s $startsignal ]; do
+ after=`TimeStamp`
+ timediff=`expr $after - $before`
+ if [ $timediff -gt $timeout_length ]; then
+ nerrors=`expr $nerrors + 1`
+ timedout=1
+ break
+ fi
+ done
+
+ # Check to see if we timed out looking for the signal before continuing.
+ if [ $timedout -gt 0 ]; then
+ echo timed out waiting for signal from test program.
+ break
+ fi
+
+ # Read in test routine parameter from signal file, then delete signal file.
+ param1=`head -n 1 $startsignal`
+ rm $startsignal
+
+ # Check if we're done with verifications, otherwise run the specified verification.
+ if [ "$param1" = "VERIFICATION_DONE" ]; then
+ verification_done=2
+ echo "all refresh verification complete" > $endsignal
+ else
+ ./flushrefresh $param1
+ echo "refresh verifiction process done" > $endsignal
+ fi
+
+ done
+fi
+
+# ============================================
+# Wait for main to finish up, and end testing.
+# ============================================
+wait $pid_main
+if test $? -ne 0; then
+ echo flushrefresh had error
+ nerrors=`expr $nerrors + 1`
+fi
+
+###############################################################################
+## Report and exit
+###############################################################################
+
+if test $nerrors -eq 0 ; then
+ echo "flush/refresh objects tests passed."
+ exit 0
+else
+ echo "flush/refresh objects tests failed with $nerrors errors."
+ exit 1
+fi
diff --git a/test/tfile.c b/test/tfile.c
index 82905d5..19a2df4 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -3847,7 +3847,8 @@ test_libver_macros(void)
VERIFY(H5_VERSION_GE(major-1,minor,release+1), TRUE, "H5_VERSION_GE");
VERIFY(H5_VERSION_GE(major,minor-1,release), TRUE, "H5_VERSION_GE");
VERIFY(H5_VERSION_GE(major,minor-1,release+1), TRUE, "H5_VERSION_GE");
- VERIFY(H5_VERSION_GE(major,minor,release-1), TRUE, "H5_VERSION_GE");
+ if(H5_VERS_RELEASE > 0)
+ VERIFY(H5_VERSION_GE(major,minor,release-1), TRUE, "H5_VERSION_GE");
VERIFY(H5_VERSION_GE(major+1,minor,release), FALSE, "H5_VERSION_GE");
VERIFY(H5_VERSION_GE(major+1,minor-1,release), FALSE, "H5_VERSION_GE");
@@ -3869,7 +3870,8 @@ test_libver_macros(void)
VERIFY(H5_VERSION_LE(major-1,minor+1,release+1), FALSE, "H5_VERSION_LE");
VERIFY(H5_VERSION_LE(major,minor-1,release), FALSE, "H5_VERSION_LE");
VERIFY(H5_VERSION_LE(major,minor-1,release+1), FALSE, "H5_VERSION_LE");
- VERIFY(H5_VERSION_LE(major,minor,release-1), FALSE, "H5_VERSION_LE");
+ if(H5_VERS_RELEASE > 0)
+ VERIFY(H5_VERSION_LE(major,minor,release-1), FALSE, "H5_VERSION_LE");
} /* test_libver_macros() */
/****************************************************************
diff --git a/tools/test/h5ls/CMakeTests.cmake b/tools/test/h5ls/CMakeTests.cmake
index e7a5dd6..a66ae40 100644
--- a/tools/test/h5ls/CMakeTests.cmake
+++ b/tools/test/h5ls/CMakeTests.cmake
@@ -261,6 +261,19 @@
set (last_test "H5LS-clearall-objects")
endif (HDF5_ENABLE_USING_MEMCHECKER)
+# See which filters are usable (and skip tests for filters we
+# don't have). Do this by searching H5pubconf.h to see which
+# filters are defined.
+
+# detect whether the encoder is present.
+ if (H5_HAVE_FILTER_DEFLATE)
+ set (USE_FILTER_DEFLATE "true")
+ endif (H5_HAVE_FILTER_DEFLATE)
+
+ if (H5_HAVE_FILTER_SZIP)
+ set (USE_FILTER_SZIP "true")
+ endif (H5_HAVE_FILTER_SZIP)
+
# test the help syntax
ADD_H5_TEST (help-1 0 -w80 -h)
ADD_H5_TEST (help-2 0 -w80 --help)
@@ -392,6 +405,8 @@
endif (H5_WORDS_BIGENDIAN)
# test for file with datasets that use Fixed Array chunk indices
-#echo "***skip testing tdset_idx.h5"
-ADD_H5_TEST (tdset_idx 0 -w80 -d tdset_idx.h5)
-
+ if (USE_FILTER_DEFLATE)
+ # data read internal filters
+ ADD_H5_TEST (tdset_idx 0 -w80 -d tdset_idx.h5)
+ endif (USE_FILTER_DEFLATE)
+
diff --git a/tools/test/h5ls/testh5ls.sh.in b/tools/test/h5ls/testh5ls.sh.in
index e2a72ba..15282f6 100644
--- a/tools/test/h5ls/testh5ls.sh.in
+++ b/tools/test/h5ls/testh5ls.sh.in
@@ -17,6 +17,9 @@
srcdir=@srcdir@
+USE_FILTER_SZIP="@USE_FILTER_SZIP@"
+USE_FILTER_DEFLATE="@USE_FILTER_DEFLATE@"
+
TESTNAME=h5ls
EXIT_SUCCESS=0
EXIT_FAILURE=1
@@ -180,10 +183,10 @@ COPY_TESTFILES_TO_TESTDIR()
INODE_SDIR=`$LS -i -d $SDIR | $AWK -F' ' '{print $1}'`
INODE_DDIR=`$LS -i -d $TESTDIR | $AWK -F' ' '{print $1}'`
if [ "$INODE_SDIR" != "$INODE_DDIR" ]; then
- $CP -f $tstfile $TESTDIR
+ $CP -f $tstfile $TESTDIR
if [ $? -ne 0 ]; then
echo "Error: FAILED to copy $tstfile ."
-
+
# Comment out this to CREATE expected file
exit $EXIT_FAILURE
fi
@@ -238,10 +241,10 @@ TOOLTEST() {
# any unexpected output from that stream too.
TESTING $H5LS $@
(
- cd $TESTDIR
+ cd $TESTDIR
$RUNSERIAL $H5LS_BIN "$@"
- ) >$actual 2>$actual_err
-
+ ) >$actual 2>$actual_err
+
exitcode=$?
# save actual and actual_err in case they are needed later.
cp $actual $actual_sav
@@ -250,37 +253,37 @@ TOOLTEST() {
STDERR_FILTER $actual_err
cat $actual_err >> $actual
if [ $h5haveexitcode = 'yes' -a $exitcode -ne $retvalexpect ]; then
- echo "*FAILED*"
- nerrors="`expr $nerrors + 1`"
- if [ yes = "$verbose" ]; then
- echo "test returned with exit code $exitcode"
- echo "test output: (up to $NLINES lines)"
- head -$NLINES $actual
- echo "***end of test output***"
- echo ""
- fi
+ echo "*FAILED*"
+ nerrors="`expr $nerrors + 1`"
+ if [ yes = "$verbose" ]; then
+ echo "test returned with exit code $exitcode"
+ echo "test output: (up to $NLINES lines)"
+ head -$NLINES $actual
+ echo "***end of test output***"
+ echo ""
+ fi
elif [ ! -f $expect ]; then
- # Create the expect file if it doesn't yet exist.
+ # Create the expect file if it doesn't yet exist.
echo " CREATED"
cp $actual $expect
elif $CMP $expect $actual; then
echo " PASSED"
else
echo "*FAILED*"
- echo " Expected result differs from actual result"
- nerrors="`expr $nerrors + 1`"
- test yes = "$verbose" && $DIFF $expect $actual |sed 's/^/ /'
+ echo " Expected result differs from actual result"
+ nerrors="`expr $nerrors + 1`"
+ test yes = "$verbose" && $DIFF $expect $actual |sed 's/^/ /'
fi
# Clean up output file
if test -z "$HDF5_NOCLEANUP"; then
- rm -f $actual $actual_err $actual_sav $actual_err_sav
+ rm -f $actual $actual_err $actual_sav $actual_err_sav
fi
}
##############################################################################
##############################################################################
-### T H E T E S T S ###
+### T H E T E S T S ###
##############################################################################
##############################################################################
# prepare for test
@@ -339,7 +342,7 @@ TOOLTEST textlinksrc-3-old.ls 0 -w80 -Er textlinksrc.h5/ext_link1
TOOLTEST textlinksrc-6-old.ls 0 -w80 -E textlinksrc.h5
TOOLTEST textlinksrc-7-old.ls 0 -w80 -E textlinksrc.h5/ext_link1
-# tests for no-dangling-links
+# tests for no-dangling-links
# if this option is given on dangling link, h5ls should return exit code 1
# when used alone , expect to print out help and return exit code 1
TOOLTEST textlinksrc-nodangle-1.ls 1 -w80 --no-dangling-links textlinksrc.h5
@@ -374,7 +377,7 @@ TOOLTEST tnestcomp-4.ls 0 -w80 -r -d -l -S tnestedcomp.h5
# test for loop detection
TOOLTEST tloop-1.ls 0 -w80 -r -d tloop.h5
-# test for string
+# test for string
TOOLTEST tstr-1.ls 0 -w80 -r -d tstr.h5
# test test file created from lib SAF team
@@ -405,22 +408,26 @@ fi
# test for non-existing file
TOOLTEST nosuchfile.ls 1 nosuchfile.h5
-# test for variable length data types in verbose mode
+# test for variable length data types in verbose mode
if test $WORDS_BIGENDIAN != "yes"; then
TOOLTEST tvldtypes2le.ls 0 -v tvldtypes1.h5
else
TOOLTEST tvldtypes2be.ls 0 -v tvldtypes1.h5
-fi
+fi
-# test for dataset region references data types in verbose mode
+# test for dataset region references data types in verbose mode
if test $WORDS_BIGENDIAN != "yes"; then
TOOLTEST tdataregle.ls 0 -v tdatareg.h5
else
TOOLTEST tdataregbe.ls 0 -v tdatareg.h5
-fi
+fi
# test for file with datasets that use Fixed Array chunk indices
+if test $USE_FILTER_DEFLATE = "yes" ; then
+ # data read internal filters
+ TOOLTEST tdset_idx.ls 0 -w80 -d tdset_idx.h5
+fi
echo "***skip testing tdset_idx.h5"
TOOLTEST tdset_idx.ls 0 -w80 -d tdset_idx.h5