summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2009-05-19 14:43:31 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2009-05-19 14:43:31 (GMT)
commitebe57002d61b1b2928b31dbc687d178901d21066 (patch)
tree0ebfe5bd0196da964a0cf5cca44d0766f9dc5742
parent0917096d34762b93f13203bec928f9dd124e7bfa (diff)
downloadhdf5-ebe57002d61b1b2928b31dbc687d178901d21066.zip
hdf5-ebe57002d61b1b2928b31dbc687d178901d21066.tar.gz
hdf5-ebe57002d61b1b2928b31dbc687d178901d21066.tar.bz2
[svn-r16960] Description:
Add a new H5F_ACC_SWMR_WRITE flag for H5Fcreate/H5Fopen, so that an application can indicate that it is modifying the file in a SWMR scenario and internal algorithms can make appropriate adjustments to order their I/O operations to meet the constraints necessary for ensuring SWMR consistency. Tested on: FreeBSD/32 6.3 (duty) in debug mode FreeBSD/64 6.3 (liberty) w/C++ & FORTRAN, in debug mode Linux/32 2.6 (jam) w/PGI compilers, w/C++ & FORTRAN, w/threadsafe, in debug mode Linux/64-amd64 2.6 (smirom) w/Intel compilers w/default API=1.6.x, w/C++ & FORTRAN, in production mode Solaris/32 2.10 (linew) w/deprecated symbols disabled, w/C++ & FORTRAN, w/szip filter, in production mode Linux/64-ia64 2.6 (cobalt) w/Intel compilers, w/C++ & FORTRAN, in production mode Linux/64-ia64 2.4 (tg-login3) w/parallel, w/FORTRAN, in debug mode Linux/64-amd64 2.6 (abe) w/parallel, w/FORTRAN, in production mode Mac OS X/32 10.5.6 (amazon) in debug mode Mac OS X/32 10.5.6 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode
-rw-r--r--src/H5F.c28
-rw-r--r--src/H5Fpkg.h2
-rw-r--r--src/H5Fpublic.h9
-rw-r--r--test/tfile.c129
4 files changed, 153 insertions, 15 deletions
diff --git a/src/H5F.c b/src/H5F.c
index fc85688..a367428 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1284,7 +1284,8 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
* file (since we can't do that while the file is open), or if the
* request was to create a non-existent file (since the file already
* exists), or if the new request adds write access (since the
- * readers don't expect the file to change under them).
+ * readers don't expect the file to change under them), or if the
+ * SWMR Write access flags don't agree.
*/
if(H5FD_close(lf) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
@@ -1294,6 +1295,9 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file exists")
if((flags & H5F_ACC_RDWR) && 0 == (shared->flags & H5F_ACC_RDWR))
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "file is already open for read-only")
+ if(((flags & H5F_ACC_SWMR_WRITE) && 0 == (shared->flags & H5F_ACC_SWMR_WRITE))
+ || (0 == (flags & H5F_ACC_SWMR_WRITE) && (shared->flags & H5F_ACC_SWMR_WRITE)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "single-writer access flag not the same for file that is already open")
/* Allocate new "high-level" file struct */
if((file = H5F_new(shared, fcpl_id, fapl_id, NULL)) == NULL)
@@ -1490,11 +1494,15 @@ H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
H5TRACE4("i", "*sIuii", filename, flags, fcpl_id, fapl_id);
/* Check/fix arguments */
- if (!filename || !*filename)
+ if(!filename || !*filename)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file name")
- if (flags & ~(H5F_ACC_EXCL|H5F_ACC_TRUNC|H5F_ACC_DEBUG))
+ /* In this routine, we only accept the following flags:
+ * H5F_ACC_EXCL, H5F_ACC_TRUNC, H5F_ACC_DEBUG and H5F_ACC_SWMR_WRITE
+ */
+ if(flags & ~(H5F_ACC_EXCL | H5F_ACC_TRUNC | H5F_ACC_DEBUG | H5F_ACC_SWMR_WRITE))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid flags")
- if ((flags & H5F_ACC_EXCL) && (flags & H5F_ACC_TRUNC))
+ /* The H5F_ACC_EXCL and H5F_ACC_TRUNC flags are mutually exclusive */
+ if((flags & H5F_ACC_EXCL) && (flags & H5F_ACC_TRUNC))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "mutually exclusive flags for file creation")
/* Check file creation property list */
@@ -1594,9 +1602,13 @@ H5Fopen(const char *filename, unsigned flags, hid_t fapl_id)
/* Check/fix arguments. */
if(!filename || !*filename)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file name")
+ /* Reject undefined flags (~H5F_ACC_PUBLIC_FLAGS) and the H5F_ACC_TRUNC & H5F_ACC_EXCL flags */
if((flags & ~H5F_ACC_PUBLIC_FLAGS) ||
(flags & H5F_ACC_TRUNC) || (flags & H5F_ACC_EXCL))
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags")
+ /* Asking for SWMR Write access on a read-only file is invalid */
+ if((flags & H5F_ACC_SWMR_WRITE) && 0 == (flags & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "single-writer access on a file open for read-only is not allowed")
if(H5P_DEFAULT == fapl_id)
fapl_id = H5P_FILE_ACCESS_DEFAULT;
else
@@ -2183,10 +2195,16 @@ H5Fget_intent(hid_t file_id, unsigned *intent_flags)
* Simplify things for them so that they only get either H5F_ACC_RDWR
* or H5F_ACC_RDONLY.
*/
- if(H5F_INTENT(file) & H5F_ACC_RDWR)
+ if(H5F_INTENT(file) & H5F_ACC_RDWR) {
*intent_flags = H5F_ACC_RDWR;
+
+ /* Check for SWMR Write access on the file */
+ if(H5F_INTENT(file) & H5F_ACC_SWMR_WRITE)
+ *intent_flags |= H5F_ACC_SWMR_WRITE;
+ } /* end if */
else
*intent_flags = H5F_ACC_RDONLY;
+
} /* end if */
done:
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 49af73e..0d5a593 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -61,7 +61,7 @@
#define H5F_SUPER_ALL_FLAGS (H5F_SUPER_WRITE_ACCESS | H5F_SUPER_FILE_OK)
/* Mask for removing private file access flags */
-#define H5F_ACC_PUBLIC_FLAGS 0x00ffu
+#define H5F_ACC_PUBLIC_FLAGS 0x003fu
/* Free space section+aggregator merge flags */
#define H5F_FS_MERGE_METADATA 0x01 /* Section can merge with metadata aggregator */
diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h
index 287e9b5..cea4ae2 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -49,6 +49,15 @@
#define H5F_ACC_EXCL (H5CHECK 0x0004u) /*fail if file already exists*/
#define H5F_ACC_DEBUG (H5CHECK 0x0008u) /*print debug info */
#define H5F_ACC_CREAT (H5CHECK 0x0010u) /*create non-existing files */
+#define H5F_ACC_SWMR_WRITE (H5CHECK 0x0020u) /*indicate that this file is
+ * open for writing in a
+ * single-writer/multi-reader (SWMR)
+ * scenario. Note that the
+ * process(es) opening the file
+ * reading shouldn't open the
+ * for RDWR access, although a
+ * special "SWMR_READ" access
+ * flag is not necessary. */
/* Value passed to H5Pset_elink_acc_flags to cause flags to be taken from the
* parent file. */
diff --git a/test/tfile.c b/test/tfile.c
index 68c7f6b..445f5c2 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -233,7 +233,7 @@ test_file_create(void)
{
hid_t dataset_id, dataspace_id; /* identifiers */
hsize_t dims[F2_RANK];
- int data[F2_DIM0][F2_DIM1];
+ unsigned data[F2_DIM0][F2_DIM1];
unsigned i,j;
/* Create the data space for the dataset. */
@@ -243,7 +243,7 @@ test_file_create(void)
CHECK(dataspace_id, FAIL, "H5Screate_simple");
/* Create the dataset. */
- dataset_id = H5Dcreate2(fid2, F2_DSET, H5T_NATIVE_INT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ dataset_id = H5Dcreate2(fid2, F2_DSET, H5T_NATIVE_UINT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
CHECK(dataset_id, FAIL, "H5Dcreate2");
for(i = 0; i < F2_DIM0; i++)
@@ -251,7 +251,7 @@ test_file_create(void)
data[i][j] = i * 10 + j;
/* Write data to the new dataset */
- ret = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
+ ret = H5Dwrite(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
CHECK(ret, FAIL, "H5Dwrite");
/* End access to the dataset and release resources used by it. */
@@ -804,7 +804,7 @@ create_objects(hid_t fid1, hid_t fid2, hid_t *ret_did, hid_t *ret_gid1,
{
hid_t dataset_id, dataspace_id; /* identifiers */
hsize_t dims[F2_RANK];
- int data[F2_DIM0][F2_DIM1];
+ unsigned data[F2_DIM0][F2_DIM1];
unsigned i,j;
/* Create the data space for the dataset. */
@@ -814,7 +814,7 @@ create_objects(hid_t fid1, hid_t fid2, hid_t *ret_did, hid_t *ret_gid1,
CHECK(dataspace_id, FAIL, "H5Screate_simple");
/* Create the dataset. */
- dataset_id = H5Dcreate2(fid1, "/dset", H5T_NATIVE_INT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+ dataset_id = H5Dcreate2(fid1, "/dset", H5T_NATIVE_UINT, dataspace_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
CHECK(dataset_id, FAIL, "H5Dcreate2");
for(i = 0; i < F2_DIM0; i++)
@@ -822,8 +822,7 @@ create_objects(hid_t fid1, hid_t fid2, hid_t *ret_did, hid_t *ret_gid1,
data[i][j] = i * 10 + j;
/* Write data to the new dataset */
- ret = H5Dwrite(dataset_id, H5T_NATIVE_INT, H5S_ALL, H5S_ALL,
- H5P_DEFAULT, data);
+ ret = H5Dwrite(dataset_id, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
CHECK(ret, FAIL, "H5Dwrite");
if(ret_did != NULL)
@@ -2014,7 +2013,7 @@ test_cached_stab_info(void)
/* Reopen file */
file_id = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
- CHECK(ret, FAIL, "H5Fopen");
+ CHECK(file_id, FAIL, "H5Fopen");
/* Verify the cached symbol table information */
ret = H5F_check_cached_stab_test(file_id);
@@ -2027,6 +2026,117 @@ test_cached_stab_info(void)
/****************************************************************
**
+** test_swmr_write(): low-level file test routine.
+** This test checks that the H5F_ACC_SWMR_WRITE access flag is
+** working properly.
+**
+*****************************************************************/
+static void
+test_swmr_write(void)
+{
+ hid_t fid, fid2; /* File IDs */
+ unsigned intent; /* File access flags */
+ herr_t ret; /* Generic return value */
+
+ /* Output message about test being performed */
+ MESSAGE(5, ("Testing H5F_ACC_SWMR_WRITE access flag\n"));
+
+
+ /* Create file, without SWMR_WRITE flag */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get the intent & check that the SWMR_WRITE flag is not set */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, H5F_ACC_RDWR, "H5Fget_intent");
+
+ /* Try to reopen file w/SWMR_WRITE flag */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+
+ /* Create file, with SWMR_WRITE flag */
+ fid = H5Fcreate(FILE1, (H5F_ACC_TRUNC | H5F_ACC_SWMR_WRITE), H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get the intent & check that the SWMR_WRITE flag is set */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
+
+ /* Try to reopen file w/o SWMR_WRITE flag */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Reopen file, with read-write and SWMR_WRITE access */
+ fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), H5P_DEFAULT);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Get the intent & check that the SWMR_WRITE flag is set */
+ ret = H5Fget_intent(fid2, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+
+ /* Try to reopen file read-only w/SWMR_WRITE flag */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_WRITE), H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+
+ /* Reopen file, with read-write and SWMR_WRITE access */
+ fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Get the intent & check that the SWMR_WRITE flag is set */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
+
+ /* Try to reopen file w/o SWMR_WRITE flag */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDWR, H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Reopen file, with read-write and SWMR_WRITE access */
+ fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), H5P_DEFAULT);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Get the intent & check that the SWMR_WRITE flag is set */
+ ret = H5Fget_intent(fid2, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, (H5F_ACC_RDWR | H5F_ACC_SWMR_WRITE), "H5Fget_intent");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+} /* end test_swmr_write() */
+
+/****************************************************************
+**
** test_file(): Main low-level file I/O test routine.
**
****************************************************************/
@@ -2058,7 +2168,8 @@ test_file(void)
#endif /*H5_CANNOT_OPEN_TWICE*/
test_userblock_file_size(); /* Tests that files created with a userblock have the correct size */
test_cached_stab_info(); /* Tests that files are created with cached stab info in the superblock */
-} /* test_file() */
+ test_swmr_write(); /* Tests for SWMR write access flag */
+} /* test_file() */
/*-------------------------------------------------------------------------