diff options
author | Robb Matzke <matzke@llnl.gov> | 1999-08-24 12:52:10 (GMT) |
---|---|---|
committer | Robb Matzke <matzke@llnl.gov> | 1999-08-24 12:52:10 (GMT) |
commit | 296d9cf76640fa1aab51479def07119236f86cb9 (patch) | |
tree | fed33399626284a57091730a748309d709edb13a | |
parent | 8e338a50298bbd928e919cd2dbd30e57e8b322ce (diff) | |
download | hdf5-296d9cf76640fa1aab51479def07119236f86cb9.zip hdf5-296d9cf76640fa1aab51479def07119236f86cb9.tar.gz hdf5-296d9cf76640fa1aab51479def07119236f86cb9.tar.bz2 |
[svn-r1585] Changes since 19990820
----------------------
./src/H5D.c
Added additional elements to a variable initializer in
H5Dvlen_get_buf_size() to shut up a warning message. Also
added the API tracing call.
./src/H5F.c
Added file opening optimizations. If the driver doesn't
support the ability to determine when two file handles refer
to the same file (like MPIO and GASS) then H5F_open() makes
fewer calls to the driver's open callback. Also, if the
tentative file access flags are the same as the original flags
then H5F_open() makes fewer calls to the file device.
./src/H5FD.c
./src/H5FDprivate.h
./src/H5FDpublic.h
Added H5FD_get_class() so the library can get information
about what file driver callbacks are defined. This will be
useful when more optimization functions are added to the VFL,
such as for MPIO derived datatype I/O.
./src/H5FDcore.c
./src/H5FDfamily.c
./src/H5FDmpio.c
./src/H5FDmulti.c
./src/H5FDsec2.c
The driver symbols (like H5FD_CORE, etc) are actually function
calls. The functions were fixed to return correct values even
after calling H5close().
./src/H5FDmulti.c
./src/H5FDmulti.h
Added support for opening a file when parts are missing (only
if the caller explicitly allows that in the file access
property list).
Moved some common code sequences into macros or functions.
Added better support for reopening files. All the application
has to know is that the file is a multi file and the base name
from which all the member names are created.
More debugging output when the file is opened with the
H5F_ACC_DEBUG flag.
Fixed various bugs.
./src/H5Fistore.c
Chunked raw data was accidently allocated as meta data instead
of raw data.
./src/H5I.c
The H5Iget_type() function fails when invoked with an old
object ID (an ID which has been closed down).
./test/h5test.c
Added an extra argument when setting the multi file access
property lists so the test fails if it can't open one of the
sub-files.
./tools/h5ls.c
Improved the algorithm for deciding what file driver to
use. It basically tries all of the predefined drivers and is
now able to open family, split, and multi files without
looking for special characters in the file name.
Added `-e' and `--errors' switches which cause errors from
libhdf5 to be reported on stderr in addition to the simple
error message displayed by h5ls.
-rw-r--r-- | src/H5D.c | 4 | ||||
-rw-r--r-- | src/H5Distore.c | 6 | ||||
-rw-r--r-- | src/H5F.c | 47 | ||||
-rw-r--r-- | src/H5FD.c | 63 | ||||
-rw-r--r-- | src/H5FDcore.c | 2 | ||||
-rw-r--r-- | src/H5FDfamily.c | 2 | ||||
-rw-r--r-- | src/H5FDmpio.c | 2 | ||||
-rw-r--r-- | src/H5FDmulti.c | 661 | ||||
-rw-r--r-- | src/H5FDmulti.h | 4 | ||||
-rw-r--r-- | src/H5FDprivate.h | 3 | ||||
-rw-r--r-- | src/H5FDpublic.h | 18 | ||||
-rw-r--r-- | src/H5FDsec2.c | 2 | ||||
-rw-r--r-- | src/H5Fistore.c | 6 | ||||
-rw-r--r-- | src/H5I.c | 7 | ||||
-rw-r--r-- | test/h5test.c | 2 | ||||
-rw-r--r-- | tools/h5ls.c | 79 |
16 files changed, 667 insertions, 241 deletions
@@ -2853,11 +2853,12 @@ herr_t H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, hsize_t *size) { - H5T_vlen_bufsize_t vlen_bufsize={0}; + H5T_vlen_bufsize_t vlen_bufsize = {0, 0, 0, 0, 0, 0}; char bogus; /* bogus value to pass to H5Diterate() */ herr_t ret_value=FAIL; FUNC_ENTER(H5Dvlen_get_buf_size, FAIL); + H5TRACE4("e","iii*h",dataset_id,type_id,space_id,size); /* Check args */ if (H5I_DATASET!=H5I_get_type(dataset_id) || @@ -2866,7 +2867,6 @@ H5Dvlen_get_buf_size(hid_t dataset_id, hid_t type_id, hid_t space_id, HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid argument"); } - /* Initialize the callback data block */ /* Save the dataset ID */ vlen_bufsize.dataset_id=dataset_id; diff --git a/src/H5Distore.c b/src/H5Distore.c index 28e8337..e3a0d49 100644 --- a/src/H5Distore.c +++ b/src/H5Distore.c @@ -492,7 +492,7 @@ H5F_istore_new_node(H5F_t *f, H5B_ins_t op, #ifdef AKC printf("calling H5MF_alloc for new chunk\n"); #endif - if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_BTREE, + if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_DRAW, udata->key.nbytes))) { HRETURN_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "couldn't allocate new file storage"); @@ -675,7 +675,7 @@ H5F_istore_insert(H5F_t *f, haddr_t addr, void *_lt_key, #ifdef AKC printf("calling H5MF_realloc for new chunk\n"); #endif - if (HADDR_UNDEF==(*new_node_p=H5MF_realloc(f, H5FD_MEM_BTREE, addr, + if (HADDR_UNDEF==(*new_node_p=H5MF_realloc(f, H5FD_MEM_DRAW, addr, lt_key->nbytes, udata->key.nbytes))) { HRETURN_ERROR (H5E_STORAGE, H5E_WRITEERROR, H5B_INS_ERROR, @@ -714,7 +714,7 @@ H5F_istore_insert(H5F_t *f, haddr_t addr, void *_lt_key, #ifdef AKC printf("calling H5MF_alloc for new chunk\n"); #endif - if (HADDR_UNDEF==(*new_node_p=H5MF_alloc(f, H5FD_MEM_BTREE, + if (HADDR_UNDEF==(*new_node_p=H5MF_alloc(f, H5FD_MEM_DRAW, udata->key.nbytes))) { HRETURN_ERROR(H5E_IO, H5E_CANTINIT, H5B_INS_ERROR, "file allocation failed"); @@ -566,6 +566,7 @@ H5F_locate_signature(H5FD_t *file) "unable to obtain EOF/EOA value"); } for (maxpow=0; addr; maxpow++) addr>>=1; + maxpow = MAX(maxpow, 9); /* * Search for the file signature at format address zero followed by @@ -906,6 +907,13 @@ H5F_dest(H5F_t *f) * Added decoding of file driver information block, which uses a * formerly reserved address slot in the boot block in order to * be compatible with previous versions of the file format. + * + * Robb Matzke, 1999-08-20 + * Optimizations for opening a file. If the driver can't + * determine when two file handles refer to the same file then + * we open the file in one step. Otherwise if the first attempt + * to open the file fails then we skip the second attempt if the + * arguments would be the same. *------------------------------------------------------------------------- */ H5F_t * @@ -925,17 +933,41 @@ H5F_open(const char *name, uintn flags, hid_t fcpl_id, hid_t fapl_id) haddr_t stored_eoa; /*relative end-of-addr in file */ uintn tent_flags; /*tentative flags */ char driver_name[9]; /*file driver name/version */ + hbool_t driver_has_cmp; /*`cmp' callback defined? */ FUNC_ENTER(H5F_open, NULL); /* - * Open the file very carefully because we don't want to wipe out a file - * which is currently open (which is possible if this call specifies - * truncation of an existing file). So turn off truncation and file - * creation and try opening it. If that fails then open as normal. + * If the driver has a `cmp' method then the driver is capable of + * determining when two file handles refer to the same file and the + * library can insure that when the application opens a file twice that + * the two handles coordinate their operations appropriately. Otherwise + * it is the application's responsibility to never open the same file + * more than once at a time. + */ + driver_has_cmp = H5FD_has_cmp(fapl_id); + + /* + * Opening a file is a two step process. First we try to open the file in + * a way which doesn't affect its state (like not truncating or creating + * it) so we can compare it with files that are already open. If that + * fails then we try again with the full set of flags (only if they're + * different than the original failed attempt). However, if the file + * driver can't distinquish between files then there's no reason to open + * the file tentatively because it's the application's responsibility to + * prevent this situation (there's no way for us to detect it here + * anyway). */ - tent_flags = flags & ~(H5F_ACC_CREAT|H5F_ACC_TRUNC|H5F_ACC_EXCL); + if (driver_has_cmp) { + tent_flags = flags & ~(H5F_ACC_CREAT|H5F_ACC_TRUNC|H5F_ACC_EXCL); + } else { + tent_flags = flags; + } if (NULL==(lf=H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) { + if (tent_flags == flags) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "unable to open file"); + } H5E_clear(); tent_flags = flags; if (NULL==(lf=H5FD_open(name, tent_flags, fapl_id, HADDR_UNDEF))) { @@ -1223,10 +1255,7 @@ H5F_open(const char *name, uintn flags, hid_t fcpl_id, hid_t fapl_id) ret_value = file; done: - if (!ret_value) { - if (file) H5F_dest(file); - if (lf) H5FD_close(lf); - } + if (!ret_value && file) H5F_dest(file); FUNC_LEAVE(ret_value); } @@ -247,6 +247,69 @@ H5FDunregister(hid_t driver_id) /*------------------------------------------------------------------------- + * Function: H5FD_get_class + * + * Purpose: Optains a pointer to the driver struct containing all the + * callback pointers, etc. The PLIST_ID argument can be a file + * access property list, a data transfer property list, or a + * file driver identifier. + * + * Return: Success: Ptr to the driver information. The pointer is + * only valid as long as the driver remains + * registered or some file or property list + * exists which references the driver. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Friday, August 20, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +H5FD_class_t * +H5FD_get_class(hid_t id) +{ + H5FD_class_t *ret_value=NULL; + H5F_access_t *fapl=NULL; + H5F_xfer_t *dxpl=NULL; + + FUNC_ENTER(H5FD_get_class, NULL); + + if (H5P_DEFAULT==id) { + ret_value = H5FD_get_class(H5F_access_dflt.driver_id); + } else if (H5I_VFL==H5I_get_type(id)) { + ret_value = H5I_object(id); + } else { + switch (H5P_get_class(id)) { + case H5P_FILE_ACCESS: + if (NULL==(fapl=H5I_object(id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, + "not a file access property list"); + } + ret_value = H5FD_get_class(fapl->driver_id); + break; + + case H5P_DATA_XFER: + if (NULL==(dxpl=H5I_object(id))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, + "not a data transfer property list"); + } + ret_value = H5FD_get_class(dxpl->driver_id); + break; + + default: + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, + "not a driver id, file access property list or " + "data transfer property list"); + } + } + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- * Function: H5FD_sb_size * * Purpose: Obtains the number of bytes required to store the driver file diff --git a/src/H5FDcore.c b/src/H5FDcore.c index 9920678..ab9b2a0 100644 --- a/src/H5FDcore.c +++ b/src/H5FDcore.c @@ -128,7 +128,7 @@ static const H5FD_class_t H5FD_core_g = { hid_t H5FD_core_init(void) { - if (!H5FD_CORE_g) { + if (H5I_VFL!=H5Iget_type(H5FD_CORE_g)) { H5FD_CORE_g = H5FDregister(&H5FD_core_g); } return H5FD_CORE_g; diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c index 4f0536c..fab72f6 100644 --- a/src/H5FDfamily.c +++ b/src/H5FDfamily.c @@ -125,7 +125,7 @@ static const H5FD_class_t H5FD_family_g = { hid_t H5FD_family_init(void) { - if (!H5FD_FAMILY_g) { + if (H5I_VFL!=H5Iget_type(H5FD_FAMILY_g)) { H5FD_FAMILY_g = H5FDregister(&H5FD_family_g); } return H5FD_FAMILY_g; diff --git a/src/H5FDmpio.c b/src/H5FDmpio.c index ac853c5..c3f47f0 100644 --- a/src/H5FDmpio.c +++ b/src/H5FDmpio.c @@ -164,7 +164,7 @@ hbool_t H5_mpi_1_metawrite_g = FALSE; hid_t H5FD_mpio_init(void) { - if (!H5FD_MPIO_g) { + if (H5I_VFL!=H5Iget_type(H5FD_MPIO_g)) { H5FD_MPIO_g = H5FDregister(&H5FD_mpio_g); #if 1 diff --git a/src/H5FDmulti.c b/src/H5FDmulti.c index a8c9325..004e07e 100644 --- a/src/H5FDmulti.c +++ b/src/H5FDmulti.c @@ -27,9 +27,49 @@ #undef MIN #define MIN(X,Y) ((X)<(Y)?(X):(Y)) +#define FALSE 0 +#define TRUE 1 + +/* Loop through all mapped files */ +#define UNIQUE_MEMBERS(MAP,LOOPVAR) { \ + H5FD_mem_t _unmapped, LOOPVAR; \ + hbool_t _seen[H5FD_MEM_NTYPES]; \ + \ + memset(_seen, 0, sizeof _seen); \ + for (_unmapped=1; _unmapped<H5FD_MEM_NTYPES; _unmapped++) { \ + LOOPVAR = MAP[_unmapped]; \ + if (H5FD_MEM_DEFAULT==LOOPVAR) LOOPVAR=_unmapped; \ + assert(LOOPVAR>0 && LOOPVAR<H5FD_MEM_NTYPES); \ + if (_seen[LOOPVAR]++) continue; + +#define MAPPED_MEMBERS(MAP,LOOPVAR) { \ + H5FD_mem_t _unmapped, LOOPVAR; \ + \ + for (_unmapped=1; _unmapped<H5FD_MEM_NTYPES; _unmapped++) { \ + LOOPVAR = MAP[_unmapped]; \ + if (H5FD_MEM_DEFAULT==LOOPVAR) LOOPVAR=_unmapped; \ + assert(LOOPVAR>0 && LOOPVAR<H5FD_MEM_NTYPES); + +#define ALL_MEMBERS(LOOPVAR) { \ + H5FD_mem_t LOOPVAR; \ + for (LOOPVAR=0; LOOPVAR<H5FD_MEM_NTYPES; LOOPVAR++) { + + +#define END_MEMBERS }} + + /* The driver identification number, initialized at runtime */ static hid_t H5FD_MULTI_g = 0; +/* Driver-specific file access properties */ +typedef struct H5FD_multi_fapl_t { + H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; /*memory usage map */ + hid_t memb_fapl[H5FD_MEM_NTYPES];/*member access properties */ + char *memb_name[H5FD_MEM_NTYPES];/*name generators */ + haddr_t memb_addr[H5FD_MEM_NTYPES];/*starting addr per member */ + hbool_t relax; /*less stringent error checking */ +} H5FD_multi_fapl_t; + /* * The description of a file belonging to this driver. The file access * properties and member names do not have to be copied into this struct @@ -38,24 +78,14 @@ static hid_t H5FD_MULTI_g = 0; */ typedef struct H5FD_multi_t { H5FD_t pub; /*public stuff, must be first */ - H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; /*map from usage to file */ - haddr_t memb_addr[H5FD_MEM_NTYPES];/*starting address per member*/ + H5FD_multi_fapl_t fa; /*driver-specific file access properties*/ haddr_t memb_next[H5FD_MEM_NTYPES];/*addr of next member */ H5FD_t *memb[H5FD_MEM_NTYPES]; /*member pointers */ - hid_t memb_fapl[H5FD_MEM_NTYPES];/*member file access props */ - char *memb_name[H5FD_MEM_NTYPES];/*name generators */ haddr_t eoa; /*end of allocated addresses */ unsigned flags; /*file open flags saved for debugging */ + char *name; /*name passed to H5Fopen or H5Fcreate */ } H5FD_multi_t; -/* Driver-specific file access properties */ -typedef struct H5FD_multi_fapl_t { - H5FD_mem_t memb_map[H5FD_MEM_NTYPES]; /*memory usage map */ - hid_t memb_fapl[H5FD_MEM_NTYPES];/*member access properties */ - char *memb_name[H5FD_MEM_NTYPES];/*name generators */ - haddr_t memb_addr[H5FD_MEM_NTYPES];/*starting addr per member */ -} H5FD_multi_fapl_t; - /* Driver specific data transfer properties */ typedef struct H5FD_multi_dxpl_t { hid_t memb_dxpl[H5FD_MEM_NTYPES];/*member data xfer properties*/ @@ -63,6 +93,8 @@ typedef struct H5FD_multi_dxpl_t { /* Private functions */ static char *my_strdup(const char *s); +static int compute_next(H5FD_multi_t *file); +static int open_members(H5FD_multi_t *file); /* Callback prototypes */ static hsize_t H5FD_multi_sb_size(H5FD_t *file); @@ -167,7 +199,7 @@ my_strdup(const char *s) hid_t H5FD_multi_init(void) { - if (!H5FD_MULTI_g) { + if (H5I_VFL!=H5Iget_type(H5FD_MULTI_g)) { H5FD_MULTI_g = H5FDregister(&H5FD_multi_g); } return H5FD_MULTI_g; @@ -226,7 +258,8 @@ H5Pset_fapl_split(hid_t fapl, const char *meta_ext, hid_t meta_plist_id, memb_addr[H5FD_MEM_SUPER] = 0; memb_addr[H5FD_MEM_DRAW] = HADDR_MAX/2; - return H5Pset_fapl_multi(fapl, memb_map, memb_fapl, memb_name, memb_addr); + return H5Pset_fapl_multi(fapl, memb_map, memb_fapl, memb_name, memb_addr, + TRUE); } @@ -247,6 +280,27 @@ H5Pset_fapl_split(hid_t fapl, const char *meta_ext, hid_t meta_plist_id, * name passed to H5FDopen(), usually from H5Fcreate() or * H5Fopen()). * + * If RELAX is set then opening an existing file for read-only + * access will not fail if some file members are missing. This + * allows a file to be accessed in a limited sense if just the + * meta data is available. + * + * Defaults: Default values for each of the optional arguments are: + * + * memb_map: The default member map has the value + * H5FD_MEM_DEFAULT for each element. + * + * memb_fapl: The value H5P_DEFAULT for each element. + * + * memb_name: The string `%s-X.h5' where `X' is one of the + * letters `s' (H5FD_MEM_SUPER), + * `b' (H5FD_MEM_BTREE), `r' (H5FD_MEM_DRAW), + * `g' (H5FD_MEM_GHEAP), 'l' (H5FD_MEM_LHEAP), + * `o' (H5FD_MEM_OHDR). + * + * memb_addr: The value HADDR_UNDEF for each element. + * + * * Example: To set up a multi file access property list which partitions * data into meta and raw files each being 1/2 of the address * space one would say: @@ -273,7 +327,7 @@ H5Pset_fapl_split(hid_t fapl, const char *meta_ext, hid_t meta_plist_id, * * hid_t fapl = H5Pcreate(H5P_FILE_ACCESS); * H5Pset_fapl_multi(fapl, memb_map, memb_fapl, - * memb_name, memb_addr); + * memb_name, memb_addr, TRUE); * * * Return: Success: Non-negative @@ -290,19 +344,47 @@ H5Pset_fapl_split(hid_t fapl, const char *meta_ext, hid_t meta_plist_id, herr_t H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, const hid_t *memb_fapl, const char **memb_name, - const haddr_t *memb_addr) + const haddr_t *memb_addr, hbool_t relax) { H5FD_multi_fapl_t fa; H5FD_mem_t mt, mmt; + H5FD_mem_t _memb_map[H5FD_MEM_NTYPES]; + hid_t _memb_fapl[H5FD_MEM_NTYPES]; + char _memb_name[H5FD_MEM_NTYPES][16]; + const char *_memb_name_ptrs[H5FD_MEM_NTYPES]; + haddr_t _memb_addr[H5FD_MEM_NTYPES]; + static const char *letters = "Xsbrglo"; /*NO TRACE*/ - /* Check arguments */ + /* Check arguments and supply default values */ if (H5P_FILE_ACCESS!=H5Pget_class(fapl_id)) return -1; - if (!memb_map) return -1; - if (!memb_fapl) return -1; - if (!memb_name) return -1; - if (!memb_addr) return -1; + if (!memb_map) { + for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { + _memb_map[mt] = H5FD_MEM_DEFAULT; + } + memb_map = _memb_map; + } + if (!memb_fapl) { + for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { + _memb_fapl[mt] = H5P_DEFAULT; + } + memb_fapl = _memb_fapl; + } + if (!memb_name) { + assert(strlen(letters)==H5FD_MEM_NTYPES); + for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { + sprintf(_memb_name[mt], "%%s-%c.h5", letters[mt]); + _memb_name_ptrs[mt] = _memb_name[mt]; + } + memb_name = _memb_name_ptrs; + } + if (!memb_addr) { + for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { + _memb_addr[mt] = (mt?mt-1:0) * HADDR_MAX/H5FD_MEM_NTYPES; + } + memb_addr = _memb_addr; + } for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { /* Map usage type */ @@ -329,6 +411,7 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, memcpy(fa.memb_fapl, memb_fapl, H5FD_MEM_NTYPES*sizeof(hid_t)); memcpy(fa.memb_name, memb_name, H5FD_MEM_NTYPES*sizeof(char*)); memcpy(fa.memb_addr, memb_addr, H5FD_MEM_NTYPES*sizeof(haddr_t)); + fa.relax = relax; return H5Pset_driver(fapl_id, H5FD_MULTI, &fa); } @@ -354,7 +437,7 @@ H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, herr_t H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map/*out*/, hid_t *memb_fapl/*out*/, char **memb_name/*out*/, - haddr_t *memb_addr/*out*/) + haddr_t *memb_addr/*out*/, hbool_t *relax) { H5FD_multi_fapl_t *fa; H5FD_mem_t mt; @@ -390,6 +473,9 @@ H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map/*out*/, if (memb_addr) { memcpy(memb_addr, fa->memb_addr, H5FD_MEM_NTYPES*sizeof(haddr_t)); } + if (relax) { + *relax = fa->relax; + } return 0; } @@ -497,9 +583,27 @@ H5Pget_dxpl_multi(hid_t dxpl_id, hid_t *memb_dxpl/*out*/) *------------------------------------------------------------------------- */ static hsize_t -H5FD_multi_sb_size(H5FD_t *_file/*unused*/) +H5FD_multi_sb_size(H5FD_t *_file) { - return H5FD_MEM_NTYPES * 8; + H5FD_multi_t *file = (H5FD_multi_t*)_file; + int nseen = 0; + hsize_t nbytes = 8; /*size of header*/ + + /* How many unique files? */ + UNIQUE_MEMBERS(file->fa.memb_map, mt) { + nseen++; + } END_MEMBERS; + + /* Addresses and EOA markers */ + nbytes += nseen * 2 * 8; + + /* Name templates */ + UNIQUE_MEMBERS(file->fa.memb_map, mt) { + size_t n = strlen(file->fa.memb_name[mt])+1; + nbytes += (n+7) & ~0x0007; + } END_MEMBERS; + + return nbytes; } @@ -510,6 +614,13 @@ H5FD_multi_sb_size(H5FD_t *_file/*unused*/) * argument is a nine-byte buffer which will be initialized with * an eight-character name/version number and null termination. * + * The encoding is a six-byte member mapping followed two bytes + * which are unused. For each unique file in usage-type order + * encode all the starting addresses as unsigned 64-bit integers, + * then all the EOA values as unsigned 64-bit integers, then all + * the template names as null terminated strings which are + * multiples of 8 characters. + * * Return: Success: 0 * * Failure: -1 @@ -526,26 +637,53 @@ H5FD_multi_sb_encode(H5FD_t *_file, char *name/*out*/, unsigned char *buf/*out*/) { H5FD_multi_t *file = (H5FD_multi_t*)_file; - H5FD_mem_t mt; haddr_t memb_eoa; + unsigned char *p; + int nseen; + size_t i; + H5FD_mem_t m; /* Name and version number */ strcpy(name, "NCSAmulti"); - /* Copy EOA values into buffer */ + assert(7==H5FD_MEM_NTYPES); + for (m=1; m<H5FD_MEM_NTYPES; m++) { + buf[m-1] = file->fa.memb_map[m]; + } + buf[7] = 0; + buf[8] = 0; + + /* + * Copy the starting addresses and EOA values into the buffer in order of + * usage type but only for types which map to something unique. + */ + + /* Encode all starting addresses and EOA values */ + nseen = 0; + p = buf+8; assert(sizeof(haddr_t)<=8); - for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { - if (file->memb[mt]) { - memb_eoa = H5FDget_eoa(file->memb[mt]); - } else { - memb_eoa = HADDR_UNDEF; - } - memcpy(buf+mt*sizeof(memb_eoa), &memb_eoa, sizeof(memb_eoa)); + UNIQUE_MEMBERS(file->fa.memb_map, mt) { + memb_eoa = H5FDget_eoa(file->memb[mt]); + memcpy(p, &(file->fa.memb_addr[mt]), sizeof(haddr_t)); + p += sizeof(haddr_t); + memcpy(p, &memb_eoa, sizeof(haddr_t)); + p += sizeof(haddr_t); + nseen++; + } END_MEMBERS; + if (H5Tconvert(H5T_NATIVE_HADDR, H5T_STD_U64LE, nseen, buf+8, NULL, + H5P_DEFAULT)<0) { + return -1; } - /* Convert to destination type */ - if (H5Tconvert(H5T_NATIVE_HADDR, H5T_STD_U64LE, H5FD_MEM_NTYPES, - buf, NULL, H5P_DEFAULT)<0) return -1; + /* Encode all name templates */ + p = buf + 8 + nseen*2*8; + UNIQUE_MEMBERS(file->fa.memb_map, mt) { + size_t n = strlen(file->fa.memb_name[mt]) + 1; + strcpy(p, file->fa.memb_name[mt]); + p += n; + for (i=n; i%8; i++) *p++ = '\0'; + } END_MEMBERS; + return 0; } @@ -557,6 +695,10 @@ H5FD_multi_sb_encode(H5FD_t *_file, char *name/*out*/, * argument is the eight-character (plus null termination) name * stored in the file. * + * The FILE argument is updated according to the information in + * the superblock. This may mean that some member files are + * closed and others are opened. + * * Return: Success: 0 * * Failure: -1 @@ -572,24 +714,123 @@ static herr_t H5FD_multi_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf) { H5FD_multi_t *file = (H5FD_multi_t*)_file; - H5FD_mem_t mt; - char x[H5FD_MEM_NTYPES*8]; + char x[2*H5FD_MEM_NTYPES*8]; + H5FD_mem_t map[H5FD_MEM_NTYPES]; + int nseen=0, i; + hbool_t map_changed=FALSE; + hbool_t in_use[H5FD_MEM_NTYPES]; + const char *memb_name[H5FD_MEM_NTYPES]; + haddr_t memb_addr[H5FD_MEM_NTYPES]; + haddr_t memb_eoa[H5FD_MEM_NTYPES]; + haddr_t *ap; /* Make sure the name/version number is correct */ if (strcmp(name, "NCSAmult")) return -1; - /* Decode EOA values */ + /* Set default values */ + ALL_MEMBERS(mt) { + memb_addr[mt] = HADDR_UNDEF; + memb_eoa[mt] = HADDR_UNDEF; + memb_name[mt] = NULL; + } END_MEMBERS; + + /* + * Read the map and count the unique members. + */ + memset(map, 0, sizeof map); + for (i=0; i<6; i++) { + map[i+1] = buf[i]; + if (file->fa.memb_map[i+1]!=map[i+1]) map_changed=TRUE; + } + UNIQUE_MEMBERS(map, mt) { + nseen++; + } END_MEMBERS; + buf += 8; + + /* Decode Address and EOA values */ assert(sizeof(haddr_t)<=8); - memcpy(x, buf, H5FD_MEM_NTYPES*8); - if (H5Tconvert(H5T_STD_U64LE, H5T_NATIVE_HADDR, H5FD_MEM_NTYPES, - x, NULL, H5P_DEFAULT)<0) return -1; - - /* Set EOA values */ - for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { - if (file->memb[mt]) { - H5FDset_eoa(file->memb[mt], ((haddr_t*)x)[mt]); + memcpy(x, buf, nseen*2*8); + buf += nseen*2*8; + if (H5Tconvert(H5T_STD_U64LE, H5T_NATIVE_HADDR, nseen*2, x, NULL, + H5P_DEFAULT)<0) return -1; + ap = (haddr_t*)x; + UNIQUE_MEMBERS(map, mt) { + memb_addr[_unmapped] = *ap++; + memb_eoa[_unmapped] = *ap++; + } END_MEMBERS; + + /* Decode name templates */ + UNIQUE_MEMBERS(map, mt) { + size_t n = strlen(buf)+1; + memb_name[_unmapped] = buf; + buf += (n+7) & ~0x0007; + } END_MEMBERS; + + /* + * Use the mapping saved in the superblock in preference to the one + * already set for the file. Since we may have opened files which are no + * longer needed we should close all those files. We'll open the new + * files at the end. + */ + if (map_changed) { +#ifdef H5FD_MULTI_DEBUG + if (file->flags & H5F_ACC_DEBUG) { + fprintf(stderr, "H5FD_MULTI: member map override\n"); + fprintf(stderr, " old value: "); + ALL_MEMBERS(mt) { + fprintf(stderr, "%s%d", mt?", ":"", + (int)(file->fa.memb_map[mt])); + } END_MEMBERS; + fprintf(stderr, "\n new value: "); + ALL_MEMBERS(mt) { + fprintf(stderr, "%s%d", mt?", ":"", (int)(map[mt])); + } END_MEMBERS; } +#endif + /* Commit map */ + ALL_MEMBERS(mt) { + file->fa.memb_map[mt] = map[mt]; + } END_MEMBERS; + + /* Close files which are unused now */ + memset(in_use, 0, sizeof in_use); + UNIQUE_MEMBERS(map, mt) { + in_use[mt] = TRUE; + } END_MEMBERS; + ALL_MEMBERS(mt) { + if (!in_use[mt] && file->memb[mt]) { +#ifdef H5FD_MULTI_DEBUG + if (file->flags & H5F_ACC_DEBUG) { + fprintf(stderr, "H5FD_MULTI: close member %d\n", (int)mt); + } +#endif + H5FDclose(file->memb[mt]); + file->memb[mt] = NULL; + } + file->fa.memb_map[mt] = map[mt]; + } END_MEMBERS; } + + /* Commit member starting addresses and name templates */ + ALL_MEMBERS(mt) { + file->fa.memb_addr[mt] = memb_addr[mt]; + if (memb_name[mt]) { + if (file->fa.memb_name[mt]) free(file->fa.memb_name[mt]); + file->fa.memb_name[mt] = my_strdup(memb_name[mt]); + } + } END_MEMBERS; + if (compute_next(file)<0) return -1; + + /* Open all necessary files */ + if (open_members(file)<0) return -1; + + /* Set the EOA marker for all open files */ + UNIQUE_MEMBERS(file->fa.memb_map, mt) { + if (file->memb[mt]) { + H5FDset_eoa(file->memb[mt], memb_eoa[mt]); + } + } END_MEMBERS; + return 0; } @@ -617,14 +858,8 @@ static void * H5FD_multi_fapl_get(H5FD_t *_file) { H5FD_multi_t *file = (H5FD_multi_t*)_file; - H5FD_multi_fapl_t fa; - memset(&fa, 0, sizeof fa); - memcpy(fa.memb_map, file->memb_map, sizeof(fa.memb_map)); - memcpy(fa.memb_fapl, file->memb_fapl, sizeof(fa.memb_fapl)); - memcpy(fa.memb_name, file->memb_name, sizeof(fa.memb_name)); - memcpy(fa.memb_addr, file->memb_addr, sizeof(fa.memb_addr)); - return H5FD_multi_fapl_copy(&fa); + return H5FD_multi_fapl_copy(&(file->fa)); } @@ -808,122 +1043,64 @@ H5FD_multi_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr) { H5FD_multi_t *file=NULL; - H5FD_mem_t mt, mmt, mt2, mmt2; - char tmp[4096]; - int seen[H5FD_MEM_NTYPES]; + hid_t close_fapl=-1; + H5FD_multi_fapl_t *fa; + H5FD_mem_t m; /* Check arguments */ if (!name || !*name) return NULL; if (0==maxaddr || HADDR_UNDEF==maxaddr) return NULL; /* - * Initialize file from file access properties. The default mapping - * creates two files -- one for meta data and one for raw data. The - * default file extensions are ".meta" and ".raw" accessed by default - * file drivers. Half the address space is used for each. + * Initialize the file from the file access properties, using default + * values if necessary. */ if (NULL==(file=calloc(1, sizeof(H5FD_multi_t)))) return NULL; if (H5P_DEFAULT==fapl_id || H5FD_MULTI!=H5Pget_driver(fapl_id)) { - for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { - file->memb_map[mt] = H5FD_MEM_DRAW==mt?mt:H5FD_MEM_SUPER; - file->memb_addr[mt] = HADDR_UNDEF; - file->memb_fapl[mt] = H5P_DEFAULT; + close_fapl = fapl_id = H5Pcreate(H5P_FILE_ACCESS); + H5Pset_fapl_multi(fapl_id, NULL, NULL, NULL, NULL, TRUE); + } + fa = H5Pget_driver_info(fapl_id); + assert(fa); + ALL_MEMBERS(mt) { + file->fa.memb_map[mt] = fa->memb_map[mt]; + file->fa.memb_addr[mt] = fa->memb_addr[mt]; + if (fa->memb_fapl[mt]>=0) { + file->fa.memb_fapl[mt] = H5Pcopy(fa->memb_fapl[mt]); + } else { + file->fa.memb_fapl[mt] = fa->memb_fapl[mt]; } - file->memb_name[H5FD_MEM_SUPER] = my_strdup("%s.meta"); - file->memb_addr[H5FD_MEM_SUPER] = 0; - - file->memb_name[H5FD_MEM_DRAW] = my_strdup("%s.raw"); - file->memb_addr[H5FD_MEM_DRAW] = maxaddr/2; - } else { - H5FD_multi_fapl_t *fa = H5Pget_driver_info(fapl_id); - assert(fa); - for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { - file->memb_map[mt] = fa->memb_map[mt]; - file->memb_addr[mt] = fa->memb_addr[mt]; - if (fa->memb_fapl[mt]>=0) { - file->memb_fapl[mt] = H5Pcopy(fa->memb_fapl[mt]); - } else { - file->memb_fapl[mt] = fa->memb_fapl[mt]; - } - if (fa->memb_name[mt]) { - file->memb_name[mt] = my_strdup(fa->memb_name[mt]); - } else { - file->memb_name[mt] = NULL; - } + if (fa->memb_name[mt]) { + file->fa.memb_name[mt] = my_strdup(fa->memb_name[mt]); + } else { + file->fa.memb_name[mt] = NULL; } - } + } END_MEMBERS; + file->fa.relax = fa->relax; file->flags = flags; + file->name = my_strdup(name); + if (close_fapl>=0) H5Pclose(close_fapl); - /* - * Figure out the memb_next[] values for each member. This is the - * beginning address of the next member. - */ - memset(seen, 0, sizeof seen); - for (mt=1; mt<H5FD_MEM_NTYPES; mt++) { - mmt = file->memb_map[mt]; - if (H5FD_MEM_DEFAULT==mmt) mmt = mt; - assert(mmt>0 && mmt<H5FD_MEM_NTYPES); - if (seen[mmt]++) continue; - - file->memb_next[mmt] = HADDR_UNDEF; - for (mt2=1; mt2<H5FD_MEM_NTYPES; mt2++) { - mmt2 = file->memb_map[mt2]; - if (H5FD_MEM_DEFAULT==mmt2) mmt2 = mt2; - assert(mmt2>0 && mmt2<H5FD_MEM_NTYPES); - if (mmt==mmt2) continue; - - if (file->memb_addr[mmt]<file->memb_addr[mmt2] && - (HADDR_UNDEF==file->memb_next[mmt] || - file->memb_next[mmt]>file->memb_addr[mmt2])) { - file->memb_next[mmt] = file->memb_addr[mmt2]; - } - } - } - - /* - * Open all the multi members. - */ - memset(seen, 0, sizeof seen); - for (mt=1; mt<H5FD_MEM_NTYPES; mt++) { - mmt = file->memb_map[mt]; - if (H5FD_MEM_DEFAULT==mmt) mmt = mt; - assert(mmt>0 && mmt<H5FD_MEM_NTYPES); - if (seen[mmt]++) continue; - assert(file->memb_name[mmt]); - sprintf(tmp, file->memb_name[mmt], name); + /* Compute derived properties and open member files */ + if (compute_next(file)<0) goto error; + if (open_members(file)<0) goto error; -#ifdef H5FD_MULTI_DEBUG - if (file->flags & H5F_ACC_DEBUG) { - fprintf(stderr, "H5FD_MULTI: opening \"%s\"\n", tmp); - } -#endif - H5E_BEGIN_TRY { - file->memb[mmt] = H5FDopen(tmp, flags, file->memb_fapl[mmt], - HADDR_UNDEF); - } H5E_END_TRY; - if (!file->memb[mmt]) { -#ifdef H5FD_MULTI_DEBUG - if (file->flags & H5F_ACC_DEBUG) { - fprintf(stderr, "H5FD_MULTI: open failed\n"); - } -#endif - goto error; - } + /* We must have opened at least the superblock file */ + if (H5FD_MEM_DEFAULT==(m=file->fa.memb_map[H5FD_MEM_SUPER])) { + m = H5FD_MEM_SUPER; } - - /* Write index file */ - if ((flags & H5F_ACC_RDWR) && - H5FD_multi_flush((H5FD_t*)file)<0) goto error; + if (NULL==file->memb[m]) goto error; return (H5FD_t*)file; error: /* Cleanup and fail */ if (file) { - for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { + ALL_MEMBERS(mt) { if (file->memb[mt]) H5FDclose(file->memb[mt]); - if (file->memb_fapl[mt]>=0) H5Pclose(file->memb_fapl[mt]); - if (file->memb_name[mt]) free(file->memb_name[mt]); - } + if (file->fa.memb_fapl[mt]>=0) H5Pclose(file->fa.memb_fapl[mt]); + if (file->fa.memb_name[mt]) free(file->fa.memb_name[mt]); + } END_MEMBERS; + if (file->name) free(file->name); free(file); } return NULL; @@ -952,14 +1129,13 @@ static herr_t H5FD_multi_close(H5FD_t *_file) { H5FD_multi_t *file = (H5FD_multi_t*)_file; - H5FD_mem_t mt; int nerrors=0; /* Flush our own data */ if (H5FD_multi_flush(_file)<0) nerrors++; /* Close as many members as possible */ - for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { + ALL_MEMBERS(mt) { if (file->memb[mt]) { #ifdef H5FD_MULTI_DEBUG if (file->flags & H5F_ACC_DEBUG) { @@ -977,14 +1153,15 @@ H5FD_multi_close(H5FD_t *_file) file->memb[mt] = NULL; } } - } + } END_MEMBERS; if (nerrors) return -1; /* Clean up other stuff */ - for (mt=0; mt<H5FD_MEM_NTYPES; mt++) { - if (file->memb_fapl[mt]>=0) H5Pclose(file->memb_fapl[mt]); - if (file->memb_name[mt]) free(file->memb_name[mt]); - } + ALL_MEMBERS(mt) { + if (file->fa.memb_fapl[mt]>=0) H5Pclose(file->fa.memb_fapl[mt]); + if (file->fa.memb_name[mt]) free(file->fa.memb_name[mt]); + } END_MEMBERS; + free(file->name); free(file); return 0; } @@ -1087,21 +1264,23 @@ H5FD_multi_set_eoa(H5FD_t *_file, haddr_t eoa) /* Find the subfile in which the new EOA value falls */ for (mt=1; mt<H5FD_MEM_NTYPES; mt++) { - mmt = file->memb_map[mt]; + mmt = file->fa.memb_map[mt]; if (H5FD_MEM_DEFAULT==mmt) mmt = mt; assert(mmt>0 && mmt<H5FD_MEM_NTYPES); - if (eoa>=file->memb_addr[mmt] && eoa<file->memb_next[mmt]) { + if (eoa>=file->fa.memb_addr[mmt] && eoa<file->memb_next[mmt]) { break; } } assert(mt<H5FD_MEM_NTYPES); /* Set subfile eoa */ - H5E_BEGIN_TRY { - status = H5FDset_eoa(file->memb[mmt], eoa-file->memb_addr[mmt]); - } H5E_END_TRY; - if (status<0) return -1; + if (file->memb[mmt]) { + H5E_BEGIN_TRY { + status = H5FDset_eoa(file->memb[mmt], eoa-file->fa.memb_addr[mmt]); + } H5E_END_TRY; + if (status<0) return -1; + } /* Save new eoa for return later */ file->eoa = eoa; @@ -1133,23 +1312,29 @@ H5FD_multi_get_eof(H5FD_t *_file) { H5FD_multi_t *file = (H5FD_multi_t*)_file; haddr_t eof=0, tmp; - H5FD_mem_t mt, mmt; - int seen[H5FD_MEM_NTYPES]; - memset(seen, 0, sizeof seen); - for (mt=1; mt<H5FD_MEM_NTYPES; mt++) { - mmt = file->memb_map[mt]; - if (H5FD_MEM_DEFAULT==mmt) mmt = mt; - assert(mmt>0 && mmt<H5FD_MEM_NTYPES); - if (seen[mmt]++) continue; + UNIQUE_MEMBERS(file->fa.memb_map, mt) { + if (file->memb[mt]) { + H5E_BEGIN_TRY { + tmp = H5FDget_eof(file->memb[mt]); + } H5E_END_TRY; + if (HADDR_UNDEF==tmp) return HADDR_UNDEF; + if (tmp>0) tmp += file->fa.memb_addr[mt]; + + } else if (file->fa.relax) { + /* + * The member is not open yet (maybe it doesn't exist). Make the + * best guess about the end-of-file. + */ + tmp = file->memb_next[mt]; + assert(HADDR_UNDEF!=tmp); + + } else { + return HADDR_UNDEF; + } - H5E_BEGIN_TRY { - tmp = H5FDget_eof(file->memb[mmt]); - } H5E_END_TRY; - if (HADDR_UNDEF==tmp) return HADDR_UNDEF; - if (tmp>0) tmp += file->memb_addr[mmt]; if (tmp>eof) eof = tmp; - } + } END_MEMBERS; return MAX(file->eoa, eof); } @@ -1178,13 +1363,13 @@ H5FD_multi_alloc(H5FD_t *_file, H5FD_mem_t type, hsize_t size) H5FD_mem_t mmt; haddr_t addr; - mmt = file->memb_map[type]; + mmt = file->fa.memb_map[type]; if (H5FD_MEM_DEFAULT==mmt) mmt = type; if (HADDR_UNDEF==(addr=H5FDalloc(file->memb[mmt], type, size))) { return HADDR_UNDEF; } - addr += file->memb_addr[mmt]; + addr += file->fa.memb_addr[mmt]; if (addr+size>file->eoa) file->eoa = addr+size; return addr; } @@ -1212,12 +1397,12 @@ H5FD_multi_free(H5FD_t *_file, H5FD_mem_t type, haddr_t addr, hsize_t size) H5FD_multi_t *file = (H5FD_multi_t*)_file; H5FD_mem_t mmt; - mmt = file->memb_map[type]; + mmt = file->fa.memb_map[type]; if (H5FD_MEM_DEFAULT==mmt) mmt = type; - assert(addr>=file->memb_addr[mmt]); + assert(addr>=file->fa.memb_addr[mmt]); assert(addr+size<=file->memb_next[mmt]); - return H5FDfree(file->memb[mmt], type, addr-file->memb_addr[mmt], size); + return H5FDfree(file->memb[mmt], type, addr-file->fa.memb_addr[mmt], size); } @@ -1256,13 +1441,13 @@ H5FD_multi_read(H5FD_t *_file, hid_t dxpl_id, haddr_t addr, hsize_t size, /* Find the file to which this address belongs */ for (mt=1; mt<H5FD_MEM_NTYPES; mt++) { - mmt = file->memb_map[mt]; + mmt = file->fa.memb_map[mt]; if (H5FD_MEM_DEFAULT==mmt) mmt = mt; assert(mmt>0 && mmt<H5FD_MEM_NTYPES); - if (file->memb_addr[mmt]>addr) continue; - if (file->memb_addr[mmt]>=start_addr) { - start_addr = file->memb_addr[mmt]; + if (file->fa.memb_addr[mmt]>addr) continue; + if (file->fa.memb_addr[mmt]>=start_addr) { + start_addr = file->fa.memb_addr[mmt]; hi = mmt; } } @@ -1308,13 +1493,13 @@ H5FD_multi_write(H5FD_t *_file, hid_t dxpl_id, haddr_t addr, hsize_t size, /* Find the file to which this address belongs */ for (mt=1; mt<H5FD_MEM_NTYPES; mt++) { - mmt = file->memb_map[mt]; + mmt = file->fa.memb_map[mt]; if (H5FD_MEM_DEFAULT==mmt) mmt = mt; assert(mmt>0 && mmt<H5FD_MEM_NTYPES); - if (file->memb_addr[mmt]>addr) continue; - if (file->memb_addr[mmt]>=start_addr) { - start_addr = file->memb_addr[mmt]; + if (file->fa.memb_addr[mmt]>addr) continue; + if (file->fa.memb_addr[mmt]>=start_addr) { + start_addr = file->fa.memb_addr[mmt]; hi = mmt; } } @@ -1346,10 +1531,12 @@ static herr_t H5FD_multi_flush(H5FD_t *_file) { H5FD_multi_t *file = (H5FD_multi_t*)_file; - H5FD_mem_t mt, mmt; + H5FD_mem_t mt; int nerrors=0; #if 0 + H5FD_mem_t mmt; + /* Debugging stuff... */ fprintf(stderr, "multifile access information:\n"); @@ -1391,3 +1578,97 @@ H5FD_multi_flush(H5FD_t *_file) return nerrors ? -1 : 0; } + +/*------------------------------------------------------------------------- + * Function: compute_next + * + * Purpose: Compute the memb_next[] values of the file based on the + * file's member map and the member starting addresses. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Monday, August 23, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +compute_next(H5FD_multi_t *file) +{ + ALL_MEMBERS(mt) { + file->memb_next[mt] = HADDR_UNDEF; + } END_MEMBERS; + + UNIQUE_MEMBERS(file->fa.memb_map, mt1) { + UNIQUE_MEMBERS(file->fa.memb_map, mt2) { + if (file->fa.memb_addr[mt1]<file->fa.memb_addr[mt2] && + (HADDR_UNDEF==file->memb_next[mt1] || + file->memb_next[mt1]>file->fa.memb_addr[mt2])) { + file->memb_next[mt1] = file->fa.memb_addr[mt2]; + } + } END_MEMBERS; + if (HADDR_UNDEF==file->memb_next[mt1]) { + file->memb_next[mt1] = HADDR_MAX; /*last member*/ + } + } END_MEMBERS; + + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: open_members + * + * Purpose: Opens all members which are not opened yet. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * Monday, August 23, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +open_members(H5FD_multi_t *file) +{ + char tmp[1024]; + int nerrors=0; + + UNIQUE_MEMBERS(file->fa.memb_map, mt) { + if (file->memb[mt]) continue; /*already open*/ + assert(file->fa.memb_name[mt]); + sprintf(tmp, file->fa.memb_name[mt], file->name); + +#ifdef H5FD_MULTI_DEBUG + if (file->flags & H5F_ACC_DEBUG) { + fprintf(stderr, "H5FD_MULTI: open member %d \"%s\"\n", + (int)mt, tmp); + } +#endif + H5E_BEGIN_TRY { + file->memb[mt] = H5FDopen(tmp, file->flags, file->fa.memb_fapl[mt], + HADDR_UNDEF); + } H5E_END_TRY; + if (!file->memb[mt]) { +#ifdef H5FD_MULTI_DEBUG + if (file->flags & H5F_ACC_DEBUG) { + fprintf(stderr, "H5FD_MULTI: open failed for member %d\n", + (int)mt); + } +#endif + if (!file->fa.relax || (file->flags & H5F_ACC_RDWR)) { + nerrors++; + } + } + } END_MEMBERS; + + return nerrors?-1:0; +} diff --git a/src/H5FDmulti.h b/src/H5FDmulti.h index dbe7c8e..ad8039a 100644 --- a/src/H5FDmulti.h +++ b/src/H5FDmulti.h @@ -17,10 +17,10 @@ hid_t H5FD_multi_init(void); herr_t H5Pset_fapl_multi(hid_t fapl_id, const H5FD_mem_t *memb_map, const hid_t *memb_fapl, const char **memb_name, - const haddr_t *memb_addr); + const haddr_t *memb_addr, hbool_t relax); herr_t H5Pget_fapl_multi(hid_t fapl_id, H5FD_mem_t *memb_map/*out*/, hid_t *memb_fapl/*out*/, char **memb_name/*out*/, - haddr_t *memb_addr/*out*/); + haddr_t *memb_addr/*out*/, hbool_t *relax/*out*/); herr_t H5Pset_dxpl_multi(hid_t dxpl_id, const hid_t *memb_dxpl); herr_t H5Pget_dxpl_multi(hid_t dxpl_id, hid_t *memb_dxpl/*out*/); diff --git a/src/H5FDprivate.h b/src/H5FDprivate.h index 93fa724..4d9e127 100644 --- a/src/H5FDprivate.h +++ b/src/H5FDprivate.h @@ -10,7 +10,10 @@ #include <H5FDpublic.h> +#define H5FD_has_cmp(id) (NULL!=H5FD_get_class(id)->cmp) + intn H5FD_term_interface(void); +H5FD_class_t *H5FD_get_class(hid_t id); hsize_t H5FD_sb_size(H5FD_t *file); herr_t H5FD_sb_encode(H5FD_t *file, char *name/*out*/, uint8_t *buf); herr_t H5FD_sb_decode(H5FD_t *file, const char *name, const uint8_t *buf); diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index a63e982..4ff4af0 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -8,16 +8,20 @@ #ifndef _H5FDpublic_H #define _H5FDpublic_H -/* Types of allocation requests */ +/* + * Types of allocation requests. The values larger than H5FD_MEM_DEFAULT + * should not change other than adding new types to the end. These numbers + * might appear in files. + */ typedef enum H5FD_mem_t { H5FD_MEM_NOLIST = -1, /*must be negative*/ H5FD_MEM_DEFAULT = 0, /*must be zero*/ - H5FD_MEM_SUPER, - H5FD_MEM_BTREE, - H5FD_MEM_DRAW, - H5FD_MEM_GHEAP, - H5FD_MEM_LHEAP, - H5FD_MEM_OHDR, + H5FD_MEM_SUPER = 1, + H5FD_MEM_BTREE = 2, + H5FD_MEM_DRAW = 3, + H5FD_MEM_GHEAP = 4, + H5FD_MEM_LHEAP = 5, + H5FD_MEM_OHDR = 6, H5FD_MEM_NTYPES /*must be last*/ } H5FD_mem_t; diff --git a/src/H5FDsec2.c b/src/H5FDsec2.c index e1ed9c3..1098dc3 100644 --- a/src/H5FDsec2.c +++ b/src/H5FDsec2.c @@ -178,7 +178,7 @@ static const H5FD_class_t H5FD_sec2_g = { hid_t H5FD_sec2_init(void) { - if (!H5FD_SEC2_g) { + if (H5I_VFL!=H5Iget_type(H5FD_SEC2_g)) { H5FD_SEC2_g = H5FDregister(&H5FD_sec2_g); } return H5FD_SEC2_g; diff --git a/src/H5Fistore.c b/src/H5Fistore.c index 28e8337..e3a0d49 100644 --- a/src/H5Fistore.c +++ b/src/H5Fistore.c @@ -492,7 +492,7 @@ H5F_istore_new_node(H5F_t *f, H5B_ins_t op, #ifdef AKC printf("calling H5MF_alloc for new chunk\n"); #endif - if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_BTREE, + if (HADDR_UNDEF==(*addr_p=H5MF_alloc(f, H5FD_MEM_DRAW, udata->key.nbytes))) { HRETURN_ERROR(H5E_IO, H5E_CANTINIT, FAIL, "couldn't allocate new file storage"); @@ -675,7 +675,7 @@ H5F_istore_insert(H5F_t *f, haddr_t addr, void *_lt_key, #ifdef AKC printf("calling H5MF_realloc for new chunk\n"); #endif - if (HADDR_UNDEF==(*new_node_p=H5MF_realloc(f, H5FD_MEM_BTREE, addr, + if (HADDR_UNDEF==(*new_node_p=H5MF_realloc(f, H5FD_MEM_DRAW, addr, lt_key->nbytes, udata->key.nbytes))) { HRETURN_ERROR (H5E_STORAGE, H5E_WRITEERROR, H5B_INS_ERROR, @@ -714,7 +714,7 @@ H5F_istore_insert(H5F_t *f, haddr_t addr, void *_lt_key, #ifdef AKC printf("calling H5MF_alloc for new chunk\n"); #endif - if (HADDR_UNDEF==(*new_node_p=H5MF_alloc(f, H5FD_MEM_BTREE, + if (HADDR_UNDEF==(*new_node_p=H5MF_alloc(f, H5FD_MEM_DRAW, udata->key.nbytes))) { HRETURN_ERROR(H5E_IO, H5E_CANTINIT, H5B_INS_ERROR, "file allocation failed"); @@ -710,7 +710,9 @@ H5I_get_type(hid_t id) * Programmer: * * Modifications: - * + * Robb Matzke, 1999-08-23 + * Also fails if the ID has a valid group but no longer exists + * in the ID tables. *------------------------------------------------------------------------- */ H5I_type_t @@ -723,7 +725,8 @@ H5Iget_type(hid_t id) ret_value = H5I_get_type(id); - if (ret_value <= H5I_BADID || ret_value >= H5I_NGROUPS) { + if (ret_value <= H5I_BADID || ret_value >= H5I_NGROUPS || + NULL==H5I_object(id)) { HGOTO_DONE(H5I_BADID); } diff --git a/test/h5test.c b/test/h5test.c index b6e5551..dfece89 100644 --- a/test/h5test.c +++ b/test/h5test.c @@ -315,7 +315,7 @@ h5_fileaccess(void) } if (H5Pset_fapl_multi(fapl, memb_map, memb_fapl, memb_name, - memb_addr)<0) { + memb_addr, FALSE)<0) { return -1; } } else if (!strcmp(name, "family")) { diff --git a/tools/h5ls.c b/tools/h5ls.c index a77d413..bf5e7eb 100644 --- a/tools/h5ls.c +++ b/tools/h5ls.c @@ -18,7 +18,10 @@ /* * File drivers */ +#include <H5FDsec2.h> +#include <H5FDmulti.h> #include <H5FDfamily.h> +#define NDRIVERS 10 /* * If defined then include the file name as part of the object name when @@ -37,6 +40,7 @@ static hbool_t fullname_g = FALSE; /*print full path names */ static hbool_t recursive_g = FALSE; /*recursive descent listing */ static hbool_t grp_literal_g = FALSE; /*list group, not contents */ static hbool_t hexdump_g = FALSE; /*show data as raw hexadecimal */ +static hbool_t show_errors_g = FALSE; /*print HDF5 error messages */ /* Info to pass to the iteration functions */ typedef struct iter_t { @@ -98,6 +102,7 @@ usage: %s [OPTIONS] [OBJECTS...]\n\ -h, -?, --help Print a usage message and exit\n\ -a, --address Print addresses for raw data\n\ -d, --data Print the values of datasets\n\ + -e, --errors Show all HDF5 error reporting\n\ -f, --full Print full path names instead of base names\n\ -g, --group Show information about a group, not its contents\n\ -l, --label Label members of compound datasets\n\ @@ -1855,18 +1860,22 @@ get_width(void) int main (int argc, char *argv[]) { - hid_t file=-1, plist=-1, root=-1; + hid_t file=-1, root=-1, fapl=-1; char *fname=NULL, *oname=NULL, *x; const char *progname; const char *s = NULL; char *rest, *container=NULL; - int argno; + int argno, dno; H5G_stat_t sb; iter_t iter; static char root_name[] = "/"; - /* Turn off HDF5's automatic error printing unless you're debugging h5ls */ - H5Eset_auto(NULL, NULL); + int ndrivers=0; + struct { + const char *name; + hid_t fapl; + } driver[NDRIVERS]; + /* Build display table */ DISPATCH(H5G_DATASET, "Dataset", H5Dopen, H5Dclose, @@ -1901,12 +1910,14 @@ main (int argc, char *argv[]) exit(0); } else if (!strcmp(argv[argno], "--address")) { address_g = TRUE; - } else if (!strcmp(argv[argno], "--group")) { - grp_literal_g = TRUE; } else if (!strcmp(argv[argno], "--data")) { data_g = TRUE; + } else if (!strcmp(argv[argno], "--errors")) { + show_errors_g = TRUE; } else if (!strcmp(argv[argno], "--full")) { fullname_g = TRUE; + } else if (!strcmp(argv[argno], "--group")) { + grp_literal_g = TRUE; } else if (!strcmp(argv[argno], "--label")) { label_g = TRUE; } else if (!strcmp(argv[argno], "--recursive")) { @@ -1968,6 +1979,9 @@ main (int argc, char *argv[]) case 'd': /* --data */ data_g = TRUE; break; + case 'e': /* --errors */ + show_errors_g = TRUE; + break; case 'f': /* --full */ fullname_g = TRUE; break; @@ -2014,6 +2028,34 @@ main (int argc, char *argv[]) usage(progname); exit(1); } + + /* Turn off HDF5's automatic error printing unless you're debugging h5ls */ + if (!show_errors_g) H5Eset_auto(NULL, NULL); + + /* + * Build a list of file access property lists which we should try when + * opening the file. Eventually we'd like some way for the user to + * augment/replace this list interactively. + */ + + driver[ndrivers].name = "sec2"; + driver[ndrivers].fapl = H5P_DEFAULT; + ndrivers++; + + driver[ndrivers].name = "family"; + driver[ndrivers].fapl = fapl = H5Pcreate(H5P_FILE_ACCESS); + H5Pset_fapl_family(fapl, 0, H5P_DEFAULT); + ndrivers++; + + driver[ndrivers].name = "split"; + driver[ndrivers].fapl = fapl = H5Pcreate(H5P_FILE_ACCESS); + H5Pset_fapl_split(fapl, "-m.h5", H5P_DEFAULT, "-r.h5", H5P_DEFAULT); + ndrivers++; + + driver[ndrivers].name = "multi"; + driver[ndrivers].fapl = fapl = H5Pcreate(H5P_FILE_ACCESS); + H5Pset_fapl_multi(fapl, NULL, NULL, NULL, NULL, TRUE); + ndrivers++; /* * Each remaining argument is an hdf5 file followed by an optional slash @@ -2035,19 +2077,20 @@ main (int argc, char *argv[]) file = -1; while (fname && *fname) { - /* Choose a file driver*/ - plist = H5Pcreate(H5P_FILE_ACCESS); - if (strchr(fname, '%')) { - H5Pset_fapl_family(plist, 0, H5P_DEFAULT); + for (dno=0; dno<ndrivers; dno++) { + H5E_BEGIN_TRY { + file = H5Fopen(fname, H5F_ACC_RDONLY, driver[dno].fapl); + } H5E_END_TRY; + if (file>=0) break; } - - /* Try to open the file */ - H5E_BEGIN_TRY { - file = H5Fopen(fname, H5F_ACC_RDONLY, plist); - } H5E_END_TRY; - H5Pclose(plist); - if (file>=0) break; /*success*/ - + if (file>=0) { + if (verbose_g) { + printf("Opened \"%s\" with %s driver.\n", + fname, driver[dno].name); + } + break; /*success*/ + } + /* Shorten the file name; lengthen the object name */ x = oname; oname = strrchr(fname, '/'); |