summaryrefslogtreecommitdiffstats
path: root/src/H5Ffamily.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Ffamily.c')
-rw-r--r--src/H5Ffamily.c167
1 files changed, 87 insertions, 80 deletions
diff --git a/src/H5Ffamily.c b/src/H5Ffamily.c
index 10572ce..73895b8 100644
--- a/src/H5Ffamily.c
+++ b/src/H5Ffamily.c
@@ -30,9 +30,10 @@
static hbool_t interface_initialize_g = FALSE;
#define INTERFACE_INIT NULL
-#define H5F_FAM_MASK(N) (((uint64)1<<(N))-1)
-#define H5F_FAM_OFFSET(ADDR,N) ((off_t)((ADDR)->offset & H5F_FAM_MASK(N)))
-#define H5F_FAM_MEMBNO(ADDR,N) ((intn)((ADDR)->offset >> (N)))
+#define H5F_FAM_OFFSET(LF,ADDR) ((off_t)((ADDR)->offset % \
+ (LF)->u.fam.memb_size.offset))
+#define H5F_FAM_MEMBNO(LF,ADDR) ((intn)((ADDR)->offset / \
+ (LF)->u.fam.memb_size.offset))
static hbool_t H5F_fam_access(const char *name,
const H5F_access_t *access_parms, int mode,
@@ -92,7 +93,6 @@ H5F_fam_open(const char *name, const H5F_access_t *access_parms,
H5F_low_t *member = NULL; /*a family member */
char member_name[4096]; /*name of family member */
intn membno; /*member number (zero-origin) */
- size_t nbits; /*num bits in an offset */
haddr_t tmp_addr; /*temporary address */
const H5F_low_class_t *memb_type; /*type of family member */
@@ -156,68 +156,70 @@ H5F_fam_open(const char *name, const H5F_access_t *access_parms,
member = NULL;
}
- /* Calculate member size */
- if (lf->u.fam.nmemb >= 2) {
+ H5F_low_size (lf->u.fam.memb[0], &tmp_addr);
+ if (1==lf->u.fam.nmemb &&
+ H5F_addr_gt (&tmp_addr, &(access_parms->u.fam.memb_size))) {
/*
- * If the first and second files exists then round the first file size
- * up to the next power of two and use that as the number of bits per
- * family member.
+ * If there's only one member and the member is larger than the
+ * specified member size, then adjust the specified member size to be
+ * the same as the actual member size, but at least 1kB
*/
- size_t size = H5F_low_size(lf->u.fam.memb[0], &tmp_addr);
- for (nbits=8*sizeof(size_t)-1; nbits>0; --nbits) {
- size_t mask = (size_t)1 << nbits;
- if (size & mask) {
- if (size != mask) {
- size++;
#ifdef H5F_DEBUG
- fprintf(stderr, "H5F: family member size was "
- "rounded up to a power of 2");
+ HDfprintf (stderr, "H5F: family member size has been increased "
+ "from %a to %a\n", &(access_parms->u.fam.memb_size),
+ &tmp_addr);
#endif
- }
- break;
- }
- }
- } else {
+ if (tmp_addr.offset<1024) tmp_addr.offset = 1024;
+ lf->u.fam.memb_size = tmp_addr;
+
+ } else if (1==lf->u.fam.nmemb) {
/*
- * Typically, the number of bits in the member offset can be up to two
- * less than the number of bits in an `off_t'. On a 32-bit machine,
- * for instance, files can be up to 2GB-1byte in size, but since HDF5
- * must have a power of two we're restricted to just 1GB. Smaller
- * values result in files of a more manageable size (from a human
- * perspective) but also limit the total logical size of the hdf5 file
- * since most OS's only allow a certain number of open file
- * descriptors (all family members are open at once).
+ * If there's just one member then use the specified size for the
+ * family members.
+ */
+ lf->u.fam.memb_size = access_parms->u.fam.memb_size;
+
+ } else if (lf->u.fam.nmemb>1 &&
+ H5F_addr_ne (&tmp_addr, &(access_parms->u.fam.memb_size))) {
+ /*
+ * If there are more than one member then use the size of the first
+ * member as the member size.
*/
#ifdef H5F_DEBUG
- if (access_parms->u.fam.offset_bits+2>8*sizeof(off_t)) {
- fprintf (stderr, "H5F: family member size may be too large.\n");
- }
+ HDfprintf (stderr, "H5F: family member size adjusted from %a to %a\n",
+ &(access_parms->u.fam.memb_size), &tmp_addr);
#endif
- nbits = MAX (access_parms->u.fam.offset_bits, 10); /*1K min*/
+ lf->u.fam.memb_size = tmp_addr;
+ for (membno=1; membno<lf->u.fam.nmemb; membno++) {
+ H5F_low_size (lf->u.fam.memb[membno], &tmp_addr);
+ if (H5F_addr_gt (&tmp_addr, &(lf->u.fam.memb_size))) {
+ HGOTO_ERROR (H5E_IO, H5E_CANTINIT, NULL, "family contains "
+ "member(s) larger than first member");
+ }
+ }
+
+ } else {
+ /* The family member size is the size of the first family member */
+ lf->u.fam.memb_size = tmp_addr;
}
- lf->u.fam.offset_bits = nbits;
-
+
#ifdef H5F_DEBUG
- if (nbits >= 30) {
- fprintf(stderr, "H5F: family members are %dGB\n",
- 1 << (nbits-30));
- } else if (nbits >= 20) {
- fprintf(stderr, "H5F: family members are %dMB\n",
- 1 << (nbits-20));
- } else if (nbits >= 10) {
- fprintf(stderr, "H5F: family members are %dkB\n",
- 1 << (nbits-10));
- } else {
- fprintf(stderr, "H5F: family members are %d bytes\n",
- 1 << nbits);
+ /*
+ * Check for funny member sizes. One common mistake is to use 2^32 as the
+ * member size but on a 32-bit machine this isn't possible. The largest
+ * file on a 32-bit machine is 2^32-1.
+ */
+ if (lf->u.fam.memb_size.offset == ((size_t)1<<(sizeof(off_t)-1))) {
+ HDfprintf (stderr, "H5F: family member size may be too large: %a\n",
+ &(lf->u.fam.memb_size));
}
#endif
-
+
/*
* Get the total family size and store it in the max_addr field.
*/
assert(lf->u.fam.nmemb >= 1);
- lf->eof.offset = (size_t)1 << lf->u.fam.offset_bits;
+ lf->eof = lf->u.fam.memb_size;
lf->eof.offset *= (lf->u.fam.nmemb-1);
lf->eof.offset += lf->u.fam.memb[lf->u.fam.nmemb-1]->eof.offset;
@@ -232,6 +234,7 @@ H5F_fam_open(const char *name, const H5F_access_t *access_parms,
}
FUNC_LEAVE(ret_value);
}
+
/*-------------------------------------------------------------------------
* Function: H5F_fam_close
@@ -296,11 +299,10 @@ static herr_t
H5F_fam_read(H5F_low_t *lf, const H5F_access_t *access_parms,
const haddr_t *addr, size_t size, uint8 *buf)
{
- size_t nbytes;
- haddr_t cur_addr;
- intn membno;
- off_t offset;
- hsize_t member_size;
+ size_t nbytes;
+ haddr_t cur_addr;
+ haddr_t offset, member_size;
+ intn membno;
FUNC_ENTER(H5F_fam_read, FAIL);
@@ -308,9 +310,10 @@ H5F_fam_read(H5F_low_t *lf, const H5F_access_t *access_parms,
assert(addr && H5F_addr_defined(addr));
assert(buf);
- member_size = (hsize_t) 1 << lf->u.fam.offset_bits;
- membno = H5F_FAM_MEMBNO(addr, lf->u.fam.offset_bits);
- offset = H5F_FAM_OFFSET(addr, lf->u.fam.offset_bits);
+ member_size = lf->u.fam.memb_size;
+ membno = H5F_FAM_MEMBNO(lf, addr);
+ H5F_addr_reset (&offset);
+ offset.offset = H5F_FAM_OFFSET(lf, addr);
cur_addr = *addr;
while (size > 0) {
@@ -318,8 +321,8 @@ H5F_fam_read(H5F_low_t *lf, const H5F_access_t *access_parms,
HDmemset(buf, 0, size);
break;
} else {
- nbytes = MIN(size, member_size-offset);
- cur_addr.offset = offset;
+ nbytes = MIN(size, member_size.offset-offset.offset);
+ cur_addr = offset;
if (H5F_low_read(lf->u.fam.memb[membno],
access_parms->u.fam.memb_access,
&cur_addr, nbytes, buf) < 0) {
@@ -329,7 +332,7 @@ H5F_fam_read(H5F_low_t *lf, const H5F_access_t *access_parms,
buf += nbytes;
size -= nbytes;
membno++;
- offset = 0;
+ H5F_addr_reset (&offset);
}
}
@@ -363,11 +366,10 @@ H5F_fam_write(H5F_low_t *lf, const H5F_access_t *access_parms,
size_t nbytes;
haddr_t cur_addr, max_addr;
intn membno;
- off_t offset;
+ haddr_t offset, member_size;
H5F_low_t *member = NULL;
char member_name[4096];
intn i;
- hsize_t member_size;
const H5F_low_class_t *memb_type = NULL;
FUNC_ENTER(H5F_fam_write, FAIL);
@@ -382,20 +384,27 @@ H5F_fam_write(H5F_low_t *lf, const H5F_access_t *access_parms,
/* Get the member driver */
memb_type = H5F_low_class (access_parms->u.fam.memb_access->driver);
- member_size = (hsize_t) 1 << lf->u.fam.offset_bits;
- membno = H5F_FAM_MEMBNO(addr, lf->u.fam.offset_bits);
- offset = H5F_FAM_OFFSET(addr, lf->u.fam.offset_bits);
+ member_size = lf->u.fam.memb_size;
+ membno = H5F_FAM_MEMBNO(lf, addr);
+ H5F_addr_reset (&offset);
+ offset.offset = H5F_FAM_OFFSET(lf, addr);
cur_addr = *addr;
while (size > 0) {
- nbytes = MIN(size, member_size - offset);
- cur_addr.offset = offset;
+ nbytes = MIN(size, member_size.offset - offset.offset);
+ cur_addr = offset;
if (membno >= lf->u.fam.nmemb) {
/*
* We're writing past the end of the last family member--create the
* new family member(s)
*/
+ if (membno >= lf->u.fam.nalloc) {
+ lf->u.fam.nalloc = (membno+1)*2;
+ lf->u.fam.memb = H5MM_xrealloc(lf->u.fam.memb,
+ (lf->u.fam.nalloc *
+ sizeof(H5F_low_t *)));
+ }
for (i = lf->u.fam.nmemb; i <= membno; i++) {
sprintf(member_name, lf->u.fam.name, i);
member = H5F_low_open(memb_type, member_name,
@@ -406,24 +415,20 @@ H5F_fam_write(H5F_low_t *lf, const H5F_access_t *access_parms,
HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, FAIL,
"can't create a new member");
}
+
/*
* For members in the middle, set their logical eof to the
* maximum possible value.
*/
if (i < membno) {
H5F_addr_reset(&max_addr);
- H5F_addr_inc(&max_addr, member_size);
+ H5F_addr_inc(&max_addr, member_size.offset);
H5F_low_seteof(member, &max_addr);
}
- if (lf->u.fam.nmemb >= lf->u.fam.nalloc) {
- lf->u.fam.nalloc *= 2;
- lf->u.fam.memb = H5MM_xrealloc(lf->u.fam.memb,
- (lf->u.fam.nalloc *
- sizeof(H5F_low_t *)));
- }
lf->u.fam.memb[lf->u.fam.nmemb++] = member;
}
}
+
/*
* Make sure the logical eof is large enough to handle the request.
*/
@@ -441,11 +446,12 @@ H5F_fam_write(H5F_low_t *lf, const H5F_access_t *access_parms,
buf += nbytes;
size -= nbytes;
membno++;
- offset = 0;
+ H5F_addr_reset (&offset);
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5F_fam_flush
@@ -479,11 +485,11 @@ H5F_fam_flush(H5F_low_t *lf, const H5F_access_t *access_parms)
/*
* Make sure that the first family member is the maximum size because
* H5F_fam_open() looks at the size of the first member to determine the
- * number of bits to use for each family member offset. We do this by
- * reading the last possible byte from the member (which defaults to zero
- * if we're reading past the end of the member) and then writing it back.
+ * size of each family member. We do this by reading the last possible
+ * byte from the member (which defaults to zero if we're reading past the
+ * end of the member) and then writing it back.
*/
- max_offset = H5F_FAM_MASK(lf->u.fam.offset_bits);
+ max_offset = lf->u.fam.memb_size.offset - 1;
H5F_addr_reset(&addr1);
H5F_addr_inc(&addr1, max_offset);
H5F_low_size(lf->u.fam.memb[0], &addr2); /*remember logical eof */
@@ -518,6 +524,7 @@ H5F_fam_flush(H5F_low_t *lf, const H5F_access_t *access_parms)
}
FUNC_LEAVE(SUCCEED);
}
+
/*-------------------------------------------------------------------------
* Function: H5F_fam_access