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:     H5B2cache.c
17  *              Jan 31 2005
18  *              Quincey Koziol <koziol@hdfgroup.org>
19  *
20  * Purpose:     Implement v2 B-tree metadata cache methods.
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #define H5B2_PACKAGE		/*suppress error about including H5B2pkg  */
30 
31 
32 /***********/
33 /* Headers */
34 /***********/
35 #include "H5private.h"		/* Generic Functions			*/
36 #include "H5B2pkg.h"		/* v2 B-trees				*/
37 #include "H5Eprivate.h"		/* Error handling		  	*/
38 #include "H5MFprivate.h"	/* File memory management		*/
39 #include "H5WBprivate.h"        /* Wrapped Buffers                      */
40 
41 
42 /****************/
43 /* Local Macros */
44 /****************/
45 
46 /* B-tree format version #'s */
47 #define H5B2_HDR_VERSION 0              /* Header */
48 #define H5B2_INT_VERSION 0              /* Internal node */
49 #define H5B2_LEAF_VERSION 0             /* Leaf node */
50 
51 /* Size of stack buffer for serialized headers */
52 #define H5B2_HDR_BUF_SIZE               128
53 
54 
55 /******************/
56 /* Local Typedefs */
57 /******************/
58 
59 
60 /********************/
61 /* Package Typedefs */
62 /********************/
63 
64 
65 /********************/
66 /* Local Prototypes */
67 /********************/
68 
69 /* Metadata cache callbacks */
70 static H5B2_hdr_t *H5B2__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
71 static herr_t H5B2__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr);
72 static herr_t H5B2__cache_hdr_dest(H5F_t *f, H5B2_hdr_t *hdr);
73 static herr_t H5B2__cache_hdr_clear(H5F_t *f, H5B2_hdr_t *hdr, hbool_t destroy);
74 static herr_t H5B2__cache_hdr_size(const H5F_t *f, const H5B2_hdr_t *hdr, size_t *size_ptr);
75 static H5B2_internal_t *H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
76 static herr_t H5B2__cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *i, unsigned H5_ATTR_UNUSED * flags_ptr);
77 static herr_t H5B2__cache_internal_dest(H5F_t *f, H5B2_internal_t *internal);
78 static herr_t H5B2__cache_internal_clear(H5F_t *f, H5B2_internal_t *i, hbool_t destroy);
79 static herr_t H5B2__cache_internal_size(const H5F_t *f, const H5B2_internal_t *i, size_t *size_ptr);
80 static H5B2_leaf_t *H5B2__cache_leaf_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *udata);
81 static herr_t H5B2__cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *l, unsigned H5_ATTR_UNUSED * flags_ptr);
82 static herr_t H5B2__cache_leaf_dest(H5F_t *f, H5B2_leaf_t *leaf);
83 static herr_t H5B2__cache_leaf_clear(H5F_t *f, H5B2_leaf_t *l, hbool_t destroy);
84 static herr_t H5B2__cache_leaf_size(const H5F_t *f, const H5B2_leaf_t *l, size_t *size_ptr);
85 
86 
87 /*********************/
88 /* Package Variables */
89 /*********************/
90 
91 /* H5B2 inherits cache-like properties from H5AC */
92 const H5AC_class_t H5AC_BT2_HDR[1] = {{
93     H5AC_BT2_HDR_ID,
94     (H5AC_load_func_t)H5B2__cache_hdr_load,
95     (H5AC_flush_func_t)H5B2__cache_hdr_flush,
96     (H5AC_dest_func_t)H5B2__cache_hdr_dest,
97     (H5AC_clear_func_t)H5B2__cache_hdr_clear,
98     (H5AC_size_func_t)H5B2__cache_hdr_size,
99 }};
100 
101 /* H5B2 inherits cache-like properties from H5AC */
102 const H5AC_class_t H5AC_BT2_INT[1] = {{
103     H5AC_BT2_INT_ID,
104     (H5AC_load_func_t)H5B2__cache_internal_load,
105     (H5AC_flush_func_t)H5B2__cache_internal_flush,
106     (H5AC_dest_func_t)H5B2__cache_internal_dest,
107     (H5AC_clear_func_t)H5B2__cache_internal_clear,
108     (H5AC_size_func_t)H5B2__cache_internal_size,
109 }};
110 
111 /* H5B2 inherits cache-like properties from H5AC */
112 const H5AC_class_t H5AC_BT2_LEAF[1] = {{
113     H5AC_BT2_LEAF_ID,
114     (H5AC_load_func_t)H5B2__cache_leaf_load,
115     (H5AC_flush_func_t)H5B2__cache_leaf_flush,
116     (H5AC_dest_func_t)H5B2__cache_leaf_dest,
117     (H5AC_clear_func_t)H5B2__cache_leaf_clear,
118     (H5AC_size_func_t)H5B2__cache_leaf_size,
119 }};
120 
121 
122 /*****************************/
123 /* Library Private Variables */
124 /*****************************/
125 
126 
127 /*******************/
128 /* Local Variables */
129 /*******************/
130 
131 
132 
133 /*-------------------------------------------------------------------------
134  * Function:	H5B2__cache_hdr_load
135  *
136  * Purpose:	Loads a B-tree header from the disk.
137  *
138  * Return:	Success:	Pointer to a new B-tree.
139  *		Failure:	NULL
140  *
141  * Programmer:	Quincey Koziol
142  *		koziol@ncsa.uiuc.edu
143  *		Feb 1 2005
144  *
145  *-------------------------------------------------------------------------
146  */
147 static H5B2_hdr_t *
H5B2__cache_hdr_load(H5F_t * f,hid_t dxpl_id,haddr_t addr,void * _udata)148 H5B2__cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
149 {
150     H5B2_hdr_t		*hdr = NULL;    /* B-tree header */
151     H5B2_hdr_cache_ud_t *udata = (H5B2_hdr_cache_ud_t *)_udata;
152     H5B2_create_t       cparam;         /* B-tree creation parameters */
153     H5B2_subid_t        id;		/* ID of B-tree class, as found in file */
154     uint16_t            depth;          /* Depth of B-tree */
155     uint32_t            stored_chksum;  /* Stored metadata checksum value */
156     uint32_t            computed_chksum; /* Computed metadata checksum value */
157     H5WB_t              *wb = NULL;     /* Wrapped buffer for header data */
158     uint8_t             hdr_buf[H5B2_HDR_BUF_SIZE]; /* Buffer for header */
159     uint8_t		*buf;           /* Pointer to header buffer */
160     const uint8_t	*p;             /* Pointer into raw data buffer */
161     H5B2_hdr_t		*ret_value;     /* Return value */
162 
163     FUNC_ENTER_STATIC
164 
165     /* Check arguments */
166     HDassert(f);
167     HDassert(H5F_addr_defined(addr));
168     HDassert(udata);
169 
170     /* Allocate new B-tree header and reset cache info */
171     if(NULL == (hdr = H5B2_hdr_alloc(udata->f)))
172         HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "allocation failed for B-tree header")
173 
174     /* Wrap the local buffer for serialized header info */
175     if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
176         HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, NULL, "can't wrap buffer")
177 
178     /* Get a pointer to a buffer that's large enough for header */
179     if(NULL == (buf = (uint8_t *)H5WB_actual(wb, hdr->hdr_size)))
180         HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, NULL, "can't get actual buffer")
181 
182     /* Read header from disk */
183     if(H5F_block_read(f, H5FD_MEM_BTREE, addr, hdr->hdr_size, dxpl_id, buf) < 0)
184         HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree header")
185 
186     /* Get temporary pointer to serialized header */
187     p = buf;
188 
189     /* Magic number */
190     if(HDmemcmp(p, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC))
191 	HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "wrong B-tree header signature")
192     p += H5_SIZEOF_MAGIC;
193 
194     /* Version */
195     if(*p++ != H5B2_HDR_VERSION)
196 	HGOTO_ERROR(H5E_BTREE, H5E_BADRANGE, NULL, "wrong B-tree header version")
197 
198     /* B-tree class */
199     id = (H5B2_subid_t)*p++;
200     if(id >= H5B2_NUM_BTREE_ID)
201         HGOTO_ERROR(H5E_BTREE, H5E_BADTYPE, NULL, "incorrect B-tree type")
202 
203     /* Node size (in bytes) */
204     UINT32DECODE(p, cparam.node_size);
205 
206     /* Raw key size (in bytes) */
207     UINT16DECODE(p, cparam.rrec_size);
208 
209     /* Depth of tree */
210     UINT16DECODE(p, depth);
211 
212     /* Split & merge %s */
213     cparam.split_percent = *p++;
214     cparam.merge_percent = *p++;
215 
216     /* Root node pointer */
217     H5F_addr_decode(udata->f, (const uint8_t **)&p, &(hdr->root.addr));
218     UINT16DECODE(p, hdr->root.node_nrec);
219     H5F_DECODE_LENGTH(udata->f, p, hdr->root.all_nrec);
220 
221     /* Metadata checksum */
222     UINT32DECODE(p, stored_chksum);
223 
224     /* Sanity check */
225     HDassert((size_t)(p - (const uint8_t *)buf) == hdr->hdr_size);
226 
227     /* Compute checksum on entire header */
228     computed_chksum = H5_checksum_metadata(buf, (hdr->hdr_size - H5B2_SIZEOF_CHKSUM), 0);
229 
230     /* Verify checksum */
231     if(stored_chksum != computed_chksum)
232         HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "incorrect metadata checksum for v2 B-tree header")
233 
234     /* Initialize B-tree header info */
235     cparam.cls = H5B2_client_class_g[id];
236     if(H5B2_hdr_init(hdr, &cparam, udata->ctx_udata, depth) < 0)
237         HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, NULL, "can't initialize B-tree header info")
238 
239     /* Set the B-tree header's address */
240     hdr->addr = addr;
241 
242     /* Set return value */
243     ret_value = hdr;
244 
245 done:
246     /* Release resources */
247     if(wb && H5WB_unwrap(wb) < 0)
248         HDONE_ERROR(H5E_BTREE, H5E_CLOSEERROR, NULL, "can't close wrapped buffer")
249     if(!ret_value && hdr)
250         if(H5B2_hdr_free(hdr) < 0)
251             HDONE_ERROR(H5E_BTREE, H5E_CANTRELEASE, NULL, "can't release v2 B-tree header")
252 
253     FUNC_LEAVE_NOAPI(ret_value)
254 } /* end H5B2__cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */
255 
256 
257 /*-------------------------------------------------------------------------
258  * Function:	H5B2__cache_hdr_flush
259  *
260  * Purpose:	Flushes a dirty B-tree header to disk.
261  *
262  * Return:	Non-negative on success/Negative on failure
263  *
264  * Programmer:	Quincey Koziol
265  *		koziol@ncsa.uiuc.edu
266  *		Feb 1 2005
267  *
268  *-------------------------------------------------------------------------
269  */
270 static herr_t
H5B2__cache_hdr_flush(H5F_t * f,hid_t dxpl_id,hbool_t destroy,haddr_t addr,H5B2_hdr_t * hdr,unsigned H5_ATTR_UNUSED * flags_ptr)271 H5B2__cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
272     H5B2_hdr_t *hdr, unsigned H5_ATTR_UNUSED * flags_ptr)
273 {
274     H5WB_t      *wb = NULL;             /* Wrapped buffer for header data */
275     uint8_t     hdr_buf[H5B2_HDR_BUF_SIZE]; /* Buffer for header */
276     herr_t      ret_value = SUCCEED;    /* Return value */
277 
278     FUNC_ENTER_STATIC
279 
280     /* check arguments */
281     HDassert(f);
282     HDassert(H5F_addr_defined(addr));
283     HDassert(hdr);
284 
285     if(hdr->cache_info.is_dirty) {
286         uint8_t	*buf;           /* Pointer to header buffer */
287         uint8_t *p;             /* Pointer into raw data buffer */
288         uint32_t metadata_chksum; /* Computed metadata checksum value */
289 
290         /* Set the B-tree header's file context for this operation */
291         hdr->f = f;
292 
293         /* Wrap the local buffer for serialized header info */
294         if(NULL == (wb = H5WB_wrap(hdr_buf, sizeof(hdr_buf))))
295             HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't wrap buffer")
296 
297         /* Get a pointer to a buffer that's large enough for header */
298         if(NULL == (buf = (uint8_t *)H5WB_actual(wb, hdr->hdr_size)))
299             HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "can't get actual buffer")
300 
301         /* Get temporary pointer to serialized header */
302         p = buf;
303 
304         /* Magic number */
305         HDmemcpy(p, H5B2_HDR_MAGIC, (size_t)H5_SIZEOF_MAGIC);
306         p += H5_SIZEOF_MAGIC;
307 
308         /* Version # */
309         *p++ = H5B2_HDR_VERSION;
310 
311         /* B-tree type */
312         *p++ = hdr->cls->id;
313 
314         /* Node size (in bytes) */
315         UINT32ENCODE(p, hdr->node_size);
316 
317         /* Raw key size (in bytes) */
318         UINT16ENCODE(p, hdr->rrec_size);
319 
320         /* Depth of tree */
321         UINT16ENCODE(p, hdr->depth);
322 
323         /* Split & merge %s */
324         H5_CHECK_OVERFLOW(hdr->split_percent, /* From: */ unsigned, /* To: */ uint8_t);
325         *p++ = (uint8_t)hdr->split_percent;
326         H5_CHECK_OVERFLOW(hdr->merge_percent, /* From: */ unsigned, /* To: */ uint8_t);
327         *p++ = (uint8_t)hdr->merge_percent;
328 
329         /* Root node pointer */
330         H5F_addr_encode(f, &p, hdr->root.addr);
331         UINT16ENCODE(p, hdr->root.node_nrec);
332         H5F_ENCODE_LENGTH(f, p, hdr->root.all_nrec);
333 
334         /* Compute metadata checksum */
335         metadata_chksum = H5_checksum_metadata(buf, (hdr->hdr_size - H5B2_SIZEOF_CHKSUM), 0);
336 
337         /* Metadata checksum */
338         UINT32ENCODE(p, metadata_chksum);
339 
340         /* Write the B-tree header. */
341         HDassert((size_t)(p - buf) == hdr->hdr_size);
342         if(H5F_block_write(f, H5FD_MEM_BTREE, addr, hdr->hdr_size, dxpl_id, buf) < 0)
343             HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree header to disk")
344 
345         hdr->cache_info.is_dirty = FALSE;
346     } /* end if */
347 
348     if(destroy)
349         if(H5B2__cache_hdr_dest(f, hdr) < 0)
350             HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree header")
351 
352 done:
353     /* Release resources */
354     if(wb && H5WB_unwrap(wb) < 0)
355         HDONE_ERROR(H5E_BTREE, H5E_CLOSEERROR, FAIL, "can't close wrapped buffer")
356 
357     FUNC_LEAVE_NOAPI(ret_value)
358 } /* H5B2__cache_hdr_flush() */
359 
360 
361 /*-------------------------------------------------------------------------
362  * Function:	H5B2__cache_hdr_dest
363  *
364  * Purpose:	Destroys a B-tree header in memory.
365  *
366  * Return:	Non-negative on success/Negative on failure
367  *
368  * Programmer:	Quincey Koziol
369  *		koziol@ncsa.uiuc.edu
370  *		Feb 1 2005
371  *
372  *-------------------------------------------------------------------------
373  */
374 static herr_t
H5B2__cache_hdr_dest(H5F_t * f,H5B2_hdr_t * hdr)375 H5B2__cache_hdr_dest(H5F_t *f, H5B2_hdr_t *hdr)
376 {
377     herr_t ret_value = SUCCEED;     /* Return value */
378 
379     FUNC_ENTER_STATIC
380 
381     /* Check arguments */
382     HDassert(hdr);
383     HDassert(hdr->rc == 0);
384 
385     /* If we're going to free the space on disk, the address must be valid */
386     HDassert(!hdr->cache_info.free_file_space_on_destroy || H5F_addr_defined(hdr->cache_info.addr));
387 
388     /* Check for freeing file space for B-tree header */
389     if(hdr->cache_info.free_file_space_on_destroy) {
390         /* Release the space on disk */
391         /* (XXX: Nasty usage of internal DXPL value! -QAK) */
392         if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, hdr->cache_info.addr, (hsize_t)hdr->hdr_size) < 0)
393             HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree header")
394     } /* end if */
395 
396     /* Release B-tree header info */
397     if(H5B2_hdr_free(hdr) < 0)
398         HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree header info")
399 
400 done:
401     FUNC_LEAVE_NOAPI(ret_value)
402 } /* end H5B2__cache_hdr_dest() */
403 
404 
405 /*-------------------------------------------------------------------------
406  * Function:	H5B2__cache_hdr_clear
407  *
408  * Purpose:	Mark a B-tree header in memory as non-dirty.
409  *
410  * Return:	Non-negative on success/Negative on failure
411  *
412  * Programmer:	Quincey Koziol
413  *		koziol@ncsa.uiuc.edu
414  *		Feb  1 2005
415  *
416  *-------------------------------------------------------------------------
417  */
418 static herr_t
H5B2__cache_hdr_clear(H5F_t * f,H5B2_hdr_t * hdr,hbool_t destroy)419 H5B2__cache_hdr_clear(H5F_t *f, H5B2_hdr_t *hdr, hbool_t destroy)
420 {
421     herr_t ret_value = SUCCEED;         /* Return value */
422 
423     FUNC_ENTER_STATIC
424 
425     /*
426      * Check arguments.
427      */
428     HDassert(hdr);
429 
430     /* Reset the dirty flag.  */
431     hdr->cache_info.is_dirty = FALSE;
432 
433     if(destroy)
434         if(H5B2__cache_hdr_dest(f, hdr) < 0)
435 	    HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree header")
436 
437 done:
438     FUNC_LEAVE_NOAPI(ret_value)
439 } /* end H5B2__cache_hdr_clear() */
440 
441 
442 /*-------------------------------------------------------------------------
443  * Function:    H5B2__cache_hdr_size
444  *
445  * Purpose:     Compute the size in bytes of a B-tree header
446  *              on disk, and return it in *size_ptr.  On failure,
447  *              the value of *size_ptr is undefined.
448  *
449  * Return:      SUCCEED (Can't fail)
450  *
451  * Programmer:  Quincey Koziol
452  *              koziol@hdfgroup.org
453  *              Feb 1 2005
454  *
455  *-------------------------------------------------------------------------
456  */
457 static herr_t
H5B2__cache_hdr_size(const H5F_t H5_ATTR_UNUSED * f,const H5B2_hdr_t * hdr,size_t * size_ptr)458 H5B2__cache_hdr_size(const H5F_t H5_ATTR_UNUSED *f, const H5B2_hdr_t *hdr, size_t *size_ptr)
459 {
460     FUNC_ENTER_STATIC_NOERR
461 
462     /* check arguments */
463     HDassert(f);
464     HDassert(hdr);
465     HDassert(size_ptr);
466 
467     /* Set size value */
468     *size_ptr = hdr->hdr_size;
469 
470     FUNC_LEAVE_NOAPI(SUCCEED)
471 } /* H5B2__cache_hdr_size() */
472 
473 
474 /*-------------------------------------------------------------------------
475  * Function:	H5B2__cache_internal_load
476  *
477  * Purpose:	Loads a B-tree internal node from the disk.
478  *
479  * Return:	Success:	Pointer to a new B-tree internal node.
480  *              Failure:        NULL
481  *
482  * Programmer:	Quincey Koziol
483  *		koziol@ncsa.uiuc.edu
484  *		Feb 2 2005
485  *
486  *-------------------------------------------------------------------------
487  */
488 static H5B2_internal_t *
H5B2__cache_internal_load(H5F_t * f,hid_t dxpl_id,haddr_t addr,void * _udata)489 H5B2__cache_internal_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, void *_udata)
490 {
491     H5B2_internal_cache_ud_t *udata = (H5B2_internal_cache_ud_t *)_udata;     /* Pointer to user data */
492     H5B2_internal_t	*internal = NULL;       /* Internal node read */
493     const uint8_t	*p;             /* Pointer into raw data buffer */
494     uint8_t		*native;        /* Pointer to native record info */
495     H5B2_node_ptr_t	*int_node_ptr;  /* Pointer to node pointer info */
496     uint32_t            stored_chksum;  /* Stored metadata checksum value */
497     uint32_t            computed_chksum; /* Computed metadata checksum value */
498     unsigned		u;              /* Local index variable */
499     H5B2_internal_t	*ret_value;     /* Return value */
500 
501     FUNC_ENTER_STATIC
502 
503     /* Check arguments */
504     HDassert(f);
505     HDassert(H5F_addr_defined(addr));
506     HDassert(udata);
507 
508     /* Allocate new internal node and reset cache info */
509     if(NULL == (internal = H5FL_MALLOC(H5B2_internal_t)))
510 	HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
511     HDmemset(&internal->cache_info, 0, sizeof(H5AC_info_t));
512 
513     /* Set the B-tree header's file context for this operation */
514     udata->hdr->f = f;
515 
516     /* Increment ref. count on B-tree header */
517     if(H5B2_hdr_incr(udata->hdr) < 0)
518         HGOTO_ERROR(H5E_BTREE, H5E_CANTINC, NULL, "can't increment ref. count on B-tree header")
519 
520     /* Share B-tree information */
521     internal->hdr = udata->hdr;
522 
523     /* Read header from disk */
524     if(H5F_block_read(f, H5FD_MEM_BTREE, addr, udata->hdr->node_size, dxpl_id, udata->hdr->page) < 0)
525         HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree internal node")
526 
527     p = udata->hdr->page;
528 
529     /* Magic number */
530     if(HDmemcmp(p, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC))
531         HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "wrong B-tree internal node signature")
532     p += H5_SIZEOF_MAGIC;
533 
534     /* Version */
535     if(*p++ != H5B2_INT_VERSION)
536 	HGOTO_ERROR(H5E_BTREE, H5E_BADRANGE, NULL, "wrong B-tree internal node version")
537 
538     /* B-tree type */
539     if(*p++ != (uint8_t)udata->hdr->cls->id)
540         HGOTO_ERROR(H5E_BTREE, H5E_BADTYPE, NULL, "incorrect B-tree type")
541 
542     /* Allocate space for the native keys in memory */
543     if(NULL == (internal->int_native = (uint8_t *)H5FL_FAC_MALLOC(udata->hdr->node_info[udata->depth].nat_rec_fac)))
544         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree internal native keys")
545 
546     /* Allocate space for the node pointers in memory */
547     if(NULL == (internal->node_ptrs = (H5B2_node_ptr_t *)H5FL_FAC_MALLOC(udata->hdr->node_info[udata->depth].node_ptr_fac)))
548         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree internal node pointers")
549 
550     /* Set the number of records in the leaf & it's depth */
551     internal->nrec = udata->nrec;
552     internal->depth = udata->depth;
553 
554     /* Deserialize records for internal node */
555     native = internal->int_native;
556     for(u = 0; u < internal->nrec; u++) {
557         /* Decode record */
558         if((udata->hdr->cls->decode)(p, native, udata->hdr->cb_ctx) < 0)
559             HGOTO_ERROR(H5E_BTREE, H5E_CANTDECODE, NULL, "unable to decode B-tree record")
560 
561         /* Move to next record */
562         p += udata->hdr->rrec_size;
563         native += udata->hdr->cls->nrec_size;
564     } /* end for */
565 
566     /* Deserialize node pointers for internal node */
567     int_node_ptr = internal->node_ptrs;
568     for(u = 0; u < (unsigned)(internal->nrec + 1); u++) {
569         /* Decode node pointer */
570         H5F_addr_decode(udata->f, (const uint8_t **)&p, &(int_node_ptr->addr));
571         UINT64DECODE_VAR(p, int_node_ptr->node_nrec, udata->hdr->max_nrec_size);
572         if(udata->depth > 1)
573             UINT64DECODE_VAR(p, int_node_ptr->all_nrec, udata->hdr->node_info[udata->depth - 1].cum_max_nrec_size)
574         else
575             int_node_ptr->all_nrec = int_node_ptr->node_nrec;
576 
577         /* Move to next node pointer */
578         int_node_ptr++;
579     } /* end for */
580 
581     /* Compute checksum on internal node */
582     computed_chksum = H5_checksum_metadata(udata->hdr->page, (size_t)(p - (const uint8_t *)udata->hdr->page), 0);
583 
584     /* Metadata checksum */
585     UINT32DECODE(p, stored_chksum);
586 
587     /* Sanity check parsing */
588     HDassert((size_t)(p - (const uint8_t *)udata->hdr->page) <= udata->hdr->node_size);
589 
590     /* Verify checksum */
591     if(stored_chksum != computed_chksum)
592         HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "incorrect metadata checksum for v2 internal node")
593 
594     /* Set return value */
595     ret_value = internal;
596 
597 done:
598     if(!ret_value && internal)
599         if(H5B2_internal_free(internal) < 0)
600             HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, NULL, "unable to destroy B-tree internal node")
601 
602     FUNC_LEAVE_NOAPI(ret_value)
603 } /* H5B2__cache_internal_load() */ /*lint !e818 Can't make udata a pointer to const */
604 
605 
606 /*-------------------------------------------------------------------------
607  * Function:	H5B2__cache_internal_flush
608  *
609  * Purpose:	Flushes a dirty B-tree internal node to disk.
610  *
611  * Return:	Non-negative on success/Negative on failure
612  *
613  * Programmer:	Quincey Koziol
614  *		koziol@ncsa.uiuc.edu
615  *		Feb 3 2005
616  *
617  *-------------------------------------------------------------------------
618  */
619 static herr_t
H5B2__cache_internal_flush(H5F_t * f,hid_t dxpl_id,hbool_t destroy,haddr_t addr,H5B2_internal_t * internal,unsigned H5_ATTR_UNUSED * flags_ptr)620 H5B2__cache_internal_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_internal_t *internal, unsigned H5_ATTR_UNUSED * flags_ptr)
621 {
622     herr_t      ret_value = SUCCEED;    /* Return value */
623 
624     FUNC_ENTER_STATIC
625 
626     /* check arguments */
627     HDassert(f);
628     HDassert(H5F_addr_defined(addr));
629     HDassert(internal);
630     HDassert(internal->hdr);
631 
632     if(internal->cache_info.is_dirty) {
633         uint8_t *p;             /* Pointer into raw data buffer */
634         uint8_t *native;        /* Pointer to native record info */
635         H5B2_node_ptr_t *int_node_ptr;      /* Pointer to node pointer info */
636         uint32_t metadata_chksum; /* Computed metadata checksum value */
637         unsigned u;             /* Local index variable */
638 
639         /* Set the B-tree header's file context for this operation */
640         internal->hdr->f = f;
641 
642         p = internal->hdr->page;
643 
644         /* Magic number */
645         HDmemcpy(p, H5B2_INT_MAGIC, (size_t)H5_SIZEOF_MAGIC);
646         p += H5_SIZEOF_MAGIC;
647 
648         /* Version # */
649         *p++ = H5B2_INT_VERSION;
650 
651         /* B-tree type */
652         *p++ = internal->hdr->cls->id;
653         HDassert((size_t)(p - internal->hdr->page) == (H5B2_INT_PREFIX_SIZE - H5B2_SIZEOF_CHKSUM));
654 
655         /* Serialize records for internal node */
656         native = internal->int_native;
657         for(u = 0; u < internal->nrec; u++) {
658             /* Encode record */
659             if((internal->hdr->cls->encode)(p, native, internal->hdr->cb_ctx) < 0)
660                 HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record")
661 
662             /* Move to next record */
663             p += internal->hdr->rrec_size;
664             native += internal->hdr->cls->nrec_size;
665         } /* end for */
666 
667         /* Serialize node pointers for internal node */
668         int_node_ptr = internal->node_ptrs;
669         for(u = 0; u < (unsigned)(internal->nrec + 1); u++) {
670             /* Encode node pointer */
671             H5F_addr_encode(f, &p, int_node_ptr->addr);
672             UINT64ENCODE_VAR(p, int_node_ptr->node_nrec, internal->hdr->max_nrec_size);
673             if(internal->depth > 1)
674                 UINT64ENCODE_VAR(p, int_node_ptr->all_nrec, internal->hdr->node_info[internal->depth - 1].cum_max_nrec_size);
675 
676             /* Move to next node pointer */
677             int_node_ptr++;
678         } /* end for */
679 
680         /* Compute metadata checksum */
681         metadata_chksum = H5_checksum_metadata(internal->hdr->page, (size_t)(p - internal->hdr->page), 0);
682 
683         /* Metadata checksum */
684         UINT32ENCODE(p, metadata_chksum);
685 
686 	/* Write the B-tree internal node */
687         HDassert((size_t)(p - internal->hdr->page) <= internal->hdr->node_size);
688 	if(H5F_block_write(f, H5FD_MEM_BTREE, addr, internal->hdr->node_size, dxpl_id, internal->hdr->page) < 0)
689 	    HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree internal node to disk")
690 
691 	internal->cache_info.is_dirty = FALSE;
692     } /* end if */
693 
694     if(destroy)
695         if(H5B2__cache_internal_dest(f, internal) < 0)
696 	    HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree internal node")
697 
698 done:
699     FUNC_LEAVE_NOAPI(ret_value)
700 } /* H5B2__cache_internal_flush() */
701 
702 
703 /*-------------------------------------------------------------------------
704  * Function:	H5B2__cache_internal_dest
705  *
706  * Purpose:	Destroys a B-tree internal node in memory.
707  *
708  * Return:	Non-negative on success/Negative on failure
709  *
710  * Programmer:	Quincey Koziol
711  *		koziol@ncsa.uiuc.edu
712  *		Feb 2 2005
713  *
714  *-------------------------------------------------------------------------
715  */
716 static herr_t
H5B2__cache_internal_dest(H5F_t * f,H5B2_internal_t * internal)717 H5B2__cache_internal_dest(H5F_t *f, H5B2_internal_t *internal)
718 {
719     herr_t ret_value = SUCCEED;     /* Return value */
720 
721     FUNC_ENTER_STATIC
722 
723     /* Check arguments */
724     HDassert(f);
725     HDassert(internal);
726     HDassert(internal->hdr);
727 
728     /* If we're going to free the space on disk, the address must be valid */
729     HDassert(!internal->cache_info.free_file_space_on_destroy || H5F_addr_defined(internal->cache_info.addr));
730 
731     /* Check for freeing file space for B-tree internal node */
732     if(internal->cache_info.free_file_space_on_destroy) {
733         /* Release the space on disk */
734         /* (XXX: Nasty usage of internal DXPL value! -QAK) */
735         if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, internal->cache_info.addr, (hsize_t)internal->hdr->node_size) < 0)
736             HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree internal node")
737     } /* end if */
738 
739     /* Release v2 b-tree internal node */
740     if(H5B2_internal_free(internal) < 0)
741         HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to release v2 B-tree internal node")
742 
743 done:
744     FUNC_LEAVE_NOAPI(ret_value)
745 } /* end H5B2__cache_internal_dest() */
746 
747 
748 /*-------------------------------------------------------------------------
749  * Function:	H5B2__cache_internal_clear
750  *
751  * Purpose:	Mark a B-tree internal node in memory as non-dirty.
752  *
753  * Return:	Non-negative on success/Negative on failure
754  *
755  * Programmer:	Quincey Koziol
756  *		koziol@ncsa.uiuc.edu
757  *		Feb  2 2005
758  *
759  *-------------------------------------------------------------------------
760  */
761 static herr_t
H5B2__cache_internal_clear(H5F_t * f,H5B2_internal_t * internal,hbool_t destroy)762 H5B2__cache_internal_clear(H5F_t *f, H5B2_internal_t *internal, hbool_t destroy)
763 {
764     herr_t ret_value = SUCCEED;
765 
766     FUNC_ENTER_STATIC
767 
768     /*
769      * Check arguments.
770      */
771     HDassert(internal);
772 
773     /* Reset the dirty flag.  */
774     internal->cache_info.is_dirty = FALSE;
775 
776     if(destroy)
777         if(H5B2__cache_internal_dest(f, internal) < 0)
778 	    HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree internal node")
779 
780 done:
781     FUNC_LEAVE_NOAPI(ret_value)
782 } /* end H5B2__cache_internal_clear() */
783 
784 
785 /*-------------------------------------------------------------------------
786  * Function:	H5B2__cache_internal_size
787  *
788  * Purpose:	Compute the size in bytes of a B-tree internal node
789  *		on disk, and return it in *size_ptr.  On failure,
790  *		the value of *size_ptr is undefined.
791  *
792  * Return:	Non-negative on success/Negative on failure
793  *
794  * Programmer:	Quincey Koziol
795  *		koziol@ncsa.uiuc.edu
796  *		Feb 2 2005
797  *
798  *-------------------------------------------------------------------------
799  */
800 static herr_t
H5B2__cache_internal_size(const H5F_t H5_ATTR_UNUSED * f,const H5B2_internal_t * internal,size_t * size_ptr)801 H5B2__cache_internal_size(const H5F_t H5_ATTR_UNUSED *f, const H5B2_internal_t *internal, size_t *size_ptr)
802 {
803     FUNC_ENTER_STATIC_NOERR
804 
805     /* check arguments */
806     HDassert(internal);
807     HDassert(internal->hdr);
808     HDassert(size_ptr);
809 
810     /* Set size value */
811     *size_ptr = internal->hdr->node_size;
812 
813     FUNC_LEAVE_NOAPI(SUCCEED)
814 } /* H5B2__cache_internal_size() */
815 
816 
817 /*-------------------------------------------------------------------------
818  * Function:	H5B2__cache_leaf_load
819  *
820  * Purpose:	Loads a B-tree leaf from the disk.
821  *
822  * Return:	Success:	Pointer to a new B-tree leaf node.
823  *		Failure:	NULL
824  *
825  * Programmer:	Quincey Koziol
826  *		koziol@ncsa.uiuc.edu
827  *		Feb 2 2005
828  *
829  *-------------------------------------------------------------------------
830  */
831 static H5B2_leaf_t *
H5B2__cache_leaf_load(H5F_t H5_ATTR_UNUSED * f,hid_t dxpl_id,haddr_t addr,void * _udata)832 H5B2__cache_leaf_load(H5F_t H5_ATTR_UNUSED *f, hid_t dxpl_id, haddr_t addr, void *_udata)
833 {
834     H5B2_leaf_cache_ud_t *udata = (H5B2_leaf_cache_ud_t *)_udata;
835     H5B2_leaf_t		*leaf = NULL;   /* Pointer to lead node loaded */
836     const uint8_t	*p;             /* Pointer into raw data buffer */
837     uint8_t		*native;        /* Pointer to native keys */
838     uint32_t            stored_chksum;  /* Stored metadata checksum value */
839     uint32_t            computed_chksum; /* Computed metadata checksum value */
840     unsigned		u;              /* Local index variable */
841     H5B2_leaf_t		*ret_value;     /* Return value */
842 
843     FUNC_ENTER_STATIC
844 
845     /* Check arguments */
846     HDassert(f);
847     HDassert(H5F_addr_defined(addr));
848     HDassert(udata);
849 
850     /* Allocate new leaf node and reset cache info */
851     if(NULL == (leaf = H5FL_MALLOC(H5B2_leaf_t)))
852         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
853     HDmemset(&leaf->cache_info, 0, sizeof(H5AC_info_t));
854 
855     /* Set the B-tree header's file context for this operation */
856     udata->hdr->f = udata->f;
857 
858     /* Increment ref. count on B-tree header */
859     if(H5B2_hdr_incr(udata->hdr) < 0)
860         HGOTO_ERROR(H5E_BTREE, H5E_CANTINC, NULL, "can't increment ref. count on B-tree header")
861 
862     /* Share B-tree header information */
863     leaf->hdr = udata->hdr;
864 
865     /* Read header from disk */
866     if(H5F_block_read(udata->f, H5FD_MEM_BTREE, addr, udata->hdr->node_size, dxpl_id, udata->hdr->page) < 0)
867         HGOTO_ERROR(H5E_BTREE, H5E_READERROR, NULL, "can't read B-tree leaf node")
868 
869     p = udata->hdr->page;
870 
871     /* Magic number */
872     if(HDmemcmp(p, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC))
873         HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree leaf node signature")
874     p += H5_SIZEOF_MAGIC;
875 
876     /* Version */
877     if(*p++ != H5B2_LEAF_VERSION)
878         HGOTO_ERROR(H5E_BTREE, H5E_CANTLOAD, NULL, "wrong B-tree leaf node version")
879 
880     /* B-tree type */
881     if(*p++ != (uint8_t)udata->hdr->cls->id)
882         HGOTO_ERROR(H5E_BTREE, H5E_BADTYPE, NULL, "incorrect B-tree type")
883 
884     /* Allocate space for the native keys in memory */
885     if(NULL == (leaf->leaf_native = (uint8_t *)H5FL_FAC_MALLOC(udata->hdr->node_info[0].nat_rec_fac)))
886         HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, NULL, "memory allocation failed for B-tree leaf native keys")
887 
888     /* Set the number of records in the leaf */
889     leaf->nrec = udata->nrec;
890 
891     /* Deserialize records for leaf node */
892     native = leaf->leaf_native;
893     for(u = 0; u < leaf->nrec; u++) {
894         /* Decode record */
895         if((udata->hdr->cls->decode)(p, native, udata->hdr->cb_ctx) < 0)
896             HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, NULL, "unable to decode B-tree record")
897 
898         /* Move to next record */
899         p += udata->hdr->rrec_size;
900         native += udata->hdr->cls->nrec_size;
901     } /* end for */
902 
903     /* Compute checksum on internal node */
904     computed_chksum = H5_checksum_metadata(udata->hdr->page, (size_t)(p - (const uint8_t *)udata->hdr->page), 0);
905 
906     /* Metadata checksum */
907     UINT32DECODE(p, stored_chksum);
908 
909     /* Sanity check parsing */
910     HDassert((size_t)(p - (const uint8_t *)udata->hdr->page) <= udata->hdr->node_size);
911 
912     /* Verify checksum */
913     if(stored_chksum != computed_chksum)
914 	HGOTO_ERROR(H5E_BTREE, H5E_BADVALUE, NULL, "incorrect metadata checksum for v2 leaf node")
915 
916     /* Set return value */
917     ret_value = leaf;
918 
919 done:
920     if(!ret_value && leaf)
921         if(H5B2_leaf_free(leaf) < 0)
922             HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, NULL, "unable to destroy B-tree leaf node")
923 
924     FUNC_LEAVE_NOAPI(ret_value)
925 } /* H5B2__cache_leaf_load() */ /*lint !e818 Can't make udata a pointer to const */
926 
927 
928 /*-------------------------------------------------------------------------
929  * Function:	H5B2__cache_leaf_flush
930  *
931  * Purpose:	Flushes a dirty B-tree leaf node to disk.
932  *
933  * Return:	Non-negative on success/Negative on failure
934  *
935  * Programmer:	Quincey Koziol
936  *		koziol@ncsa.uiuc.edu
937  *		Feb 2 2005
938  *
939  *-------------------------------------------------------------------------
940  */
941 static herr_t
H5B2__cache_leaf_flush(H5F_t * f,hid_t dxpl_id,hbool_t destroy,haddr_t addr,H5B2_leaf_t * leaf,unsigned H5_ATTR_UNUSED * flags_ptr)942 H5B2__cache_leaf_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_leaf_t *leaf, unsigned H5_ATTR_UNUSED * flags_ptr)
943 {
944     herr_t      ret_value = SUCCEED;    /* Return value */
945 
946     FUNC_ENTER_STATIC
947 
948     /* check arguments */
949     HDassert(f);
950     HDassert(H5F_addr_defined(addr));
951     HDassert(leaf);
952     HDassert(leaf->hdr);
953 
954     if(leaf->cache_info.is_dirty) {
955         uint8_t *p;             /* Pointer into raw data buffer */
956         uint8_t *native;        /* Pointer to native keys */
957         uint32_t metadata_chksum; /* Computed metadata checksum value */
958         unsigned u;             /* Local index variable */
959 
960         /* Set the B-tree header's file context for this operation */
961         leaf->hdr->f = f;
962 
963         p = leaf->hdr->page;
964 
965         /* magic number */
966         HDmemcpy(p, H5B2_LEAF_MAGIC, (size_t)H5_SIZEOF_MAGIC);
967         p += H5_SIZEOF_MAGIC;
968 
969         /* version # */
970         *p++ = H5B2_LEAF_VERSION;
971 
972         /* b-tree type */
973         *p++ = leaf->hdr->cls->id;
974         HDassert((size_t)(p - leaf->hdr->page) == (H5B2_LEAF_PREFIX_SIZE - H5B2_SIZEOF_CHKSUM));
975 
976         /* Serialize records for leaf node */
977         native = leaf->leaf_native;
978         for(u = 0; u < leaf->nrec; u++) {
979             /* Encode record */
980             if((leaf->hdr->cls->encode)(p, native, leaf->hdr->cb_ctx) < 0)
981                 HGOTO_ERROR(H5E_BTREE, H5E_CANTENCODE, FAIL, "unable to encode B-tree record")
982 
983             /* Move to next record */
984             p += leaf->hdr->rrec_size;
985             native += leaf->hdr->cls->nrec_size;
986         } /* end for */
987 
988         /* Compute metadata checksum */
989         metadata_chksum = H5_checksum_metadata(leaf->hdr->page, (size_t)(p - leaf->hdr->page), 0);
990 
991         /* Metadata checksum */
992         UINT32ENCODE(p, metadata_chksum);
993 
994 	/* Write the B-tree leaf node */
995         HDassert((size_t)(p - leaf->hdr->page) <= leaf->hdr->node_size);
996 	if(H5F_block_write(f, H5FD_MEM_BTREE, addr, leaf->hdr->node_size, dxpl_id, leaf->hdr->page) < 0)
997 	    HGOTO_ERROR(H5E_BTREE, H5E_CANTFLUSH, FAIL, "unable to save B-tree leaf node to disk")
998 
999 	leaf->cache_info.is_dirty = FALSE;
1000     } /* end if */
1001 
1002     if(destroy)
1003         if(H5B2__cache_leaf_dest(f, leaf) < 0)
1004 	    HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
1005 
1006 done:
1007     FUNC_LEAVE_NOAPI(ret_value)
1008 } /* H5B2__cache_leaf_flush() */
1009 
1010 
1011 /*-------------------------------------------------------------------------
1012  * Function:	H5B2__cache_leaf_dest
1013  *
1014  * Purpose:	Destroys a B-tree leaf node in memory.
1015  *
1016  * Return:	Non-negative on success/Negative on failure
1017  *
1018  * Programmer:	Quincey Koziol
1019  *		koziol@ncsa.uiuc.edu
1020  *		Feb 2 2005
1021  *
1022  *-------------------------------------------------------------------------
1023  */
1024 static herr_t
H5B2__cache_leaf_dest(H5F_t * f,H5B2_leaf_t * leaf)1025 H5B2__cache_leaf_dest(H5F_t *f, H5B2_leaf_t *leaf)
1026 {
1027     herr_t ret_value = SUCCEED;     /* Return value */
1028 
1029     FUNC_ENTER_STATIC
1030 
1031     /* Check arguments */
1032     HDassert(f);
1033     HDassert(leaf);
1034     HDassert(leaf->hdr);
1035 
1036     /* If we're going to free the space on disk, the address must be valid */
1037     HDassert(!leaf->cache_info.free_file_space_on_destroy || H5F_addr_defined(leaf->cache_info.addr));
1038 
1039     /* Check for freeing file space for B-tree leaf node */
1040     if(leaf->cache_info.free_file_space_on_destroy) {
1041         /* Release the space on disk */
1042         /* (XXX: Nasty usage of internal DXPL value! -QAK) */
1043         if(H5MF_xfree(f, H5FD_MEM_BTREE, H5AC_dxpl_id, leaf->cache_info.addr, (hsize_t)leaf->hdr->node_size) < 0)
1044             HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free v2 B-tree leaf node")
1045     } /* end if */
1046 
1047     /* Destroy v2 b-tree leaf node */
1048     if(H5B2_leaf_free(leaf) < 0)
1049         HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
1050 
1051 done:
1052     FUNC_LEAVE_NOAPI(ret_value)
1053 } /* end H5B2__cache_leaf_dest() */
1054 
1055 
1056 /*-------------------------------------------------------------------------
1057  * Function:	H5B2__cache_leaf_clear
1058  *
1059  * Purpose:	Mark a B-tree leaf node in memory as non-dirty.
1060  *
1061  * Return:	Non-negative on success/Negative on failure
1062  *
1063  * Programmer:	Quincey Koziol
1064  *		koziol@ncsa.uiuc.edu
1065  *		Feb  2 2005
1066  *
1067  *-------------------------------------------------------------------------
1068  */
1069 static herr_t
H5B2__cache_leaf_clear(H5F_t * f,H5B2_leaf_t * leaf,hbool_t destroy)1070 H5B2__cache_leaf_clear(H5F_t *f, H5B2_leaf_t *leaf, hbool_t destroy)
1071 {
1072     herr_t ret_value = SUCCEED;
1073 
1074     FUNC_ENTER_STATIC
1075 
1076     /*
1077      * Check arguments.
1078      */
1079     HDassert(leaf);
1080 
1081     /* Reset the dirty flag.  */
1082     leaf->cache_info.is_dirty = FALSE;
1083 
1084     if(destroy)
1085         if(H5B2__cache_leaf_dest(f, leaf) < 0)
1086 	    HGOTO_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to destroy B-tree leaf node")
1087 
1088 done:
1089     FUNC_LEAVE_NOAPI(ret_value)
1090 } /* end H5B2__cache_leaf_clear() */
1091 
1092 
1093 /*-------------------------------------------------------------------------
1094  * Function:	H5B2__cache_leaf_size
1095  *
1096  * Purpose:	Compute the size in bytes of a B-tree leaf node
1097  *		on disk, and return it in *size_ptr.  On failure,
1098  *		the value of *size_ptr is undefined.
1099  *
1100  * Return:	Non-negative on success/Negative on failure
1101  *
1102  * Programmer:	Quincey Koziol
1103  *		koziol@ncsa.uiuc.edu
1104  *		Feb 2 2005
1105  *
1106  *-------------------------------------------------------------------------
1107  */
1108 static herr_t
H5B2__cache_leaf_size(const H5F_t H5_ATTR_UNUSED * f,const H5B2_leaf_t * leaf,size_t * size_ptr)1109 H5B2__cache_leaf_size(const H5F_t H5_ATTR_UNUSED *f, const H5B2_leaf_t *leaf, size_t *size_ptr)
1110 {
1111     FUNC_ENTER_STATIC_NOERR
1112 
1113     /* check arguments */
1114     HDassert(leaf);
1115     HDassert(leaf->hdr);
1116     HDassert(size_ptr);
1117 
1118     /* Set size value */
1119     *size_ptr = leaf->hdr->node_size;
1120 
1121     FUNC_LEAVE_NOAPI(SUCCEED)
1122 } /* H5B2__cache_leaf_size() */
1123 
1124