From 6a3cb617d3aa57f439065118fbc68afcb1465a54 Mon Sep 17 00:00:00 2001 From: Robb Matzke Date: Mon, 4 Aug 1997 11:19:57 -0500 Subject: [svn-r12] ./src/H5AC.c Fails sooner if the type of object requested doesn't match the type of object cached. ./src/H5B.c ./src/H5Bprivate.h ./src/H5Fprivate.h ./src/H5G.c ./src/H5Gnode.c ./src/H5Gprivate.h ./src/H5H.c ./src/H5Hprivate.h Changed lots of `H5*_HDR_SIZE' macros to `H5*_SIZEOF_HDR' to make things more consistent. Added H5*_SIZEOF_MAGIC macros. Added debugging functions to some of the packages. ./src/H5F.c Fixed a bug with reading past the end of a buffer. ./src/H5Tproto.h Added prototypes for H5Tadd_field() and H5Tget_fields(). ./src/debug.c Low-level file debugging program. ./src/Makefile Builds `debug' as one of the main targets. The target is called `debug_hdf5' so it doesn't conflict with the `debug' target that was already there. But the executable is called `debug'. --- src/H5AC.c | 15 +++++ src/H5B.c | 78 ++++++++++++++++++++----- src/H5Bprivate.h | 18 ++++-- src/H5F.c | 98 +++++++++++++++++++++++++++++++- src/H5Fprivate.h | 2 + src/H5G.c | 4 +- src/H5Gnode.c | 106 ++++++++++++++++++++++++++++++++-- src/H5Gprivate.h | 11 +++- src/H5H.c | 170 +++++++++++++++++++++++++++++++++++++++++++++++-------- src/H5Hprivate.h | 5 ++ src/H5Tproto.h | 3 + src/Makefile | 8 ++- src/debug.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 609 insertions(+), 51 deletions(-) create mode 100644 src/debug.c diff --git a/src/H5AC.c b/src/H5AC.c index cca36bc..140a52d 100644 --- a/src/H5AC.c +++ b/src/H5AC.c @@ -96,6 +96,12 @@ H5AC_dest (hdf5_file_t *f) * * Modifications: * + * Robb Matzke, 4 Aug 1997 + * Fails immediately if the cached object is at the correct address + * but is of the wrong type. This happens if the caller doesn't know + * what type of object is at the address and calls this function with + * various type identifiers until one succeeds (cf., the debugger). + * *------------------------------------------------------------------------- */ void * @@ -119,6 +125,15 @@ H5AC_find (hdf5_file_t *f, const H5AC_class_t *type, haddr_t addr, } /* + * Fail if the item in the cache is at the correct address but is + * of the wrong type. + */ + if (f->cache[idx].type && f->cache[idx].addr==addr && + f->cache[idx].type!=type) { + return NULL; + } + + /* * Load a new thing. If it can't be loaded, then return an error * without preempting anything. */ diff --git a/src/H5B.c b/src/H5B.c index fadc6f5..89316b2 100644 --- a/src/H5B.c +++ b/src/H5B.c @@ -181,7 +181,7 @@ H5B_new (hdf5_file_t *f, const H5B_class_t *type, size_t sizeof_rkey) * `page' buffer. Each native key pointer should be null until the key is * translated to native format. */ - for (i=0,offset=H5B_HDR_SIZE(f); + for (i=0,offset=H5B_SIZEOF_HDR(f); i<2*type->k; i++,offset+=bt->sizeof_rkey+H5F_SIZEOF_OFFSET(f)) { @@ -249,7 +249,7 @@ H5B_load (hdf5_file_t *f, haddr_t addr, const void *_data) p = bt->page; /* magic number */ - if (memcmp (p, H5B_MAGIC, 4)) goto error; + if (memcmp (p, H5B_MAGIC, H5B_SIZEOF_MAGIC)) goto error; p += 4; /* node type and level */ @@ -326,7 +326,7 @@ H5B_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5B_t *bt) if (bt->dirty) { /* magic number */ - memcpy (p, H5B_MAGIC, 4); + memcpy (p, H5B_MAGIC, H5B_SIZEOF_MAGIC); p += 4; /* node type and level */ @@ -513,14 +513,14 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor) /* * Copy data into the new node from the old node. */ - memcpy (bt->page + H5B_HDR_SIZE(f), - old->page + H5B_HDR_SIZE(f) + delta*recsize, + memcpy (bt->page + H5B_SIZEOF_HDR(f), + old->page + H5B_SIZEOF_HDR(f) + delta*recsize, type->k * recsize); memcpy (bt->native, old->native + delta * type->sizeof_nkey, (type->k+1) * type->sizeof_nkey); - for (i=0,offset=H5B_HDR_SIZE(f); i<=2*type->k; i++,offset+=recsize) { + for (i=0,offset=H5B_SIZEOF_HDR(f); i<=2*type->k; i++,offset+=recsize) { /* key */ if (i<=type->k) { @@ -555,8 +555,8 @@ H5B_split (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, intn anchor) old->nchildren = type->k; if (H5B_ANCHOR_RT==anchor) { - memcpy (old->page + H5B_HDR_SIZE(f), - old->page + H5B_HDR_SIZE(f) + delta*recsize, + memcpy (old->page + H5B_SIZEOF_HDR(f), + old->page + H5B_SIZEOF_HDR(f) + delta*recsize, type->k * recsize); memmove (old->native, old->native + delta * type->sizeof_nkey, @@ -803,8 +803,8 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, /* * The MD_KEY is the left key of the new node. */ - memmove (bt->page + H5B_HDR_SIZE(f) + (idx+1)*recsize, - bt->page + H5B_HDR_SIZE(f) + idx*recsize, + memmove (bt->page + H5B_SIZEOF_HDR(f) + (idx+1)*recsize, + bt->page + H5B_SIZEOF_HDR(f) + idx*recsize, (bt->nchildren-idx)*recsize + bt->sizeof_rkey); memmove (bt->native + (idx+1) * type->sizeof_nkey, @@ -822,9 +822,9 @@ H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, /* * The MD_KEY is the right key of the new node. */ - memmove (bt->page + (H5B_HDR_SIZE(f) + + memmove (bt->page + (H5B_SIZEOF_HDR(f) + (idx+1)*recsize + bt->sizeof_rkey), - bt->page + (H5B_HDR_SIZE(f) + + bt->page + (H5B_SIZEOF_HDR(f) + idx*recsize + bt->sizeof_rkey), (bt->nchildren-idx) * recsize); @@ -1170,8 +1170,60 @@ H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type, *total_nkey_size = (2 * type->k + 1) * type->sizeof_nkey; } - return (H5B_HDR_SIZE(f) + /*node header */ + return (H5B_SIZEOF_HDR(f) + /*node header */ 2 * type->k * H5F_SIZEOF_OFFSET(f) + /*child pointers*/ (2*type->k+1) * sizeof_rkey); /*keys */ } + +/*------------------------------------------------------------------------- + * Function: H5B_debug + * + * Purpose: Prints debugging info about a B-tree. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Aug 4 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, + intn fwidth, const H5B_class_t *type) +{ + H5B_t *bt = H5AC_find (f, H5AC_BT, addr, type); + + if (!bt) return -1; + + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Tree type ID:", + (int)(bt->type->id)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Size of raw (disk) key:", + (unsigned long)(bt->sizeof_rkey)); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Dirty flag:", + (int)(bt->dirty)); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Number of initial dirty children:", + (int)(bt->ndirty)); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Level:", + (int)(bt->level)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Address of left sibling:", + (unsigned long)(bt->left)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Address of right sibling:", + (unsigned long)(bt->right)); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Number of children:", + (int)(bt->nchildren)); + return 0; +} diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index 3a029e4..bb9d95c 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -21,11 +21,20 @@ #include "H5Fprivate.h" -#define H5B_MAGIC "TREE" /* tree node magic number */ -#define H5B_HDR_SIZE(F) (8+2*H5F_SIZEOF_OFFSET(F)) +#define H5B_MAGIC "TREE" /*tree node magic number */ +#define H5B_SIZEOF_MAGIC 4 /*size of magic number */ + +#define H5B_SIZEOF_HDR(F) \ + (H5B_SIZEOF_MAGIC + /*magic number */ \ + 4 + /*type, level, num entries */ \ + 2*H5F_SIZEOF_OFFSET(F)) /*left and right sibling addresses */ #define H5B_ANCHOR_LT 0 /* left node is anchored, right is new */ #define H5B_ANCHOR_RT 1 /* right node is anchored, left is new */ + +typedef enum H5B_subid_t { + H5B_SUBTYPE_SNODE =0 /*B-tree is for symbol table nodes */ +} H5B_subid_t; /* @@ -33,7 +42,7 @@ * variable of this type that contains class variables and methods. */ typedef struct H5B_class_t { - intn id; /*id as found in file */ + H5B_subid_t id; /*id as found in file */ intn k; /* max children is 2k */ size_t sizeof_nkey; /*size of native (memory) key */ size_t (*get_sizeof_rkey)(hdf5_file_t*); @@ -75,7 +84,8 @@ typedef struct H5B_t { /* * Library prototypes. */ -herr_t H5B_debug (hdf5_file_t *f, haddr_t addr, const H5B_class_t *type); +herr_t H5B_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, + intn fwidth, const H5B_class_t *type); haddr_t H5B_new (hdf5_file_t *f, const H5B_class_t *type, size_t sizeof_rkey); herr_t H5B_find (hdf5_file_t *f, const H5B_class_t *type, haddr_t addr, void *udata); diff --git a/src/H5F.c b/src/H5F.c index 7a43ca9..8e37967 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -584,6 +584,7 @@ hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_temp) haddr_t curr_off=0; /* The current offset to check in the file */ size_t file_len=0; /* The length of the file we are checking */ hatom_t ret_value = FAIL; + size_t variable_size; /*size of the variable part of the bb */ FUNC_ENTER(H5F_mask, ID_H5Fopen, H5F_init_interface, FAIL); @@ -670,9 +671,9 @@ hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_temp) /* Read in the fixed-size part of the boot-block */ if(H5F_READ(new_file->file_handle,temp_buf,16)==FAIL) - HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL); + HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL); - /* Decode the boot block */ + /* Decode fixed-size part of the boot block */ p=temp_buf; new_file->file_create_parms.bootblock_ver=*p++; /* Decode Boot-block version # */ new_file->file_create_parms.smallobject_ver=*p++; /* Decode Small-Object Heap version # */ @@ -684,6 +685,17 @@ hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_temp) p++; /* Decode the reserved byte :-) */ UINT32DECODE(p,new_file->file_create_parms.btree_page_size); /* Decode the B-Tree page size */ UINT32DECODE(p,new_file->consist_flags); /* Decode File-Consistancy flags */ + + /* Read the variable-size part of the boot-block */ + variable_size = H5F_SIZEOF_OFFSET(new_file) + /*offset of global small-object heap*/ + H5F_SIZEOF_OFFSET(new_file) + /*offset of global free list*/ + H5F_SIZEOF_SIZE(new_file) + /*logical size of HDF5 file*/ + H5G_SIZEOF_ENTRY(new_file); /*root symbol table entry*/ + if (H5F_READ(new_file->file_handle, temp_buf, variable_size)<0) + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL); + + /* Decode the variable-size part of the boot block */ + p = temp_buf; H5F_decode_offset(new_file,p,new_file->smallobj_off); /* Decode offset of global small-object heap */ H5F_decode_offset(new_file,p,new_file->freespace_off); /* Decode offset of global free-space heap */ H5F_decode_length(new_file,p,new_file->logical_len); /* Decode logical length of file */ @@ -846,3 +858,85 @@ H5F_block_write (hdf5_file_t *f, haddr_t addr, size_t size, void *buf) PABLO_TRACE_OFF(H5F_mask, ID_H5F_block_write); return SUCCEED; } + + +/*------------------------------------------------------------------------- + * Function: H5F_debug + * + * Purpose: Prints a file header to the specified stream. Each line + * is indented and the field name occupies the specified width + * number of characters. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Aug 1 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, + intn fwidth) +{ + fprintf (stream, "%*sFile Boot Block...\n", indent, ""); + + fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, + "Directory:", + f->dir); + fprintf (stream, "%*s%-*s %s\n", indent, "", fwidth, + "File name:", + f->filename); + fprintf (stream, "%*s%-*s 0x%08x\n", indent, "", fwidth, + "Permissions", + (unsigned)(f->acc_perm)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Reference count:", + (unsigned)(f->ref_count)); + fprintf (stream, "%*s%-*s 0x%08lx\n", indent, "", fwidth, + "Consistency flags:", + (unsigned long)(f->consist_flags)); + fprintf (stream, "%*s%-*s %ld\n", indent, "", fwidth, + "Small object heap address:", + (long)(f->smallobj_off)); + fprintf (stream, "%*s%-*s %ld\n", indent, "", fwidth, + "Free list address:", + (long)(f->freespace_off)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Logical file length:", + (unsigned long)(f->logical_len)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Size of user block:", + (unsigned long)(f->file_create_parms.userblock_size)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Size of file size_t type:", + (unsigned)(f->file_create_parms.offset_size)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Size of file off_t type:", + (unsigned)(f->file_create_parms.length_size)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Bytes per B-tree page:", + (unsigned)(f->file_create_parms.btree_page_size)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Boot block version number:", + (unsigned)(f->file_create_parms.bootblock_ver)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Small object heap version number:", + (unsigned)(f->file_create_parms.smallobject_ver)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Free list version number:", + (unsigned)(f->file_create_parms.freespace_ver)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Object directory version number:", + (unsigned)(f->file_create_parms.objectdir_ver)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Shared header version number:", + (unsigned)(f->file_create_parms.sharedheader_ver)); + + + return 0; +} diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 2856b6a..fde8fb3 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -92,6 +92,8 @@ void H5F_encode_offset_unusual(const hdf5_file_t *f, uint8 **p, uint8 *o); intn H5F_compare_filename(const VOIDP obj, const VOIDP key); herr_t H5F_block_read (hdf5_file_t *f, haddr_t addr, size_t size, void *buf); herr_t H5F_block_write (hdf5_file_t *f, haddr_t addr, size_t size, void *buf); +herr_t H5F_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, + intn fwidth); #endif /* HDF5FILE_H */ diff --git a/src/H5G.c b/src/H5G.c index 3c1f21a..fa7da12 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -347,7 +347,7 @@ H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) abort(); } - *pp = p_ret + 2*H5F_SIZEOF_OFFSET(f) + 4 + 24; + *pp = p_ret + H5G_SIZEOF_ENTRY(f); return 0; } @@ -433,7 +433,7 @@ H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) abort(); } - *pp = p_ret + 2*H5F_SIZEOF_OFFSET(f) + 4 + 24; + *pp = p_ret + H5G_SIZEOF_ENTRY(f); return 0; } diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 52638eb..3ce046e 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -60,7 +60,7 @@ static const H5AC_class_t H5AC_SNODE[1] = {{ /* H5G inherits B-tree like properties from H5B */ const H5B_class_t H5B_SNODE[1] = {{ - 0, /*id */ + H5B_SUBTYPE_SNODE, /*id */ 64, /*k */ sizeof (H5G_node_key_t), /*sizeof_nkey */ H5G_node_sizeof_rkey, /*get_sizeof_rkey */ @@ -167,7 +167,8 @@ H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key) static size_t H5G_node_size (hdf5_file_t *f) { - return H5G_HDR_SIZE(f) + (2*H5G_NODE_K) * (2*H5F_SIZEOF_OFFSET(f)); + return H5G_NODE_SIZEOF_HDR(f) + + (2*H5G_NODE_K) * H5G_SIZEOF_ENTRY(f); } @@ -244,7 +245,7 @@ H5G_node_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5G_node_t *sym) buf = p = H5MM_xmalloc (size); /* magic number */ - HDmemcpy (p, H5G_NODE_MAGIC, 4); + HDmemcpy (p, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC); p += 4; /* version number */ @@ -303,7 +304,7 @@ H5G_node_load (hdf5_file_t *f, haddr_t addr, const void *_udata) H5F_block_read (f, addr, size, buf); /* magic */ - if (HDmemcmp (p, H5G_NODE_MAGIC, 4)) goto error; + if (HDmemcmp (p, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) goto error; p += 4; /* version */ @@ -693,3 +694,100 @@ H5G_node_list (hdf5_file_t *f, haddr_t addr, void *_udata) return 0; } + +/*------------------------------------------------------------------------- + * Function: H5G_node_debug + * + * Purpose: Prints debugging information about a symbol table node + * or a B-tree node for a symbol table B-tree. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Aug 4 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, + intn fwidth) +{ + int i, j; + char buf[64]; + H5G_node_t *sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + + /* + * If we couldn't load the symbol table node, then try loading the + * B-tree node. + */ + if (!sn) { + return H5B_debug (f, addr, stream, indent, fwidth, H5B_SNODE); + } + + + if (!sn) return -1; + fprintf (stream, "%*sSymbol Table Node...\n", indent, ""); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Dirty:", + sn->dirty); + fprintf (stream, "%*s%-*s %d of %d\n", indent, "", fwidth, + "Number of Symbols:", + sn->nsyms, 2*H5G_NODE_K); + + indent += 3; + fwidth = MAX (0, fwidth-3); + for (i=0; insyms; i++) { + fprintf (stream, "%*sSymbol %d:\n", indent-3, "", i); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Name offset into private heap:", + (unsigned long)(sn->entry[i].name_off)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Object header address:", + (unsigned long)(sn->entry[i].header)); + + fprintf (stream, "%*s%-*s ", indent, "", fwidth, + "Symbol type:"); + switch (sn->entry[i].type) { + case H5G_NOTHING_CACHED: + fprintf (stream, "Nothing Cached\n"); + break; + + case H5G_CACHED_SDATA: + fprintf (stream, "S-data\n"); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Number type:", + (unsigned)(sn->entry[i].cache.sdata.nt)); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + "Dimensionality:", + (unsigned)(sn->entry[i].cache.sdata.ndim)); + for (j=0; jentry[i].cache.sdata.ndim && j<4; j++) { + sprintf (buf, "Dimension %d", j); + fprintf (stream, "%*s%-*s %u\n", indent, "", fwidth, + buf, + (unsigned)(sn->entry[i].cache.sdata.dim[j])); + } + break; + + case H5G_CACHED_SYMTAB: + fprintf (stream, "Symbol Table\n"); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "B-tree address:", + (unsigned long)(sn->entry[i].cache.symtab.btree)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Heap address:", + (unsigned long)(sn->entry[i].cache.symtab.heap)); + break; + + default: + fprintf (stream, "*** Unknown symbol type %d\n", sn->entry[i].type); + break; + } + } + return 0; +} + diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 73a06ee..5e08c4d 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -25,9 +25,16 @@ #include "H5Fprivate.h" #define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */ +#define H5G_NODE_SIZEOF_MAGIC 4 /*sizeof symbol node magic number */ #define H5G_NODE_VERS 1 /*symbol table node version number */ #define H5G_NODE_K 64 /*min degree. max degree is twice this */ -#define H5G_HDR_SIZE(F) 8 +#define H5G_NODE_SIZEOF_HDR(F) (H5G_NODE_SIZEOF_MAGIC + 4) +#define H5G_SIZEOF_ENTRY(F) \ + (H5F_SIZEOF_OFFSET(F) + /*offset of name into heap */ \ + H5F_SIZEOF_OFFSET(F) + /*address of object header */ \ + 4 + /*entry type */ \ + 24) /*scratch pad space */ + /* * Various types of object header information can be cached in a symbol @@ -126,6 +133,8 @@ extern const H5B_class_t H5B_SNODE[1]; /* * Library prototypes... */ +herr_t H5G_node_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, + intn fwidth); haddr_t H5G_new (hdf5_file_t *f, size_t init); haddr_t H5G_find (hdf5_file_t *f, haddr_t addr, const char *name, H5G_entry_t *entry); diff --git a/src/H5H.c b/src/H5H.c index 9805bbd..11ed3b2 100644 --- a/src/H5H.c +++ b/src/H5H.c @@ -22,10 +22,17 @@ #include "H5MFprivate.h" /*file memory management */ #include "H5MMprivate.h" /*core memory management */ -#define H5H_MAGIC "HEAP" /*heap magic number */ #define H5H_FREE_NULL 1 /*end of free list on disk */ -#define H5H_HDR_SIZE(F) (4+H5F_SIZEOF_SIZE(F)+2*H5F_SIZEOF_OFFSET(F)) -#define H5H_SIZEOF_FREE(F) (H5F_SIZEOF_SIZE(F)+H5F_SIZEOF_OFFSET(F)) + +#define H5H_SIZEOF_HDR(F) \ + (H5H_SIZEOF_MAGIC + /*heap signature */ \ + H5F_SIZEOF_SIZE (F) + /*data size */ \ + H5F_SIZEOF_OFFSET (F) + /*free list head */ \ + H5F_SIZEOF_OFFSET (F)) /*data address */ + +#define H5H_SIZEOF_FREE(F) \ + (H5F_SIZEOF_OFFSET (F) + /*ptr to next free block */ \ + H5F_SIZEOF_SIZE (F)) /*size of this free block */ typedef struct H5H_free_t { off_t offset; /*offset of free block */ @@ -92,15 +99,15 @@ H5H_new (hdf5_file_t *f, size_t size_hint) } /* allocate file version */ - total_size = H5H_HDR_SIZE(f) + size_hint; + total_size = H5H_SIZEOF_HDR(f) + size_hint; if ((addr = H5MF_alloc (f, total_size))<0) return -1; /* allocate memory version */ heap = H5MM_xcalloc (1, sizeof(H5H_t)); - heap->addr = addr + H5H_HDR_SIZE(f); + heap->addr = addr + H5H_SIZEOF_HDR(f); heap->disk_alloc = size_hint; heap->mem_alloc = size_hint; - heap->chunk = H5MM_xmalloc (H5H_HDR_SIZE(f) + size_hint); + heap->chunk = H5MM_xmalloc (H5H_SIZEOF_HDR(f) + size_hint); /* free list */ if (size_hint) { @@ -146,15 +153,15 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata) haddr_t free_block; assert (addr>0); - assert (H5H_HDR_SIZE(f) <= sizeof hdr); + assert (H5H_SIZEOF_HDR(f) <= sizeof hdr); assert (!udata); - if (H5F_block_read (f, addr, H5H_HDR_SIZE(f), hdr)<0) goto error; + if (H5F_block_read (f, addr, H5H_SIZEOF_HDR(f), hdr)<0) goto error; p = hdr; /* magic number */ - if (HDmemcmp (hdr, H5H_MAGIC, 4)) goto error; - p += 4; + if (HDmemcmp (hdr, H5H_MAGIC, H5H_SIZEOF_MAGIC)) goto error; + p += H5H_SIZEOF_MAGIC; /* heap data size */ H5F_decode_length (f, p, heap->disk_alloc); @@ -166,10 +173,10 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata) /* data */ H5F_decode_offset (f, p, heap->addr); - heap->chunk = H5MM_xmalloc (H5H_HDR_SIZE(f) + heap->mem_alloc); + heap->chunk = H5MM_xmalloc (H5H_SIZEOF_HDR(f) + heap->mem_alloc); if (heap->disk_alloc && H5F_block_read (f, heap->addr, heap->disk_alloc, - heap->chunk + H5H_HDR_SIZE(f))<0) { + heap->chunk + H5H_SIZEOF_HDR(f))<0) { goto error; } @@ -184,7 +191,7 @@ H5H_load (hdf5_file_t *f, haddr_t addr, const void *udata) tail = fl; if (!heap->freelist) heap->freelist = fl; - p = heap->chunk + H5H_HDR_SIZE(f) + free_block; + p = heap->chunk + H5H_SIZEOF_HDR(f) + free_block; H5F_decode_offset (f, p, free_block); H5F_decode_length (f, p, fl->size); @@ -241,7 +248,7 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) /* * Write the header. */ - HDmemcpy (p, H5H_MAGIC, 4); p += 4; + HDmemcpy (p, H5H_MAGIC, H5H_SIZEOF_MAGIC); p += H5H_SIZEOF_MAGIC; H5F_encode_length (f, p, heap->mem_alloc); H5F_encode_offset (f, p, fl?fl->offset:-1); H5F_encode_offset (f, p, heap->addr); @@ -250,7 +257,7 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) * Write the free list. */ while (fl) { - p = heap->chunk + H5H_HDR_SIZE(f) + fl->offset; + p = heap->chunk + H5H_SIZEOF_HDR(f) + fl->offset; if (fl->next) { H5F_encode_offset (f, p, fl->next->offset); } else { @@ -263,17 +270,17 @@ H5H_flush (hdf5_file_t *f, hbool_t destroy, haddr_t addr, H5H_t *heap) /* * Copy buffer to disk. */ - if (heap->addr == addr + H5H_HDR_SIZE(f)) { - if (H5F_block_write (f, addr, H5H_HDR_SIZE(f)+heap->disk_alloc, + if (heap->addr == addr + H5H_SIZEOF_HDR(f)) { + if (H5F_block_write (f, addr, H5H_SIZEOF_HDR(f)+heap->disk_alloc, heap->chunk)<0) { return -1; } } else { - if (H5F_block_write (f, addr, H5H_HDR_SIZE(f), heap->chunk)<0) { + if (H5F_block_write (f, addr, H5H_SIZEOF_HDR(f), heap->chunk)<0) { return -1; } if (H5F_block_write (f, heap->addr, heap->disk_alloc, - heap->chunk + H5H_HDR_SIZE(f))<0) { + heap->chunk + H5H_SIZEOF_HDR(f))<0) { return -1; } } @@ -333,7 +340,7 @@ H5H_read (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, void *buf) assert (offset+size<=heap->mem_alloc); if (!buf) buf = H5MM_xmalloc (size); - HDmemcpy (buf, heap->chunk+H5H_HDR_SIZE(f)+offset, size); + HDmemcpy (buf, heap->chunk+H5H_SIZEOF_HDR(f)+offset, size); return buf; } @@ -374,7 +381,7 @@ H5H_peek (hdf5_file_t *f, haddr_t addr, off_t offset) H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); assert (offset>=0 && offsetmem_alloc); - return heap->chunk+H5H_HDR_SIZE(f)+offset; + return heap->chunk+H5H_SIZEOF_HDR(f)+offset; } @@ -502,13 +509,13 @@ H5H_insert (hdf5_file_t *f, haddr_t addr, size_t size, const void *buf) (unsigned long)(heap->mem_alloc + need_more)); heap->mem_alloc += need_more; heap->chunk = H5MM_xrealloc (heap->chunk, - H5H_HDR_SIZE(f)+heap->mem_alloc); + H5H_SIZEOF_HDR(f)+heap->mem_alloc); } /* * Copy the data into the heap */ - HDmemcpy (heap->chunk + H5H_HDR_SIZE(f) + offset, buf, size); + HDmemcpy (heap->chunk + H5H_SIZEOF_HDR(f) + offset, buf, size); return offset; } @@ -547,7 +554,7 @@ H5H_write (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, assert (buf); heap->dirty += 1; - HDmemcpy (heap->chunk+H5H_HDR_SIZE(f)+offset, buf, size); + HDmemcpy (heap->chunk+H5H_SIZEOF_HDR(f)+offset, buf, size); return 0; } @@ -651,3 +658,118 @@ H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size) return 0; } + + +/*------------------------------------------------------------------------- + * Function: H5H_debug + * + * Purpose: Prints debugging information about a heap. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Aug 1 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5H_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, + intn fwidth) +{ + H5H_t *h = H5AC_find (f, H5AC_HEAP, addr, NULL); + int i, j, overlap; + uint8 c; + H5H_free_t *freelist=NULL; + uint8 *marker = NULL; + size_t amount_free = 0; + + if (!h) return -1; + + fprintf (stream, "%*sHeap...\n", indent, ""); + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Dirty:", + (int)(h->dirty)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Data bytes allocated on disk:", + (unsigned long)(h->disk_alloc)); + fprintf (stream, "%*s%-*s %lu\n", indent, "", fwidth, + "Data bytes allocated in core:", + (unsigned long)(h->mem_alloc)); + + + /* + * Traverse the free list and check that all free blocks fall within + * the heap and that no two free blocks point to the same region of + * the heap. + */ + marker = H5MM_xcalloc (h->mem_alloc, 1); + for (freelist=h->freelist; freelist; freelist=freelist->next) { + fprintf (stream, "%*s%-*s %8lu, %8lu\n", indent, "", fwidth, + "Free Block (offset,size):", + (unsigned long)(freelist->offset), + (unsigned long)(freelist->size)); + if (freelist->offset + freelist->size > h->mem_alloc) { + fprintf (stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n"); + } else { + for (i=overlap=0; isize; i++) { + if (marker[freelist->offset+i]) overlap++; + marker[freelist->offset+i] = 1; + } + if (overlap) { + fprintf (stream,"***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n"); + } else { + amount_free += freelist->size; + } + } + } + + if (h->mem_alloc) { + fprintf (stream, "%*s%-*s %d\n", indent, "", fwidth, + "Percent of heap used:", + 100 * (h->mem_alloc - amount_free) / h->mem_alloc); + } + + /* + * Print the data in a VMS-style octal dump. + */ + fprintf (stream, "%*sData follows (`__' indicates free region)...\n", + indent, ""); + for (i=0; idisk_alloc; i+=16) { + fprintf (stream, "%*s %8d: ", indent, "", i); + for (j=0; j<16; j++) { + if (i+jdisk_alloc) { + if (marker[i+j]) { + fprintf (stream, "__ "); + } else { + c = h->chunk[H5H_SIZEOF_HDR(f)+i+j]; + fprintf (stream, "%02x ", c); + } + } else { + fprintf (stream, " "); + } + if (7==j) fputc (' ', stream); + } + + for (j=0; j<16; j++) { + if (i+jdisk_alloc) { + if (marker[i+j]) { + fputc (' ', stream); + } else { + c = h->chunk[H5H_SIZEOF_HDR(f)+i+j]; + if (c>' ' && c<'~') fputc (c, stream); + else fputc ('.', stream); + } + } + } + + fputc ('\n', stream); + } + + H5MM_xfree (marker); + return 0; +} diff --git a/src/H5Hprivate.h b/src/H5Hprivate.h index f896b4a..0c31df3 100644 --- a/src/H5Hprivate.h +++ b/src/H5Hprivate.h @@ -20,6 +20,9 @@ #include "H5Hproto.h" #include "H5Fprivate.h" +#define H5H_MAGIC "HEAP" /*heap magic number */ +#define H5H_SIZEOF_MAGIC 4 + /* * Library prototypes... */ @@ -31,6 +34,8 @@ off_t H5H_insert (hdf5_file_t *f, haddr_t addr, size_t size, const void *buf); herr_t H5H_write (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size, const void *buf); herr_t H5H_remove (hdf5_file_t *f, haddr_t addr, off_t offset, size_t size); +herr_t H5H_debug (hdf5_file_t *f, haddr_t addr, FILE *stream, intn indent, + intn fwidth); #endif diff --git a/src/H5Tproto.h b/src/H5Tproto.h index 5e32b0f..908445e 100644 --- a/src/H5Tproto.h +++ b/src/H5Tproto.h @@ -48,6 +48,9 @@ hbool_t H5Tis_atomic(hatom_t tid); herr_t H5Tset_type(hatom_t tid,hatom_t base,uint8 len,uint8 arch); uintn H5Tsize(hatom_t tid, uint8 len, uint8 arch, hbool_t mem_flag); herr_t H5T_release(hatom_t oid); +herr_t H5Tadd_field (hatom_t tid, const char *name, hatom_t base, uint8 len, + uint8 arch, hatom_t space); +herr_t H5Tget_fields(hatom_t tid, hatom_t *field_list); #if defined c_plusplus || defined __cplusplus } diff --git a/src/Makefile b/src/Makefile index 13eeea4..022f392 100644 --- a/src/Makefile +++ b/src/Makefile @@ -34,7 +34,7 @@ $(TARGET): $(OBJ) $(AR) $(ARFLAGS) $(TARGET) $(OBJ) $(RANLIB) $(TARGET) -all test: $(TARGET) +all test: $(TARGET) debug_hdf5 debug: $(OBJ) $(AR) $(ARFLAGS) $(TARGET) $(OBJ) @@ -46,6 +46,12 @@ clean: ########################################################################### +debug_hdf5: $(TARGET) debug.o + $(CC) -o debug debug.o -L. -lhdf5 + +debug.o: debug.c $(INCL) + $(CC) $(CFLAGS) debug.c + H5.o: H5.c $(INCL) H5private.h H5proto.h $(CC) $(CFLAGS) H5.c diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..f061d4c --- /dev/null +++ b/src/debug.c @@ -0,0 +1,142 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: debug.c + * Jul 18 1997 + * Robb Matzke + * + * Purpose: Debugs an existing HDF5 file at a low level. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include "hdf5.h" + +#include "H5private.h" +#include "H5Bprivate.h" +#include "H5Fprivate.h" +#include "H5Gprivate.h" +#include "H5Hprivate.h" + +#define INDENT 3 +#define VCOL 50 + + +/*------------------------------------------------------------------------- + * Function: main + * + * Usage: debug FILENAME [OFFSET] + * + * Return: Success: exit (0) + * + * Failure: exit (non-zero) + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 18 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +int +main (int argc, char *argv[]) +{ + hatom_t fid; + hdf5_file_t *f; + haddr_t addr = 0; + uint8 sig[16]; + intn i; + + /* + * Parse command arguments. + */ + if (argc>2) { + printf ("New address: %s\n", argv[2]); + addr = strtol (argv[2], NULL, 0); + } + + /* + * Open the file and get the file descriptor. + */ + if ((fid = H5Fopen (argv[1], 0, 0))<0) { + fprintf (stderr, "cannot open file\n"); + exit (1); + } + if (NULL==(f=H5Aatom_object (fid))) { + fprintf (stderr, "cannot obtain hdf5_file_t pointer\n"); + exit (2); + } + + /* + * Read the signature at the specified file position. + */ + printf ("Reading signature at byte %lu\n", (unsigned long)addr); + if (H5F_block_read (f, addr, sizeof(sig), sig)<0) { + fprintf (stderr, "cannot read signature\n"); + exit (3); + } + + if (!memcmp (sig, HDF5_FILE_SIGNATURE, HDF5_FILE_SIGNATURE_LEN)) { + /* + * Debug the boot block. + */ + H5F_debug (f, 0, stdout, 0, VCOL); + + } else if (!memcmp (sig, H5H_MAGIC, H5H_SIZEOF_MAGIC)) { + /* + * Debug a heap. + */ + H5H_debug (f, addr, stdout, 0, VCOL); + + } else if (!memcmp (sig, H5G_NODE_MAGIC, H5G_NODE_SIZEOF_MAGIC)) { + /* + * Debug a symbol table node. + */ + H5G_node_debug (f, addr, stdout, 0, VCOL); + + } else if (!memcmp (sig, H5B_MAGIC, H5B_SIZEOF_MAGIC)) { + /* + * Debug a B-tree. B-trees are debugged through the B-tree + * subclass. The subclass identifier is the byte immediately + * after the B-tree signature. + */ + H5B_subid_t subtype = sig[H5B_SIZEOF_MAGIC]; + switch (subtype) { + case H5B_SUBTYPE_SNODE: + H5G_node_debug (f, addr, stdout, 0, VCOL); + break; + + default: + fprintf (stderr, "Unknown B-tree subtype %u\n", (unsigned)(subtype)); + exit (4); + } + + } else { + /* + * Got some other unrecognized signature. + */ + printf ("%-*s ", VCOL, "Signature:"); + for (i=0; i<8; i++) { + if (sig[i]>' ' && sig[i]<='~' && '\\'!=sig[i]) { + putchar (sig[i]); + } else if ('\\'==sig[i]) { + putchar ('\\'); + putchar ('\\'); + } else { + printf ("\\%03o", sig[i]); + } + } + putchar ('\n'); + + fprintf (stderr, "unknown signature\n"); + exit (4); + } + + H5Fclose (fid); + exit (0); +} -- cgit v0.12