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 files COPYING and Copyright.html.  COPYING can be found at the root   *
9  * of the source code distribution tree; Copyright.html can be found at the  *
10  * root level of an installed copy of the electronic HDF5 document set and   *
11  * is linked from the top-level documents page.  It can also be found at     *
12  * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
13  * access to either file, you may request a copy from help@hdfgroup.org.     *
14  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /*-------------------------------------------------------------------------
17  *
18  * Created:		H5HFman.c
19  *			Feb 24 2006
20  *			Quincey Koziol <koziol@ncsa.uiuc.edu>
21  *
22  * Purpose:		"Managed" object routines for fractal heaps.
23  *
24  *-------------------------------------------------------------------------
25  */
26 
27 /****************/
28 /* Module Setup */
29 /****************/
30 
31 #define H5HF_PACKAGE		/*suppress error about including H5HFpkg  */
32 
33 /***********/
34 /* Headers */
35 /***********/
36 #include "H5private.h"		/* Generic Functions			*/
37 #include "H5Eprivate.h"		/* Error handling		  	*/
38 #include "H5HFpkg.h"		/* Fractal heaps			*/
39 #include "H5MFprivate.h"	/* File memory management		*/
40 #include "H5MMprivate.h"	/* Memory management			*/
41 #include "H5VMprivate.h"		/* Vectors and arrays 			*/
42 
43 /****************/
44 /* Local Macros */
45 /****************/
46 
47 /* Macro to check if we can apply all filters in the pipeline.  Use whenever
48  * performing a modification operation */
49  #define H5HF_MAN_WRITE_CHECK_PLINE(HDR)                                       \
50 {                                                                              \
51     if(!((HDR)->checked_filters)) {                                            \
52         if((HDR)->pline.nused)                                                 \
53             if(H5Z_can_apply_direct(&((HDR)->pline)) < 0)                      \
54                 HGOTO_ERROR(H5E_ARGS, H5E_CANTINIT, FAIL, "I/O filters can't operate on this heap") \
55                                                                                \
56         (HDR)->checked_filters = TRUE;                                         \
57     } /* end if */                                                             \
58 }
59 
60 
61 /******************/
62 /* Local Typedefs */
63 /******************/
64 
65 
66 /********************/
67 /* Package Typedefs */
68 /********************/
69 
70 
71 /********************/
72 /* Local Prototypes */
73 /********************/
74 static herr_t H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id,
75     const uint8_t *id, H5HF_operator_t op, void *op_data, unsigned op_flags);
76 
77 /*********************/
78 /* Package Variables */
79 /*********************/
80 
81 
82 /*****************************/
83 /* Library Private Variables */
84 /*****************************/
85 
86 
87 /*******************/
88 /* Local Variables */
89 /*******************/
90 
91 
92 
93 /*-------------------------------------------------------------------------
94  * Function:	H5HF_man_insert
95  *
96  * Purpose:	Insert an object in a managed direct block
97  *
98  * Return:	SUCCEED/FAIL
99  *
100  * Programmer:	Quincey Koziol
101  *		koziol@ncsa.uiuc.edu
102  *		Mar 13 2006
103  *
104  *-------------------------------------------------------------------------
105  */
106 herr_t
H5HF_man_insert(H5HF_hdr_t * hdr,hid_t dxpl_id,size_t obj_size,const void * obj,void * _id)107 H5HF_man_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t obj_size, const void *obj,
108     void *_id)
109 {
110     H5HF_free_section_t *sec_node = NULL;   /* Pointer to free space section */
111     H5HF_direct_t *dblock = NULL;       /* Pointer to direct block to modify */
112     haddr_t dblock_addr = HADDR_UNDEF;  /* Direct block address */
113     size_t dblock_size;                 /* Direct block size */
114     uint8_t *id = (uint8_t *)_id;       /* Pointer to ID buffer */
115     size_t blk_off;                     /* Offset of object within block */
116     htri_t node_found;                  /* Whether an existing free list node was found */
117     herr_t ret_value = SUCCEED;         /* Return value */
118 
119     FUNC_ENTER_NOAPI_NOINIT
120 
121     /*
122      * Check arguments.
123      */
124     HDassert(hdr);
125     HDassert(obj_size > 0);
126     HDassert(obj);
127     HDassert(id);
128 
129     /* Check pipeline */
130     H5HF_MAN_WRITE_CHECK_PLINE(hdr)
131 
132     /* Look for free space */
133     if((node_found = H5HF_space_find(hdr, dxpl_id, (hsize_t)obj_size, &sec_node)) < 0)
134         HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap")
135 
136     /* If we didn't find a node, go create a direct block big enough to hold the requested block */
137     if(!node_found)
138         /* Allocate direct block big enough to hold requested size */
139         if(H5HF_man_dblock_new(hdr, dxpl_id, obj_size, &sec_node) < 0)
140             HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create fractal heap direct block")
141 
142     /* Check for row section */
143     if(sec_node->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
144             sec_node->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW) {
145 
146         /* Allocate 'single' selection out of 'row' selection */
147         if(H5HF_man_iblock_alloc_row(hdr, dxpl_id, &sec_node) < 0)
148             HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up row section")
149     } /* end if */
150     HDassert(sec_node->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
151 
152     /* Check for 'single' section being serialized */
153     if(sec_node->sect_info.state == H5FS_SECT_SERIALIZED) {
154         if(H5HF_sect_single_revive(hdr, dxpl_id, sec_node) < 0)
155             HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
156     } /* end if */
157     HDassert(sec_node->sect_info.state == H5FS_SECT_LIVE);
158 
159     /* Retrieve direct block address from section */
160     if(H5HF_sect_single_dblock_info(hdr, dxpl_id, sec_node, &dblock_addr, &dblock_size) < 0)
161         HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information")
162 
163     /* Lock direct block */
164     if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sec_node->u.single.parent, sec_node->u.single.par_entry, H5AC_WRITE)))
165         HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
166 
167     /* Insert object into block */
168 
169     /* Get the offset of the object within the block */
170     H5_CHECK_OVERFLOW((sec_node->sect_info.addr - dblock->block_off), hsize_t, size_t);
171     blk_off = (size_t)(sec_node->sect_info.addr - dblock->block_off);
172 
173     /* Sanity checks */
174     HDassert(sec_node->sect_info.size >= obj_size);
175 
176     /* Reduce (& possibly re-add) single section */
177     if(H5HF_sect_single_reduce(hdr, dxpl_id, sec_node, obj_size) < 0)
178         HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce single section node")
179     sec_node = NULL;
180 
181     /* Encode the object in the block */
182     {
183         uint8_t *p;                         /* Temporary pointer to obj info in block */
184 
185         /* Point to location for object */
186         p = dblock->blk + blk_off;
187 
188         /* Copy the object's data into the heap */
189         HDmemcpy(p, obj, obj_size);
190         p += obj_size;
191 
192         /* Sanity check */
193         HDassert((size_t)(p - (dblock->blk + blk_off)) == obj_size);
194     } /* end block */
195 
196     /* Set the heap ID for the new object (heap offset & obj length) */
197     H5HF_MAN_ID_ENCODE(id, hdr, (dblock->block_off + blk_off), obj_size);
198 
199     /* Update statistics about heap */
200     hdr->man_nobjs++;
201 
202     /* Reduce space available in heap (marks header dirty) */
203     if(H5HF_hdr_adj_free(hdr, -(ssize_t)obj_size) < 0)
204         HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap")
205 
206 done:
207     /* Release section node on error */
208     if(ret_value < 0)
209         if(sec_node && H5HF_sect_single_free((H5FS_section_info_t *)sec_node) < 0)
210             HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release section node")
211 
212     /* Release the direct block (marked as dirty) */
213     if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__DIRTIED_FLAG) < 0)
214         HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
215 
216     FUNC_LEAVE_NOAPI(ret_value)
217 } /* end H5HF_man_insert() */
218 
219 
220 /*-------------------------------------------------------------------------
221  * Function:	H5HF_man_op_real
222  *
223  * Purpose:	Internal routine to perform an operation on a managed heap
224  *              object
225  *
226  * Return:	SUCCEED/FAIL
227  *
228  * Programmer:	Quincey Koziol
229  *		koziol@ncsa.uiuc.edu
230  *		Mar 17 2006
231  *
232  *-------------------------------------------------------------------------
233  */
234 static herr_t
H5HF_man_op_real(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,H5HF_operator_t op,void * op_data,unsigned op_flags)235 H5HF_man_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
236     H5HF_operator_t op, void *op_data, unsigned op_flags)
237 {
238     H5HF_direct_t *dblock = NULL;       /* Pointer to direct block to query */
239     H5AC_protect_t dblock_access;       /* Access method for direct block */
240     haddr_t dblock_addr;                /* Direct block address */
241     size_t dblock_size;                 /* Direct block size */
242     unsigned dblock_cache_flags;        /* Flags for unprotecting direct block */
243     hsize_t obj_off;                    /* Object's offset in heap */
244     size_t obj_len;                     /* Object's length in heap */
245     size_t blk_off;                     /* Offset of object in block */
246     uint8_t *p;                         /* Temporary pointer to obj info in block */
247     herr_t ret_value = SUCCEED;         /* Return value */
248 
249     FUNC_ENTER_NOAPI_NOINIT
250 
251     /*
252      * Check arguments.
253      */
254     HDassert(hdr);
255     HDassert(id);
256     HDassert(op);
257 
258     /* Set the access mode for the direct block */
259     if(op_flags & H5HF_OP_MODIFY) {
260         /* Check pipeline */
261         H5HF_MAN_WRITE_CHECK_PLINE(hdr)
262 
263         dblock_access = H5AC_WRITE;
264         dblock_cache_flags = H5AC__DIRTIED_FLAG;
265     } /* end if */
266     else {
267         dblock_access = H5AC_READ;
268         dblock_cache_flags = H5AC__NO_FLAGS_SET;
269     } /* end else */
270 
271     /* Skip over the flag byte */
272     id++;
273 
274     /* Decode the object offset within the heap & its length */
275     UINT64DECODE_VAR(id, obj_off, hdr->heap_off_size);
276     UINT64DECODE_VAR(id, obj_len, hdr->heap_len_size);
277 
278     /* Check for bad offset or length */
279     if(obj_off == 0)
280         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "invalid fractal heap offset")
281     if(obj_off > hdr->man_size)
282         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object offset too large")
283     if(obj_len == 0)
284         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "invalid fractal heap object size")
285     if(obj_len > hdr->man_dtable.cparam.max_direct_size)
286         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object size too large for direct block")
287     if(obj_len > hdr->max_man_size)
288         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object should be standalone")
289 
290     /* Check for root direct block */
291     if(hdr->man_dtable.curr_root_rows == 0) {
292         /* Set direct block info */
293         dblock_addr = hdr->man_dtable.table_addr;
294         dblock_size = hdr->man_dtable.cparam.start_block_size;
295 
296         /* Lock direct block */
297         if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, NULL, 0, dblock_access)))
298             HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
299     } /* end if */
300     else {
301         H5HF_indirect_t *iblock;        /* Pointer to indirect block */
302         hbool_t did_protect;            /* Whether we protected the indirect block or not */
303         unsigned entry;                 /* Entry of block */
304 
305         /* Look up indirect block containing direct block */
306         if(H5HF_man_dblock_locate(hdr, dxpl_id, obj_off, &iblock, &entry, &did_protect, H5AC_READ) < 0)
307             HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
308 
309         /* Set direct block info */
310         dblock_addr =  iblock->ents[entry].addr;
311         H5_CHECK_OVERFLOW((hdr->man_dtable.row_block_size[entry / hdr->man_dtable.cparam.width]), hsize_t, size_t);
312         dblock_size =  (size_t)hdr->man_dtable.row_block_size[entry / hdr->man_dtable.cparam.width];
313 
314         /* Check for offset of invalid direct block */
315         if(!H5F_addr_defined(dblock_addr)) {
316             /* Unlock indirect block */
317             if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
318                 HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
319 
320             HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap ID not in allocated direct block")
321         } /* end if */
322 
323         /* Lock direct block */
324         if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, iblock, entry, dblock_access))) {
325             /* Unlock indirect block */
326             if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
327                 HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
328 
329             HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
330         } /* end if */
331 
332         /* Unlock indirect block */
333         if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
334             HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
335         iblock = NULL;
336     } /* end else */
337 
338     /* Compute offset of object within block */
339     HDassert((obj_off - dblock->block_off) < (hsize_t)dblock_size);
340     blk_off = (size_t)(obj_off - dblock->block_off);
341 
342     /* Check for object's offset in the direct block prefix information */
343     if(blk_off < (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr))
344         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "object located in prefix of direct block")
345 
346     /* Check for object's length overrunning the end of the direct block */
347     if((blk_off + obj_len) > dblock_size)
348         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "object overruns end of direct block")
349 
350     /* Point to location for object */
351     p = dblock->blk + blk_off;
352 
353     /* Call the user's 'op' callback */
354     if(op(p, obj_len, op_data) < 0)
355         HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "application's callback failed")
356 
357 done:
358     /* Unlock direct block */
359     if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, dblock_cache_flags) < 0)
360         HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
361 
362     FUNC_LEAVE_NOAPI(ret_value)
363 } /* end H5HF_man_op_real() */
364 
365 
366 /*-------------------------------------------------------------------------
367  * Function:	H5HF_man_read
368  *
369  * Purpose:	Read an object from a managed heap
370  *
371  * Return:	SUCCEED/FAIL
372  *
373  * Programmer:	Quincey Koziol
374  *		koziol@ncsa.uiuc.edu
375  *		Mar 17 2006
376  *
377  *-------------------------------------------------------------------------
378  */
379 herr_t
H5HF_man_read(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,void * obj)380 H5HF_man_read(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, void *obj)
381 {
382     herr_t ret_value = SUCCEED;         /* Return value */
383 
384     FUNC_ENTER_NOAPI_NOINIT
385 
386     /*
387      * Check arguments.
388      */
389     HDassert(hdr);
390     HDassert(id);
391     HDassert(obj);
392 
393     /* Call the internal 'op' routine routine */
394     if(H5HF_man_op_real(hdr, dxpl_id, id, H5HF_op_read, obj, 0) < 0)
395         HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
396 
397 done:
398     FUNC_LEAVE_NOAPI(ret_value)
399 } /* end H5HF_man_read() */
400 
401 
402 /*-------------------------------------------------------------------------
403  * Function:	H5HF_man_write
404  *
405  * Purpose:	Write an object to a managed heap
406  *
407  * Return:	SUCCEED/FAIL
408  *
409  * Programmer:	Quincey Koziol
410  *		koziol@hdfgroup.org
411  *		Dec 18 2006
412  *
413  *-------------------------------------------------------------------------
414  */
415 herr_t
H5HF_man_write(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,const void * obj)416 H5HF_man_write(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
417     const void *obj)
418 {
419     herr_t ret_value = SUCCEED;         /* Return value */
420 
421     FUNC_ENTER_NOAPI_NOINIT
422 
423     /*
424      * Check arguments.
425      */
426     HDassert(hdr);
427     HDassert(id);
428     HDassert(obj);
429 
430     /* Call the internal 'op' routine routine */
431     /* (Casting away const OK - QAK) */
432     if(H5HF_man_op_real(hdr, dxpl_id, id, H5HF_op_write, (void *)obj, H5HF_OP_MODIFY) < 0)
433         HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
434 
435 done:
436     FUNC_LEAVE_NOAPI(ret_value)
437 } /* end H5HF_man_write() */
438 
439 
440 /*-------------------------------------------------------------------------
441  * Function:	H5HF_man_op
442  *
443  * Purpose:	Operate directly on an object from a managed heap
444  *
445  * Return:	SUCCEED/FAIL
446  *
447  * Programmer:	Quincey Koziol
448  *		koziol@ncsa.uiuc.edu
449  *		Sept 11 2006
450  *
451  *-------------------------------------------------------------------------
452  */
453 herr_t
H5HF_man_op(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,H5HF_operator_t op,void * op_data)454 H5HF_man_op(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
455     H5HF_operator_t op, void *op_data)
456 {
457     herr_t ret_value = SUCCEED;         /* Return value */
458 
459     FUNC_ENTER_NOAPI_NOINIT
460 
461     /*
462      * Check arguments.
463      */
464     HDassert(hdr);
465     HDassert(id);
466     HDassert(op);
467 
468     /* Call the internal 'op' routine routine */
469     if(H5HF_man_op_real(hdr, dxpl_id, id, op, op_data, 0) < 0)
470         HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
471 
472 done:
473     FUNC_LEAVE_NOAPI(ret_value)
474 } /* end H5HF_man_op() */
475 
476 
477 /*-------------------------------------------------------------------------
478  * Function:	H5HF_man_remove
479  *
480  * Purpose:	Remove an object from a managed heap
481  *
482  * Return:	SUCCEED/FAIL
483  *
484  * Programmer:	Quincey Koziol
485  *		koziol@ncsa.uiuc.edu
486  *		May 15 2006
487  *
488  *-------------------------------------------------------------------------
489  */
490 herr_t
H5HF_man_remove(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id)491 H5HF_man_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id)
492 {
493     H5HF_free_section_t *sec_node = NULL; /* Pointer to free space section for block */
494     H5HF_indirect_t *iblock = NULL;     /* Pointer to indirect block */
495     hbool_t did_protect;                /* Whether we protected the indirect block or not */
496     hsize_t obj_off;                    /* Object's offset in heap */
497     size_t obj_len;                     /* Object's length in heap */
498     size_t dblock_size;                 /* Direct block size */
499     hsize_t dblock_block_off;           /* Offset of the direct block within the heap's address space */
500     unsigned dblock_entry;              /* Entry of direct block in parent indirect block */
501     size_t blk_off;                     /* Offset of object in block */
502     herr_t ret_value = SUCCEED;         /* Return value */
503 
504     FUNC_ENTER_NOAPI_NOINIT
505 
506     /*
507      * Check arguments.
508      */
509     HDassert(hdr);
510     HDassert(id);
511 
512     /* Check pipeline */
513     H5HF_MAN_WRITE_CHECK_PLINE(hdr)
514 
515     /* Skip over the flag byte */
516     id++;
517 
518     /* Decode the object offset within the heap & it's length */
519     UINT64DECODE_VAR(id, obj_off, hdr->heap_off_size);
520     UINT64DECODE_VAR(id, obj_len, hdr->heap_len_size);
521 
522     /* Check for bad offset or length */
523     if(obj_off == 0)
524         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "invalid fractal heap offset")
525     if(obj_off > hdr->man_size)
526         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object offset too large")
527     if(obj_len == 0)
528         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "invalid fractal heap object size")
529     if(obj_len > hdr->man_dtable.cparam.max_direct_size)
530         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object size too large for direct block")
531     if(obj_len > hdr->max_man_size)
532         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object should be standalone")
533 
534     /* Check for root direct block */
535     if(hdr->man_dtable.curr_root_rows == 0) {
536         /* Set direct block info */
537         dblock_size = hdr->man_dtable.cparam.start_block_size;
538         dblock_block_off = 0;
539         dblock_entry = 0;
540     } /* end if */
541     else {
542         /* Look up indirect block containing direct block */
543         if(H5HF_man_dblock_locate(hdr, dxpl_id, obj_off, &iblock, &dblock_entry, &did_protect, H5AC_WRITE) < 0)
544             HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
545 
546         /* Check for offset of invalid direct block */
547         if(!H5F_addr_defined(iblock->ents[dblock_entry].addr))
548             HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap ID not in allocated direct block")
549 
550         /* Set direct block info */
551         H5_CHECK_OVERFLOW((hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width]), hsize_t, size_t);
552         dblock_size =  (size_t)(hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width]);
553 
554         /* Compute the direct block's offset in the heap's address space */
555         /* (based on parent indirect block's block offset) */
556         dblock_block_off = iblock->block_off;
557         dblock_block_off += hdr->man_dtable.row_block_off[dblock_entry / hdr->man_dtable.cparam.width];
558         dblock_block_off += hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width] * (dblock_entry % hdr->man_dtable.cparam.width);
559     } /* end else */
560 
561     /* Compute offset of object within block */
562     HDassert((obj_off - dblock_block_off) < (hsize_t)dblock_size);
563     blk_off = (size_t)(obj_off - dblock_block_off);
564 
565     /* Check for object's offset in the direct block prefix information */
566     if(blk_off < (size_t)H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr))
567         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "object located in prefix of direct block")
568 
569     /* Check for object's length overrunning the end of the direct block */
570     if((blk_off + obj_len) > dblock_size)
571         HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "object overruns end of direct block")
572 
573     /* Create free space section node */
574     if(NULL == (sec_node = H5HF_sect_single_new(obj_off, obj_len, iblock, dblock_entry)))
575         HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for direct block's free space")
576 
577     /* Unlock indirect block */
578     if(iblock) {
579         if(H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
580             HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
581         iblock = NULL;
582     } /* end if */
583 
584     /* Increase space available in heap (marks header dirty) */
585     if(H5HF_hdr_adj_free(hdr, (ssize_t)obj_len) < 0)
586         HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap")
587 
588     /* Update statistics about heap */
589     hdr->man_nobjs--;
590 
591     /* Return free space to the heap's list of space */
592     if(H5HF_space_add(hdr, dxpl_id, sec_node, H5FS_ADD_RETURNED_SPACE) < 0)
593         HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
594     sec_node = NULL;
595 
596 done:
597     if(ret_value < 0) {
598         /* Release section node */
599         if(sec_node && H5HF_sect_single_free((H5FS_section_info_t *)sec_node) < 0)
600             HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to release section node")
601     } /* end if */
602 
603     /* Unlock indirect block */
604     if(iblock && H5HF_man_iblock_unprotect(iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
605         HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
606 
607     FUNC_LEAVE_NOAPI(ret_value)
608 } /* end H5HF_man_remove() */
609 
610