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