1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://www.hdfgroup.org/licenses. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /*-------------------------------------------------------------------------
15 *
16 * Created: H5Odbg.c
17 * Nov 17 2006
18 * Quincey Koziol
19 *
20 * Purpose: Object header debugging routines.
21 *
22 *-------------------------------------------------------------------------
23 */
24
25 /****************/
26 /* Module Setup */
27 /****************/
28
29 #include "H5Omodule.h" /* This source code file is part of the H5O module */
30
31 /***********/
32 /* Headers */
33 /***********/
34 #include "H5private.h" /* Generic Functions */
35 #include "H5Eprivate.h" /* Error handling */
36 #include "H5MMprivate.h" /* Memory management */
37 #include "H5Opkg.h" /* Object headers */
38 #include "H5Ppublic.h" /* Property Lists */
39
40 /****************/
41 /* Local Macros */
42 /****************/
43
44 /******************/
45 /* Local Typedefs */
46 /******************/
47
48 /********************/
49 /* Package Typedefs */
50 /********************/
51
52 /********************/
53 /* Local Prototypes */
54 /********************/
55
56 /*********************/
57 /* Package Variables */
58 /*********************/
59
60 /*****************************/
61 /* Library Private Variables */
62 /*****************************/
63
64 /*******************/
65 /* Local Variables */
66 /*******************/
67
68 #ifdef H5O_DEBUG
69
70 /*-------------------------------------------------------------------------
71 * Function: H5O__assert
72 *
73 * Purpose: Sanity check the information for an object header data
74 * structure.
75 *
76 * Return: SUCCEED (Doesn't fail, just crashes)
77 *
78 * Programmer: Quincey Koziol
79 * Oct 17 2006
80 *
81 *-------------------------------------------------------------------------
82 */
83 herr_t
H5O__assert(const H5O_t * oh)84 H5O__assert(const H5O_t *oh)
85 {
86 H5O_mesg_t *curr_msg; /* Pointer to current message to examine */
87 H5O_mesg_t *tmp_msg; /* Pointer to temporary message to examine */
88 unsigned cont_msgs_found = 0; /* # of continuation messages for object */
89 size_t meta_space; /* Size of header metadata */
90 size_t mesg_space; /* Size of message raw data */
91 size_t free_space; /* Size of free space in header */
92 size_t hdr_size; /* Size of header's chunks */
93 unsigned u, v; /* Local index variables */
94
95 FUNC_ENTER_PACKAGE_NOERR
96
97 /* Initialize the tracking variables */
98 hdr_size = 0;
99 meta_space = (size_t)H5O_SIZEOF_HDR(oh) + (size_t)(H5O_SIZEOF_CHKHDR_OH(oh) * (oh->nchunks - 1));
100 mesg_space = 0;
101 free_space = 0;
102
103 /* Loop over all chunks in object header */
104 for (u = 0; u < oh->nchunks; u++) {
105 /* Accumulate the size of the header on header */
106 hdr_size += oh->chunk[u].size;
107
108 /* If the chunk has a gap, add it to the free space */
109 free_space += oh->chunk[u].gap;
110
111 /* Check for valid raw data image */
112 HDassert(oh->chunk[u].image);
113 HDassert(oh->chunk[u].size > (size_t)H5O_SIZEOF_CHKHDR_OH(oh));
114
115 /* All chunks must be allocated on disk */
116 HDassert(H5F_addr_defined(oh->chunk[u].addr));
117
118 /* Version specific checks */
119 if (oh->version > H5O_VERSION_1) {
120 /* Make certain that the magic number is correct for each chunk */
121 HDassert(
122 !HDmemcmp(oh->chunk[u].image, (u == 0 ? H5O_HDR_MAGIC : H5O_CHK_MAGIC), H5_SIZEOF_MAGIC));
123
124 /* Check for valid gap size */
125 HDassert(oh->chunk[u].gap < (size_t)H5O_SIZEOF_MSGHDR_OH(oh));
126 } /* end if */
127 else
128 /* Gaps should never occur in version 1 of the format */
129 HDassert(oh->chunk[u].gap == 0);
130 } /* end for */
131
132 /* Check for correct chunk #0 size flags */
133 if (oh->version > H5O_VERSION_1) {
134 uint64_t chunk0_size = oh->chunk[0].size - (size_t)H5O_SIZEOF_HDR(oh);
135
136 if (chunk0_size <= 255)
137 HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_1);
138 else if (chunk0_size <= 65535)
139 HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_2);
140 else if (chunk0_size <= 4294967295)
141 HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_4);
142 else
143 HDassert((oh->flags & H5O_HDR_CHUNK0_SIZE) == H5O_HDR_CHUNK0_8);
144 } /* end if */
145
146 /* Loop over all messages in object header */
147 for (u = 0, curr_msg = &oh->mesg[0]; u < oh->nmesgs; u++, curr_msg++) {
148 uint8_t H5_ATTR_NDEBUG_UNUSED *curr_hdr; /* Start of current message header */
149 size_t curr_tot_size; /* Total size of current message (including header) */
150
151 curr_hdr = curr_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh);
152 curr_tot_size = curr_msg->raw_size + (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
153
154 /* Accumulate information, based on the type of message */
155 if (H5O_NULL_ID == curr_msg->type->id)
156 free_space += curr_tot_size;
157 else if (H5O_CONT_ID == curr_msg->type->id) {
158 H5O_cont_t * cont = (H5O_cont_t *)curr_msg->native;
159 hbool_t H5_ATTR_NDEBUG_UNUSED found_chunk = FALSE; /* Found a chunk that matches */
160
161 HDassert(cont);
162
163 /* Increment # of continuation messages found */
164 cont_msgs_found++;
165
166 /* Sanity check that every continuation message has a matching chunk */
167 /* (and only one) */
168 for (v = 0; v < oh->nchunks; v++) {
169 if (H5F_addr_eq(cont->addr, oh->chunk[v].addr) && cont->size == oh->chunk[v].size) {
170 HDassert(cont->chunkno == v);
171 HDassert(!found_chunk);
172 found_chunk = TRUE;
173 } /* end if */
174 } /* end for */
175 HDassert(found_chunk);
176
177 meta_space += curr_tot_size;
178 } /* end if */
179 else {
180 meta_space += (size_t)H5O_SIZEOF_MSGHDR_OH(oh);
181 mesg_space += curr_msg->raw_size;
182
183 /* Make sure the message has a native form if it is marked dirty */
184 HDassert(curr_msg->native || !curr_msg->dirty);
185 } /* end else */
186
187 /* Make certain that the message is in a valid chunk */
188 HDassert(curr_msg->chunkno < oh->nchunks);
189
190 /* Make certain null messages aren't in chunks with gaps */
191 if (H5O_NULL_ID == curr_msg->type->id)
192 HDassert(oh->chunk[curr_msg->chunkno].gap == 0);
193
194 /* Make certain that the message is completely in a chunk message area */
195 HDassert(curr_tot_size <= (oh->chunk[curr_msg->chunkno].size) -
196 (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[curr_msg->chunkno].gap));
197 if (curr_msg->chunkno == 0)
198 HDassert(curr_hdr >=
199 oh->chunk[curr_msg->chunkno].image + (H5O_SIZEOF_HDR(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
200 else
201 HDassert(curr_hdr >= oh->chunk[curr_msg->chunkno].image +
202 (H5O_SIZEOF_CHKHDR_OH(oh) - H5O_SIZEOF_CHKSUM_OH(oh)));
203 HDassert(curr_msg->raw + curr_msg->raw_size <=
204 (oh->chunk[curr_msg->chunkno].image + oh->chunk[curr_msg->chunkno].size) -
205 (H5O_SIZEOF_CHKSUM_OH(oh) + oh->chunk[curr_msg->chunkno].gap));
206
207 /* Make certain that no other messages overlap this message */
208 for (v = 0, tmp_msg = &oh->mesg[0]; v < oh->nmesgs; v++, tmp_msg++) {
209 if (u != v)
210 HDassert(!((tmp_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)) >= curr_hdr &&
211 (tmp_msg->raw - H5O_SIZEOF_MSGHDR_OH(oh)) < (curr_hdr + curr_tot_size)));
212 } /* end for */
213 } /* end for */
214
215 /* Sanity check that the # of cont. messages is correct for the # of chunks */
216 HDassert(oh->nchunks == (cont_msgs_found + 1));
217
218 /* Sanity check that all the bytes are accounted for */
219 HDassert(hdr_size == (free_space + meta_space + mesg_space));
220
221 FUNC_LEAVE_NOAPI(SUCCEED)
222 } /* end H5O__assert() */
223 #endif /* H5O_DEBUG */
224
225 /*-------------------------------------------------------------------------
226 * Function: H5O_debug_id
227 *
228 * Purpose: Act as a proxy for calling the 'debug' method for a
229 * particular class of object header.
230 *
231 * Return: Non-negative on success/Negative on failure
232 *
233 * Programmer: Quincey Koziol
234 * Feb 13 2003
235 *
236 *-------------------------------------------------------------------------
237 */
238 herr_t
H5O_debug_id(unsigned type_id,H5F_t * f,const void * mesg,FILE * stream,int indent,int fwidth)239 H5O_debug_id(unsigned type_id, H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidth)
240 {
241 const H5O_msg_class_t *type; /* Actual H5O class type for the ID */
242 herr_t ret_value = FAIL; /* Return value */
243
244 FUNC_ENTER_NOAPI(FAIL)
245
246 /* Check args */
247 HDassert(type_id < NELMTS(H5O_msg_class_g));
248 type = H5O_msg_class_g[type_id]; /* map the type ID to the actual type object */
249 HDassert(type);
250 HDassert(type->debug);
251 HDassert(f);
252 HDassert(mesg);
253 HDassert(stream);
254 HDassert(indent >= 0);
255 HDassert(fwidth >= 0);
256
257 /* Call the debug method in the class */
258 if ((ret_value = (type->debug)(f, mesg, stream, indent, fwidth)) < 0)
259 HGOTO_ERROR(H5E_OHDR, H5E_BADTYPE, FAIL, "unable to debug message")
260
261 done:
262 FUNC_LEAVE_NOAPI(ret_value)
263 } /* end H5O_debug_id() */
264
265 /*-------------------------------------------------------------------------
266 * Function: H5O__debug_real
267 *
268 * Purpose: Prints debugging info about an object header.
269 *
270 * Return: SUCCEED/FAIL
271 *
272 * Programmer: Robb Matzke
273 * Aug 6 1997
274 *
275 *-------------------------------------------------------------------------
276 */
277 herr_t
H5O__debug_real(H5F_t * f,H5O_t * oh,haddr_t addr,FILE * stream,int indent,int fwidth)278 H5O__debug_real(H5F_t *f, H5O_t *oh, haddr_t addr, FILE *stream, int indent, int fwidth)
279 {
280 size_t mesg_total = 0, chunk_total = 0, gap_total = 0;
281 unsigned *sequence = NULL;
282 unsigned i; /* Local index variable */
283 herr_t ret_value = SUCCEED;
284
285 FUNC_ENTER_PACKAGE
286
287 /* check args */
288 HDassert(f);
289 HDassert(oh);
290 HDassert(H5F_addr_defined(addr));
291 HDassert(stream);
292 HDassert(indent >= 0);
293 HDassert(fwidth >= 0);
294
295 /* debug */
296 HDfprintf(stream, "%*sObject Header...\n", indent, "");
297
298 HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
299 "Dirty:", oh->cache_info.is_dirty ? "TRUE" : "FALSE");
300 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Version:", oh->version);
301 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
302 "Header size (in bytes):", (unsigned)H5O_SIZEOF_HDR(oh));
303 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, "Number of links:", oh->nlink);
304
305 /* Extra information for later versions */
306 if (oh->version > H5O_VERSION_1) {
307 /* Display object's status flags */
308 HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Attribute creation order tracked:",
309 (oh->flags & H5O_HDR_ATTR_CRT_ORDER_TRACKED) ? "Yes" : "No");
310 HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Attribute creation order indexed:",
311 (oh->flags & H5O_HDR_ATTR_CRT_ORDER_INDEXED) ? "Yes" : "No");
312 HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Attribute storage phase change values:",
313 (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) ? "Non-default" : "Default");
314 HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
315 "Timestamps:", (oh->flags & H5O_HDR_STORE_TIMES) ? "Enabled" : "Disabled");
316 if (oh->flags & ~H5O_HDR_ALL_FLAGS)
317 HDfprintf(stream, "*** UNKNOWN OBJECT HEADER STATUS FLAG: %02x!\n", (unsigned)oh->flags);
318
319 /* Only dump times, if they are tracked */
320 if (oh->flags & H5O_HDR_STORE_TIMES) {
321 struct tm *tm; /* Time structure */
322 char buf[128]; /* Buffer for formatting time info */
323
324 /* Time fields */
325 tm = HDlocaltime(&oh->atime);
326 HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
327 HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Access Time:", buf);
328 tm = HDlocaltime(&oh->mtime);
329 HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
330 HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Modification Time:", buf);
331 tm = HDlocaltime(&oh->ctime);
332 HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
333 HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Change Time:", buf);
334 tm = HDlocaltime(&oh->btime);
335 HDstrftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %Z", tm);
336 HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Birth Time:", buf);
337 } /* end if */
338
339 /* Attribute tracking fields */
340 if (oh->flags & H5O_HDR_ATTR_STORE_PHASE_CHANGE) {
341 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
342 "Max. compact attributes:", (unsigned)oh->max_compact);
343 HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
344 "Min. dense attributes:", (unsigned)oh->min_dense);
345 } /* end if */
346 } /* end if */
347
348 HDfprintf(stream, "%*s%-*s %zu (%zu)\n", indent, "", fwidth,
349 "Number of messages (allocated):", oh->nmesgs, oh->alloc_nmesgs);
350 HDfprintf(stream, "%*s%-*s %zu (%zu)\n", indent, "", fwidth, "Number of chunks (allocated):", oh->nchunks,
351 oh->alloc_nchunks);
352
353 /* debug each chunk */
354 for (i = 0, chunk_total = 0; i < oh->nchunks; i++) {
355 size_t chunk_size;
356
357 HDfprintf(stream, "%*sChunk %d...\n", indent, "", i);
358
359 HDfprintf(stream, "%*s%-*s %" PRIuHADDR "\n", indent + 3, "", MAX(0, fwidth - 3),
360 "Address:", oh->chunk[i].addr);
361
362 /* Decrement chunk 0's size by the object header prefix size */
363 if (0 == i) {
364 if (H5F_addr_ne(oh->chunk[i].addr, addr))
365 HDfprintf(stream, "*** WRONG ADDRESS FOR CHUNK #0!\n");
366 chunk_size = oh->chunk[i].size - (size_t)H5O_SIZEOF_HDR(oh);
367 } /* end if */
368 else
369 chunk_size = oh->chunk[i].size;
370
371 /* Accumulate chunk's size to total */
372 chunk_total += chunk_size;
373 gap_total += oh->chunk[i].gap;
374
375 HDfprintf(stream, "%*s%-*s %zu\n", indent + 3, "", MAX(0, fwidth - 3), "Size in bytes:", chunk_size);
376
377 HDfprintf(stream, "%*s%-*s %zu\n", indent + 3, "", MAX(0, fwidth - 3), "Gap:", oh->chunk[i].gap);
378 } /* end for */
379
380 /* debug each message */
381 if (NULL == (sequence = (unsigned *)H5MM_calloc(NELMTS(H5O_msg_class_g) * sizeof(unsigned))))
382 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
383 for (i = 0, mesg_total = 0; i < oh->nmesgs; i++) {
384 const H5O_msg_class_t *debug_type; /* Type of message to use for callbacks */
385 unsigned chunkno; /* Chunk for message */
386
387 /* Accumulate message's size to total */
388 mesg_total += (size_t)H5O_SIZEOF_MSGHDR_OH(oh) + oh->mesg[i].raw_size;
389
390 /* For version 2 object header, add size of "OCHK" for continuation chunk */
391 if (oh->mesg[i].type->id == H5O_CONT_ID)
392 mesg_total += H5O_SIZEOF_CHKHDR_OH(oh);
393
394 HDfprintf(stream, "%*sMessage %d...\n", indent, "", i);
395
396 /* check for bad message id */
397 if (oh->mesg[i].type->id >= (int)NELMTS(H5O_msg_class_g)) {
398 HDfprintf(stream, "*** BAD MESSAGE ID 0x%04x\n", oh->mesg[i].type->id);
399 continue;
400 } /* end if */
401
402 /* message name and size */
403 HDfprintf(stream, "%*s%-*s 0x%04x `%s' (%d)\n", indent + 3, "", MAX(0, fwidth - 3),
404 "Message ID (sequence number):", (unsigned)(oh->mesg[i].type->id), oh->mesg[i].type->name,
405 sequence[oh->mesg[i].type->id]++);
406 HDfprintf(stream, "%*s%-*s %s\n", indent + 3, "", MAX(0, fwidth - 3),
407 "Dirty:", oh->mesg[i].dirty ? "TRUE" : "FALSE");
408 HDfprintf(stream, "%*s%-*s ", indent + 3, "", MAX(0, fwidth - 3), "Message flags:");
409 if (oh->mesg[i].flags) {
410 hbool_t flag_printed = FALSE;
411
412 /* Sanity check that all flags in format are covered below */
413 HDcompile_assert(H5O_MSG_FLAG_BITS ==
414 (H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_SHARED | H5O_MSG_FLAG_DONTSHARE |
415 H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE | H5O_MSG_FLAG_MARK_IF_UNKNOWN |
416 H5O_MSG_FLAG_WAS_UNKNOWN | H5O_MSG_FLAG_SHAREABLE |
417 H5O_MSG_FLAG_FAIL_IF_UNKNOWN_ALWAYS));
418
419 if (oh->mesg[i].flags & H5O_MSG_FLAG_CONSTANT) {
420 HDfprintf(stream, "%sC", (flag_printed ? ", " : "<"));
421 flag_printed = TRUE;
422 } /* end if */
423 if (oh->mesg[i].flags & H5O_MSG_FLAG_SHARED) {
424 HDfprintf(stream, "%sS", (flag_printed ? ", " : "<"));
425 flag_printed = TRUE;
426 } /* end if */
427 if (oh->mesg[i].flags & H5O_MSG_FLAG_DONTSHARE) {
428 HDfprintf(stream, "%sDS", (flag_printed ? ", " : "<"));
429 flag_printed = TRUE;
430 } /* end if */
431 if (oh->mesg[i].flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_AND_OPEN_FOR_WRITE) {
432 HDfprintf(stream, "%sFIUW", (flag_printed ? ", " : "<"));
433 flag_printed = TRUE;
434 } /* end if */
435 if (oh->mesg[i].flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN) {
436 HDfprintf(stream, "%sMIU", (flag_printed ? ", " : "<"));
437 flag_printed = TRUE;
438 } /* end if */
439 if (oh->mesg[i].flags & H5O_MSG_FLAG_WAS_UNKNOWN) {
440 HDassert(oh->mesg[i].flags & H5O_MSG_FLAG_MARK_IF_UNKNOWN);
441 HDfprintf(stream, "%sWU", (flag_printed ? ", " : "<"));
442 flag_printed = TRUE;
443 } /* end if */
444 if (oh->mesg[i].flags & H5O_MSG_FLAG_SHAREABLE) {
445 HDfprintf(stream, "%sSA", (flag_printed ? ", " : "<"));
446 flag_printed = TRUE;
447 } /* end if */
448 if (oh->mesg[i].flags & H5O_MSG_FLAG_FAIL_IF_UNKNOWN_ALWAYS) {
449 HDfprintf(stream, "%sFIUA", (flag_printed ? ", " : "<"));
450 flag_printed = TRUE;
451 } /* end if */
452 if (!flag_printed)
453 HDfprintf(stream, "-");
454 HDfprintf(stream, ">\n");
455 if (oh->mesg[i].flags & ~H5O_MSG_FLAG_BITS)
456 HDfprintf(stream, "%*s%-*s 0x%02x\n", indent + 3, "", MAX(0, fwidth - 3),
457 "*** ADDITIONAL UNKNOWN FLAGS --->", oh->mesg[i].flags & ~H5O_MSG_FLAG_BITS);
458 } /* end if */
459 else
460 HDfprintf(stream, "<none>\n");
461
462 HDfprintf(stream, "%*s%-*s %u\n", indent + 3, "", MAX(0, fwidth - 3),
463 "Chunk number:", oh->mesg[i].chunkno);
464 chunkno = oh->mesg[i].chunkno;
465 if (chunkno >= oh->nchunks)
466 HDfprintf(stream, "*** BAD CHUNK NUMBER\n");
467 HDfprintf(stream, "%*s%-*s (%zu, %zu) bytes\n", indent + 3, "", MAX(0, fwidth - 3),
468 "Raw message data (offset, size) in chunk:",
469 (size_t)(oh->mesg[i].raw - oh->chunk[chunkno].image), oh->mesg[i].raw_size);
470
471 /* check the size */
472 if ((oh->mesg[i].raw + oh->mesg[i].raw_size > oh->chunk[chunkno].image + oh->chunk[chunkno].size) ||
473 (oh->mesg[i].raw < oh->chunk[chunkno].image))
474 HDfprintf(stream, "*** BAD MESSAGE RAW ADDRESS\n");
475
476 /* decode the message */
477 debug_type = oh->mesg[i].type;
478 if (NULL == oh->mesg[i].native && debug_type->decode)
479 H5O_LOAD_NATIVE(f, H5O_DECODEIO_NOCHANGE, oh, &oh->mesg[i], FAIL)
480
481 /* print the message */
482 HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3), "Message Information:");
483 if (debug_type->debug && oh->mesg[i].native != NULL)
484 (debug_type->debug)(f, oh->mesg[i].native, stream, indent + 6, MAX(0, fwidth - 6));
485 else
486 HDfprintf(stream, "%*s<No info for this message>\n", indent + 6, "");
487 } /* end for */
488
489 if ((mesg_total + gap_total) != chunk_total)
490 HDfprintf(stream, "*** TOTAL SIZE DOES NOT MATCH ALLOCATED SIZE!\n");
491
492 done:
493 /* Release resources */
494 if (sequence)
495 sequence = (unsigned *)H5MM_xfree(sequence);
496
497 FUNC_LEAVE_NOAPI(ret_value)
498 } /* end H5O__debug_real() */
499
500 /*-------------------------------------------------------------------------
501 * Function: H5O_debug
502 *
503 * Purpose: Prints debugging info about an object header.
504 *
505 * Return: Non-negative on success/Negative on failure
506 *
507 * Programmer: Robb Matzke
508 * Aug 6 1997
509 *
510 *-------------------------------------------------------------------------
511 */
512 herr_t
H5O_debug(H5F_t * f,haddr_t addr,FILE * stream,int indent,int fwidth)513 H5O_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth)
514 {
515 H5O_t * oh = NULL; /* Object header to display */
516 H5O_loc_t loc; /* Object location for object to delete */
517 herr_t ret_value = SUCCEED; /* Return value */
518
519 FUNC_ENTER_NOAPI(FAIL)
520
521 /* check args */
522 HDassert(f);
523 HDassert(H5F_addr_defined(addr));
524 HDassert(stream);
525 HDassert(indent >= 0);
526 HDassert(fwidth >= 0);
527
528 /* Set up the object location */
529 loc.file = f;
530 loc.addr = addr;
531 loc.holding_file = FALSE;
532
533 if (NULL == (oh = H5O_protect(&loc, H5AC__READ_ONLY_FLAG, FALSE)))
534 HGOTO_ERROR(H5E_OHDR, H5E_CANTPROTECT, FAIL, "unable to load object header")
535
536 /* debug */
537 if (H5O__debug_real(f, oh, addr, stream, indent, fwidth) < 0)
538 HGOTO_ERROR(H5E_OHDR, H5E_SYSTEM, FAIL, "debug dump call failed")
539
540 done:
541 if (oh && H5O_unprotect(&loc, oh, H5AC__NO_FLAGS_SET) < 0)
542 HDONE_ERROR(H5E_OHDR, H5E_CANTUNPROTECT, FAIL, "unable to release object header")
543
544 FUNC_LEAVE_NOAPI(ret_value)
545 } /* end H5O_debug() */
546