summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5F.c9
-rw-r--r--src/H5FDfamily.c190
-rw-r--r--src/H5Fpublic.h2
3 files changed, 169 insertions, 32 deletions
diff --git a/src/H5F.c b/src/H5F.c
index 442baac..227bf9c 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -2070,6 +2070,7 @@ H5Fcreate(const char *filename, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
H5F_t *new_file = NULL; /*file struct for new file */
hid_t ret_value; /*return value */
+ hid_t estack_id;
FUNC_ENTER_API(H5Fcreate, FAIL)
H5TRACE4("i","sIuii",filename,flags,fcpl_id,fapl_id);
@@ -2554,9 +2555,15 @@ H5F_read_superblock(H5F_t *f, hid_t dxpl_id, H5G_entry_t *root_ent, haddr_t addr
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read file driver information")
} /* end if */
+ /* Check if driver matches family driver saved. Unfortunately, we can't push this function to
+ * each specific driver because we're checking if the driver is correct.*/
+ if(!HDstrncmp(driver_name, "NCSAfami", 8) && HDstrcmp(lf->cls->name, "family"))
+ HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "family driver should be used")
+
if (H5FD_sb_decode(lf, driver_name, p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to decode driver information")
-
+ p += driver_size; /* advance past driver information section */
+
/* Compute driver info block checksum */
assert(sizeof(chksum) == sizeof(shared->drvr_chksum));
for (q = (uint8_t *)&chksum, chksum = 0, i = 0; i < (driver_size + 16); ++i)
diff --git a/src/H5FDfamily.c b/src/H5FDfamily.c
index 83e6c75..28824e3 100644
--- a/src/H5FDfamily.c
+++ b/src/H5FDfamily.c
@@ -58,7 +58,8 @@ static hid_t H5FD_FAMILY_g = 0;
typedef struct H5FD_family_t {
H5FD_t pub; /*public stuff, must be first */
hid_t memb_fapl_id; /*file access property list for members */
- hsize_t memb_size; /*maximum size of each member file */
+ hsize_t memb_size; /*actual size of each member file */
+ hsize_t pmem_size; /*member size passed in from property */
unsigned nmembs; /*number of family members */
unsigned amembs; /*number of member slots allocated */
H5FD_t **memb; /*dynamic array of member pointers */
@@ -84,6 +85,11 @@ static void *H5FD_family_fapl_copy(const void *_old_fa);
static herr_t H5FD_family_fapl_free(void *_fa);
static void *H5FD_family_dxpl_copy(const void *_old_dx);
static herr_t H5FD_family_dxpl_free(void *_dx);
+static hsize_t H5FD_family_sb_size(H5FD_t *_file);
+static herr_t H5FD_family_sb_encode(H5FD_t *_file, char *name/*out*/,
+ unsigned char *buf/*out*/);
+static herr_t H5FD_family_sb_decode(H5FD_t *_file, const char *name,
+ const unsigned char *buf);
static H5FD_t *H5FD_family_open(const char *name, unsigned flags,
hid_t fapl_id, haddr_t maxaddr);
static herr_t H5FD_family_close(H5FD_t *_file);
@@ -103,10 +109,10 @@ static herr_t H5FD_family_flush(H5FD_t *_file, hid_t dxpl_id, unsigned closing);
static const H5FD_class_t H5FD_family_g = {
"family", /*name */
HADDR_MAX, /*maxaddr */
- H5F_CLOSE_WEAK, /* fc_degree */
- NULL, /*sb_size */
- NULL, /*sb_encode */
- NULL, /*sb_decode */
+ H5F_CLOSE_WEAK, /*fc_degree */
+ H5FD_family_sb_size, /*sb_size */
+ H5FD_family_sb_encode, /*sb_encode */
+ H5FD_family_sb_decode, /*sb_decode */
sizeof(H5FD_family_fapl_t), /*fapl_size */
H5FD_family_fapl_get, /*fapl_get */
H5FD_family_fapl_copy, /*fapl_copy */
@@ -550,6 +556,139 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FD_family_sb_size
+ *
+ * Purpose: Returns the size of the private information to be stored in
+ * the superblock.
+ *
+ * Return: Success: The super block driver data size.
+ *
+ * Failure: never fails
+ *
+ * Programmer: Raymond Lu
+ * Tuesday, May 10, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hsize_t
+H5FD_family_sb_size(H5FD_t *_file)
+{
+ H5FD_family_t *file = (H5FD_family_t*)_file;
+ hsize_t ret_value = 0; /*size of header*/
+
+ FUNC_ENTER_NOAPI(H5FD_family_sb_size, FAIL)
+
+ /* 8 bytes field for the size of member file size field should be
+ * enough for now. */
+ ret_value += 8;
+
+ /* name template, NULL termination included */
+ ret_value += HDstrlen(file->name) + 1;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_family_sb_encode
+ *
+ * Purpose: Encode driver information for the superblock. The NAME
+ * argument is a nine-byte buffer which will be initialized with
+ * an eight-character name/version number and null termination.
+ *
+ * The encoding is the member file size and name template.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Raymond Lu
+ * Tuesday, May 10, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_family_sb_encode(H5FD_t *_file, char *name/*out*/,
+ unsigned char *buf/*out*/)
+{
+ H5FD_family_t *file = (H5FD_family_t*)_file;
+ unsigned char *p = buf;
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_family_sb_encode, FAIL)
+
+ /* Name and version number */
+ strncpy(name, "NCSAfami",8);
+ name[8] = '\0';
+
+ /* copy member file size */
+ UINT64ENCODE(buf, file->memb_size);
+ p += 8;
+
+ /* copy name template */
+ HDmemcpy(p, file->name, HDstrlen(file->name) + 1);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FD_family_sb_decode
+ *
+ * Purpose: Decodes the superblock information for this driver. The NAME
+ * 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.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Raymond Lu
+ * Tuesday, May 10, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FD_family_sb_decode(H5FD_t *_file, const char *name, const unsigned char *buf)
+{
+ H5FD_family_t *file = (H5FD_family_t*)_file;
+ unsigned char *p = buf;
+ uint64_t msize;
+ char err_msg[128];
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FD_family_sb_decode, FAIL)
+
+ /* Read member file size. Skip name template for now although it's saved. */
+ UINT64DECODE(p, msize);
+
+ /* Default - use the saved member size */
+ if(file->pmem_size == H5F_FAMILY_DEFAULT)
+ file->memb_size = msize;
+
+ /* Check if member size is correct */
+ if(file->memb_size != msize) {
+ sprintf(err_msg, "family member size should be %lu", msize);
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, err_msg)
+ }
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
+
+/*-------------------------------------------------------------------------
* Function: H5FD_family_open
*
* Purpose: Creates and/or opens a family of files as an HDF5 file.
@@ -581,7 +720,7 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
H5FD_family_t *file=NULL;
H5FD_t *ret_value=NULL;
char memb_name[4096], temp[4096];
- hsize_t eof1=HADDR_UNDEF, eof2=HADDR_UNDEF;
+ hsize_t eof=HADDR_UNDEF;
unsigned t_flags = flags & ~H5F_ACC_CREAT;
H5P_genplist_t *plist; /* Property list pointer */
@@ -600,7 +739,8 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
file->memb_fapl_id = H5P_FILE_ACCESS_DEFAULT;
if(H5I_inc_ref(file->memb_fapl_id)<0)
HGOTO_ERROR(H5E_VFL, H5E_CANTINC, NULL, "unable to increment ref count on VFL driver")
- file->memb_size = 1024*1024*1024; /*1GB*/
+ file->memb_size = 1024*1024*1024; /*1GB. Actual member size to be updated later */
+ file->pmem_size = 1024*1024*1024; /*1GB. Member size passed in through property */
} else {
H5FD_family_fapl_t *fa;
@@ -617,7 +757,8 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
file->memb_fapl_id = H5P_copy_plist(plist);
} /* end else */
- file->memb_size = fa->memb_size;
+ file->memb_size = fa->memb_size; /* Actual member size to be updated later */
+ file->pmem_size = fa->memb_size; /* Member size passed in through property */
}
file->name = H5MM_strdup(name);
file->flags = flags;
@@ -662,27 +803,11 @@ H5FD_family_open(const char *name, unsigned flags, hid_t fapl_id,
file->nmembs++;
}
- /*
- * Get file size of the first 2 member files if exist. Check if user sets
- * reasonable member size.
+ /* If the file is reopened and there's only one member file existing, this file maybe
+ * smaller than the size specified through H5Pset_fapl_family(). Update the actual
+ * member size.
*/
- if(HADDR_UNDEF==(eof1 = H5FD_get_eof(file->memb[0])))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "file get eof1 request failed")
- if(file->memb[1] && (HADDR_UNDEF==(eof2 = H5FD_get_eof(file->memb[1]))))
- HGOTO_ERROR(H5E_VFL, H5E_CANTINIT, NULL, "file get eof2 request failed")
-
- if(eof1 && (eof2==HADDR_UNDEF || !eof2)) {
- /* If there is only 1 member file, new member size can't be smaller than
- * current member size.
- */
- if(file->memb_size<eof1)
- file->memb_size = eof1;
- } else if(eof1 && eof2) {
- /* If there are at least 2 member files, new member size can only be equal
- * to the 1st member size
- */
- file->memb_size = eof1;
- }
+ if ((eof=H5FDget_eof(file->memb[0]))) file->memb_size = eof;
ret_value=(H5FD_t *)file;
@@ -692,6 +817,8 @@ done:
unsigned nerrors=0; /* Number of errors closing member files */
unsigned u; /* Local index variable */
+ /* Close as many members as possible. Use private function here to avoid clearing
+ * the error stack. We need the error message to indicate wrong member file size. */
for (u=0; u<file->nmembs; u++)
if (file->memb[u])
if (H5FD_close(file->memb[u])<0)
@@ -739,10 +866,11 @@ H5FD_family_close(H5FD_t *_file)
FUNC_ENTER_NOAPI(H5FD_family_close, FAIL)
- /* Close as many members as possible */
+ /* Close as many members as possible. Use private function here to avoid clearing
+ * the error stack. We need the error message to indicate wrong member file size. */
for (u=0; u<file->nmembs; u++) {
if (file->memb[u]) {
- if (H5FDclose(file->memb[u])<0)
+ if (H5FD_close(file->memb[u])<0)
nerrors++;
else
file->memb[u] = NULL;
@@ -929,7 +1057,7 @@ H5FD_family_set_eoa(H5FD_t *_file, haddr_t eoa)
if (NULL==file->memb[u])
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to open member file")
}
-
+
/* Set the EOA marker for the member */
H5_CHECK_OVERFLOW(file->memb_size,hsize_t,haddr_t);
if (addr>(haddr_t)file->memb_size) {
diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h
index 79a2769..91edaa2 100644
--- a/src/H5Fpublic.h
+++ b/src/H5Fpublic.h
@@ -59,6 +59,8 @@
#define H5F_OBJ_ATTR (0x0010u)
#define H5F_OBJ_ALL (H5F_OBJ_FILE|H5F_OBJ_DATASET|H5F_OBJ_GROUP|H5F_OBJ_DATATYPE|H5F_OBJ_ATTR)
+#define H5F_FAMILY_DEFAULT 0
+
#ifdef H5_HAVE_PARALLEL
/*
* Use this constant string as the MPI_Info key to set H5Fmpio debug flags.