summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5D.c4
-rw-r--r--src/H5Distore.c6
-rw-r--r--src/H5F.c47
-rw-r--r--src/H5FD.c63
-rw-r--r--src/H5FDcore.c2
-rw-r--r--src/H5FDfamily.c2
-rw-r--r--src/H5FDmpio.c2
-rw-r--r--src/H5FDmulti.c661
-rw-r--r--src/H5FDmulti.h4
-rw-r--r--src/H5FDprivate.h3
-rw-r--r--src/H5FDpublic.h18
-rw-r--r--src/H5FDsec2.c2
-rw-r--r--src/H5Fistore.c6
-rw-r--r--src/H5I.c7
-rw-r--r--test/h5test.c2
-rw-r--r--tools/h5ls.c79
16 files changed, 667 insertions, 241 deletions
diff --git a/src/H5D.c b/src/H5D.c
index 49de18d..423e739 100644
--- a/src/H5D.c
+++ b/src/H5D.c
@@ -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");
diff --git a/src/H5F.c b/src/H5F.c
index e908625..dcbea3c 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -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);
}
diff --git a/src/H5FD.c b/src/H5FD.c
index 86759d7..c025090 100644
--- a/src/H5FD.c
+++ b/src/H5FD.c
@@ -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");
diff --git a/src/H5I.c b/src/H5I.c
index ff3b6c6..54026e9 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -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, '/');