summaryrefslogtreecommitdiffstats
path: root/src/H5FDmulti.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5FDmulti.c')
-rw-r--r--src/H5FDmulti.c661
1 files changed, 471 insertions, 190 deletions
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;
+}