summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST1
-rw-r--r--config/linux9
-rw-r--r--src/H5.c2
-rw-r--r--src/H5Bprivate.h2
-rw-r--r--src/H5F.c64
-rw-r--r--src/H5Ffamily.c167
-rw-r--r--src/H5Fprivate.h12
-rw-r--r--src/H5Gpkg.h2
-rw-r--r--src/H5MF.c2
-rw-r--r--src/H5P.c48
-rw-r--r--src/H5Ppublic.h4
-rw-r--r--src/Makefile.in15
-rw-r--r--src/h5ls.c30
-rw-r--r--src/h5repart.c388
-rw-r--r--test/big.c9
15 files changed, 601 insertions, 154 deletions
diff --git a/MANIFEST b/MANIFEST
index 895a9c8..7742101 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -201,6 +201,7 @@
./src/Makefile.in
./src/debug.c
./src/h5ls.c
+./src/h5repart.c
./src/hdf5.h
./test/.distdep
./test/Makefile.in
diff --git a/config/linux b/config/linux
index 5aab032..e4c0111 100644
--- a/config/linux
+++ b/config/linux
@@ -12,7 +12,12 @@
CC=${CC:-gcc}
case `$CC -v 2>&1 |tail -1 |sed 's/gcc version //'` in
2.7.*)
- echo "You have an old version of gcc, please upgrade to 2.8.1 or better"
+ echo " +------------------------------------------------+"
+ echo " | You have an old version of gcc. Please upgrade |"
+ echo " | to 2.8.1 or better. Continuing anyway, but |"
+ echo " | code generation may be wrong on some platforms.|"
+ echo " +------------------------------------------------+"
+ sleep 5
;;
2.8.*)
CFLAGS="$CFLAGS -Wundef -Wsign-compare"
@@ -29,7 +34,7 @@ DEBUG_CPPFLAGS="-DH5F_OPT_SEEK=0 -DH5F_LOW_DFLT=H5F_LOW_SEC2"
# What compiler flags should be used for building a production
# library?
-PROD_CFLAGS="-O3 -finline-functions -malign-double -fomit-frame-pointer -march=pentiumpro -fschedule-insns2"
+PROD_CFLAGS="-mcpu=pentiumpro -march=pentiumpro -O3 -finline-functions -malign-double -fomit-frame-pointer -fschedule-insns2"
PROD_CPPFLAGS=
# What compiler flags enable code profiling?
diff --git a/src/H5.c b/src/H5.c
index c9e755e..4e48221 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -848,7 +848,7 @@ H5_timer_begin (H5_timer_t *timer)
#endif
gettimeofday (&etime, NULL);
- timer->etime = etime.tv_sec + etime.tv_usec/1e6;
+ timer->etime = (double)etime.tv_sec + (double)etime.tv_usec/1e6;
}
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index 40aa65c..17addf5 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -40,7 +40,7 @@
2*H5F_SIZEOF_ADDR(F)) /*left and right sibling addresses */
#define H5B_K(F,TYPE) /*K value given file and Btree subclass */ \
- ((F)->shared->create_parms.btree_k[(TYPE)->id])
+ ((F)->shared->create_parms->btree_k[(TYPE)->id])
typedef enum H5B_ins_t {
H5B_INS_ERROR = -1, /*error return value */
diff --git a/src/H5F.c b/src/H5F.c
index d726edf..972ffc9 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -260,7 +260,7 @@ H5Fget_create_template(hid_t fid)
/* Create the template object to return */
if (NULL==(tmpl=H5P_copy (H5P_FILE_CREATE,
- &(file->shared->create_parms)))) {
+ file->shared->create_parms))) {
HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL,
"unable to copy file creation properties");
}
@@ -310,7 +310,7 @@ H5Fget_access_template (hid_t file_id)
/* Create the template object to return */
if (NULL==(tmpl=H5P_copy (H5P_FILE_ACCESS,
- &(f->shared->access_parms)))) {
+ f->shared->access_parms))) {
HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL,
"unable to copy file access properties");
}
@@ -548,6 +548,8 @@ H5F_dest(H5F_t *f)
ret_value = FAIL; /*but keep going*/
}
f->shared->cwfs = H5MM_xfree (f->shared->cwfs);
+ H5P_close (H5P_FILE_CREATE, f->shared->create_parms);
+ H5P_close (H5P_FILE_ACCESS, f->shared->access_parms);
f->shared = H5MM_xfree(f->shared);
}
f->name = H5MM_xfree(f->name);
@@ -819,14 +821,14 @@ H5F_open(const char *name, uintn flags,
* the properties may need to be updated.
*/
if (1 == f->shared->nrefs) {
- f->shared->create_parms = *create_parms;
- f->shared->access_parms = *access_parms;
- if (H5F_LOW_FAMILY==f->shared->access_parms.driver) {
- size_t x = f->shared->lf->u.fam.offset_bits;
- f->shared->access_parms.u.fam.offset_bits = x;
+ f->shared->create_parms = H5P_copy (H5P_FILE_CREATE, create_parms);
+ f->shared->access_parms = H5P_copy (H5P_FILE_ACCESS, access_parms);
+ if (H5F_LOW_FAMILY==f->shared->access_parms->driver) {
+ haddr_t x = f->shared->lf->u.fam.memb_size;
+ f->shared->access_parms->u.fam.memb_size = x;
}
}
- cp = &(f->shared->create_parms);
+ cp = f->shared->create_parms;
/*
* Read or write the file boot block.
@@ -840,7 +842,7 @@ H5F_open(const char *name, uintn flags,
*/
H5F_addr_reset(&(f->shared->boot_addr));
H5F_addr_inc(&(f->shared->boot_addr),
- f->shared->create_parms.userblock_size);
+ f->shared->create_parms->userblock_size);
f->shared->base_addr = f->shared->boot_addr;
f->shared->consist_flags = 0x03;
@@ -852,7 +854,7 @@ H5F_open(const char *name, uintn flags,
} else if (1 == f->shared->nrefs) {
/* For existing files we must read the boot block. */
if (H5F_locate_signature(f->shared->lf,
- &(f->shared->access_parms),
+ f->shared->access_parms,
&(f->shared->boot_addr)) < 0) {
HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, NULL, "can't find signature");
}
@@ -957,7 +959,7 @@ H5F_open(const char *name, uintn flags,
* The userdefined data is the area of the file before the base
* address.
*/
- f->shared->create_parms.userblock_size = f->shared->base_addr.offset;
+ f->shared->create_parms->userblock_size = f->shared->base_addr.offset;
}
/*
@@ -1265,18 +1267,18 @@ H5F_flush(H5F_t *f, hbool_t invalidate)
HDmemcpy(p, H5F_SIGNATURE, H5F_SIGNATURE_LEN);
p += H5F_SIGNATURE_LEN;
- *p++ = f->shared->create_parms.bootblock_ver;
- *p++ = f->shared->create_parms.freespace_ver;
- *p++ = f->shared->create_parms.objectdir_ver;
+ *p++ = f->shared->create_parms->bootblock_ver;
+ *p++ = f->shared->create_parms->freespace_ver;
+ *p++ = f->shared->create_parms->objectdir_ver;
*p++ = 0; /*reserved*/
- *p++ = f->shared->create_parms.sharedheader_ver;
+ *p++ = f->shared->create_parms->sharedheader_ver;
assert (H5F_SIZEOF_ADDR(f)<=255);
*p++ = (uint8)H5F_SIZEOF_ADDR(f);
assert (H5F_SIZEOF_SIZE(f)<=255);
*p++ = (uint8)H5F_SIZEOF_SIZE(f);
*p++ = 0; /*reserved */
- UINT16ENCODE(p, f->shared->create_parms.sym_leaf_k);
- UINT16ENCODE(p, f->shared->create_parms.btree_k[H5B_SNODE_ID]);
+ UINT16ENCODE(p, f->shared->create_parms->sym_leaf_k);
+ UINT16ENCODE(p, f->shared->create_parms->btree_k[H5B_SNODE_ID]);
UINT32ENCODE(p, f->shared->consist_flags);
H5F_addr_encode(f, &p, &(f->shared->base_addr));
H5F_addr_encode(f, &p, &(f->shared->freespace_addr));
@@ -1291,13 +1293,13 @@ H5F_flush(H5F_t *f, hbool_t invalidate)
}
/* write the boot block to disk */
- if (H5F_low_write(f->shared->lf, &(f->shared->access_parms),
+ if (H5F_low_write(f->shared->lf, f->shared->access_parms,
&(f->shared->boot_addr), (size_t)(p-buf), buf)<0) {
HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "can't write header");
}
/* Flush file buffers to disk */
- if (H5F_low_flush(f->shared->lf, &(f->shared->access_parms)) < 0) {
+ if (H5F_low_flush(f->shared->lf, f->shared->access_parms) < 0) {
HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed");
}
FUNC_LEAVE(SUCCEED);
@@ -1372,7 +1374,7 @@ H5F_close(H5F_t *f)
if (f->intent & H5F_ACC_DEBUG) H5AC_debug(f);
/* Close files and release resources */
- H5F_low_close(f->shared->lf, &(f->shared->access_parms));
+ H5F_low_close(f->shared->lf, f->shared->access_parms);
}
if (H5F_dest(f)<0) {
HRETURN_ERROR (H5E_FILE, H5E_CANTINIT, FAIL,
@@ -1478,7 +1480,7 @@ H5F_block_read(H5F_t *f, const haddr_t *addr, hsize_t size, void *buf)
H5F_addr_add(&abs_addr, addr);
/* Read the data */
- if (H5F_low_read(f->shared->lf, &(f->shared->access_parms),
+ if (H5F_low_read(f->shared->lf, f->shared->access_parms,
&abs_addr, (size_t)size, buf) < 0) {
HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "low-level read failed");
}
@@ -1526,7 +1528,7 @@ H5F_block_write(H5F_t *f, const haddr_t *addr, hsize_t size, const void *buf)
H5F_addr_add(&abs_addr, addr);
/* Write the data */
- if (H5F_low_write(f->shared->lf, &(f->shared->access_parms),
+ if (H5F_low_write(f->shared->lf, f->shared->access_parms,
&abs_addr, (size_t)size, buf)) {
HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low-level write failed");
}
@@ -1606,31 +1608,31 @@ H5F_debug(H5F_t *f, const haddr_t __unused__ *addr, FILE * stream,
fprintf(stream, "%*s%-*s %lu bytes\n", indent, "", fwidth,
"Size of user block:",
- (unsigned long) (f->shared->create_parms.userblock_size));
+ (unsigned long) (f->shared->create_parms->userblock_size));
fprintf(stream, "%*s%-*s %u bytes\n", indent, "", fwidth,
"Size of file size_t type:",
- (unsigned) (f->shared->create_parms.sizeof_size));
+ (unsigned) (f->shared->create_parms->sizeof_size));
fprintf(stream, "%*s%-*s %u bytes\n", indent, "", fwidth,
"Size of file haddr_t type:",
- (unsigned) (f->shared->create_parms.sizeof_addr));
+ (unsigned) (f->shared->create_parms->sizeof_addr));
fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Symbol table leaf node 1/2 rank:",
- (unsigned) (f->shared->create_parms.sym_leaf_k));
+ (unsigned) (f->shared->create_parms->sym_leaf_k));
fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Symbol table internal node 1/2 rank:",
- (unsigned) (f->shared->create_parms.btree_k[H5B_SNODE_ID]));
+ (unsigned) (f->shared->create_parms->btree_k[H5B_SNODE_ID]));
fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Boot block version number:",
- (unsigned) (f->shared->create_parms.bootblock_ver));
+ (unsigned) (f->shared->create_parms->bootblock_ver));
fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Free list version number:",
- (unsigned) (f->shared->create_parms.freespace_ver));
+ (unsigned) (f->shared->create_parms->freespace_ver));
fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Object directory version number:",
- (unsigned) (f->shared->create_parms.objectdir_ver));
+ (unsigned) (f->shared->create_parms->objectdir_ver));
fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
"Shared header version number:",
- (unsigned) (f->shared->create_parms.sharedheader_ver));
+ (unsigned) (f->shared->create_parms->sharedheader_ver));
fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
"Root group symbol table entry:",
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
diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h
index d9ce06d..cce26e1 100644
--- a/src/H5Fprivate.h
+++ b/src/H5Fprivate.h
@@ -49,8 +49,8 @@
#define H5F_SIGNATURE_LEN 8
/* size of size_t and off_t as they exist on disk */
-#define H5F_SIZEOF_ADDR(F) ((F)->shared->create_parms.sizeof_addr)
-#define H5F_SIZEOF_SIZE(F) ((F)->shared->create_parms.sizeof_size)
+#define H5F_SIZEOF_ADDR(F) ((F)->shared->create_parms->sizeof_addr)
+#define H5F_SIZEOF_SIZE(F) ((F)->shared->create_parms->sizeof_size)
/*
* Private file open flags.
@@ -249,7 +249,7 @@ typedef struct H5F_access_t {
/* Properties for file families */
struct {
struct H5F_access_t *memb_access; /*plist for the members */
- size_t offset_bits; /*number of bits in offset */
+ haddr_t memb_size; /*number of bits in offset */
} fam;
/* Properties for the split driver */
@@ -323,7 +323,7 @@ typedef struct H5F_low_t {
intn nmemb; /* Number of family members */
intn nalloc; /* Size of member table in elements */
struct H5F_low_t **memb; /* An array of family members */
- size_t offset_bits; /* Number of bits in a member offset*/
+ haddr_t memb_size; /*Size of each family member */
} fam;
/* Split meta/raw data */
@@ -401,8 +401,8 @@ typedef struct H5F_file_t {
haddr_t freespace_addr; /* Relative address of free-space info */
haddr_t hdf5_eof; /* Relative addr of end of all hdf5 data*/
struct H5AC_t *cache; /* The object cache */
- H5F_create_t create_parms; /* File-creation property list */
- H5F_access_t access_parms; /* File-access property list */
+ H5F_create_t *create_parms; /* File-creation property list */
+ H5F_access_t *access_parms; /* File-access property list */
struct H5G_t *root_grp; /* Open root group */
intn ncwfs; /* Num entries on cwfs list */
struct H5HG_heap_t **cwfs; /* Global heap cache */
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index 3b449fd..38e07ed 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -21,7 +21,7 @@
#define H5G_NODE_VERS 1 /*symbol table node version number */
#define H5G_SIZE_HINT 1024 /*default root grp size hint */
-#define H5G_NODE_K(F) ((unsigned)((F)->shared->create_parms.sym_leaf_k))
+#define H5G_NODE_K(F) ((unsigned)((F)->shared->create_parms->sym_leaf_k))
#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4)
#define H5G_DEFAULT_ROOT_SIZE 32
diff --git a/src/H5MF.c b/src/H5MF.c
index fd5031b..a87dc39 100644
--- a/src/H5MF.c
+++ b/src/H5MF.c
@@ -73,7 +73,7 @@ H5MF_alloc(H5F_t *f, intn op, hsize_t size, haddr_t *addr/*out*/)
* from there. But for now we just allocate more memory from the end of
* the file.
*/
- if (H5F_low_extend(f->shared->lf, &(f->shared->access_parms), op,
+ if (H5F_low_extend(f->shared->lf, f->shared->access_parms, op,
size, addr/*out*/) < 0) {
HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
"low level mem management failed");
diff --git a/src/H5P.c b/src/H5P.c
index fa94d6e..6e8c337 100644
--- a/src/H5P.c
+++ b/src/H5P.c
@@ -1574,10 +1574,10 @@ H5Pget_split (hid_t tid, size_t meta_ext_size, char *meta_ext/*out*/,
* Function: H5Pset_family
*
* Purpose: Sets the low-level driver to stripe the hdf5 address space
- * across a family of files. The OFFSET_BITS argument indicates
- * how many of the low-order bits of an address will be used for
- * the offset within the file, and is only meaningful when
- * creating new files.
+ * across a family of files. The MEMB_SIZE argument indicates
+ * the size in bytes of each family member and is only
+ * meaningful when creating new files or opening families that
+ * have only one member.
*
* Return: Success: SUCCEED
*
@@ -1591,7 +1591,7 @@ H5Pget_split (hid_t tid, size_t meta_ext_size, char *meta_ext/*out*/,
*-------------------------------------------------------------------------
*/
herr_t
-H5Pset_family (hid_t tid, size_t offset_bits, hid_t memb_tid)
+H5Pset_family (hid_t tid, hsize_t memb_size, hid_t memb_tid)
{
H5F_access_t *tmpl = NULL;
@@ -1605,6 +1605,10 @@ H5Pset_family (hid_t tid, size_t offset_bits, hid_t memb_tid)
HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL,
"not a file access template");
}
+ if (memb_size && memb_size<1024) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADRANGE, FAIL,
+ "family member size is too small");
+ }
if (H5P_DEFAULT!=memb_tid &&
(H5P_FILE_ACCESS != H5Pget_class(memb_tid) ||
NULL == (tmpl = H5I_object(memb_tid)))) {
@@ -1614,7 +1618,8 @@ H5Pset_family (hid_t tid, size_t offset_bits, hid_t memb_tid)
/* Set driver */
tmpl->driver = H5F_LOW_FAMILY;
- tmpl->u.fam.offset_bits = offset_bits;
+ H5F_addr_reset (&(tmpl->u.fam.memb_size));
+ H5F_addr_inc (&(tmpl->u.fam.memb_size), memb_size);
tmpl->u.fam.memb_access = H5P_copy (H5P_FILE_ACCESS, memb_tmpl);
FUNC_LEAVE (SUCCEED);
@@ -1644,7 +1649,7 @@ H5Pset_family (hid_t tid, size_t offset_bits, hid_t memb_tid)
*-------------------------------------------------------------------------
*/
herr_t
-H5Pget_family (hid_t tid, size_t *offset_bits/*out*/, hid_t *memb_tid/*out*/)
+H5Pget_family (hid_t tid, hsize_t *memb_size/*out*/, hid_t *memb_tid/*out*/)
{
H5F_access_t *tmpl = NULL;
@@ -1662,13 +1667,15 @@ H5Pget_family (hid_t tid, size_t *offset_bits/*out*/, hid_t *memb_tid/*out*/)
}
/* Output args */
+ if (memb_size) {
+ *memb_size = tmpl->u.fam.memb_size.offset;
+ }
if (memb_tid) {
assert (tmpl->u.fam.memb_access);
*memb_tid = H5P_create (H5P_FILE_ACCESS,
H5P_copy (H5P_FILE_ACCESS,
tmpl->u.fam.memb_access));
}
- if (offset_bits) *offset_bits = tmpl->u.fam.offset_bits;
FUNC_LEAVE (SUCCEED);
}
@@ -2356,6 +2363,8 @@ H5P_copy (H5P_class_t type, const void *src)
int i;
const H5D_create_t *dc_src = NULL;
H5D_create_t *dc_dst = NULL;
+ const H5F_access_t *fa_src = NULL;
+ H5F_access_t *fa_dst = NULL;
FUNC_ENTER (H5P_copy, NULL);
@@ -2392,6 +2401,29 @@ H5P_copy (H5P_class_t type, const void *src)
break;
case H5P_FILE_ACCESS:
+ fa_src = (const H5F_access_t*)src;
+ fa_dst = (H5F_access_t*)dst;
+ switch (fa_src->driver) {
+ case H5F_LOW_ERROR:
+ case H5F_LOW_SEC2:
+ case H5F_LOW_STDIO:
+ case H5F_LOW_CORE:
+ case H5F_LOW_MPIO:
+ /* Nothing to do */
+ break;
+
+ case H5F_LOW_FAMILY:
+ fa_dst->u.fam.memb_access = H5P_copy (H5P_FILE_ACCESS,
+ fa_src->u.fam.memb_access);
+ break;
+
+ case H5F_LOW_SPLIT:
+ fa_dst->u.split.meta_access=H5P_copy (H5P_FILE_ACCESS,
+ fa_src->u.split.meta_access);
+ fa_dst->u.split.raw_access = H5P_copy (H5P_FILE_ACCESS,
+ fa_src->u.split.raw_access);
+ break;
+ }
break;
case H5P_DATASET_CREATE:
diff --git a/src/H5Ppublic.h b/src/H5Ppublic.h
index 503f8c5..e9717d1 100644
--- a/src/H5Ppublic.h
+++ b/src/H5Ppublic.h
@@ -81,8 +81,8 @@ herr_t H5Pget_split (hid_t tid, size_t meta_ext_size, char *meta_ext/*out*/,
hid_t *meta_properties/*out*/, size_t raw_ext_size,
char *raw_ext/*out*/, hid_t *raw_properties/*out*/);
-herr_t H5Pset_family (hid_t tid, size_t offset_bits, hid_t memb_tid);
-herr_t H5Pget_family (hid_t tid, size_t *offset_bits/*out*/,
+herr_t H5Pset_family (hid_t tid, hsize_t memb_size, hid_t memb_tid);
+herr_t H5Pget_family (hid_t tid, hsize_t *memb_size/*out*/,
hid_t *memb_tid/*out*/);
herr_t H5Pset_buffer (hid_t plist_id, size_t size, void *tconv, void *bkg);
size_t H5Pget_buffer (hid_t plist_id, void **tconv/*out*/, void **bkg/*out*/);
diff --git a/src/Makefile.in b/src/Makefile.in
index cd18e59..0f7db53 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -11,7 +11,7 @@ CPPFLAGS=-I. @CPPFLAGS@
# These are our main targets:
LIB=libhdf5.a
-PROGS=debug h5ls
+PROGS=debug h5ls h5repart
# Source and object files for the library (lexicographically)...
PARALLEL_SRC=H5Fmpio.c
@@ -29,21 +29,21 @@ LIB_OBJ=$(LIB_SRC:.c=.o)
MOSTLYCLEAN=H5detect.o H5detect H5Tinit.o H5Tinit.c
# Source and object files for programs...
-PROG_SRC=debug.c h5ls.c
+PROG_SRC=debug.c h5ls.c h5repart.c
PROG_OBJ=$(PROG_SRC:.c=.o)
# Public header files (to be installed)...
PUB_HDR=H5public.h H5Apublic.h H5ACpublic.h H5Bpublic.h H5Ppublic.h \
H5Dpublic.h H5Epublic.h H5Fpublic.h H5Gpublic.h H5HGpublic.h H5HLpublic.h \
- H5Ipublic.h H5MFpublic.h H5MMpublic.h H5Opublic.h H5Spublic.h \
- H5Tpublic.h H5config.h hdf5.h
+ H5Ipublic.h H5MFpublic.h H5MMpublic.h H5Opublic.h H5Spublic.h H5Tpublic.h \
+ H5config.h hdf5.h
# Other header files (not to be installed)...
PRIVATE_HDR=H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \
H5Pprivate.h H5Dprivate.h H5Dpkg.h H5Eprivate.h H5Fprivate.h H5Gprivate.h \
H5Gpkg.h H5HGprivate.h H5HLprivate.h H5Iprivate.h H5MFprivate.h \
- H5MMprivate.h H5Oprivate.h H5Sprivate.h H5Tprivate.h H5Tpkg.h H5Vprivate.h \
- H5Zprivate.h
+ H5MMprivate.h H5Oprivate.h H5Sprivate.h H5Tprivate.h H5Tpkg.h \
+ H5Vprivate.h H5Zprivate.h
# Number format detection
H5Tinit.c: H5detect
@@ -60,4 +60,7 @@ debug: debug.o $(LIB)
h5ls: h5ls.o $(LIB)
$(CC) $(CFLAGS) -o $@ h5ls.o $(LIB) $(LIBS)
+h5repart: h5repart.o $(LIB)
+ $(CC) $(CFLAGS) -o $@ h5repart.o $(LIB) $(LIBS)
+
@CONCLUDE@
diff --git a/src/h5ls.c b/src/h5ls.c
index ca2c139..f96448c 100644
--- a/src/h5ls.c
+++ b/src/h5ls.c
@@ -5,7 +5,6 @@
* Programmer: Robb Matzke <matzke@llnl.gov>
* Monday, March 23, 1998
*/
-#include <assert.h>
#include <hdf5.h>
#include <stdio.h>
#include <stdlib.h>
@@ -20,6 +19,16 @@
# define __unused__ __attribute__((unused))
#endif
+static void
+usage (const char *progname)
+{
+ fprintf (stderr, "usage: %s FILE [GROUP]\n", progname);
+ fprintf (stderr, " The file name may contain a printf integer format "
+ "to open a file family.\n");
+ exit (1);
+}
+
+
/*-------------------------------------------------------------------------
* Function: list
@@ -111,11 +120,14 @@ int
main (int argc, char *argv[])
{
hid_t file, plist=H5P_DEFAULT;
- herr_t status;
const char *fname = NULL;
const char *gname = "/";
-
- assert (argc>=2 && argc<=3);
+ const char *progname;
+
+ /* Arguments */
+ if ((progname=strrchr (argv[0], '/'))) progname++;
+ else progname = argv[0];
+ if (argc<2 || argc>3) usage (progname);
fname = argv[1];
if (argc>=3) gname = argv[2];
@@ -127,12 +139,8 @@ main (int argc, char *argv[])
plist = H5Pcreate (H5P_FILE_ACCESS);
H5Pset_family (plist, 0, H5P_DEFAULT);
}
- file = H5Fopen (fname, H5F_ACC_RDONLY, plist);
- assert (file>=0);
-
- status = H5Giterate (file, gname, NULL, list, NULL);
- assert (status>=0);
-
- H5Fclose (file);
+ if ((file = H5Fopen (fname, H5F_ACC_RDONLY, plist))<0) exit (1);
+ if (H5Giterate (file, gname, NULL, list, NULL)<0) exit (1);
+ if (H5Fclose (file)<0) exit (1);
return 0;
}
diff --git a/src/h5repart.c b/src/h5repart.c
new file mode 100644
index 0000000..8faa9ea
--- /dev/null
+++ b/src/h5repart.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 1998 NCSA
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Wednesday, May 13, 1998
+ *
+ * Purpose: Repartitions a file family. This program can be used to
+ * split a single file into a family of files, join a family of
+ * files into a single file, or copy one family to another while
+ * changing the size of the family members. It can also be used
+ * to copy a single file to a single file with holes.
+ */
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <hdf5.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define FALSE 0
+#define TRUE 1
+#define NAMELEN 4096
+#define GB *1024*1024*1024
+
+#define MIN(X,Y) ((X)<(Y)?(X):(Y))
+#define MIN3(X,Y,Z) MIN(MIN(X,Y),Z)
+
+
+/*-------------------------------------------------------------------------
+ * Function: usage
+ *
+ * Purpose: Prints a usage message.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, May 13, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+usage (const char *progname)
+{
+ fprintf (stderr, "usage: %s [-[b|m] N[g|m|k]] SRC DST\n", progname);
+ fprintf (stderr, " -b N The I/O block size, defaults to 1kB\n");
+ fprintf (stderr, " -m N The destination member size or 1GB\n");
+ fprintf (stderr, " SRC The name of the source file\n");
+ fprintf (stderr, " DST The name of the destination files\n");
+ fprintf (stderr, "Sizes may be suffixed with `g' for GB, `m' for MB or "
+ "`k' for kB.\n");
+ fprintf (stderr, "File family names include an integer printf "
+ "format such as `%%d'\n");
+ exit (1);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: get_size
+ *
+ * Purpose: Reads a size option of the form `-XNS' where `X' is any
+ * letter, `N' is a multi-character positive decimal number, and
+ * `S' is an optional suffix letter in the set [GgMmk]. The
+ * option may also be split among two arguments as: `-X NS'.
+ * The input value of ARGNO is the argument number for the
+ * switch in the ARGV vector and ARGC is the number of entries
+ * in that vector.
+ *
+ * Return: Success: The value N multiplied according to the
+ * suffix S. On return ARGNO will be the number
+ * of the next argument to process.
+ *
+ * Failure: Calls usage() which exits with a non-zero
+ * status.
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, May 13, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static off_t
+get_size (const char *progname, int *argno, int argc, char *argv[])
+{
+ off_t retval;
+ char *suffix;
+
+ if (isdigit (argv[*argno][2])) {
+ retval = strtol (argv[*argno]+2, &suffix, 10);
+ (*argno)++;
+ } else if (argv[*argno][2] || *argno+1>=argc) {
+ usage (progname);
+ } else {
+ retval = strtol (argv[*argno+1], &suffix, 0);
+ if (suffix==argv[*argno+1]) usage (progname);
+ *argno += 2;
+ }
+ if (suffix && suffix[0] && !suffix[1]) {
+ switch (*suffix) {
+ case 'G':
+ case 'g':
+ retval *= 1024 * 1024 * 1024;
+ break;
+ case 'M':
+ case 'm':
+ retval *= 1024 * 1024;
+ break;
+ case 'k':
+ retval *= 1024;
+ break;
+ default:
+ usage (progname);
+ }
+ } else if (suffix && suffix[0]) {
+ usage (progname);
+ }
+ return retval;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: main
+ *
+ * Purpose: Split an hdf5 file
+ *
+ * Return: Success:
+ *
+ * Failure:
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, May 13, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+main (int argc, char *argv[])
+{
+ const char *prog_name; /*program name */
+ size_t blk_size=1024; /*size of each I/O block */
+ char *buf=NULL; /*I/O block buffer */
+ size_t n, i; /*counters */
+ ssize_t nio; /*I/O return value */
+ int argno=1; /*program argument number */
+ int src, dst=-1; /*source & destination files */
+ int need_seek=FALSE; /*destination needs to seek? */
+ int need_write; /*data needs to be written? */
+ struct stat sb; /*temporary file stat buffer */
+ int verbose=FALSE; /*display file names? */
+ size_t left_overs=0; /*amount of zeros left over */
+
+ const char *src_gen_name; /*general source name */
+ char src_name[NAMELEN]; /*source member name */
+ off_t src_offset=0; /*offset in source member */
+ int src_is_family; /*is source name a family name? */
+ int src_membno=0; /*source member number */
+ off_t src_size; /*source logical member size */
+ off_t src_act_size; /*source actual member size */
+
+ const char *dst_gen_name; /*general destination name */
+ char dst_name[NAMELEN]; /*destination member name */
+ off_t dst_offset=0; /*offset in destination member */
+ int dst_is_family; /*is dst name a family name? */
+ int dst_membno=0; /*destination member number */
+ off_t dst_size=1 GB; /*destination logical memb size */
+
+ /*
+ * Get the program name from argv[0]. Use only the last component.
+ */
+ if ((prog_name=strrchr (argv[0], '/'))) prog_name++;
+ else prog_name = argv[0];
+
+ /*
+ * Parse switches.
+ */
+ while (argno<argc && '-'==argv[argno][0]) {
+ if (!strcmp (argv[argno], "-v")) {
+ verbose = TRUE;
+ argno++;
+ } else if ('b'==argv[argno][1]) {
+ blk_size = get_size (prog_name, &argno, argc, argv);
+ } else if ('m'==argv[argno][1]) {
+ dst_size = get_size (prog_name, &argno, argc, argv);
+ } else {
+ usage (prog_name);
+ }
+ }
+
+ /*
+ * Get the name for the source file and open the first member. The size
+ * of the first member determines the logical size of all the members.
+ */
+ if (argno>=argc) usage (prog_name);
+ src_gen_name = argv[argno++];
+ sprintf (src_name, src_gen_name, src_membno);
+ src_is_family = strcmp (src_name, src_gen_name);
+ if ((src=open (src_name, O_RDONLY))<0) {
+ perror (src_name);
+ exit (1);
+ }
+ if (fstat (src, &sb)<0) {
+ perror ("fstat");
+ exit (1);
+ }
+ src_size = src_act_size = sb.st_size;
+ if (verbose) fprintf (stderr, "< %s\n", src_name);
+
+ /*
+ * Get the name for the destination file and open the first member.
+ */
+ if (argno>=argc) usage (prog_name);
+ dst_gen_name = argv[argno++];
+ sprintf (dst_name, dst_gen_name, dst_membno);
+ dst_is_family = strcmp (dst_name, dst_gen_name);
+ if ((dst=open (dst_name, O_RDWR|O_CREAT|O_TRUNC, 0666))<0) {
+ perror (dst_name);
+ exit (1);
+ }
+ if (verbose) fprintf (stderr, "> %s\n", dst_name);
+
+ /* No more arguments */
+ if (argno<argc) usage (prog_name);
+
+ /* Now the real work, split the file */
+ buf = malloc (blk_size);
+ while (src_offset<src_size) {
+
+ /* Read a block. The amount to read is the minimum of:
+ * 1. The I/O block size
+ * 2. What's left to write in the destination member
+ * 3. Left over zeros or what's left in the source member.
+ */
+ n = blk_size;
+ if (dst_is_family) n = (size_t)MIN((off_t)n, dst_size-dst_offset);
+ if (left_overs) {
+ n = MIN (n, left_overs);
+ left_overs -= n;
+ need_write = FALSE;
+ } else if (src_offset<src_act_size) {
+ n = (size_t)MIN ((off_t)n, src_act_size-src_offset);
+ if ((nio=read (src, buf, n))<0) {
+ perror ("read");
+ exit (1);
+ } else if ((size_t)nio!=n) {
+ fprintf (stderr, "%s: short read\n", src_name);
+ exit (1);
+ }
+ for (i=0; i<n; i++) {
+ if (buf[i]) break;
+ }
+ need_write = (i<n);
+ } else {
+ n = 0;
+ left_overs = src_size - src_act_size;
+ need_write = FALSE;
+ }
+
+ /*
+ * If the block contains non-zero data then write it to the
+ * destination, otherwise just remember that we'll have to do a seek
+ * later in the destination when we finally get non-zero data.
+ */
+ if (need_write) {
+ if (need_seek && lseek (dst, dst_offset, SEEK_SET)<0) {
+ perror ("lseek");
+ exit (1);
+ }
+ if ((nio=write (dst, buf, n))<0) {
+ perror ("write");
+ exit (1);
+ } else if ((size_t)nio!=n) {
+ fprintf (stderr, "%s: short write\n", dst_name);
+ exit (1);
+ }
+ need_seek = FALSE;
+ } else {
+ need_seek = TRUE;
+ }
+
+ /*
+ * Update the source offset and open the next source family member if
+ * necessary. The source stream ends at the first member which
+ * cannot be opened because it doesn't exist. At the end of the
+ * source stream, update the destination offset and break out of the
+ * loop. The destination offset must be updated so we can fix
+ * trailing holes.
+ */
+ src_offset += n;
+ if (src_offset==src_act_size) {
+ close (src);
+ if (!src_is_family) {
+ dst_offset += n;
+ break;
+ }
+ sprintf (src_name, src_gen_name, ++src_membno);
+ if ((src=open (src_name, O_RDONLY))<0 && ENOENT==errno) {
+ dst_offset += n;
+ break;
+ } else if (src<0) {
+ perror (src_name);
+ exit (1);
+ }
+ if (fstat (src, &sb)<0) {
+ perror ("fstat");
+ exit (1);
+ }
+ src_act_size = sb.st_size;
+ if (src_act_size>src_size) {
+ fprintf (stderr, "%s: member truncated to %lu bytes\n",
+ src_name, (unsigned long)src_size);
+ }
+ src_offset = 0;
+ if (verbose) fprintf (stderr, "< %s\n", src_name);
+ }
+
+ /*
+ * Update the destination offset, opening a new member if one will be
+ * needed. The first member is extended to the logical member size
+ * but other members might be smaller if they end with a hole.
+ */
+ dst_offset += n;
+ if (dst_is_family && dst_offset==dst_size) {
+ if (0==dst_membno) {
+ if (lseek (dst, dst_size-1, SEEK_SET)<0) {
+ perror ("lseek");
+ exit (1);
+ }
+ if (read (dst, buf, 1)<0) {
+ perror ("read");
+ exit (1);
+ }
+ if (lseek (dst, dst_size-1, SEEK_SET)<0) {
+ perror ("lseek");
+ exit (1);
+ }
+ if (write (dst, buf, 1)<0) {
+ perror ("write");
+ exit (1);
+ }
+ }
+ close (dst);
+ sprintf (dst_name, dst_gen_name, ++dst_membno);
+ if ((dst=open (dst_name, O_RDWR|O_CREAT|O_TRUNC, 0666))<0) {
+ perror (dst_name);
+ exit (1);
+ }
+ dst_offset = 0;
+ need_seek = FALSE;
+ if (verbose) fprintf (stderr, "> %s\n", dst_name);
+ }
+ }
+
+ /*
+ * Make sure the last family member is the right size and then close it.
+ * The last member can't end with a hole or hdf5 will think that the
+ * family has been truncated.
+ */
+ if (need_seek) {
+ if (lseek (dst, dst_offset-1, SEEK_SET)<0) {
+ perror ("lseek");
+ exit (1);
+ }
+ if (read (dst, buf, 1)<0) {
+ perror ("read");
+ exit (1);
+ }
+ if (lseek (dst, dst_offset-1, SEEK_SET)<0) {
+ perror ("lseek");
+ exit (1);
+ }
+ if (write (dst, buf, 1)<0) {
+ perror ("write");
+ exit (1);
+ }
+ }
+ close (dst);
+
+ /* Free resources and return */
+ free (buf);
+ return 0;
+}
diff --git a/test/big.c b/test/big.c
index b54a50a..226eeb0 100644
--- a/test/big.c
+++ b/test/big.c
@@ -16,6 +16,7 @@
#define FNAME "big%05d.h5"
#define WRT_N 50
#define WRT_SIZE 4*1024
+#define FAMILY_SIZE 1024*1024*1024
static hsize_t
randll (hsize_t limit)
@@ -66,7 +67,7 @@ writer (int wrt_n)
* which is a family of files. Each member of the family will be 1GB
*/
plist = H5Pcreate (H5P_FILE_ACCESS);
- H5Pset_family (plist, 30, H5P_DEFAULT);
+ H5Pset_family (plist, FAMILY_SIZE, H5P_DEFAULT);
file = H5Fcreate (FNAME, H5F_ACC_TRUNC, H5P_DEFAULT, plist);
H5Pclose (plist);
@@ -131,7 +132,7 @@ reader (const char *script_name)
/* Open HDF5 file */
plist = H5Pcreate (H5P_FILE_ACCESS);
- H5Pset_family (plist, 30, H5P_DEFAULT);
+ H5Pset_family (plist, FAMILY_SIZE, H5P_DEFAULT);
file = H5Fopen (FNAME, H5F_ACC_RDONLY, plist);
H5Pclose (plist);
@@ -145,7 +146,7 @@ reader (const char *script_name)
/* Read each region */
while (fgets (ln, sizeof(ln), script)) {
if ('#'!=ln[0]) break;
- i = strtol (ln+1, &s, 10);
+ i = (int)strtol (ln+1, &s, 10);
hs_offset[0] = HDstrtoll (s, NULL, 0);
HDfprintf (stdout, "#%03d 0x%016Hx", i, hs_offset[0]);
fflush (stdout);
@@ -198,7 +199,7 @@ main (int argc, char *argv[])
if (1==argc) {
writer (WRT_N);
} else if (isdigit (argv[1][0])) {
- writer (strtol (argv[1], NULL, 0));
+ writer ((int)strtol(argv[1], NULL, 0));
} else {
reader (argv[1]);
}