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://support.hdfgroup.org/ftp/HDF5/releases.  *
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:		H5HFdbg.c
17  *			Feb 24 2006
18  *			Quincey Koziol <koziol@ncsa.uiuc.edu>
19  *
20  * Purpose:		Dump debugging information about a fractal heap
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #include "H5HFmodule.h"         /* This source code file is part of the H5HF module */
30 #define H5HF_DEBUGGING          /* Need access to fractal heap debugging routines */
31 
32 /***********/
33 /* Headers */
34 /***********/
35 #include "H5private.h"		/* Generic Functions			*/
36 #include "H5Eprivate.h"		/* Error handling		  	*/
37 #include "H5FLprivate.h"	/* Free Lists                           */
38 #include "H5HFpkg.h"		/* Fractal heaps			*/
39 #include "H5MMprivate.h"	/* Memory management			*/
40 #include "H5VMprivate.h"		/* Vectors and arrays 			*/
41 
42 /****************/
43 /* Local Macros */
44 /****************/
45 
46 
47 /******************/
48 /* Local Typedefs */
49 /******************/
50 
51 /* User data for direct block debugging iterator callback */
52 typedef struct {
53     FILE *stream;               /* Stream for output */
54     int indent;                 /* Indention amount */
55     int fwidth;                 /* Field width mount */
56     haddr_t dblock_addr;        /* Direct block's address */
57     hsize_t dblock_size;        /* Direct block's size */
58     uint8_t *marker;            /* 'Marker' array for free space */
59     size_t sect_count;          /* Number of free space sections in block */
60     size_t amount_free;         /* Amount of free space in block */
61 } H5HF_debug_iter_ud1_t;
62 
63 /* User data for free space section iterator callback */
64 typedef struct {
65     H5FS_t *fspace;             /* Free space manager */
66     FILE *stream;               /* Stream for output */
67     int indent;                 /* Indention amount */
68     int fwidth;                 /* Field width mount */
69 } H5HF_debug_iter_ud2_t;
70 
71 
72 /********************/
73 /* Package Typedefs */
74 /********************/
75 
76 
77 /********************/
78 /* Local Prototypes */
79 /********************/
80 
81 static herr_t H5HF_dtable_debug(const H5HF_dtable_t *dtable, FILE *stream,
82     int indent, int fwidth);
83 
84 
85 /*********************/
86 /* Package Variables */
87 /*********************/
88 
89 
90 /*****************************/
91 /* Library Private Variables */
92 /*****************************/
93 
94 
95 /*******************/
96 /* Local Variables */
97 /*******************/
98 
99 
100 /*-------------------------------------------------------------------------
101  * Function:	H5HF_id_print
102  *
103  * Purpose:	Prints a fractal heap ID.
104  *
105  * Return:	Non-negative on success/Negative on failure
106  *
107  * Programmer:	Quincey Koziol
108  *		koziol@hdfgroup.org
109  *		Aug 20 2015
110  *
111  *-------------------------------------------------------------------------
112  */
113 herr_t
H5HF_id_print(H5HF_t * fh,const void * _id,FILE * stream,int indent,int fwidth)114 H5HF_id_print(H5HF_t *fh, const void *_id, FILE *stream, int indent, int fwidth)
115 {
116     const uint8_t *id = (const uint8_t *)_id;   /* Object ID */
117     uint8_t id_flags;                   /* Heap ID flag bits */
118     hsize_t obj_off;                    /* Offset of object */
119     size_t obj_len;                     /* Length of object */
120     char id_type;                       /* Character for the type of heap ID */
121     herr_t      ret_value = SUCCEED;    /* Return value */
122 
123     FUNC_ENTER_NOAPI_NOINIT
124 
125     /*
126      * Check arguments.
127      */
128     HDassert(fh);
129     HDassert(id);
130     HDassert(stream);
131     HDassert(indent >= 0);
132     HDassert(fwidth >= 0);
133 
134     /* Get the ID flags */
135     id_flags = *id;
136 
137     /* Check for correct heap ID version */
138     if((id_flags & H5HF_ID_VERS_MASK) != H5HF_ID_VERS_CURR)
139         HGOTO_ERROR(H5E_HEAP, H5E_VERSION, FAIL, "incorrect heap ID version")
140 
141     /* Check type of object in heap */
142     if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_MAN) {
143         id_type = 'M';
144     } /* end if */
145     else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_HUGE) {
146         id_type = 'H';
147     } /* end if */
148     else if((id_flags & H5HF_ID_TYPE_MASK) == H5HF_ID_TYPE_TINY) {
149         id_type = 'T';
150     } /* end if */
151     else {
152 HDfprintf(stderr, "%s: Heap ID type not supported yet!\n", FUNC);
153 HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "heap ID type not supported yet")
154     } /* end else */
155 
156     /* Get the length of the heap object */
157     if(H5HF_get_obj_len(fh, id, &obj_len) < 0)
158         HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve heap ID length")
159 
160     /* Get the offset of the heap object */
161     if(H5HF_get_obj_off(fh, id, &obj_off) < 0)
162         HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve heap ID length")
163 
164     /* Display the heap ID */
165     HDfprintf(stream, "%*s%-*s (%c, %Hu, %Zu)\n", indent, "", fwidth,
166 	      "Heap ID info: (type, offset, length)",
167               id_type, obj_off, obj_len);
168 
169 done:
170     FUNC_LEAVE_NOAPI(ret_value)
171 } /* end H5HF_id_print() */
172 
173 
174 /*-------------------------------------------------------------------------
175  * Function:	H5HF_dtable_debug
176  *
177  * Purpose:	Prints debugging info about a doubling table
178  *
179  * Return:	Non-negative on success/Negative on failure
180  *
181  * Programmer:	Quincey Koziol
182  *		koziol@ncsa.uiuc.edu
183  *		Feb 28 2006
184  *
185  *-------------------------------------------------------------------------
186  */
187 static herr_t
H5HF_dtable_debug(const H5HF_dtable_t * dtable,FILE * stream,int indent,int fwidth)188 H5HF_dtable_debug(const H5HF_dtable_t *dtable, FILE *stream, int indent, int fwidth)
189 {
190     FUNC_ENTER_NOAPI_NOINIT_NOERR
191 
192     /*
193      * Check arguments.
194      */
195     HDassert(dtable);
196     HDassert(stream);
197     HDassert(indent >= 0);
198     HDassert(fwidth >= 0);
199 
200     /*
201      * Print the values.
202      */
203     /* Creation parameter values */
204     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
205 	      "Doubling table width:",
206 	      dtable->cparam.width);
207     HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
208 	      "Starting block size:",
209 	      dtable->cparam.start_block_size);
210     HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
211 	      "Max. direct block size:",
212 	      dtable->cparam.max_direct_size);
213     HDfprintf(stream, "%*s%-*s %u (bits)\n", indent, "", fwidth,
214 	      "Max. index size:",
215 	      dtable->cparam.max_index);
216     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
217 	      "Starting # of rows in root indirect block:",
218 	      dtable->cparam.start_root_rows);
219 
220     /* Run-time varying parameter values */
221     HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
222 	      "Table's root address:",
223 	      dtable->table_addr);
224     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
225 	      "Current # of rows in root indirect block:",
226 	      dtable->curr_root_rows);
227 
228     /* Computed values */
229     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
230 	      "Max. # of rows in root indirect block:",
231 	      dtable->max_root_rows);
232     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
233 	      "Max. # of direct rows in any indirect block:",
234 	      dtable->max_direct_rows);
235     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
236 	      "# of bits for IDs in first row:",
237 	      dtable->first_row_bits);
238     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
239 	      "# of IDs in first row:",
240 	      dtable->num_id_first_row);
241 
242     FUNC_LEAVE_NOAPI(SUCCEED)
243 } /* end H5HF_dtable_debug() */
244 
245 
246 /*-------------------------------------------------------------------------
247  * Function:	H5HF_hdr_print
248  *
249  * Purpose:	Prints info about a fractal heap header.
250  *
251  * Return:	Non-negative on success/Negative on failure
252  *
253  * Programmer:	Quincey Koziol
254  *		koziol@hdfgroup.org
255  *		Feb 23 2012
256  *
257  *-------------------------------------------------------------------------
258  */
259 void
H5HF_hdr_print(const H5HF_hdr_t * hdr,hbool_t dump_internal,FILE * stream,int indent,int fwidth)260 H5HF_hdr_print(const H5HF_hdr_t *hdr, hbool_t dump_internal, FILE *stream, int indent, int fwidth)
261 {
262     FUNC_ENTER_NOAPI_NOINIT_NOERR
263 
264     /*
265      * Check arguments.
266      */
267     HDassert(hdr);
268     HDassert(stream);
269     HDassert(indent >= 0);
270     HDassert(fwidth >= 0);
271 
272     /* Print opening message */
273     HDfprintf(stream, "%*sFractal Heap Header...\n", indent, "");
274 
275     /*
276      * Print the values.
277      */
278     HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth,
279 	      "Heap is:",
280 	      hdr->man_dtable.curr_root_rows > 0 ? "Indirect" : "Direct");
281     HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
282 	      "Objects stored in 'debugging' format:",
283 	      hdr->debug_objs);
284     HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
285 	      "'Write once' flag:",
286 	      hdr->write_once);
287     HDfprintf(stream, "%*s%-*s %t\n", indent, "", fwidth,
288 	      "'Huge' object IDs have wrapped:",
289 	      hdr->huge_ids_wrapped);
290     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
291 	      "Free space in managed blocks:",
292 	      hdr->total_man_free);
293     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
294 	      "Managed space data block size:",
295 	      hdr->man_size);
296     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
297 	      "Total managed space allocated:",
298 	      hdr->man_alloc_size);
299     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
300 	      "Offset of managed space iterator:",
301 	      hdr->man_iter_off);
302     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
303 	      "Number of managed objects in heap:",
304 	      hdr->man_nobjs);
305     HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
306 	      "Address of free space manager for managed blocks:",
307 	      hdr->fs_addr);
308     HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
309 	      "Max. size of managed object:",
310 	      (unsigned long)hdr->max_man_size);
311     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
312 	      "'Huge' object space used:",
313 	      hdr->huge_size);
314     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
315 	      "Number of 'huge' objects in heap:",
316 	      hdr->huge_nobjs);
317     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
318 	      "ID of next 'huge' object:",
319 	      hdr->huge_next_id);
320     HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
321 	      "Address of v2 B-tree for 'huge' objects:",
322 	      hdr->huge_bt2_addr);
323     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
324 	      "'Tiny' object space used:",
325 	      hdr->tiny_size);
326     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
327 	      "Number of 'tiny' objects in heap:",
328 	      hdr->tiny_nobjs);
329 
330     HDfprintf(stream, "%*sManaged Objects Doubling-Table Info...\n", indent, "");
331     H5HF_dtable_debug(&hdr->man_dtable, stream, indent + 3, MAX(0, fwidth - 3));
332 
333     /* Print information about I/O filters */
334     if(hdr->filter_len > 0) {
335         HDfprintf(stream, "%*sI/O filter Info...\n", indent, "");
336         if(hdr->man_dtable.curr_root_rows == 0) {
337             HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
338                       "Compressed size of root direct block:",
339                       hdr->pline_root_direct_size);
340             HDfprintf(stream, "%*s%-*s %x\n", indent + 3, "", MAX(0, fwidth - 3),
341                       "Filter mask for root direct block:",
342                       hdr->pline_root_direct_filter_mask);
343         } /* end if */
344         H5O_debug_id(H5O_PLINE_ID, hdr->f, &(hdr->pline), stream, indent + 3, MAX(0, fwidth - 3));
345     } /* end if */
346 
347     /* Print internal (runtime) information, if requested */
348     if(dump_internal) {
349         HDfprintf(stream, "%*sFractal Heap Header Internal Information:\n", indent, "");
350 
351         /* Dump root iblock, if there is one */
352         HDfprintf(stream, "%*s%-*s %x\n", indent + 3, "", MAX(0, fwidth - 3),
353                   "Root indirect block flags:",
354                   hdr->root_iblock_flags);
355         HDfprintf(stream, "%*s%-*s %p\n", indent + 3, "", MAX(0, fwidth - 3),
356                   "Root indirect block pointer:",
357                   hdr->root_iblock);
358         if(hdr->root_iblock)
359             H5HF_iblock_print(hdr->root_iblock, dump_internal, stream, indent + 3, fwidth);
360     } /* end if */
361 
362     FUNC_LEAVE_NOAPI_VOID
363 } /* end H5HF_hdr_print() */
364 
365 
366 /*-------------------------------------------------------------------------
367  * Function:	H5HF_hdr_debug
368  *
369  * Purpose:	Prints debugging info about a fractal heap header.
370  *
371  * Return:	Non-negative on success/Negative on failure
372  *
373  * Programmer:	Quincey Koziol
374  *		koziol@ncsa.uiuc.edu
375  *		Feb 24 2006
376  *
377  *-------------------------------------------------------------------------
378  */
379 herr_t
H5HF_hdr_debug(H5F_t * f,haddr_t addr,FILE * stream,int indent,int fwidth)380 H5HF_hdr_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth)
381 {
382     H5HF_hdr_t	*hdr = NULL;             /* Fractal heap header info */
383     herr_t      ret_value = SUCCEED;    /* Return value */
384 
385     FUNC_ENTER_NOAPI(FAIL)
386 
387     /*
388      * Check arguments.
389      */
390     HDassert(f);
391     HDassert(H5F_addr_defined(addr));
392     HDassert(stream);
393     HDassert(indent >= 0);
394     HDassert(fwidth >= 0);
395 
396     /* Load the fractal heap header */
397     if(NULL == (hdr = H5HF__hdr_protect(f, addr, H5AC__READ_ONLY_FLAG)))
398 	HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
399 
400     /* Print the information about the heap's header */
401     H5HF_hdr_print(hdr, FALSE, stream, indent, fwidth);
402 
403 done:
404     if(hdr && H5AC_unprotect(f, H5AC_FHEAP_HDR, addr, hdr, H5AC__NO_FLAGS_SET) < 0)
405         HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
406 
407     FUNC_LEAVE_NOAPI(ret_value)
408 } /* end H5HF_hdr_debug() */
409 
410 
411 /*-------------------------------------------------------------------------
412  * Function:	H5HF_dblock_debug_cb
413  *
414  * Purpose:	Detect free space within a direct block
415  *
416  * Return:	Non-negative on success/Negative on failure
417  *
418  * Programmer:	Quincey Koziol
419  *		koziol@ncsa.uiuc.edu
420  *		May 13 2006
421  *
422  *-------------------------------------------------------------------------
423  */
424 static herr_t
H5HF_dblock_debug_cb(H5FS_section_info_t * _sect,void * _udata)425 H5HF_dblock_debug_cb(H5FS_section_info_t *_sect, void *_udata)
426 {
427     H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect;       /* Section to dump info */
428     H5HF_debug_iter_ud1_t *udata = (H5HF_debug_iter_ud1_t *)_udata;         /* User data for callbacks */
429     haddr_t sect_start, sect_end;       /* Section's beginning and ending offsets */
430     haddr_t dblock_start, dblock_end;   /* Direct block's beginning and ending offsets */
431 
432     FUNC_ENTER_NOAPI_NOINIT_NOERR
433 
434     /*
435      * Check arguments.
436      */
437     HDassert(sect);
438     HDassert(udata);
439 
440     /* Set up some local variables, for convenience */
441     sect_start = sect->sect_info.addr;
442     sect_end = (sect->sect_info.addr + sect->sect_info.size) - 1;
443     HDassert(sect_end >= sect_start);
444     dblock_start = udata->dblock_addr;
445     dblock_end = (udata->dblock_addr + udata->dblock_size) - 1;
446     HDassert(dblock_end >= dblock_start);
447 
448     /* Check for overlap between free space section & direct block */
449     if((sect_start <= dblock_end && sect_end >=dblock_start) || /* section within or overlaps w/beginning of direct block*/
450             (sect_start <= dblock_end && sect_end >=dblock_end)) {  /* section overlaps w/end of direct block */
451         char temp_str[32];      /* Temporary string for formatting */
452         size_t start, end;      /* Start & end of the overlapping area */
453         size_t len;             /* Length of the overlapping area */
454         size_t overlap;         /* Track any overlaps */
455         size_t u;               /* Local index variable */
456 
457         /* Calculate the starting & ending */
458         if(sect_start < dblock_start)
459             start = 0;
460         else
461             H5_CHECKED_ASSIGN(start, size_t, (sect_start - dblock_start), hsize_t)
462         if(sect_end > dblock_end)
463             H5_CHECKED_ASSIGN(end, size_t, udata->dblock_size, hsize_t)
464         else
465             H5_CHECKED_ASSIGN(end, size_t, ((sect_end - dblock_start) + 1), hsize_t)
466 
467         /* Calculate the length */
468         len = end - start;
469 
470         HDsnprintf(temp_str, sizeof(temp_str), "Section #%u:", (unsigned)udata->sect_count);
471 	HDfprintf(udata->stream, "%*s%-*s %8Zu, %8Zu\n", udata->indent + 3, "", MAX(0, udata->fwidth - 9),
472 		temp_str,
473 		start, len);
474         udata->sect_count++;
475 
476         /* Mark this node's free space & check for overlaps w/other sections */
477         overlap = 0;
478         for(u = start; u < end; u++) {
479             if(udata->marker[u])
480                 overlap++;
481             udata->marker[u] = 1;
482         } /* end for */
483 
484         /* Flag overlaps */
485         if (overlap)
486             fprintf(udata->stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n");
487         else
488             udata->amount_free += len;
489     } /* end if */
490 
491     FUNC_LEAVE_NOAPI(SUCCEED)
492 } /* end H5HF_dblock_debug_cb() */
493 
494 
495 /*-------------------------------------------------------------------------
496  * Function:	H5HF_dblock_debug
497  *
498  * Purpose:	Prints debugging info about a fractal heap direct block.
499  *
500  * Return:	Non-negative on success/Negative on failure
501  *
502  * Programmer:	Quincey Koziol
503  *		koziol@ncsa.uiuc.edu
504  *		Feb 28 2006
505  *
506  *-------------------------------------------------------------------------
507  */
508 herr_t
H5HF_dblock_debug(H5F_t * f,haddr_t addr,FILE * stream,int indent,int fwidth,haddr_t hdr_addr,size_t block_size)509 H5HF_dblock_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth,
510     haddr_t hdr_addr, size_t block_size)
511 {
512     H5HF_hdr_t	*hdr = NULL;            /* Fractal heap header info */
513     H5HF_direct_t *dblock = NULL;       /* Fractal heap direct block info */
514     size_t	blk_prefix_size;        /* Size of prefix for block */
515     size_t	amount_free;            /* Amount of free space in block */
516     uint8_t	*marker = NULL;         /* Track free space for block */
517     herr_t      ret_value = SUCCEED;    /* Return value */
518 
519     FUNC_ENTER_NOAPI(FAIL)
520 
521     /*
522      * Check arguments.
523      */
524     HDassert(f);
525     HDassert(H5F_addr_defined(addr));
526     HDassert(stream);
527     HDassert(indent >= 0);
528     HDassert(fwidth >= 0);
529     HDassert(H5F_addr_defined(hdr_addr));
530     HDassert(block_size > 0);
531 
532     /* Load the fractal heap header */
533     if(NULL == (hdr = H5HF__hdr_protect(f, hdr_addr, H5AC__READ_ONLY_FLAG)))
534 	HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
535 
536     /*
537      * Load the heap direct block
538      */
539     if(NULL == (dblock = H5HF__man_dblock_protect(hdr, addr, block_size, NULL, 0, H5AC__READ_ONLY_FLAG)))
540 	HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap direct block")
541 
542     /* Print opening message */
543     HDfprintf(stream, "%*sFractal Heap Direct Block...\n", indent, "");
544 
545     /*
546      * Print the values.
547      */
548     HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
549 	      "Address of fractal heap that owns this block:",
550 	      hdr->heap_addr);
551     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
552 	      "Offset of direct block in heap:",
553 	      dblock->block_off);
554     blk_prefix_size = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
555     HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
556 	      "Size of block header:",
557               blk_prefix_size);
558 
559     /* Allocate space for the free space markers */
560     if(NULL == (marker = (uint8_t *)H5MM_calloc(dblock->size)))
561 	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
562 
563     /* Initialize the free space information for the heap */
564     if(H5HF__space_start(hdr, FALSE) < 0)
565         HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
566 
567     /* If there is a free space manager for the heap, check for sections that overlap this block */
568     if(hdr->fspace) {
569         H5HF_debug_iter_ud1_t udata;        /* User data for callbacks */
570 
571         /* Prepare user data for section iteration callback */
572         udata.stream = stream;
573         udata.indent = indent;
574         udata.fwidth = fwidth;
575         udata.dblock_addr = dblock->block_off;
576         udata.dblock_size = block_size;
577         udata.marker = marker;
578         udata.sect_count = 0;
579         udata.amount_free = 0;
580 
581         /* Print header */
582         HDfprintf(stream, "%*sFree Blocks (offset, size):\n", indent, "");
583 
584         /* Iterate over the free space sections, to detect overlaps with this block */
585         if(H5FS_sect_iterate(f, hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0)
586             HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
587 
588         /* Close the free space information */
589         if(H5HF__space_close(hdr) < 0)
590             HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info")
591 
592         /* Keep the amount of space free */
593         amount_free = udata.amount_free;
594 
595         /* Check for no free space */
596         if(amount_free == 0)
597             HDfprintf(stream, "%*s<none>\n", indent + 3, "");
598     } /* end if */
599     else
600         amount_free = 0;
601 
602     HDfprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth,
603             "Percent of available space for data used:",
604             ((double)100.0f * (double)((dblock->size - blk_prefix_size) - amount_free) / (double)(dblock->size - blk_prefix_size)));
605 
606     /*
607      * Print the data in a VMS-style octal dump.
608      */
609     H5_buffer_dump(stream, indent, dblock->blk, marker, (size_t)0, dblock->size);
610 
611 done:
612     if(dblock && H5AC_unprotect(f, H5AC_FHEAP_DBLOCK, addr, dblock, H5AC__NO_FLAGS_SET) < 0)
613         HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap direct block")
614     if(hdr && H5AC_unprotect(f, H5AC_FHEAP_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
615         HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
616     H5MM_xfree(marker);
617 
618     FUNC_LEAVE_NOAPI(ret_value)
619 } /* end H5HF_dblock_debug() */
620 
621 
622 /*-------------------------------------------------------------------------
623  * Function:	H5HF_iblock_print
624  *
625  * Purpose:	Prints debugging info about a fractal heap indirect block.
626  *
627  * Return:	Non-negative on success/Negative on failure
628  *
629  * Programmer:	Quincey Koziol
630  *		koziol@hdfgroup.org
631  *		Feb 23 2012
632  *
633  *-------------------------------------------------------------------------
634  */
635 void
H5HF_iblock_print(const H5HF_indirect_t * iblock,hbool_t dump_internal,FILE * stream,int indent,int fwidth)636 H5HF_iblock_print(const H5HF_indirect_t *iblock,
637     hbool_t dump_internal, FILE *stream, int indent, int fwidth)
638 {
639     const H5HF_hdr_t *hdr;              /* Pointer to heap's header */
640     char temp_str[64];                  /* Temporary string, for formatting */
641     size_t	u, v;                   /* Local index variable */
642 
643     FUNC_ENTER_NOAPI_NOINIT_NOERR
644 
645     /*
646      * Check arguments.
647      */
648     HDassert(iblock);
649     HDassert(iblock->hdr);
650     HDassert(stream);
651     HDassert(indent >= 0);
652     HDassert(fwidth >= 0);
653 
654     /* Set up convenience variables */
655     hdr = iblock->hdr;
656 
657     /* Print opening message */
658     HDfprintf(stream, "%*sFractal Heap Indirect Block...\n", indent, "");
659 
660     /*
661      * Print the values.
662      */
663     HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth,
664 	      "Address of fractal heap that owns this block:",
665 	      hdr->heap_addr);
666     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
667 	      "Offset of indirect block in heap:",
668 	      iblock->block_off);
669     HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth,
670 	      "Size of indirect block:",
671 	      iblock->size);
672     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
673 	      "Current # of rows:",
674 	      iblock->nrows);
675     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
676 	      "Max. # of rows:",
677 	      iblock->max_rows);
678     HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
679 	      "Max direct block rows:",
680 	      hdr->man_dtable.max_direct_rows);
681 
682     /* Print the entry tables */
683     if(hdr->filter_len > 0)
684         HDfprintf(stream, "%*sDirect Block Entries: (address/compressed size/filter mask)\n", indent, "");
685     else
686         HDfprintf(stream, "%*sDirect Block Entries: (address)\n", indent, "");
687     for(u = 0; u < hdr->man_dtable.max_direct_rows && u < iblock->nrows; u++) {
688         HDsnprintf(temp_str, sizeof(temp_str), "Row #%u: (block size: %lu)", (unsigned)u, (unsigned long)hdr->man_dtable.row_block_size[u]);
689         HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
690                 temp_str);
691         for(v = 0; v < hdr->man_dtable.cparam.width; v++) {
692             size_t off = (u * hdr->man_dtable.cparam.width) + v;
693 
694             HDsnprintf(temp_str, sizeof(temp_str), "Col #%u:", (unsigned)v);
695             if(hdr->filter_len > 0)
696                 HDfprintf(stream, "%*s%-*s %9a/%6Zu/%x\n", indent + 6, "", MAX(0, fwidth - 6),
697                         temp_str,
698                         iblock->ents[off].addr,
699                         iblock->filt_ents[off].size,
700                         iblock->filt_ents[off].filter_mask);
701             else
702                 HDfprintf(stream, "%*s%-*s %9a\n", indent + 6, "", MAX(0, fwidth - 6),
703                         temp_str,
704                         iblock->ents[off].addr);
705         } /* end for */
706     } /* end for */
707     HDfprintf(stream, "%*sIndirect Block Entries:\n", indent, "");
708     if(iblock->nrows > hdr->man_dtable.max_direct_rows) {
709         unsigned    first_row_bits;         /* Number of bits used bit addresses in first row */
710         unsigned    num_indirect_rows;      /* Number of rows of blocks in each indirect block */
711 
712         first_row_bits = H5VM_log2_of2((uint32_t)hdr->man_dtable.cparam.start_block_size) +
713                             H5VM_log2_of2(hdr->man_dtable.cparam.width);
714         for(u = hdr->man_dtable.max_direct_rows; u < iblock->nrows; u++) {
715             num_indirect_rows = (H5VM_log2_gen(hdr->man_dtable.row_block_size[u]) - first_row_bits) + 1;
716             HDsnprintf(temp_str, sizeof(temp_str), "Row #%u: (# of rows: %u)", (unsigned)u, num_indirect_rows);
717             HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
718                     temp_str);
719             for(v = 0; v < hdr->man_dtable.cparam.width; v++) {
720                 size_t off = (u * hdr->man_dtable.cparam.width) + v;
721 
722                 HDsnprintf(temp_str, sizeof(temp_str), "Col #%u:", (unsigned)v);
723                 HDfprintf(stream, "%*s%-*s %9a\n", indent + 6, "", MAX(0, fwidth - 6),
724                         temp_str,
725                         iblock->ents[off].addr);
726             } /* end for */
727         } /* end for */
728     } /* end if */
729     else
730         HDfprintf(stream, "%*s%-*s\n", indent + 3, "", MAX(0, fwidth - 3),
731                   "<none>");
732 
733     /* Print internal (runtime) information, if requested */
734     if(dump_internal) {
735         HDfprintf(stream, "%*sFractal Indirect Block Internal Information:\n", indent, "");
736 
737         /* Print general information */
738         HDfprintf(stream, "%*s%-*s %Zu\n", indent + 3, "", MAX(0, fwidth - 3),
739                   "Reference count:",
740                   iblock->rc);
741 
742         /* Print parent's information */
743         HDfprintf(stream, "%*s%-*s %p\n", indent + 3, "", MAX(0, fwidth - 3),
744                   "Parent indirect block address:",
745                   iblock->parent);
746         if(iblock->parent)
747             H5HF_iblock_print(iblock->parent, TRUE, stream, indent + 6, fwidth);
748     } /* end if */
749 
750     FUNC_LEAVE_NOAPI_VOID
751 } /* end H5HF_iblock_print() */
752 
753 
754 /*-------------------------------------------------------------------------
755  * Function:	H5HF_iblock_debug
756  *
757  * Purpose:	Prints debugging info about a fractal heap indirect block.
758  *
759  * Return:	Non-negative on success/Negative on failure
760  *
761  * Programmer:	Quincey Koziol
762  *		koziol@ncsa.uiuc.edu
763  *		Mar  7 2006
764  *
765  *-------------------------------------------------------------------------
766  */
767 herr_t
H5HF_iblock_debug(H5F_t * f,haddr_t addr,FILE * stream,int indent,int fwidth,haddr_t hdr_addr,unsigned nrows)768 H5HF_iblock_debug(H5F_t *f, haddr_t addr, FILE *stream, int indent, int fwidth,
769     haddr_t hdr_addr, unsigned nrows)
770 {
771     H5HF_hdr_t	*hdr = NULL;            /* Fractal heap header info */
772     H5HF_indirect_t *iblock = NULL;     /* Fractal heap direct block info */
773     hbool_t did_protect;                /* Whether we protected the indirect block or not */
774     herr_t      ret_value = SUCCEED;    /* Return value */
775 
776     FUNC_ENTER_NOAPI(FAIL)
777 
778     /*
779      * Check arguments.
780      */
781     HDassert(f);
782     HDassert(H5F_addr_defined(addr));
783     HDassert(stream);
784     HDassert(indent >= 0);
785     HDassert(fwidth >= 0);
786     HDassert(H5F_addr_defined(hdr_addr));
787     HDassert(nrows > 0);
788 
789     /* Load the fractal heap header */
790     if(NULL == (hdr = H5HF__hdr_protect(f, hdr_addr, H5AC__READ_ONLY_FLAG)))
791 	HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
792 
793     /*
794      * Load the heap indirect block
795      */
796     if(NULL == (iblock = H5HF__man_iblock_protect(hdr, addr, nrows, NULL, 0, FALSE, H5AC__READ_ONLY_FLAG, &did_protect)))
797 	HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap indirect block")
798 
799     /* Print the information about the heap's indirect block */
800     H5HF_iblock_print(iblock, FALSE, stream, indent, fwidth);
801 
802 done:
803     if(iblock && H5HF__man_iblock_unprotect(iblock, H5AC__NO_FLAGS_SET, did_protect) < 0)
804         HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap direct block")
805     if(hdr && H5AC_unprotect(f, H5AC_FHEAP_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
806         HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
807 
808     FUNC_LEAVE_NOAPI(ret_value)
809 } /* end H5HF_iblock_debug() */
810 
811 
812 /*-------------------------------------------------------------------------
813  * Function:	H5HF_sects_debug_cb
814  *
815  * Purpose:	Prints debugging info about a free space section for a fractal heap.
816  *
817  * Return:	Non-negative on success/Negative on failure
818  *
819  * Programmer:	Quincey Koziol
820  *		koziol@ncsa.uiuc.edu
821  *		May 13 2006
822  *
823  *-------------------------------------------------------------------------
824  */
825 static herr_t
H5HF_sects_debug_cb(H5FS_section_info_t * _sect,void * _udata)826 H5HF_sects_debug_cb(H5FS_section_info_t *_sect, void *_udata)
827 {
828     H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect;       /* Section to dump info */
829     H5HF_debug_iter_ud2_t *udata = (H5HF_debug_iter_ud2_t *)_udata;         /* User data for callbacks */
830     herr_t      ret_value = SUCCEED;    /* Return value */
831 
832     FUNC_ENTER_NOAPI_NOINIT
833 
834     /*
835      * Check arguments.
836      */
837     HDassert(sect);
838     HDassert(udata);
839 
840     /* Print generic section information */
841     HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth,
842 	      "Section type:",
843 	      (sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE ? "single" :
844                   (sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ? "first row" :
845                   (sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW ? "normal row" : "unknown"))));
846     HDfprintf(udata->stream, "%*s%-*s %a\n", udata->indent, "", udata->fwidth,
847 	      "Section address:",
848 	      sect->sect_info.addr);
849     HDfprintf(udata->stream, "%*s%-*s %Hu\n", udata->indent, "", udata->fwidth,
850 	      "Section size:",
851 	      sect->sect_info.size);
852 #ifdef QAK
853     HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth,
854 	      "Section state:",
855 	      (sect->sect_info.state == H5FS_SECT_LIVE ? "live" : "serialized"));
856 #endif /* QAK */
857 
858     /* Dump section-specific debugging information */
859     if(H5FS_sect_debug(udata->fspace, _sect, udata->stream, udata->indent + 3, MAX(0, udata->fwidth - 3)) < 0)
860         HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't dump section's debugging info")
861 
862 done:
863     FUNC_LEAVE_NOAPI(ret_value)
864 } /* end H5HF_sects_debug_cb() */
865 
866 
867 /*-------------------------------------------------------------------------
868  * Function:	H5HF_sects_debug
869  *
870  * Purpose:	Prints debugging info about free space sections for a fractal heap.
871  *
872  * Return:	Non-negative on success/Negative on failure
873  *
874  * Programmer:	Quincey Koziol
875  *		koziol@ncsa.uiuc.edu
876  *		May  9 2006
877  *
878  *-------------------------------------------------------------------------
879  */
880 herr_t
H5HF_sects_debug(H5F_t * f,haddr_t fh_addr,FILE * stream,int indent,int fwidth)881 H5HF_sects_debug(H5F_t *f, haddr_t fh_addr, FILE *stream, int indent,
882     int fwidth)
883 {
884     H5HF_hdr_t	*hdr = NULL;            /* Fractal heap header info */
885     herr_t      ret_value = SUCCEED;    /* Return value */
886 
887     FUNC_ENTER_NOAPI(FAIL)
888 
889     /*
890      * Check arguments.
891      */
892     HDassert(f);
893     HDassert(H5F_addr_defined(fh_addr));
894     HDassert(stream);
895     HDassert(indent >= 0);
896     HDassert(fwidth >= 0);
897 
898     /* Load the fractal heap header */
899     if(NULL == (hdr = H5HF__hdr_protect(f, fh_addr, H5AC__READ_ONLY_FLAG)))
900 	HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap header")
901 
902     /* Initialize the free space information for the heap */
903     if(H5HF__space_start(hdr, FALSE) < 0)
904         HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
905 
906     /* If there is a free space manager for the heap, iterate over them */
907     if(hdr->fspace) {
908         H5HF_debug_iter_ud2_t udata;        /* User data for callbacks */
909 
910         /* Prepare user data for section iteration callback */
911         udata.fspace = hdr->fspace;
912         udata.stream = stream;
913         udata.indent = indent;
914         udata.fwidth = fwidth;
915 
916         /* Iterate over all the free space sections */
917         if(H5FS_sect_iterate(f, hdr->fspace, H5HF_sects_debug_cb, &udata) < 0)
918             HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space")
919 
920         /* Close the free space information */
921         if(H5HF__space_close(hdr) < 0)
922             HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info")
923     } /* end if */
924 
925 done:
926     if(hdr && H5AC_unprotect(f, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
927         HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header")
928 
929     FUNC_LEAVE_NOAPI(ret_value)
930 } /* end H5HF_sects_debug() */
931 
932