summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2002-06-05 18:18:56 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2002-06-05 18:18:56 (GMT)
commitb803308acd00ef670afd1aae57ced7ac19244013 (patch)
tree1d12997fb06c9ecef8e5fc47b88cf672652a34a9
parent6b1208407f5886c917f1ebb38bac058eeb980e30 (diff)
downloadhdf5-b803308acd00ef670afd1aae57ced7ac19244013.zip
hdf5-b803308acd00ef670afd1aae57ced7ac19244013.tar.gz
hdf5-b803308acd00ef670afd1aae57ced7ac19244013.tar.bz2
[svn-r5538] Purpose:
Code improvement. Description: Added boot block and driver info block checksumming feature to the shared file information. This prevents these blocks from being written out multiple times when they haven't changed. This reduces the number of I/O operations which hit the disk for my test program from 15 to 14 (i.e. from 393 to 14, overall). Platforms tested: Solaris 2.7 (arabica) w/FORTRAN and FreeBSD 4.5 (sleipnir) w/C++
-rw-r--r--src/H5F.c140
-rw-r--r--src/H5Fpkg.h2
2 files changed, 101 insertions, 41 deletions
diff --git a/src/H5F.c b/src/H5F.c
index 463f46e..961a8e9 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -1620,6 +1620,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
H5FD_t *lf=NULL; /*file driver part of `shared' */
uint8_t buf[256]; /*temporary I/O buffer */
const uint8_t *p; /*ptr into temp I/O buffer */
+ uint8_t *q; /*ptr into temp I/O buffer */
size_t fixed_size=24; /*fixed sizeof superblock */
size_t variable_size; /*variable sizeof superblock */
size_t driver_size; /*size of driver info block */
@@ -1641,6 +1642,8 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
H5P_genplist_t *c_plist;
H5P_genplist_t *a_plist; /* Property list */
H5F_close_degree_t fc_degree;
+ unsigned chksum; /* Checksum temporary variable */
+ unsigned i; /* Index variable */
FUNC_ENTER_NOAPI(H5F_open, NULL);
@@ -1860,9 +1863,8 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
H5G_SIZEOF_ENTRY(file); /*root group ptr*/
assert(variable_size<=sizeof(buf));
if (H5FD_set_eoa(lf, shared->boot_addr+fixed_size+variable_size)<0 ||
- H5FD_read(lf, H5FD_MEM_SUPER, H5P_DATASET_XFER_DEFAULT, shared->boot_addr+fixed_size, variable_size, buf)<0)
+ H5FD_read(lf, H5FD_MEM_SUPER, H5P_DATASET_XFER_DEFAULT, shared->boot_addr+fixed_size, variable_size, &buf[fixed_size])<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read superblock");
- p = buf;
H5F_addr_decode(file, &p, &(shared->base_addr)/*out*/);
H5F_addr_decode(file, &p, &(shared->freespace_addr)/*out*/);
H5F_addr_decode(file, &p, &stored_eoa/*out*/);
@@ -1870,6 +1872,14 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
if (H5G_ent_decode(file, &p, &root_ent/*out*/)<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root symbol entry");
+ /* Compute boot block checksum */
+ assert(sizeof(chksum)==sizeof(shared->boot_chksum));
+ for(q=(uint8_t *)&chksum, chksum=0, i=0; i<(fixed_size+variable_size); i++)
+ q[i%sizeof(shared->boot_chksum)] ^= buf[i];
+
+ /* Set the boot block checksum */
+ shared->boot_chksum=chksum;
+
/* Decode the optional driver information block */
if (H5F_addr_defined(shared->driver_addr)) {
haddr_t drv_addr = shared->base_addr + shared->driver_addr;
@@ -1894,10 +1904,19 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id)
/* Read driver information and decode */
if (H5FD_set_eoa(lf, drv_addr+16+driver_size)<0 ||
- H5FD_read(lf, H5FD_MEM_SUPER, H5P_DATASET_XFER_DEFAULT, drv_addr+16, driver_size, buf)<0)
+ H5FD_read(lf, H5FD_MEM_SUPER, H5P_DATASET_XFER_DEFAULT, drv_addr+16, driver_size, &buf[16])<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read file driver information");
- if (H5FD_sb_decode(lf, driver_name, buf)<0)
+ if (H5FD_sb_decode(lf, driver_name, &buf[16])<0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to decode driver information");
+
+ /* Compute driver info block checksum */
+ assert(sizeof(chksum)==sizeof(shared->drvr_chksum));
+ for(q=(uint8_t *)&chksum, chksum=0, i=0; i<(driver_size+16); i++)
+ q[i%sizeof(shared->drvr_chksum)] ^= buf[i];
+
+ /* Set the driver info block checksum */
+ shared->drvr_chksum=chksum;
+
} /* end if */
/* Make sure we can open the root group */
@@ -2288,20 +2307,31 @@ H5Fflush(hid_t object_id, H5F_scope_t scope)
* Quincey Koziol, 2002-05-20
* Added 'closing' parameter
*
+ * Quincey Koziol, 2002-06-05
+ * Added boot block & driver info block checksumming, to avoid
+ * writing them out when they haven't changed.
+ *
*-------------------------------------------------------------------------
*/
static herr_t
H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate,
hbool_t alloc_only, hbool_t closing)
{
- uint8_t sbuf[2048], dbuf[2048], *p=NULL;
- unsigned nerrors=0, i;
- size_t superblock_size, driver_size;
- char driver_name[9];
- int boot_vers, freespace_vers,
- obj_dir_vers, share_head_vers,
- btree_k[H5B_NUM_BTREE_ID];
- unsigned sym_leaf_k;
+ uint8_t sbuf[1024]; /* Superblock encoding buffer */
+ uint8_t dbuf[1024]; /* Driver info block encoding buffer */
+ uint8_t *p=NULL; /* Temporary pointer into encoding buffers */
+ unsigned nerrors=0; /* Errors from nested flushes */
+ unsigned i; /* Index variable */
+ unsigned chksum; /* Checksum temporary variable */
+ size_t superblock_size;/* Size of superblock, in bytes */
+ size_t driver_size; /* Size of driver info block, in bytes */
+ char driver_name[9]; /* Name of driver, for driver info block */
+ int boot_vers; /* Boot block version */
+ int freespace_vers; /* Freespace info version */
+ int obj_dir_vers; /* Object header info version */
+ int share_head_vers;/* Shared header info version */
+ int btree_k[H5B_NUM_BTREE_ID]; /* B-tree size info */
+ unsigned sym_leaf_k; /* Number of symbols in B-tree leafs */
H5P_genplist_t *plist; /* Property list */
FUNC_ENTER_NOINIT(H5F_flush);
@@ -2328,24 +2358,27 @@ H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate,
}
}
- /* flush the data sieve buffer, if we have a dirty one */
- if(!alloc_only && f->shared->sieve_buf && f->shared->sieve_dirty) {
- /* Write dirty data sieve buffer to file */
- if (H5F_block_write(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, H5P_DATASET_XFER_DEFAULT, f->shared->sieve_buf)<0)
- HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
-
- /* Reset sieve buffer dirty flag */
- f->shared->sieve_dirty=0;
+ /* Avoid flushing buffers & caches when alloc_only set */
+ if(!alloc_only) {
+ /* flush the data sieve buffer, if we have a dirty one */
+ if(f->shared->sieve_buf && f->shared->sieve_dirty) {
+ /* Write dirty data sieve buffer to file */
+ if (H5F_block_write(f, H5FD_MEM_DRAW, f->shared->sieve_loc, f->shared->sieve_size, H5P_DATASET_XFER_DEFAULT, f->shared->sieve_buf)<0)
+ HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "block write failed");
+
+ /* Reset sieve buffer dirty flag */
+ f->shared->sieve_dirty=0;
+ } /* end if */
+
+ /* flush the entire raw data cache */
+ if (H5F_istore_flush (f, invalidate)<0)
+ HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush raw data cache");
+
+ /* flush (and invalidate) the entire meta data cache */
+ if (H5AC_flush(f, NULL, HADDR_UNDEF, invalidate)<0)
+ HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush meta data cache");
} /* end if */
- /* flush the entire raw data cache */
- if (!alloc_only && H5F_istore_flush (f, invalidate)<0)
- HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush raw data cache");
-
- /* flush (and invalidate) the entire meta data cache */
- if (!alloc_only && H5AC_flush(f, NULL, HADDR_UNDEF, invalidate)<0)
- HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush meta data cache");
-
/* Get the shared file creation property list */
if(NULL == (plist = H5I_object(f->shared->fcpl_id)))
HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
@@ -2387,6 +2420,9 @@ H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate,
H5G_ent_encode(f, &p, H5G_entof(f->shared->root_grp));
superblock_size = p-sbuf;
+ /* Double check we didn't overrun the block (unlikely) */
+ assert(superblock_size<=sizeof(sbuf));
+
/*
* Encode the driver information block.
*/
@@ -2411,6 +2447,9 @@ H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate,
/* Driver name */
HDmemcpy(dbuf+8, driver_name, 8);
+
+ /* Double check we didn't overrun the block (unlikely) */
+ assert(driver_size<=sizeof(dbuf));
} /* end if */
if (alloc_only) {
@@ -2438,15 +2477,37 @@ H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate,
f->shared->driver_addr = superblock_size;
} else {
- /* Write superblock */
- if (H5FD_write(f->shared->lf, H5FD_MEM_SUPER, H5P_DATASET_XFER_DEFAULT, f->shared->boot_addr, superblock_size, sbuf)<0)
- HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write superblock");
-
- /* Write driver information block */
+ /* Compute boot block checksum */
+ assert(sizeof(chksum)==sizeof(f->shared->boot_chksum));
+ for(p=(uint8_t *)&chksum, chksum=0, i=0; i<superblock_size; i++)
+ p[i%sizeof(f->shared->boot_chksum)] ^= sbuf[i];
+
+ /* Compare with current checksums */
+ if(chksum!=f->shared->boot_chksum) {
+ /* Write superblock */
+ if (H5FD_write(f->shared->lf, H5FD_MEM_SUPER, H5P_DATASET_XFER_DEFAULT, f->shared->boot_addr, superblock_size, sbuf)<0)
+ HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write superblock");
+
+ /* Update checksum information if different */
+ f->shared->boot_chksum=chksum;
+ } /* end if */
+
+ /* Check for driver info block */
if (HADDR_UNDEF!=f->shared->driver_addr) {
- if (H5FD_write(f->shared->lf, H5FD_MEM_SUPER, H5P_DATASET_XFER_DEFAULT,
- f->shared->base_addr+superblock_size, driver_size, dbuf)<0)
- HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write driver information block");
+ /* Compute driver info block checksum */
+ assert(sizeof(chksum)==sizeof(f->shared->drvr_chksum));
+ for(p=(uint8_t *)&chksum, chksum=0, i=0; i<driver_size; i++)
+ p[i%sizeof(f->shared->drvr_chksum)] ^= dbuf[i];
+
+ /* Compare with current checksums */
+ if(chksum!=f->shared->boot_chksum) {
+ /* Write driver information block */
+ if (H5FD_write(f->shared->lf, H5FD_MEM_SUPER, H5P_DATASET_XFER_DEFAULT, f->shared->base_addr+superblock_size, driver_size, dbuf)<0)
+ HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "unable to write driver information block");
+
+ /* Update checksum information if different */
+ f->shared->drvr_chksum=chksum;
+ } /* end if */
} /* end if */
} /* end else */
@@ -2455,11 +2516,8 @@ H5F_flush(H5F_t *f, H5F_scope_t scope, hbool_t invalidate,
HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed");
/* Check flush errors for children - errors are already on the stack */
- if (nerrors)
- HRETURN(FAIL);
-
- FUNC_LEAVE(SUCCEED);
-}
+ FUNC_LEAVE(nerrors ? FAIL : SUCCEED);
+} /* end H5F_flush() */
/*-------------------------------------------------------------------------
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 30439b4..6f034b6 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -98,6 +98,8 @@ typedef struct H5F_file_t {
haddr_t base_addr; /* Absolute base address for rel.addrs. */
haddr_t freespace_addr; /* Relative address of free-space info */
haddr_t driver_addr; /* File driver information block address*/
+ unsigned boot_chksum; /* Boot block checksum */
+ unsigned drvr_chksum; /* Driver info block checksum */
struct H5AC_t *cache; /* The object cache */
hid_t fcpl_id; /* File creation property list ID */
int mdc_nelmts; /* Size of meta data cache (elements) */