From e117aee161db792d2dd9ee9f235f95803feb9178 Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Tue, 14 Jul 2009 16:13:50 -0500 Subject: [svn-r17184] Description: Add "SWMR read" file access flag, for applications that are concurrently reading from a file open with the "SWMR write" access flag. This flag relaxes the internal checks for reading beyond the 'eoa' for the file (since the eoa for the file could be out of date until the SWMR write application flushes or closes the file) 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.7 (amazon) in debug mode Mac OS X/32 10.5.7 (amazon) w/C++ & FORTRAN, w/threadsafe, in production mode --- src/H5F.c | 35 +++++++++++++++++++---- src/H5Fpkg.h | 2 +- src/H5Fpublic.h | 16 ++++++++--- test/tfile.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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() */ -- cgit v0.12