diff options
-rw-r--r-- | src/H5F.c | 35 | ||||
-rw-r--r-- | src/H5Fpkg.h | 2 | ||||
-rw-r--r-- | src/H5Fpublic.h | 16 | ||||
-rw-r--r-- | test/tfile.c | 86 |
4 files changed, 128 insertions, 11 deletions
@@ -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() */ |