diff options
-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, '/'); |