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