diff options
Diffstat (limited to 'src/H5Odbg.c')
-rw-r--r-- | src/H5Odbg.c | 417 |
1 files changed, 417 insertions, 0 deletions
diff --git a/src/H5Odbg.c b/src/H5Odbg.c new file mode 100644 index 0000000..72c6d93 --- /dev/null +++ b/src/H5Odbg.c @@ -0,0 +1,417 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5Odbg.c + * Nov 17 2006 + * Quincey Koziol <koziol@hdfgroup.org> + * + * Purpose: Object header debugging routines. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5O_PACKAGE /*suppress error about including H5Opkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5Opkg.h" /* Object headers */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + +#ifdef H5O_DEBUG + +/*------------------------------------------------------------------------- + * Function: H5O_assert + * + * Purpose: Sanity check the information for an object header data + * structure. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@hdfgroup.org + * Oct 17 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_assert(const H5O_t *oh) +{ + H5O_mesg_t *curr_msg; /* Pointer to current message to examine */ + H5O_mesg_t *tmp_msg; /* Pointer to temporary message to examine */ + unsigned u, v; /* Local index variables */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5O_assert) + + /* Loop over all chunks in object header */ + for(u = 0; u < oh->nchunks; u++) { + /* Check for valid raw data image */ + HDassert(oh->chunk[u].image); + HDassert(oh->chunk[u].size > (size_t)H5O_SIZEOF_CHKHDR_OH(oh)); + + /* All chunks must be allocated on disk */ + HDassert(H5F_addr_defined(oh->chunk[u].addr)); + + /* Version specific checks */ + if(oh->version > H5O_VERSION_1) { + /* Make certain that the magic number is correct for each chunk */ + HDassert(!HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5O_SIZEOF_MAGIC)); + + /* Check for valid gap size */ + HDassert(oh->chunk[u].gap < (size_t)H5O_SIZEOF_MSGHDR_OH(oh)); + } /* end if */ + else + /* Gaps should never occur in version 1 of the format */ + HDassert(oh->chunk[u].gap == 0); + } /* end for */ + + /* Loop over all messages in object header */ + for(u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) { + /* Make certain that the message is in a valid chunk */ + HDassert(curr_msg->chunkno < oh->nchunks); + + /* Make certain null messages aren't in chunks with gaps */ + if(H5O_NULL_ID == curr_msg->type->id) + HDassert(oh->chunk[curr_msg->chunkno].gap == 0); + + /* Make certain that the message is completely in a chunk message area */ + HDassert(curr_msg->raw_size <= (oh->chunk[curr_msg->chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[curr_msg->chunkno].gap)); + if(curr_msg->chunkno == 0) + HDassert(curr_msg->raw >= oh->chunk[curr_msg->chunkno].image + (H5O_SIZEOF_HDR_OH(oh) - H5O_SIZEOF_CHKSUM_OH(oh))); + else + HDassert(curr_msg->raw >= oh->chunk[curr_msg->chunkno].image + (H5O_SIZEOF_CHKHDR_OH(oh) - H5O_SIZEOF_CHKSUM_OH(oh))); + HDassert(curr_msg->raw + curr_msg->raw_size <= (oh->chunk[curr_msg->chunkno].image + oh->chunk[curr_msg->chunkno].size) - (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[curr_msg->chunkno].gap)); + + /* Make certain that no other messages overlap this message */ + for(v = 0, tmp_msg = &oh->mesg[0]; v < oh->nmesgs; v++, tmp_msg++) { + if(u != v) + HDassert(!(tmp_msg->raw >= curr_msg->raw && tmp_msg->raw < (curr_msg->raw + curr_msg->raw_size))); + } /* end for */ + } /* end for */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5O_assert() */ +#endif /* H5O_DEBUG */ + + +/*------------------------------------------------------------------------- + * Function: H5O_debug_id + * + * Purpose: Act as a proxy for calling the 'debug' method for a + * particular class of object header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Feb 13 2003 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_debug_id(unsigned type_id, H5F_t *f, hid_t dxpl_id, const void *mesg, FILE *stream, int indent, int fwidth) +{ + const H5O_msg_class_t *type; /* Actual H5O class type for the ID */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5O_debug_id,FAIL) + + /* Check args */ + HDassert(type_id < NELMTS(H5O_msg_class_g)); + type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */ + HDassert(type); + HDassert(type->debug); + HDassert(f); + HDassert(mesg); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + /* Call the debug method in the class */ + if((ret_value = (type->debug)(f, dxpl_id, mesg, stream, indent, fwidth)) < 0) + HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "unable to debug message") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_debug_id() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_debug_real + * + * Purpose: Prints debugging info about an object header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_debug_real(H5F_t *f, hid_t dxpl_id, H5O_t *oh, haddr_t addr, FILE *stream, int indent, int fwidth) +{ + unsigned i, chunkno; + size_t mesg_total = 0, chunk_total = 0; + int *sequence; + void *(*decode)(H5F_t*, hid_t, const uint8_t*); + herr_t (*debug)(H5F_t*, hid_t, const void*, FILE*, int, int)=NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5O_debug_real, FAIL) + + /* check args */ + HDassert(f); + HDassert(oh); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + /* debug */ + HDfprintf(stream, "%*sObject Header...\n", indent, ""); + + HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth, + "Dirty:", + oh->cache_info.is_dirty); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Version:", + oh->version); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Header size (in bytes):", + (unsigned)H5O_SIZEOF_HDR_OH(oh)); + HDfprintf(stream, "%*s%-*s %d\n", indent, "", fwidth, + "Number of links:", + oh->nlink); + HDfprintf(stream, "%*s%-*s %Zu (%Zu)\n", indent, "", fwidth, + "Number of messages (allocated):", + oh->nmesgs, oh->alloc_nmesgs); + HDfprintf(stream, "%*s%-*s %Zu (%Zu)\n", indent, "", fwidth, + "Number of chunks (allocated):", + oh->nchunks, oh->alloc_nchunks); + + /* debug each chunk */ + for(i = 0, chunk_total = 0; i < oh->nchunks; i++) { + size_t chunk_size; + + chunk_total += oh->chunk[i].size; + HDfprintf(stream, "%*sChunk %d...\n", indent, "", i); + + HDfprintf(stream, "%*s%-*s %t\n", indent + 3, "", MAX(0, fwidth - 3), + "Dirty:", + oh->chunk[i].dirty); + + HDfprintf(stream, "%*s%-*s %a\n", indent + 3, "", MAX(0, fwidth - 3), + "Address:", + oh->chunk[i].addr); + + if(0 == i) { + if(H5F_addr_ne(oh->chunk[i].addr, addr)) + HDfprintf(stream, "*** WRONG ADDRESS!\n"); + chunk_size = oh->chunk[i].size - H5O_SIZEOF_HDR_OH(oh); + } /* end if */ + else + chunk_size = oh->chunk[i].size; + HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3), + "Size in bytes:", + chunk_size); + + HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3), + "Gap:", + oh->chunk[i].gap); + } /* end for */ + + /* debug each message */ + if(NULL == (sequence = H5MM_calloc(NELMTS(H5O_msg_class_g) * sizeof(int)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + for(i = 0, mesg_total = 0; i < oh->nmesgs; i++) { + mesg_total += H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[i].raw_size; + HDfprintf(stream, "%*sMessage %d...\n", indent, "", i); + + /* check for bad message id */ + if(oh->mesg[i].type->id >= (int)NELMTS(H5O_msg_class_g)) { + HDfprintf(stream, "*** BAD MESSAGE ID 0x%04x\n", + oh->mesg[i].type->id); + continue; + } /* end if */ + + /* message name and size */ + HDfprintf(stream, "%*s%-*s 0x%04x `%s' (%d)\n", + indent + 3, "", MAX(0, fwidth - 3), + "Message ID (sequence number):", + (unsigned) (oh->mesg[i].type->id), + oh->mesg[i].type->name, + sequence[oh->mesg[i].type->id]++); + HDfprintf (stream, "%*s%-*s %t\n", indent+3, "", MAX (0, fwidth-3), + "Dirty:", + oh->mesg[i].dirty); + HDfprintf (stream, "%*s%-*s %s\n", indent+3, "", MAX (0, fwidth-3), + "Shared:", + (oh->mesg[i].flags & H5O_FLAG_SHARED) ? "Yes" : "No"); + HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", MAX(0, fwidth - 3), + "Constant:", + (oh->mesg[i].flags & H5O_FLAG_CONSTANT) ? "Yes" : "No"); + if(oh->mesg[i].flags & ~H5O_FLAG_BITS) { + HDfprintf (stream, "%*s%-*s 0x%02x\n", indent+3,"",MAX(0,fwidth-3), + "*** ADDITIONAL UNKNOWN FLAGS --->", + oh->mesg[i].flags & ~H5O_FLAG_BITS); + } /* end if */ + HDfprintf(stream, "%*s%-*s %Zu bytes\n", indent+3, "", MAX(0,fwidth-3), + "Raw size in obj header:", + oh->mesg[i].raw_size); + HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", MAX(0, fwidth - 3), + "Chunk number:", + oh->mesg[i].chunkno); + chunkno = oh->mesg[i].chunkno; + if(chunkno >= oh->nchunks) + HDfprintf(stream, "*** BAD CHUNK NUMBER\n"); + HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3), + "Raw data offset in chunk:", + (size_t)(oh->mesg[i].raw - oh->chunk[chunkno].image)); + + /* check the size */ + if((oh->mesg[i].raw + oh->mesg[i].raw_size > + oh->chunk[chunkno].image + oh->chunk[chunkno].size) || + (oh->mesg[i].raw < oh->chunk[chunkno].image)) + HDfprintf(stream, "*** BAD MESSAGE RAW ADDRESS\n"); + + /* decode the message */ + if(oh->mesg[i].flags & H5O_FLAG_SHARED) { + decode = H5O_MSG_SHARED->decode; + debug = H5O_MSG_SHARED->debug; + } else { + decode = oh->mesg[i].type->decode; + debug = oh->mesg[i].type->debug; + } /* end else */ + if(NULL==oh->mesg[i].native && decode) + oh->mesg[i].native = (decode)(f, dxpl_id, oh->mesg[i].raw); + if(NULL == oh->mesg[i].native) + debug = NULL; + + /* print the message */ + HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), + "Message Information:"); + if(debug) + (debug)(f, dxpl_id, oh->mesg[i].native, stream, indent + 6, MAX(0, fwidth - 6)); + else + HDfprintf(stream, "%*s<No info for this message>\n", indent + 6, ""); + + /* If the message is shared then also print the pointed-to message */ + if(oh->mesg[i].flags & H5O_FLAG_SHARED) { + H5O_shared_t *shared = (H5O_shared_t*)(oh->mesg[i].native); + void *mesg; + + mesg = H5O_shared_read(f, dxpl_id, shared, oh->mesg[i].type, NULL); + if(oh->mesg[i].type->debug) + (oh->mesg[i].type->debug)(f, dxpl_id, mesg, stream, indent + 3, MAX (0, fwidth - 3)); + H5O_free_real(oh->mesg[i].type, mesg); + } /* end if */ + } /* end for */ + sequence = H5MM_xfree(sequence); + + if(mesg_total != chunk_total) + HDfprintf(stream, "*** TOTAL SIZE DOES NOT MATCH ALLOCATED SIZE!\n"); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_debug_real() */ + + +/*------------------------------------------------------------------------- + * Function: H5O_debug + * + * Purpose: Prints debugging info about an object header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 6 1997 + * + *------------------------------------------------------------------------- + */ +herr_t +H5O_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth) +{ + H5O_t *oh = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_NOAPI(H5O_debug, FAIL) + + /* check args */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + if(NULL == (oh = H5AC_protect(f, dxpl_id, H5AC_OHDR, addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, FAIL, "unable to load object header") + + /* debug */ + H5O_debug_real(f, dxpl_id, oh, addr, stream, indent, fwidth); + +done: + if(oh && H5AC_unprotect(f, dxpl_id, H5AC_OHDR, addr, oh, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_OHDR, H5E_PROTECT, FAIL, "unable to release object header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5O_debug() */ + |