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:		H5HFhuge.c
17  *			Aug  7 2006
18  *			Quincey Koziol <koziol@hdfgroup.org>
19  *
20  * Purpose:		Routines for "huge" objects in fractal heap
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #include "H5HFmodule.h"         /* This source code file is part of the H5HF module */
30 
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 
41 
42 /****************/
43 /* Local Macros */
44 /****************/
45 
46 /* v2 B-tree creation macros */
47 #define H5HF_HUGE_BT2_NODE_SIZE         512
48 #define H5HF_HUGE_BT2_SPLIT_PERC        100
49 #define H5HF_HUGE_BT2_MERGE_PERC         40
50 
51 
52 /******************/
53 /* Local Typedefs */
54 /******************/
55 
56 
57 /********************/
58 /* Package Typedefs */
59 /********************/
60 
61 
62 /********************/
63 /* Local Prototypes */
64 /********************/
65 
66 /* Local v2 B-tree operations */
67 static herr_t H5HF_huge_bt2_create(H5HF_hdr_t *hdr, hid_t dxpl_id);
68 
69 /* Local 'huge' object support routines */
70 static hsize_t H5HF_huge_new_id(H5HF_hdr_t *hdr);
71 static herr_t H5HF_huge_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id,
72     const uint8_t *id, hbool_t is_read, H5HF_operator_t op, void *op_data);
73 
74 
75 /*********************/
76 /* Package Variables */
77 /*********************/
78 
79 
80 /*****************************/
81 /* Library Private Variables */
82 /*****************************/
83 
84 
85 /*******************/
86 /* Local Variables */
87 /*******************/
88 
89 
90 /*-------------------------------------------------------------------------
91  * Function:	H5HF_huge_bt2_create
92  *
93  * Purpose:	Create the v2 B-tree for tracking the huge objects in the heap
94  *
95  * Return:	SUCCEED/FAIL
96  *
97  * Programmer:	Quincey Koziol
98  *		koziol@hdfgroup.org
99  *		Aug  7 2006
100  *
101  *-------------------------------------------------------------------------
102  */
103 static herr_t
H5HF_huge_bt2_create(H5HF_hdr_t * hdr,hid_t dxpl_id)104 H5HF_huge_bt2_create(H5HF_hdr_t *hdr, hid_t dxpl_id)
105 {
106     H5B2_create_t bt2_cparam;           /* v2 B-tree creation parameters */
107     herr_t ret_value = SUCCEED;         /* Return value */
108 
109     FUNC_ENTER_NOAPI_NOINIT
110 
111     /*
112      * Check arguments.
113      */
114     HDassert(hdr);
115 
116     /* Compute the size of 'raw' records on disk */
117     /* (Note: the size for huge IDs could be set to 'huge_id_size', instead
118      *  of 'sizeof_size', but that would make the v2 B-tree callback routines
119      *  depend on the heap header, which makes the v2 B-tree flush routines
120      *  difficult to write.  "Waste" an extra byte or for small heaps (where
121      *  the 'huge_id_size' is < 'sizeof_size' in order to make this easier -QAK)
122      */
123     if(hdr->huge_ids_direct) {
124         if(hdr->filter_len > 0) {
125             bt2_cparam.rrec_size = (size_t)((unsigned)hdr->sizeof_addr    /* Address of object */
126                 + (unsigned)hdr->sizeof_size    /* Length of object */
127                 + (unsigned)4                   /* Filter mask for filtered object */
128                 + (unsigned)hdr->sizeof_size);  /* Size of de-filtered object in memory */
129             bt2_cparam.cls = H5HF_HUGE_BT2_FILT_DIR;
130         } /* end if */
131         else {
132             bt2_cparam.rrec_size = (size_t)((unsigned)hdr->sizeof_addr    /* Address of object */
133                 + (unsigned)hdr->sizeof_size);  /* Length of object */
134             bt2_cparam.cls = H5HF_HUGE_BT2_DIR;
135         } /* end else */
136     } /* end if */
137     else {
138         if(hdr->filter_len > 0) {
139             bt2_cparam.rrec_size = (size_t)((unsigned)hdr->sizeof_addr    /* Address of filtered object */
140                 + (unsigned)hdr->sizeof_size    /* Length of filtered object */
141                 + (unsigned)4                   /* Filter mask for filtered object */
142                 + (unsigned)hdr->sizeof_size    /* Size of de-filtered object in memory */
143                 + (unsigned)hdr->sizeof_size);  /* Unique ID for object */
144             bt2_cparam.cls = H5HF_HUGE_BT2_FILT_INDIR;
145         } /* end if */
146         else {
147             bt2_cparam.rrec_size = (size_t)((unsigned)hdr->sizeof_addr    /* Address of object */
148                 + (unsigned)hdr->sizeof_size    /* Length of object */
149                 + (unsigned)hdr->sizeof_size);  /* Unique ID for object */
150             bt2_cparam.cls = H5HF_HUGE_BT2_INDIR;
151         } /* end else */
152     } /* end else */
153     bt2_cparam.node_size = (size_t)H5HF_HUGE_BT2_NODE_SIZE;
154     bt2_cparam.split_percent = H5HF_HUGE_BT2_SPLIT_PERC;
155     bt2_cparam.merge_percent = H5HF_HUGE_BT2_MERGE_PERC;
156 
157     /* Create v2 B-tree for tracking 'huge' objects */
158     if(NULL == (hdr->huge_bt2 = H5B2_create(hdr->f, dxpl_id, &bt2_cparam, hdr->f)))
159         HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create v2 B-tree for tracking 'huge' heap objects")
160 
161     /* Retrieve the v2 B-tree's address in the file */
162     if(H5B2_get_addr(hdr->huge_bt2, &hdr->huge_bt2_addr) < 0)
163         HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get v2 B-tree address for tracking 'huge' heap objects")
164 
165 done:
166     FUNC_LEAVE_NOAPI(ret_value)
167 } /* end H5HF_huge_bt2_create() */
168 
169 
170 /*-------------------------------------------------------------------------
171  * Function:	H5HF_huge_init
172  *
173  * Purpose:	Initialize information for tracking 'huge' objects
174  *
175  * Return:	SUCCEED/FAIL
176  *
177  * Programmer:	Quincey Koziol
178  *		koziol@hdfgroup.org
179  *		Aug  7 2006
180  *
181  *-------------------------------------------------------------------------
182  */
183 herr_t
H5HF_huge_init(H5HF_hdr_t * hdr)184 H5HF_huge_init(H5HF_hdr_t *hdr)
185 {
186     FUNC_ENTER_NOAPI_NOINIT_NOERR
187 
188     /*
189      * Check arguments.
190      */
191     HDassert(hdr);
192 
193     /* Compute information about 'huge' objects for the heap */
194 
195     /* Check if we can completely hold the 'huge' object's offset & length in
196      *  the file in the heap ID (which will speed up accessing it) and we don't
197      *  have any I/O pipeline filters.
198      */
199 #ifdef QAK
200 HDfprintf(stderr, "%s: hdr->id_len = %u\n", "H5HF_huge_init", (unsigned)hdr->id_len);
201 HDfprintf(stderr, "%s: hdr->filter_len = %u\n", "H5HF_huge_init", (unsigned)hdr->filter_len);
202 #endif /* QAK */
203     if(hdr->filter_len > 0) {
204         if((hdr->id_len - 1) >= (unsigned)(hdr->sizeof_addr + hdr->sizeof_size + 4 + hdr->sizeof_size)) {
205             /* Indicate that v2 B-tree doesn't have to be used to locate object */
206             hdr->huge_ids_direct = TRUE;
207 
208             /* Set the size of 'huge' object IDs */
209             hdr->huge_id_size = (uint8_t)(hdr->sizeof_addr + hdr->sizeof_size + hdr->sizeof_size);
210         } /* end if */
211         else
212             /* Indicate that v2 B-tree must be used to access object */
213             hdr->huge_ids_direct = FALSE;
214     } /* end if */
215     else {
216         if((hdr->sizeof_addr + hdr->sizeof_size) <= (hdr->id_len - 1)) {
217             /* Indicate that v2 B-tree doesn't have to be used to locate object */
218             hdr->huge_ids_direct = TRUE;
219 
220             /* Set the size of 'huge' object IDs */
221             hdr->huge_id_size = (uint8_t)(hdr->sizeof_addr + hdr->sizeof_size);
222         } /* end if */
223         else
224             /* Indicate that v2 B-tree must be used to locate object */
225             hdr->huge_ids_direct = FALSE;
226     } /* end else */
227     if(!hdr->huge_ids_direct) {
228         /* Set the size and maximum value of 'huge' object ID */
229         if((hdr->id_len - 1) < sizeof(hsize_t)) {
230             hdr->huge_id_size = (uint8_t)(hdr->id_len - 1);
231             hdr->huge_max_id = ((hsize_t)1 << (hdr->huge_id_size * 8)) - 1;
232         } /*end if */
233         else {
234             hdr->huge_id_size = sizeof(hsize_t);
235             hdr->huge_max_id = HSIZET_MAX;
236         } /* end else */
237     } /* end if */
238     hdr->huge_bt2 = NULL;
239 
240     FUNC_LEAVE_NOAPI(SUCCEED)
241 } /* end H5HF_huge_init() */
242 
243 
244 /*-------------------------------------------------------------------------
245  * Function:	H5HF_huge_new_id
246  *
247  * Purpose:	Determine a new ID for an indirectly accessed 'huge' object
248  *              (either filtered or not)
249  *
250  * Return:	SUCCEED/FAIL
251  *
252  * Programmer:	Quincey Koziol
253  *		koziol@hdfgroup.org
254  *		Aug 15 2006
255  *
256  *-------------------------------------------------------------------------
257  */
258 static hsize_t
H5HF_huge_new_id(H5HF_hdr_t * hdr)259 H5HF_huge_new_id(H5HF_hdr_t *hdr)
260 {
261     hsize_t new_id;             /* New object's ID */
262     hsize_t ret_value = 0;      /* Return value */
263 
264     FUNC_ENTER_NOAPI_NOINIT
265 
266     /*
267      * Check arguments.
268      */
269     HDassert(hdr);
270 
271     /* Check for wrapping around 'huge' object ID space */
272     if(hdr->huge_ids_wrapped)
273         /* Fail for now - eventually should iterate through v2 B-tree, looking for available ID */
274         HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, 0, "wrapping 'huge' object IDs not supported yet")
275     else {
276         /* Get new 'huge' object ID to use for object */
277         /* (avoids using ID 0) */
278         new_id = ++hdr->huge_next_id;
279 
280         /* Check for wrapping 'huge' object IDs around */
281         if(hdr->huge_next_id == hdr->huge_max_id)
282             hdr->huge_ids_wrapped = TRUE;
283     } /* end else */
284 
285     /* Set return value */
286     ret_value = new_id;
287 
288 done:
289     FUNC_LEAVE_NOAPI(ret_value)
290 } /* end H5HF_huge_new_id() */
291 
292 
293 /*-------------------------------------------------------------------------
294  * Function:	H5HF_huge_insert
295  *
296  * Purpose:	Insert a 'huge' object into the file and track it
297  *
298  * Return:	SUCCEED/FAIL
299  *
300  * Programmer:	Quincey Koziol
301  *		koziol@hdfgroup.org
302  *		Aug  7 2006
303  *
304  *-------------------------------------------------------------------------
305  */
306 herr_t
H5HF_huge_insert(H5HF_hdr_t * hdr,hid_t dxpl_id,size_t obj_size,void * obj,void * _id)307 H5HF_huge_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t obj_size, void *obj,
308     void *_id)
309 {
310     uint8_t *id = (uint8_t *)_id;       /* Pointer to ID buffer */
311     haddr_t obj_addr;                   /* Address of object in the file */
312     void *write_buf;                    /* Pointer to buffer to write */
313     size_t write_size;                  /* Size of [possibly filtered] object written to file */
314     unsigned filter_mask = 0;           /* Filter mask for object (only used for filtered objects) */
315     herr_t ret_value = SUCCEED;         /* Return value */
316 
317     FUNC_ENTER_NOAPI_NOINIT
318 #ifdef QAK
319 HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size);
320 #endif /* QAK */
321 
322     /*
323      * Check arguments.
324      */
325     HDassert(hdr);
326     HDassert(obj_size > hdr->max_man_size);
327     HDassert(obj);
328     HDassert(id);
329 
330     /* Check if the v2 B-tree for tracking 'huge' heap objects has been created yet */
331     if(!H5F_addr_defined(hdr->huge_bt2_addr)) {
332         /* Go create (& open) v2 B-tree */
333         if(H5HF_huge_bt2_create(hdr, dxpl_id) < 0)
334             HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create v2 B-tree for tracking 'huge' heap objects")
335     } /* end if */
336     else {
337         /* Check if v2 B-tree is open yet */
338         if(NULL == hdr->huge_bt2) {
339             /* Open existing v2 B-tree */
340             if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
341                 HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
342         } /* end if */
343     } /* end else */
344     HDassert(hdr->huge_bt2);
345 
346     /* Check for I/O pipeline filter on heap */
347     if(hdr->filter_len > 0) {
348         H5Z_cb_t filter_cb = {NULL, NULL};  /* Filter callback structure */
349         size_t nbytes;                      /* Number of bytes used */
350 
351         /* Allocate buffer to perform I/O filtering on */
352         write_size = obj_size;
353         if(NULL == (write_buf = H5MM_malloc(write_size)))
354             HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
355         HDmemcpy(write_buf, obj, write_size);
356 
357         /* Push direct block data through I/O filter pipeline */
358         nbytes = write_size;
359         if(H5Z_pipeline(&(hdr->pline), 0, &filter_mask, H5Z_NO_EDC,
360                  filter_cb, &nbytes, &write_size, &write_buf) < 0)
361             HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "output pipeline failed")
362 #ifdef QAK
363 HDfprintf(stderr, "%s: nbytes = %Zu, write_size = %Zu, write_buf = %p\n", FUNC, nbytes, write_size, write_buf);
364 HDfprintf(stderr, "%s: obj_size = %Zu, obj = %p\n", FUNC, obj_size, obj);
365 #endif /* QAK */
366 
367         /* Update size of object on disk */
368         write_size = nbytes;
369     } /* end if */
370     else {
371         write_buf = obj;
372         write_size = obj_size;
373     } /* end else */
374 
375     /* Allocate space in the file for storing the 'huge' object */
376     if(HADDR_UNDEF == (obj_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, dxpl_id, (hsize_t)write_size)))
377         HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap huge object")
378 
379     /* Write the object's data to disk */
380     if(H5F_block_write(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, write_size, H5AC_rawdata_dxpl_id, write_buf) < 0)
381         HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "writing 'huge' object to file failed")
382 
383     /* Release buffer for writing, if we had one */
384     if(write_buf != obj) {
385         HDassert(hdr->filter_len > 0);
386         H5MM_xfree(write_buf);
387     } /* end if */
388 
389     /* Perform different actions for directly & indirectly accessed 'huge' objects */
390     if(hdr->huge_ids_direct) {
391         if(hdr->filter_len > 0) {
392             H5HF_huge_bt2_filt_dir_rec_t obj_rec;        /* Record for tracking object */
393 
394             /* Initialize record for tracking object in v2 B-tree */
395             obj_rec.addr = obj_addr;
396             obj_rec.len = write_size;
397             obj_rec.filter_mask = filter_mask;
398             obj_rec.obj_size = obj_size;
399 #ifdef QAK
400 HDfprintf(stderr, "%s: obj_rec = {%a, %Hu, %x, %Hu}\n", FUNC, obj_rec.addr, obj_rec.len, obj_rec.filter_mask, obj_rec.obj_size);
401 #endif /* QAK */
402 
403             /* Insert record for object in v2 B-tree */
404             if(H5B2_insert(hdr->huge_bt2, dxpl_id, &obj_rec) < 0)
405                 HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "couldn't insert object tracking record in v2 B-tree")
406 
407             /* Encode ID for user */
408             *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
409             H5F_addr_encode(hdr->f, &id, obj_addr);
410             H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)write_size);
411             UINT32ENCODE(id, filter_mask);
412             H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)obj_size);
413         } /* end if */
414         else {
415             H5HF_huge_bt2_dir_rec_t obj_rec;        /* Record for tracking object */
416 
417             /* Initialize record for tracking object in v2 B-tree */
418             obj_rec.addr = obj_addr;
419             obj_rec.len = write_size;
420 #ifdef QAK
421 HDfprintf(stderr, "%s: obj_rec = {%a, %Hu}\n", FUNC, obj_rec.addr, obj_rec.len);
422 #endif /* QAK */
423 
424             /* Insert record for object in v2 B-tree */
425             if(H5B2_insert(hdr->huge_bt2, dxpl_id, &obj_rec) < 0)
426                 HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "couldn't insert object tracking record in v2 B-tree")
427 
428             /* Encode ID for user */
429             *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
430             H5F_addr_encode(hdr->f, &id, obj_addr);
431             H5F_ENCODE_LENGTH(hdr->f, id, (hsize_t)write_size);
432         } /* end if */
433     } /* end if */
434     else {
435         H5HF_huge_bt2_filt_indir_rec_t filt_indir_rec;      /* Record for tracking filtered object */
436         H5HF_huge_bt2_indir_rec_t indir_rec;    /* Record for tracking non-filtered object */
437         void *ins_rec;          /* Pointer to record to insert */
438         hsize_t new_id;         /* New ID for object */
439 
440         /* Get new ID for object */
441         if(0 == (new_id = H5HF_huge_new_id(hdr)))
442             HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't generate new ID for object")
443 
444         if(hdr->filter_len > 0) {
445             /* Initialize record for object in v2 B-tree */
446             filt_indir_rec.addr = obj_addr;
447             filt_indir_rec.len = write_size;
448             filt_indir_rec.filter_mask = filter_mask;
449             filt_indir_rec.obj_size = obj_size;
450             filt_indir_rec.id = new_id;
451 #ifdef QAK
452 HDfprintf(stderr, "%s: filt_indir_rec = {%a, %Hu, %x, %Hu, %Hu}\n", FUNC, filt_indir_rec.addr, filt_indir_rec.len, filt_indir_rec.filter_mask, filt_indir_rec.obj_size, filt_indir_rec.id);
453 #endif /* QAK */
454 
455             /* Set pointer to record to insert */
456             ins_rec = &filt_indir_rec;
457         } /* end if */
458         else {
459             /* Initialize record for object in v2 B-tree */
460             indir_rec.addr = obj_addr;
461             indir_rec.len = write_size;
462             indir_rec.id = new_id;
463 #ifdef QAK
464 HDfprintf(stderr, "%s: indir_rec = {%a, %Hu, %Hu}\n", FUNC, indir_rec.addr, indir_rec.len, indir_rec.id);
465 #endif /* QAK */
466 
467             /* Set pointer to record to insert */
468             ins_rec = &indir_rec;
469         } /* end else */
470 
471         /* Insert record for tracking object in v2 B-tree */
472         if(H5B2_insert(hdr->huge_bt2, dxpl_id, ins_rec) < 0)
473             HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "couldn't insert object tracking record in v2 B-tree")
474 
475         /* Encode ID for user */
476         *id++ = H5HF_ID_VERS_CURR | H5HF_ID_TYPE_HUGE;
477         UINT64ENCODE_VAR(id, new_id, hdr->huge_id_size)
478     } /* end else */
479 
480     /* Update statistics about heap */
481     hdr->huge_size += obj_size;
482     hdr->huge_nobjs++;
483 
484     /* Mark heap header as modified */
485     if(H5HF_hdr_dirty(hdr) < 0)
486         HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
487 
488 done:
489     FUNC_LEAVE_NOAPI(ret_value)
490 } /* end H5HF_huge_insert() */
491 
492 
493 /*-------------------------------------------------------------------------
494  * Function:	H5HF_huge_get_obj_len
495  *
496  * Purpose:	Get the size of a 'huge' object in a fractal heap
497  *
498  * Return:	SUCCEED/FAIL
499  *
500  * Programmer:	Quincey Koziol
501  *		koziol@hdfgroup.org
502  *		Aug  8 2006
503  *
504  *-------------------------------------------------------------------------
505  */
506 herr_t
H5HF_huge_get_obj_len(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,size_t * obj_len_p)507 H5HF_huge_get_obj_len(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
508     size_t *obj_len_p)
509 {
510     herr_t ret_value = SUCCEED;         /* Return value */
511 
512     FUNC_ENTER_NOAPI_NOINIT
513 
514     /*
515      * Check arguments.
516      */
517     HDassert(hdr);
518     HDassert(H5F_addr_defined(hdr->huge_bt2_addr));
519     HDassert(id);
520     HDassert(obj_len_p);
521 
522     /* Skip over the flag byte */
523     id++;
524 
525     /* Check if 'huge' object ID encodes address & length directly */
526     if(hdr->huge_ids_direct) {
527         if(hdr->filter_len > 0) {
528             /* Skip over filtered object info */
529             id += hdr->sizeof_addr + hdr->sizeof_size + 4;
530 
531             /* Retrieve the object's length */
532             H5F_DECODE_LENGTH(hdr->f, id, *obj_len_p);
533         } /* end if */
534         else {
535             /* Skip over object offset in file */
536             id += hdr->sizeof_addr;
537 
538             /* Retrieve the object's length */
539             H5F_DECODE_LENGTH(hdr->f, id, *obj_len_p);
540         } /* end else */
541     } /* end if */
542     else {
543         /* Check if v2 B-tree is open yet */
544         if(NULL == hdr->huge_bt2) {
545             /* Open existing v2 B-tree */
546             if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
547                 HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
548         } /* end if */
549 
550         if(hdr->filter_len > 0) {
551             H5HF_huge_bt2_filt_indir_rec_t found_rec;  /* Record found from tracking object */
552             H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
553 
554             /* Get ID for looking up 'huge' object in v2 B-tree */
555             UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
556 
557             /* Look up object in v2 B-tree */
558             if(H5B2_find(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_filt_indir_found, &found_rec) != TRUE)
559                 HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
560 
561             /* Retrieve the object's length */
562             *obj_len_p = (size_t)found_rec.obj_size;
563         } /* end if */
564         else {
565             H5HF_huge_bt2_indir_rec_t found_rec;  /* Record found from tracking object */
566             H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
567 
568             /* Get ID for looking up 'huge' object in v2 B-tree */
569             UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
570 
571             /* Look up object in v2 B-tree */
572             if(H5B2_find(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_indir_found, &found_rec) != TRUE)
573                 HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
574 
575             /* Retrieve the object's length */
576             *obj_len_p = (size_t)found_rec.len;
577         } /* end else */
578     } /* end else */
579 
580 done:
581     FUNC_LEAVE_NOAPI(ret_value)
582 } /* end H5HF_huge_get_obj_len() */
583 
584 
585 /*-------------------------------------------------------------------------
586  * Function:	H5HF__huge_get_obj_off
587  *
588  * Purpose:	Get the offset of a 'huge' object in a fractal heap
589  *
590  * Return:	SUCCEED/FAIL
591  *
592  * Programmer:	Quincey Koziol
593  *		koziol@hdfgroup.org
594  *		Aug  8 2006
595  *
596  *-------------------------------------------------------------------------
597  */
598 herr_t
H5HF__huge_get_obj_off(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,hsize_t * obj_off_p)599 H5HF__huge_get_obj_off(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
600     hsize_t *obj_off_p)
601 {
602     haddr_t obj_addr;                   /* Object's address in the file */
603     herr_t ret_value = SUCCEED;         /* Return value */
604 
605     FUNC_ENTER_NOAPI_NOINIT
606 
607     /*
608      * Check arguments.
609      */
610     HDassert(hdr);
611     HDassert(H5F_addr_defined(hdr->huge_bt2_addr));
612     HDassert(id);
613     HDassert(obj_off_p);
614 
615     /* Skip over the flag byte */
616     id++;
617 
618     /* Check if 'huge' object ID encodes address & length directly */
619     if(hdr->huge_ids_direct) {
620         /* Retrieve the object's address (common) */
621         H5F_addr_decode(hdr->f, &id, &obj_addr);
622     } /* end if */
623     else {
624         /* Sanity check */
625         HDassert(H5F_addr_defined(hdr->huge_bt2_addr));
626 
627         /* Check if v2 B-tree is open yet */
628         if(NULL == hdr->huge_bt2) {
629             /* Open existing v2 B-tree */
630             if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
631                 HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
632         } /* end if */
633 
634         if(hdr->filter_len > 0) {
635             H5HF_huge_bt2_filt_indir_rec_t found_rec;  /* Record found from tracking object */
636             H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
637 
638             /* Get ID for looking up 'huge' object in v2 B-tree */
639             UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
640 
641             /* Look up object in v2 B-tree */
642             if(H5B2_find(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_filt_indir_found, &found_rec) != TRUE)
643                 HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
644 
645             /* Retrieve the object's address & length */
646             obj_addr = found_rec.addr;
647         } /* end if */
648         else {
649             H5HF_huge_bt2_indir_rec_t found_rec;  /* Record found from tracking object */
650             H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
651 
652             /* Get ID for looking up 'huge' object in v2 B-tree */
653             UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
654 
655             /* Look up object in v2 B-tree */
656             if(H5B2_find(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_indir_found, &found_rec) != TRUE)
657                 HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
658 
659             /* Retrieve the object's address & length */
660             obj_addr = found_rec.addr;
661         } /* end else */
662     } /* end else */
663 
664     /* Set the value to return */
665     *obj_off_p = (hsize_t)obj_addr;
666 
667 done:
668     FUNC_LEAVE_NOAPI(ret_value)
669 } /* end H5HF__huge_get_obj_off() */
670 
671 
672 /*-------------------------------------------------------------------------
673  * Function:	H5HF_huge_op_real
674  *
675  * Purpose:	Internal routine to perform an operation on a 'huge' object
676  *
677  * Return:	SUCCEED/FAIL
678  *
679  * Programmer:	Quincey Koziol
680  *		koziol@hdfgroup.org
681  *		Aug  8 2006
682  *
683  *-------------------------------------------------------------------------
684  */
685 static herr_t
H5HF_huge_op_real(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,hbool_t is_read,H5HF_operator_t op,void * op_data)686 H5HF_huge_op_real(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
687     hbool_t is_read, H5HF_operator_t op, void *op_data)
688 {
689     void *read_buf = NULL;              /* Pointer to buffer for reading */
690     haddr_t obj_addr;                   /* Object's address in the file */
691     size_t obj_size = 0;                /* Object's size in the file */
692     unsigned filter_mask = 0;           /* Filter mask for object (only used for filtered objects) */
693     herr_t ret_value = SUCCEED;         /* Return value */
694 
695     FUNC_ENTER_NOAPI_NOINIT
696 
697     /*
698      * Check arguments.
699      */
700     HDassert(hdr);
701     HDassert(id);
702     HDassert(is_read || op);
703 
704     /* Skip over the flag byte */
705     id++;
706 
707     /* Check for 'huge' object ID that encodes address & length directly */
708     if(hdr->huge_ids_direct) {
709         /* Retrieve the object's address and length (common) */
710         H5F_addr_decode(hdr->f, &id, &obj_addr);
711         H5F_DECODE_LENGTH(hdr->f, id, obj_size);
712 
713         /* Retrieve extra information needed for filtered objects */
714         if(hdr->filter_len > 0)
715             UINT32DECODE(id, filter_mask);
716     } /* end if */
717     else {
718         /* Sanity check */
719         HDassert(H5F_addr_defined(hdr->huge_bt2_addr));
720 
721         /* Check if v2 B-tree is open yet */
722         if(NULL == hdr->huge_bt2) {
723             /* Open existing v2 B-tree */
724             if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
725                 HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
726         } /* end if */
727 
728         if(hdr->filter_len > 0) {
729             H5HF_huge_bt2_filt_indir_rec_t found_rec;  /* Record found from tracking object */
730             H5HF_huge_bt2_filt_indir_rec_t search_rec; /* Record for searching for object */
731 
732             /* Get ID for looking up 'huge' object in v2 B-tree */
733             UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
734 
735             /* Look up object in v2 B-tree */
736             if(H5B2_find(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_filt_indir_found, &found_rec) != TRUE)
737                 HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
738 
739             /* Retrieve the object's address & length */
740             obj_addr = found_rec.addr;
741             H5_CHECKED_ASSIGN(obj_size, size_t, found_rec.len, hsize_t);
742             filter_mask = found_rec.filter_mask;
743         } /* end if */
744         else {
745             H5HF_huge_bt2_indir_rec_t found_rec;  /* Record found from tracking object */
746             H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
747 
748             /* Get ID for looking up 'huge' object in v2 B-tree */
749             UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
750 
751             /* Look up object in v2 B-tree */
752             if(H5B2_find(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_indir_found, &found_rec) != TRUE)
753                 HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
754 
755             /* Retrieve the object's address & length */
756             obj_addr = found_rec.addr;
757             H5_CHECKED_ASSIGN(obj_size, size_t, found_rec.len, hsize_t);
758         } /* end else */
759     } /* end else */
760 
761     /* Set up buffer for reading */
762     if(hdr->filter_len > 0 || !is_read) {
763         if(NULL == (read_buf = H5MM_malloc((size_t)obj_size)))
764             HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "memory allocation failed for pipeline buffer")
765     } /* end if */
766     else
767         read_buf = op_data;
768 
769     /* Read the object's (possibly filtered) data from the file */
770     /* (reads directly into application's buffer if no filters are present) */
771     if(H5F_block_read(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, (size_t)obj_size, H5AC_rawdata_dxpl_id, read_buf) < 0)
772         HGOTO_ERROR(H5E_HEAP, H5E_READERROR, FAIL, "can't read 'huge' object's data from the file")
773 
774     /* Check for I/O pipeline filter on heap */
775     if(hdr->filter_len > 0) {
776         H5Z_cb_t filter_cb = {NULL, NULL};  /* Filter callback structure */
777         size_t read_size;                   /* Object's size in the file */
778         size_t nbytes;                      /* Number of bytes used */
779 
780         /* De-filter the object */
781         read_size = nbytes = obj_size;
782         if(H5Z_pipeline(&(hdr->pline), H5Z_FLAG_REVERSE, &filter_mask, H5Z_NO_EDC, filter_cb, &nbytes, &read_size, &read_buf) < 0)
783             HGOTO_ERROR(H5E_HEAP, H5E_CANTFILTER, FAIL, "input filter failed")
784         obj_size = nbytes;
785     } /* end if */
786 
787     /* Perform correct operation on buffer read in */
788     if(is_read) {
789         /* Copy object to user's buffer if there's filters on heap data */
790         /* (if there's no filters, the object was read directly into the user's buffer) */
791         if(hdr->filter_len > 0)
792             HDmemcpy(op_data, read_buf, (size_t)obj_size);
793     } /* end if */
794     else {
795         /* Call the user's 'op' callback */
796         if(op(read_buf, (size_t)obj_size, op_data) < 0) {
797             /* Release buffer */
798             read_buf = H5MM_xfree(read_buf);
799 
800             /* Indicate error */
801             HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "application's callback failed")
802         } /* end if */
803     } /* end if */
804 
805 done:
806     /* Release the buffer for reading */
807     if(read_buf && read_buf != op_data)
808         read_buf = H5MM_xfree(read_buf);
809 
810     FUNC_LEAVE_NOAPI(ret_value)
811 } /* end H5HF_huge_op_real() */
812 
813 
814 /*-------------------------------------------------------------------------
815  * Function:	H5HF_huge_write
816  *
817  * Purpose:	Write a 'huge' object to the heap
818  *
819  * Note:	This implementation somewhat limited: it doesn't handle
820  *		heaps with filters, which would require re-compressing the
821  *		huge object and probably changing the address of the object
822  *		on disk (and possibly the heap ID for "direct" huge IDs).
823  *
824  * Return:	SUCCEED/FAIL
825  *
826  * Programmer:	Quincey Koziol
827  *		koziol@hdfgroup.org
828  *		Feb 21 2007
829  *
830  *-------------------------------------------------------------------------
831  */
832 herr_t
H5HF_huge_write(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,const void * obj)833 H5HF_huge_write(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
834     const void *obj)
835 {
836     haddr_t obj_addr;                   /* Object's address in the file */
837     size_t obj_size;                    /* Object's size in the file */
838     herr_t ret_value = SUCCEED;         /* Return value */
839 
840     FUNC_ENTER_NOAPI_NOINIT
841 
842     /*
843      * Check arguments.
844      */
845     HDassert(hdr);
846     HDassert(id);
847     HDassert(obj);
848 
849     /* Check for filters on the heap */
850     if(hdr->filter_len > 0)
851         HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "modifying 'huge' object with filters not supported yet")
852 
853     /* Skip over the flag byte */
854     id++;
855 
856     /* Check for 'huge' object ID that encodes address & length directly */
857     if(hdr->huge_ids_direct) {
858         /* Retrieve the object's address and length (common) */
859         H5F_addr_decode(hdr->f, &id, &obj_addr);
860         H5F_DECODE_LENGTH(hdr->f, id, obj_size);
861     } /* end if */
862     else {
863         H5HF_huge_bt2_indir_rec_t found_rec;  /* Record found from tracking object */
864         H5HF_huge_bt2_indir_rec_t search_rec; /* Record for searching for object */
865 
866         /* Sanity check */
867         HDassert(H5F_addr_defined(hdr->huge_bt2_addr));
868 
869         /* Check if v2 B-tree is open yet */
870         if(NULL == hdr->huge_bt2) {
871             /* Open existing v2 B-tree */
872             if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
873                 HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
874         } /* end if */
875 
876         /* Get ID for looking up 'huge' object in v2 B-tree */
877         UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
878 
879         /* Look up object in v2 B-tree */
880         if(H5B2_find(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_indir_found, &found_rec) != TRUE)
881             HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "can't find object in B-tree")
882 
883         /* Retrieve the object's address & length */
884         obj_addr = found_rec.addr;
885         H5_CHECKED_ASSIGN(obj_size, size_t, found_rec.len, hsize_t);
886     } /* end else */
887 
888     /* Write the object's data to the file */
889     /* (writes directly from application's buffer) */
890     if(H5F_block_write(hdr->f, H5FD_MEM_FHEAP_HUGE_OBJ, obj_addr, obj_size, H5AC_rawdata_dxpl_id, obj) < 0)
891         HGOTO_ERROR(H5E_HEAP, H5E_WRITEERROR, FAIL, "writing 'huge' object to file failed")
892 
893 done:
894     FUNC_LEAVE_NOAPI(ret_value)
895 } /* end H5HF_huge_write() */
896 
897 
898 /*-------------------------------------------------------------------------
899  * Function:	H5HF_huge_read
900  *
901  * Purpose:	Read a 'huge' object from the heap
902  *
903  * Return:	SUCCEED/FAIL
904  *
905  * Programmer:	Quincey Koziol
906  *		koziol@ncsa.uiuc.edu
907  *		Sept 11 2006
908  *
909  *-------------------------------------------------------------------------
910  */
911 herr_t
H5HF_huge_read(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,void * obj)912 H5HF_huge_read(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id, void *obj)
913 {
914     herr_t ret_value = SUCCEED;         /* Return value */
915 
916     FUNC_ENTER_NOAPI_NOINIT
917 
918     /*
919      * Check arguments.
920      */
921     HDassert(hdr);
922     HDassert(id);
923     HDassert(obj);
924 
925     /* Call the internal 'op' routine */
926     if(H5HF_huge_op_real(hdr, dxpl_id, id, TRUE, NULL, obj) < 0)
927         HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
928 
929 done:
930     FUNC_LEAVE_NOAPI(ret_value)
931 } /* end H5HF_huge_read() */
932 
933 
934 /*-------------------------------------------------------------------------
935  * Function:	H5HF_huge_op
936  *
937  * Purpose:	Operate directly on a 'huge' object
938  *
939  * Return:	SUCCEED/FAIL
940  *
941  * Programmer:	Quincey Koziol
942  *		koziol@ncsa.uiuc.edu
943  *		Sept 11 2006
944  *
945  *-------------------------------------------------------------------------
946  */
947 herr_t
H5HF_huge_op(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id,H5HF_operator_t op,void * op_data)948 H5HF_huge_op(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id,
949     H5HF_operator_t op, void *op_data)
950 {
951     herr_t ret_value = SUCCEED;         /* Return value */
952 
953     FUNC_ENTER_NOAPI_NOINIT
954 
955     /*
956      * Check arguments.
957      */
958     HDassert(hdr);
959     HDassert(id);
960     HDassert(op);
961 
962     /* Call the internal 'op' routine routine */
963     if(H5HF_huge_op_real(hdr, dxpl_id, id, FALSE, op, op_data) < 0)
964         HGOTO_ERROR(H5E_HEAP, H5E_CANTOPERATE, FAIL, "unable to operate on heap object")
965 
966 done:
967     FUNC_LEAVE_NOAPI(ret_value)
968 } /* end H5HF_huge_op() */
969 
970 
971 /*-------------------------------------------------------------------------
972  * Function:	H5HF_huge_remove
973  *
974  * Purpose:	Remove a 'huge' object from the file and the v2 B-tree tracker
975  *
976  * Return:	SUCCEED/FAIL
977  *
978  * Programmer:	Quincey Koziol
979  *		koziol@hdfgroup.org
980  *		Aug  8 2006
981  *
982  *-------------------------------------------------------------------------
983  */
984 herr_t
H5HF_huge_remove(H5HF_hdr_t * hdr,hid_t dxpl_id,const uint8_t * id)985 H5HF_huge_remove(H5HF_hdr_t *hdr, hid_t dxpl_id, const uint8_t *id)
986 {
987     H5HF_huge_remove_ud_t udata;       /* User callback data for v2 B-tree remove call */
988     herr_t ret_value = SUCCEED;         /* Return value */
989 
990     FUNC_ENTER_NOAPI_NOINIT
991 
992     /*
993      * Check arguments.
994      */
995     HDassert(hdr);
996     HDassert(H5F_addr_defined(hdr->huge_bt2_addr));
997     HDassert(id);
998 
999     /* Check if v2 B-tree is open yet */
1000     if(NULL == hdr->huge_bt2) {
1001         /* Open existing v2 B-tree */
1002         if(NULL == (hdr->huge_bt2 = H5B2_open(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f)))
1003             HGOTO_ERROR(H5E_HEAP, H5E_CANTOPENOBJ, FAIL, "unable to open v2 B-tree for tracking 'huge' heap objects")
1004     } /* end if */
1005 
1006     /* Skip over the flag byte */
1007     id++;
1008 
1009     /* Set up the common callback info */
1010     udata.hdr = hdr;
1011     udata.dxpl_id = dxpl_id;
1012 
1013     /* Check for 'huge' object ID that encodes address & length directly */
1014     if(hdr->huge_ids_direct) {
1015         if(hdr->filter_len > 0) {
1016             H5HF_huge_bt2_filt_dir_rec_t search_rec;     /* Record for searching for object */
1017 
1018             /* Retrieve the object's address and length */
1019             /* (used as key in v2 B-tree record) */
1020             H5F_addr_decode(hdr->f, &id, &search_rec.addr);
1021             H5F_DECODE_LENGTH(hdr->f, id, search_rec.len);
1022 
1023             /* Remove the record for tracking the 'huge' object from the v2 B-tree */
1024             /* (space in the file for the object is freed in the 'remove' callback) */
1025             if(H5B2_remove(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_filt_dir_remove, &udata) < 0)
1026                 HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
1027         } /* end if */
1028         else {
1029             H5HF_huge_bt2_dir_rec_t search_rec;     /* Record for searching for object */
1030 
1031             /* Retrieve the object's address and length */
1032             /* (used as key in v2 B-tree record) */
1033             H5F_addr_decode(hdr->f, &id, &search_rec.addr);
1034             H5F_DECODE_LENGTH(hdr->f, id, search_rec.len);
1035 
1036             /* Remove the record for tracking the 'huge' object from the v2 B-tree */
1037             /* (space in the file for the object is freed in the 'remove' callback) */
1038             if(H5B2_remove(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_dir_remove, &udata) < 0)
1039                 HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
1040         } /* end else */
1041     } /* end if */
1042     else {
1043         if(hdr->filter_len > 0) {
1044             H5HF_huge_bt2_filt_indir_rec_t search_rec;     /* Record for searching for object */
1045 
1046             /* Get ID for looking up 'huge' object in v2 B-tree */
1047             UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
1048 
1049             /* Remove the record for tracking the 'huge' object from the v2 B-tree */
1050             /* (space in the file for the object is freed in the 'remove' callback) */
1051             if(H5B2_remove(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_filt_indir_remove, &udata) < 0)
1052                 HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
1053         } /* end if */
1054         else {
1055             H5HF_huge_bt2_indir_rec_t search_rec;     /* Record for searching for object */
1056 
1057             /* Get ID for looking up 'huge' object in v2 B-tree */
1058             UINT64DECODE_VAR(id, search_rec.id, hdr->huge_id_size)
1059 
1060             /* Remove the record for tracking the 'huge' object from the v2 B-tree */
1061             /* (space in the file for the object is freed in the 'remove' callback) */
1062             if(H5B2_remove(hdr->huge_bt2, dxpl_id, &search_rec, H5HF__huge_bt2_indir_remove, &udata) < 0)
1063                 HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove object from B-tree")
1064         } /* end else */
1065     } /* end else */
1066 
1067     /* Update statistics about heap */
1068     hdr->huge_size -= udata.obj_len;
1069     hdr->huge_nobjs--;
1070 
1071     /* Mark heap header as modified */
1072     if(H5HF_hdr_dirty(hdr) < 0)
1073         HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
1074 
1075 done:
1076     FUNC_LEAVE_NOAPI(ret_value)
1077 } /* end H5HF_huge_remove() */
1078 
1079 
1080 /*-------------------------------------------------------------------------
1081  * Function:	H5HF_huge_term
1082  *
1083  * Purpose:	Shut down the information for tracking 'huge' objects
1084  *
1085  * Return:	SUCCEED/FAIL
1086  *
1087  * Programmer:	Quincey Koziol
1088  *		koziol@hdfgroup.org
1089  *		Aug  8 2006
1090  *
1091  *-------------------------------------------------------------------------
1092  */
1093 herr_t
H5HF_huge_term(H5HF_hdr_t * hdr,hid_t dxpl_id)1094 H5HF_huge_term(H5HF_hdr_t *hdr, hid_t dxpl_id)
1095 {
1096     herr_t ret_value = SUCCEED;         /* Return value */
1097 
1098     FUNC_ENTER_NOAPI_NOINIT
1099 
1100     /*
1101      * Check arguments.
1102      */
1103     HDassert(hdr);
1104 
1105     /* Check if v2 B-tree index is open */
1106     if(hdr->huge_bt2) {
1107         /* Sanity check */
1108         HDassert(H5F_addr_defined(hdr->huge_bt2_addr));
1109 
1110         /* Close v2 B-tree index */
1111         if(H5B2_close(hdr->huge_bt2, dxpl_id) < 0)
1112             HGOTO_ERROR(H5E_HEAP, H5E_CANTCLOSEOBJ, FAIL, "can't close v2 B-tree")
1113         hdr->huge_bt2 = NULL;
1114     } /* end if */
1115 
1116     /* Check if there are no more 'huge' objects in the heap and delete the
1117      *  v2 B-tree that tracks them, if so
1118      */
1119     if(H5F_addr_defined(hdr->huge_bt2_addr) && hdr->huge_nobjs == 0) {
1120         /* Sanity check */
1121         HDassert(hdr->huge_size == 0);
1122 
1123         /* Delete the v2 B-tree */
1124         /* (any v2 B-tree class will work here) */
1125         if(H5B2_delete(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, NULL, NULL) < 0)
1126             HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
1127 
1128         /* Reset the information about 'huge' objects in the file */
1129         hdr->huge_bt2_addr = HADDR_UNDEF;
1130         hdr->huge_next_id = 0;
1131         hdr->huge_ids_wrapped = FALSE;
1132 
1133         /* Mark heap header as modified */
1134         if(H5HF_hdr_dirty(hdr) < 0)
1135             HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty")
1136     } /* end if */
1137 
1138 done:
1139     FUNC_LEAVE_NOAPI(ret_value)
1140 } /* end H5HF_huge_term() */
1141 
1142 
1143 /*-------------------------------------------------------------------------
1144  * Function:	H5HF_huge_delete
1145  *
1146  * Purpose:	Delete all the 'huge' objects in the heap, and the v2 B-tree
1147  *              tracker for them
1148  *
1149  * Return:	SUCCEED/FAIL
1150  *
1151  * Programmer:	Quincey Koziol
1152  *		koziol@hdfgroup.org
1153  *		Aug  8 2006
1154  *
1155  *-------------------------------------------------------------------------
1156  */
1157 herr_t
H5HF_huge_delete(H5HF_hdr_t * hdr,hid_t dxpl_id)1158 H5HF_huge_delete(H5HF_hdr_t *hdr, hid_t dxpl_id)
1159 {
1160     H5HF_huge_remove_ud_t udata;       /* User callback data for v2 B-tree remove call */
1161     H5B2_remove_t op;                   /* Callback for v2 B-tree removal */
1162     herr_t ret_value = SUCCEED;         /* Return value */
1163 
1164     FUNC_ENTER_NOAPI_NOINIT
1165 
1166     /*
1167      * Check arguments.
1168      */
1169     HDassert(hdr);
1170     HDassert(H5F_addr_defined(hdr->huge_bt2_addr));
1171     HDassert(hdr->huge_nobjs);
1172     HDassert(hdr->huge_size);
1173 
1174     /* Set up the callback info */
1175     udata.hdr = hdr;
1176     udata.dxpl_id = dxpl_id;
1177 
1178     /* Set the v2 B-tree callback operator */
1179     if(hdr->huge_ids_direct) {
1180         if(hdr->filter_len > 0)
1181             op = H5HF__huge_bt2_filt_dir_remove;
1182         else
1183             op = H5HF__huge_bt2_dir_remove;
1184     } /* end if */
1185     else {
1186         if(hdr->filter_len > 0)
1187             op = H5HF__huge_bt2_filt_indir_remove;
1188         else
1189             op = H5HF__huge_bt2_indir_remove;
1190     } /* end else */
1191 
1192     /* Delete the v2 B-tree */
1193     if(H5B2_delete(hdr->f, dxpl_id, hdr->huge_bt2_addr, hdr->f, op, &udata) < 0)
1194         HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete v2 B-tree")
1195 
1196 done:
1197     FUNC_LEAVE_NOAPI(ret_value)
1198 } /* end H5HF_huge_delete() */
1199 
1200