From 34f5a59b9eb995997536575eeb796f745a2be784 Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Wed, 13 May 1998 12:58:24 -0500 Subject: [svn-r398] Changes since 19980501 ---------------------- ./src/H5Bprivate.h ./src/H5F.c ./src/H5Ffamily.c ./src/H5Fprivate.h ./src/H5Gpkg.h ./src/H5MF.c ./src/H5P.c ./src/H5Ppublic.h ./test/big.c ./html/Big.html ./html/Files.html Family members can now be any size >1kB. Got rid of some places where we were reading a property list after it was closed. ./MANIFEST ./src/Makefile.in ./src/h5repart.c A program to repartition file families. The source and/or destination may be files or file families. Examples: testhdf5 -c -o stab h5repart -m 1m tstab2.h5 x%05d.h5 h5repart -m 100k x%05d.h5 y%05d.h5 h5repart y%05d.h5 z.h5 diff tstab2.h5 z.h5 ./src/h5ls.c Added a usage message, replaced assertions with error messages. ./config/linux Made a warning message more obvious. Added better optimization flags for Pentium-Pro's. --- MANIFEST | 1 + config/linux | 9 +- src/H5.c | 2 +- src/H5Bprivate.h | 2 +- src/H5F.c | 64 ++++----- src/H5Ffamily.c | 167 ++++++++++++------------ src/H5Fprivate.h | 12 +- src/H5Gpkg.h | 2 +- src/H5MF.c | 2 +- src/H5P.c | 48 +++++-- src/H5Ppublic.h | 4 +- src/Makefile.in | 15 ++- src/h5ls.c | 30 +++-- src/h5repart.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/big.c | 9 +- 15 files changed, 601 insertions(+), 154 deletions(-) create mode 100644 src/h5repart.c 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; membnou.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 * Monday, March 23, 1998 */ -#include #include #include #include @@ -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 + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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) 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 (argnosrc_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]); } -- cgit v0.12