summaryrefslogtreecommitdiffstats
path: root/src/H5Fsuper_cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Fsuper_cache.c')
-rw-r--r--src/H5Fsuper_cache.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/src/H5Fsuper_cache.c b/src/H5Fsuper_cache.c
index 361f8a1..65cef15 100644
--- a/src/H5Fsuper_cache.c
+++ b/src/H5Fsuper_cache.c
@@ -84,6 +84,8 @@ static herr_t H5F__cache_drvrinfo_image_len(const void *thing, size_t *image_len
static herr_t H5F__cache_drvrinfo_serialize(const H5F_t *f, void *image, size_t len,
void *thing);
static herr_t H5F__cache_drvrinfo_free_icr(void *thing);
+static herr_t H5F__cache_superblock_refresh(H5F_t *f, void * _thing, const void * _image,
+ size_t * len_ptr);
/* Local encode/decode routines */
static herr_t H5F__superblock_prefix_decode(H5F_super_t *sblock,
@@ -114,6 +116,7 @@ const H5AC_class_t H5AC_SUPERBLOCK[1] = {{
NULL, /* 'notify' callback */
H5F__cache_superblock_free_icr, /* 'free_icr' callback */
NULL, /* 'fsf_size' callback */
+ H5F__cache_superblock_refresh, /* VFD SWMR 'refresh' callback */
}};
/* H5F driver info block inherits cache-like properties from H5AC */
@@ -132,6 +135,7 @@ const H5AC_class_t H5AC_DRVRINFO[1] = {{
NULL, /* 'notify' callback */
H5F__cache_drvrinfo_free_icr, /* 'free_icr' callback */
NULL, /* 'fsf_size' callback */
+ NULL, /* VFD SWMR 'refresh' callback */
}};
@@ -1087,3 +1091,257 @@ H5F__cache_drvrinfo_free_icr(void *_thing)
FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5F__cache_drvrinfo_free_icr() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F__cache_superblock_refresh
+ *
+ * Purpose: Examine the supplied image buffer, and update the
+ * superblock accordingly.
+ *
+ * This function is only called when the file is opened in
+ * VFD SWMR reader mode -- which implies that the file has
+ * been opened R/O. Thus the internal representation of
+ * the superblock must be clean, and may be modified without
+ * concern for local changes.
+ *
+ * Further, most of the superblock is fixed once the file
+ * is created, for the most part, this function simply
+ * verifies the expected values.
+ *
+ * Return: Success: Pointer to new object
+ * Failure: NULL
+ *
+ * Programmer: John Mainzer
+ * 12/21/19
+ *
+ * Changes: None.
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5F__cache_superblock_refresh(H5F_t *f, void * _thing, const void * _image,
+ size_t * len_ptr)
+{
+ H5F_super_t *sblock = (H5F_super_t *)_thing;
+ const uint8_t *image = (const uint8_t *)_image;
+ size_t expected_image_len;
+ unsigned super_vers; /* Superblock version */
+ uint8_t sizeof_addr; /* Size of addresses in file */
+ uint8_t sizeof_size; /* Size of offsets in file */
+ uint32_t status_flags; /* File status flags */
+ unsigned sym_leaf_k; /* Size of leaves in symbol tables */
+ haddr_t base_addr; /* Absolute base address for rel.addrs. */
+ /* (superblock for file is at this offset) */
+ haddr_t stored_eof;
+ haddr_t ext_addr; /* Relative address of superblock extension */
+ haddr_t driver_addr; /* File driver information block address */
+ haddr_t root_addr; /* Root group address */
+ H5G_entry_t root_ent; /* Root group symbol table entry */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_STATIC
+
+ /* santity checks */
+ HDassert(f);
+ HDassert(sblock);
+ HDassert(sblock == f->shared->sblock);
+ HDassert(image);
+ HDassert(len_ptr);
+ HDassert(*len_ptr >= H5F_SUPERBLOCK_FIXED_SIZE + 6);
+
+ /* skip the signature */
+ image += H5F_SIGNATURE_LEN;
+
+ /* get the superblock version */
+ super_vers = *image++;
+
+ if ( sblock->super_vers != super_vers )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected superblock vers")
+
+ /* verify sizes of addresses and offsets */
+ if(super_vers < HDF5_SUPERBLOCK_VERSION_2) {
+ sizeof_addr = image[4];
+ sizeof_size = image[5];
+ } /* end if */
+ else {
+ sizeof_addr = image[0];
+ sizeof_size = image[1];
+ } /* end else */
+
+ if ( sblock->sizeof_addr != sizeof_addr )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected sizeof_addr")
+
+ if ( sblock->sizeof_size != sizeof_size )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected sizeof_size")
+
+ /* compute expected image len */
+ expected_image_len = H5F_SUPERBLOCK_FIXED_SIZE +
+ (size_t)H5F_SUPERBLOCK_VARLEN_SIZE(super_vers, sizeof_addr, sizeof_size);
+
+ if ( expected_image_len != *len_ptr ) {
+
+ *len_ptr = expected_image_len;
+ HGOTO_DONE(SUCCEED)
+ }
+
+ /* at this point, we know that the supplied image is of
+ * the correct length.
+ */
+
+ /* validate the older version of the superblock */
+ if(sblock->super_vers < HDF5_SUPERBLOCK_VERSION_2) {
+
+ unsigned snode_btree_k; /* B-tree symbol table internal node 'K' value */
+ unsigned chunk_btree_k; /* B-tree chunk internal node 'K' value */
+
+ /* Freespace version (hard-wired) */
+ if(HDF5_FREESPACE_VERSION != *image++)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad free space version number")
+
+ /* Root group version number (hard-wired) */
+ if(HDF5_OBJECTDIR_VERSION != *image++)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad object directory version number")
+
+ /* Skip over reserved byte */
+ image++;
+
+ /* Shared header version number (hard-wired) */
+ if(HDF5_SHAREDHEADER_VERSION != *image++)
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "bad shared-header format version number")
+
+ /* Skip over size of file addresses (already decoded and checked) */
+ image++;
+
+ /* Skip over size of file sizes (already decoded and checked) */
+ image++;
+
+ /* Skip over reserved byte */
+ image++;
+
+ /* Various B-tree sizes */
+ UINT16DECODE(image, sym_leaf_k);
+ if ( sym_leaf_k != sblock->sym_leaf_k )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected sym_leaf_k")
+
+ /* Need 'get' call to set other array values */
+ UINT16DECODE(image, snode_btree_k);
+ if ( snode_btree_k != sblock->btree_k[H5B_SNODE_ID] )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected snode_btree_k")
+
+ /* File status flags (not really used yet) */
+ UINT32DECODE(image, status_flags);
+ if ( status_flags != sblock->status_flags )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected status_flags")
+
+ /*
+ * If the superblock version # is greater than 0, read in the indexed
+ * storage B-tree internal 'K' value
+ */
+ if(sblock->super_vers > HDF5_SUPERBLOCK_VERSION_DEF) {
+ UINT16DECODE(image, chunk_btree_k);
+
+ if ( chunk_btree_k != sblock->btree_k[H5B_CHUNK_ID] )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected chunk_btree_k")
+
+ /* Reserved bytes are present only in version 1 */
+ if(sblock->super_vers == HDF5_SUPERBLOCK_VERSION_1)
+ image += 2; /* reserved */
+ } /* end if */
+
+ /* Remainder of "variable-sized" portion of superblock */
+ H5F_addr_decode(f, (const uint8_t **)&image, &base_addr/*out*/);
+ H5F_addr_decode(f, (const uint8_t **)&image, &ext_addr/*out*/);
+ H5F_addr_decode(f, (const uint8_t **)&image, &stored_eof/*out*/);
+ H5F_addr_decode(f, (const uint8_t **)&image, &driver_addr/*out*/);
+
+ if ( base_addr != sblock->base_addr )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected base_addr")
+
+ if ( ext_addr != sblock->ext_addr )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected ext_addr")
+
+ /* use stored_eof to update EOA below */
+
+ if ( driver_addr != sblock->driver_addr )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected driver_addr")
+
+ /* decode the root group symbol table entry */
+ if(H5G_ent_decode(f, (const uint8_t **)&image, &root_ent) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTDECODE, FAIL, "can't decode root group symbol table entry")
+
+ /* Set the root group address to the correct value */
+ root_addr = root_ent.header;
+
+ if ( root_addr != sblock->root_addr )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected root_addr")
+
+ HDassert(root_ent.type == H5G_CACHED_STAB);
+
+ if ( ( root_ent.type != sblock->root_ent->type ) ||
+ ( root_ent.cache.stab.btree_addr !=
+ sblock->root_ent->cache.stab.btree_addr ) ||
+ ( root_ent.cache.stab.heap_addr !=
+ sblock->root_ent->cache.stab.heap_addr ) )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected root_ent data")
+
+
+ /* NOTE: Driver info block is decoded separately, later */
+
+ } /* end if */
+ else {
+ uint32_t read_chksum;
+ uint32_t computed_chksum;
+
+ /* Skip over size of file addresses (already decoded and checked) */
+ image++;
+
+ /* Skip over size of file sizes (already decoded and checked) */
+ image++;
+
+ /* File status flags (not really used yet) */
+ status_flags = *image++;
+ if ( status_flags != sblock->status_flags )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected status_flags")
+
+ /* Base, superblock extension, end of file & root group object header addresses */
+ H5F_addr_decode(f, (const uint8_t **)&image, &base_addr/*out*/);
+ H5F_addr_decode(f, (const uint8_t **)&image, &ext_addr/*out*/);
+ H5F_addr_decode(f, (const uint8_t **)&image, &stored_eof/*out*/);
+ H5F_addr_decode(f, (const uint8_t **)&image, &driver_addr/*out*/);
+
+ if ( base_addr != sblock->base_addr )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected base_addr")
+
+ if ( ext_addr != sblock->ext_addr )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected ext_addr")
+
+ /* use stored_eof to update EOA below */
+
+ if ( driver_addr != sblock->driver_addr )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected driver_addr")
+
+ /* Decode checksum */
+ UINT32DECODE(image, read_chksum);
+
+ if ( H5F_get_checksums((const uint8_t *)_image,
+ (size_t)(image - (const uint8_t *)_image),
+ NULL, &computed_chksum) < 0 )
+ HGOTO_ERROR(H5E_FILE, H5E_SYSTEM, FAIL, "can't compute chksum")
+
+ if ( read_chksum != computed_chksum )
+ HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL, "unexpected checksum")
+
+ } /* end else */
+
+ /* Sanity check */
+ HDassert((size_t)(image - (const uint8_t *)_image) <= *len_ptr);
+
+ /* update the EOA */
+ if(H5F__set_eoa(f, H5FD_MEM_DEFAULT, stored_eof - base_addr) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "unable to update EOA")
+
+done:
+
+ FUNC_LEAVE_NOAPI(ret_value)
+
+} /* end H5F__cache_superblock_refresh() */