summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Lu <songyulu@hdfgroup.org>2005-05-20 18:24:26 (GMT)
committerRaymond Lu <songyulu@hdfgroup.org>2005-05-20 18:24:26 (GMT)
commit9cf358dbb8140fb538c3ef0d52e77ef9e4ca1833 (patch)
tree96ff1aca2a9b7f1667692a680051212943855862
parentba95b9133c12258fcd795f2b3e3597d9273b2f89 (diff)
downloadhdf5-9cf358dbb8140fb538c3ef0d52e77ef9e4ca1833.zip
hdf5-9cf358dbb8140fb538c3ef0d52e77ef9e4ca1833.tar.gz
hdf5-9cf358dbb8140fb538c3ef0d52e77ef9e4ca1833.tar.bz2
[svn-r10776] Purpose: Bug fix
Description: See details from Bug #213. Family member file size wasn't saved anywhere in file. When family file is opened, the first member size determine the member size. Solution: This is the first step of fixing this bug. Member size and name template(unused at this stage) are saved in file superblock. When file is reopened, the size passed in through H5Pset_fapl_family is checked against the size saved in superblock. A different size will trigger a failure with an error message indicating the right size. Wrong driver to open family file will cause a failure, too. The second step will change multi driver that wrong driver will cause a failure. Platforms tested: fuss and h5committest
-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.