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