summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5F.c35
-rw-r--r--src/H5Fpkg.h2
-rw-r--r--src/H5Fpublic.h16
-rw-r--r--test/tfile.c86
4 files changed, 128 insertions, 11 deletions
diff --git a/src/H5F.c b/src/H5F.c
index 86348d6..841164a 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1296,7 +1296,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
* 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), or if the
- * SWMR Write access flags don't agree.
+ * SWMR write/read access flags don't agree.
*/
if(H5FD_close(lf) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to close low-level file info")
@@ -1308,7 +1308,10 @@ 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 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")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "SWMR write access flag not the same for file that is already open")
+ if(((flags & H5F_ACC_SWMR_READ) && 0 == (shared->flags & H5F_ACC_SWMR_READ))
+ || (0 == (flags & H5F_ACC_SWMR_READ) && (shared->flags & H5F_ACC_SWMR_READ)))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "SWMR read 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)
@@ -1399,6 +1402,19 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
if(H5F_super_read(file, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
+ /* Check if the file is open for SWMR read access */
+ if(flags & H5F_ACC_SWMR_READ) {
+ /* If the file is open for SWMR read access, adjust the end of the
+ * allocated space (the 'eoa') to allow access to any address in the
+ * file. This is done because the eoa stored in the file's superblock
+ * might be out of sync with the objects being written within the
+ * file by the application performing SWMR write operations.
+ */
+ /* (Account for the stored EOA being absolute offset -NAF) */
+ if(H5FD_set_eoa(lf, H5FD_MEM_SUPER, (file->shared->maxaddr - file->shared->base_addr)) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, NULL, "can't relax 'eoa' for SWMR read access")
+ } /* end if */
+
/* Open the root group */
if(H5G_mkroot(file, dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group")
@@ -1617,9 +1633,12 @@ H5Fopen(const char *filename, unsigned flags, hid_t fapl_id)
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 */
+ /* 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")
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "SWMR write access on a file open for read-only access is not allowed")
+ /* Asking for SWMR read access on a non-read-only file is invalid */
+ if((flags & H5F_ACC_SWMR_READ) && (flags & H5F_ACC_RDWR))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "SWMR read access on a file open for read-write access is not allowed")
if(H5P_DEFAULT == fapl_id)
fapl_id = H5P_FILE_ACCESS_DEFAULT;
else
@@ -2209,13 +2228,17 @@ H5Fget_intent(hid_t file_id, unsigned *intent_flags)
if(H5F_INTENT(file) & H5F_ACC_RDWR) {
*intent_flags = H5F_ACC_RDWR;
- /* Check for SWMR Write access on the file */
+ /* 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
+ else {
*intent_flags = H5F_ACC_RDONLY;
+ /* Check for SWMR read access on the file */
+ if(H5F_INTENT(file) & H5F_ACC_SWMR_READ)
+ *intent_flags |= H5F_ACC_SWMR_READ;
+ } /* end else */
} /* end if */
done:
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index fbeaf5b..da7ef24 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 0x003fu
+#define H5F_ACC_PUBLIC_FLAGS 0x007fu
/* 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 cea4ae2..16d3c05 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -54,10 +54,18 @@
* 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. */
+ * for reading must open the file
+ * with RDONLY access, and use
+ * the special "SWMR_READ" access
+ * flag. */
+#define H5F_ACC_SWMR_READ (H5CHECK 0x0040u) /*indicate that this file is
+ * open for reading in a
+ * single-writer/multi-reader (SWMR)
+ * scenario. Note that the
+ * process(es) opening the file
+ * for SWMR reading must also
+ * open the file with the RDONLY
+ * flag. */
/* 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 445f5c2..25c1590 100644
--- a/test/tfile.c
+++ b/test/tfile.c
@@ -2137,6 +2137,91 @@ test_swmr_write(void)
/****************************************************************
**
+** test_swmr_read(): low-level file test routine.
+** This test checks that the H5F_ACC_SWMR_READ access flag is
+** working properly.
+**
+*****************************************************************/
+static void
+test_swmr_read(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_READ access flag\n"));
+
+
+ /* Try to create file w/SWMR_READ flag */
+ H5E_BEGIN_TRY {
+ fid = H5Fcreate(FILE1, (H5F_ACC_TRUNC | H5F_ACC_SWMR_READ), H5P_DEFAULT, H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fcreate");
+
+
+ /* Create file, without SWMR_READ flag */
+ fid = H5Fcreate(FILE1, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fcreate");
+
+ /* Get the intent & check that the SWMR_READ 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_READ flag */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_READ), H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+
+
+ /* Try to open file, with read-write access & SWMR_READ flag */
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(FILE1, (H5F_ACC_RDWR | H5F_ACC_SWMR_READ), H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid, FAIL, "H5Fopen");
+
+
+ /* Open file, with SWMR_READ flag */
+ fid = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), H5P_DEFAULT);
+ CHECK(fid, FAIL, "H5Fopen");
+
+ /* Get the intent & check that the SWMR_READ flag is set */
+ ret = H5Fget_intent(fid, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), "H5Fget_intent");
+
+ /* Try to reopen file w/o SWMR_READ flag */
+ H5E_BEGIN_TRY {
+ fid2 = H5Fopen(FILE1, H5F_ACC_RDONLY, H5P_DEFAULT);
+ } H5E_END_TRY;
+ VERIFY(fid2, FAIL, "H5Fopen");
+
+ /* Reopen file, with read-only and SWMR_READ access */
+ fid2 = H5Fopen(FILE1, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), H5P_DEFAULT);
+ CHECK(fid2, FAIL, "H5Fopen");
+
+ /* Get the intent & check that the SWMR_READ flag is set */
+ ret = H5Fget_intent(fid2, &intent);
+ CHECK(ret, FAIL, "H5Fget_intent");
+ VERIFY(intent, (H5F_ACC_RDONLY | H5F_ACC_SWMR_READ), "H5Fget_intent");
+
+ /* Close file */
+ ret = H5Fclose(fid2);
+ CHECK(ret, FAIL, "H5Fclose");
+
+ /* Close file */
+ ret = H5Fclose(fid);
+ CHECK(ret, FAIL, "H5Fclose");
+} /* end test_swmr_read() */
+
+/****************************************************************
+**
** test_file(): Main low-level file I/O test routine.
**
****************************************************************/
@@ -2169,6 +2254,7 @@ test_file(void)
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_swmr_write(); /* Tests for SWMR write access flag */
+ test_swmr_read(); /* Tests for SWMR read access flag */
} /* test_file() */