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://www.hdfgroup.org/licenses.               *
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:		H5B2leaf.c
17  *			Dec 01 2016
18  *			Quincey Koziol
19  *
20  * Purpose:		Routines for managing v2 B-tree leaf ndoes.
21  *
22  *-------------------------------------------------------------------------
23  */
24 
25 /****************/
26 /* Module Setup */
27 /****************/
28 
29 #include "H5B2module.h" /* This source code file is part of the H5B2 module */
30 
31 /***********/
32 /* Headers */
33 /***********/
34 #include "H5private.h"   /* Generic Functions			*/
35 #include "H5B2pkg.h"     /* v2 B-trees				*/
36 #include "H5Eprivate.h"  /* Error handling		  	*/
37 #include "H5MFprivate.h" /* File memory management		*/
38 #include "H5MMprivate.h" /* Memory management			*/
39 
40 /****************/
41 /* Local Macros */
42 /****************/
43 
44 /******************/
45 /* Local Typedefs */
46 /******************/
47 
48 /********************/
49 /* Package Typedefs */
50 /********************/
51 
52 /********************/
53 /* Local Prototypes */
54 /********************/
55 static herr_t H5B2__shadow_leaf(H5B2_leaf_t *leaf, H5B2_node_ptr_t *curr_node_ptr);
56 
57 /*********************/
58 /* Package Variables */
59 /*********************/
60 
61 /* Declare a free list to manage the H5B2_leaf_t struct */
62 H5FL_DEFINE(H5B2_leaf_t);
63 
64 /*****************************/
65 /* Library Private Variables */
66 /*****************************/
67 
68 /*******************/
69 /* Local Variables */
70 /*******************/
71 
72 /*-------------------------------------------------------------------------
73  * Function:	H5B2__create_leaf
74  *
75  * Purpose:	Creates empty leaf node of a B-tree and update node pointer
76  *              to point to it.
77  *
78  * Return:	Non-negative on success/Negative on failure
79  *
80  * Programmer:	Quincey Koziol
81  *		Feb  2 2005
82  *
83  *-------------------------------------------------------------------------
84  */
85 herr_t
H5B2__create_leaf(H5B2_hdr_t * hdr,void * parent,H5B2_node_ptr_t * node_ptr)86 H5B2__create_leaf(H5B2_hdr_t *hdr, void *parent, H5B2_node_ptr_t *node_ptr)
87 {
88     H5B2_leaf_t *leaf      = NULL;    /* Pointer to new leaf node created */
89     hbool_t      inserted  = FALSE;   /* Whether the leaf node was inserted into cache */
90     herr_t       ret_value = SUCCEED; /* Return value */
91 
92     FUNC_ENTER_PACKAGE
93 
94     /* Check arguments. */
95     HDassert(hdr);
96     HDassert(node_ptr);
97 
98     /* Allocate memory for leaf information */
99     if (NULL == (leaf = H5FL_CALLOC(H5B2_leaf_t)))
100         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf info")
101 
102     /* Increment ref. count on B-tree header */
103     if (H5B2__hdr_incr(hdr) < 0)
104         HGOTO_ERROR(H5E_BTREE, H5E_CANTINC, FAIL, "can't increment ref. count on B-tree header")
105 
106     /* Share B-tree header information */
107     leaf->hdr = hdr;
108 
109     /* Allocate space for the native keys in memory */
110     if (NULL == (leaf->leaf_native = (uint8_t *)H5FL_FAC_MALLOC(hdr->node_info[0].nat_rec_fac)))
111         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for B-tree leaf native keys")
112     HDmemset(leaf->leaf_native, 0, hdr->cls->nrec_size * hdr->node_info[0].max_nrec);
113 
114     /* Set parent */
115     leaf->parent = parent;
116 
117     /* Set shadowed epoch to header's epoch */
118     leaf->shadow_epoch = hdr->shadow_epoch;
119 
120     /* Allocate space on disk for the leaf */
121     if (HADDR_UNDEF == (node_ptr->addr = H5MF_alloc(hdr->f, H5FD_MEM_BTREE, (hsize_t)hdr->node_size)))
122         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for B-tree leaf node")
123 
124     /* Cache the new B-tree node */
125     if (H5AC_insert_entry(hdr->f, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0)
126         HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't add B-tree leaf to cache")
127     inserted = TRUE;
128 
129     /* Add leaf node as child of 'top' proxy */
130     if (hdr->top_proxy) {
131         if (H5AC_proxy_entry_add_child(hdr->top_proxy, hdr->f, leaf) < 0)
132             HGOTO_ERROR(H5E_BTREE, H5E_CANTSET, FAIL, "unable to add v2 B-tree node as child of proxy")
133         leaf->top_proxy = hdr->top_proxy;
134     } /* end if */
135 
136 done:
137     if (ret_value < 0) {
138         if (leaf) {
139             /* Remove from cache, if inserted */
140             if (inserted)
141                 if (H5AC_remove_entry(leaf) < 0)
142                     HDONE_ERROR(H5E_BTREE, H5E_CANTREMOVE, FAIL,
143                                 "unable to remove v2 B-tree leaf node from cache")
144 
145             /* Release leaf node's disk space */
146             if (H5F_addr_defined(node_ptr->addr) &&
147                 H5MF_xfree(hdr->f, H5FD_MEM_BTREE, node_ptr->addr, (hsize_t)hdr->node_size) < 0)
148                 HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL,
149                             "unable to release file space for v2 B-tree leaf node")
150 
151             /* Destroy leaf node */
152             if (H5B2__leaf_free(leaf) < 0)
153                 HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to release v2 B-tree leaf node")
154         } /* end if */
155     }     /* end if */
156 
157     FUNC_LEAVE_NOAPI(ret_value)
158 } /* H5B2__create_leaf() */
159 
160 /*-------------------------------------------------------------------------
161  * Function:	H5B2__protect_leaf
162  *
163  * Purpose:	"Protect" an leaf node in the metadata cache
164  *
165  * Return:	Pointer to leaf node on success/NULL on failure
166  *
167  * Programmer:	Quincey Koziol
168  *		May  5 2010
169  *
170  *-------------------------------------------------------------------------
171  */
172 H5B2_leaf_t *
H5B2__protect_leaf(H5B2_hdr_t * hdr,void * parent,H5B2_node_ptr_t * node_ptr,hbool_t shadow,unsigned flags)173 H5B2__protect_leaf(H5B2_hdr_t *hdr, void *parent, H5B2_node_ptr_t *node_ptr, hbool_t shadow, unsigned flags)
174 {
175     H5B2_leaf_cache_ud_t udata;            /* User-data for callback */
176     H5B2_leaf_t *        leaf;             /* v2 B-tree leaf node */
177     H5B2_leaf_t *        ret_value = NULL; /* Return value */
178 
179     FUNC_ENTER_PACKAGE
180 
181     /* Check arguments. */
182     HDassert(hdr);
183     HDassert(node_ptr);
184     HDassert(H5F_addr_defined(node_ptr->addr));
185 
186     /* only H5AC__READ_ONLY_FLAG may appear in flags */
187     HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
188 
189     /* Set up user data for callback */
190     udata.f      = hdr->f;
191     udata.hdr    = hdr;
192     udata.parent = parent;
193     udata.nrec   = node_ptr->node_nrec;
194 
195     /* Protect the leaf node */
196     if (NULL == (leaf = (H5B2_leaf_t *)H5AC_protect(hdr->f, H5AC_BT2_LEAF, node_ptr->addr, &udata, flags)))
197         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to protect B-tree leaf node")
198 
199     /* Create top proxy, if it doesn't exist */
200     if (hdr->top_proxy && NULL == leaf->top_proxy) {
201         /* Add leaf node as child of 'top' proxy */
202         if (H5AC_proxy_entry_add_child(hdr->top_proxy, hdr->f, leaf) < 0)
203             HGOTO_ERROR(H5E_BTREE, H5E_CANTSET, NULL, "unable to add v2 B-tree leaf node as child of proxy")
204         leaf->top_proxy = hdr->top_proxy;
205     } /* end if */
206 
207     /* Shadow the node, if requested */
208     if (shadow)
209         if (H5B2__shadow_leaf(leaf, node_ptr) < 0)
210             HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, NULL, "unable to shadow leaf node")
211 
212     /* Set return value */
213     ret_value = leaf;
214 
215 done:
216     /* Clean up on error */
217     if (!ret_value) {
218         /* Release the leaf node, if it was protected */
219         if (leaf) {
220             /* Remove from v2 B-tree's proxy, if added */
221             if (leaf->top_proxy) {
222                 if (H5AC_proxy_entry_remove_child(leaf->top_proxy, leaf) < 0)
223                     HDONE_ERROR(
224                         H5E_BTREE, H5E_CANTUNDEPEND, NULL,
225                         "unable to destroy flush dependency between leaf node and v2 B-tree 'top' proxy")
226                 leaf->top_proxy = NULL;
227             } /* end if */
228 
229             /* Unprotect leaf node */
230             if (H5AC_unprotect(hdr->f, H5AC_BT2_LEAF, node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0)
231                 HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, NULL,
232                             "unable to unprotect v2 B-tree leaf node, address = %llu",
233                             (unsigned long long)node_ptr->addr)
234         } /* end if */
235     }     /* end if */
236 
237     FUNC_LEAVE_NOAPI(ret_value)
238 } /* H5B2__protect_leaf() */
239 
240 /*-------------------------------------------------------------------------
241  * Function:	H5B2__neighbor_leaf
242  *
243  * Purpose:	Locate a record relative to the specified information in a
244  *              B-tree leaf node and return that information by filling in
245  *              fields of the
246  *              caller-supplied UDATA pointer depending on the type of leaf node
247  *		requested.  The UDATA can point to additional data passed
248  *		to the key comparison function.
249  *
250  *              The 'OP' routine is called with the record found and the
251  *              OP_DATA pointer, to allow caller to return information about
252  *              the record.
253  *
254  *              The RANGE indicates whether to search for records less than or
255  *              equal to, or greater than or equal to the information passed
256  *              in with UDATA.
257  *
258  * Return:	Non-negative on success, negative on failure.
259  *
260  * Programmer:	Quincey Koziol
261  *		Mar  9 2005
262  *
263  *-------------------------------------------------------------------------
264  */
265 herr_t
H5B2__neighbor_leaf(H5B2_hdr_t * hdr,H5B2_node_ptr_t * curr_node_ptr,void * neighbor_loc,H5B2_compare_t comp,void * parent,void * udata,H5B2_found_t op,void * op_data)266 H5B2__neighbor_leaf(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr, void *neighbor_loc, H5B2_compare_t comp,
267                     void *parent, void *udata, H5B2_found_t op, void *op_data)
268 {
269     H5B2_leaf_t *leaf;                /* Pointer to leaf node */
270     unsigned     idx       = 0;       /* Location of record which matches key */
271     int          cmp       = 0;       /* Comparison value of records */
272     herr_t       ret_value = SUCCEED; /* Return value */
273 
274     FUNC_ENTER_PACKAGE
275 
276     /* Check arguments. */
277     HDassert(hdr);
278     HDassert(curr_node_ptr);
279     HDassert(H5F_addr_defined(curr_node_ptr->addr));
280     HDassert(op);
281 
282     /* Lock current B-tree node */
283     if (NULL == (leaf = H5B2__protect_leaf(hdr, parent, curr_node_ptr, FALSE, H5AC__READ_ONLY_FLAG)))
284         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
285 
286     /* Locate node pointer for child */
287     if (H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0)
288         HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records")
289     if (cmp > 0)
290         idx++;
291     else if (cmp == 0 && comp == H5B2_COMPARE_GREATER)
292         idx++;
293 
294     /* Set the neighbor location, if appropriate */
295     if (comp == H5B2_COMPARE_LESS) {
296         if (idx > 0)
297             neighbor_loc = H5B2_LEAF_NREC(leaf, hdr, idx - 1);
298     } /* end if */
299     else {
300         HDassert(comp == H5B2_COMPARE_GREATER);
301 
302         if (idx < leaf->nrec)
303             neighbor_loc = H5B2_LEAF_NREC(leaf, hdr, idx);
304     } /* end else */
305 
306     /* Make callback if neighbor record has been found */
307     if (neighbor_loc) {
308         /* Make callback for current record */
309         if ((op)(neighbor_loc, op_data) < 0)
310             HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL,
311                         "'found' callback failed for B-tree neighbor operation")
312     } /* end if */
313     else
314         HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "unable to find neighbor record in B-tree")
315 
316 done:
317     /* Release the B-tree leaf node */
318     if (leaf && H5AC_unprotect(hdr->f, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, H5AC__NO_FLAGS_SET) < 0)
319         HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree leaf node")
320 
321     FUNC_LEAVE_NOAPI(ret_value)
322 } /* H5B2__neighbor_leaf() */
323 
324 /*-------------------------------------------------------------------------
325  * Function:	H5B2__insert_leaf
326  *
327  * Purpose:	Adds a new record to a B-tree leaf node.
328  *
329  * Return:	Non-negative on success/Negative on failure
330  *
331  * Programmer:	Quincey Koziol
332  *		Mar  3 2005
333  *
334  *-------------------------------------------------------------------------
335  */
336 herr_t
H5B2__insert_leaf(H5B2_hdr_t * hdr,H5B2_node_ptr_t * curr_node_ptr,H5B2_nodepos_t curr_pos,void * parent,void * udata)337 H5B2__insert_leaf(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, void *parent,
338                   void *udata)
339 {
340     H5B2_leaf_t *leaf;                            /* Pointer to leaf node */
341     unsigned     leaf_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting the leaf node */
342     int          cmp;                             /* Comparison value of records */
343     unsigned     idx       = 0;                   /* Location of record which matches key */
344     herr_t       ret_value = SUCCEED;             /* Return value */
345 
346     FUNC_ENTER_PACKAGE
347 
348     /* Check arguments. */
349     HDassert(hdr);
350     HDassert(curr_node_ptr);
351     HDassert(H5F_addr_defined(curr_node_ptr->addr));
352 
353     /* Lock current B-tree node */
354     if (NULL == (leaf = H5B2__protect_leaf(hdr, parent, curr_node_ptr, FALSE, H5AC__NO_FLAGS_SET)))
355         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
356 
357     /* Must have a leaf node with enough space to insert a record now */
358     HDassert(curr_node_ptr->node_nrec < hdr->node_info[0].max_nrec);
359 
360     /* Sanity check number of records */
361     HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec);
362     HDassert(leaf->nrec == curr_node_ptr->node_nrec);
363 
364     /* Check for inserting into empty leaf */
365     if (leaf->nrec == 0)
366         idx = 0;
367     else {
368         /* Find correct location to insert this record */
369         if (H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0)
370             HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records")
371         if (cmp == 0)
372             HGOTO_ERROR(H5E_BTREE, H5E_EXISTS, FAIL, "record is already in B-tree")
373         if (cmp > 0)
374             idx++;
375 
376         /* Make room for new record */
377         if (idx < leaf->nrec)
378             HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx + 1), H5B2_LEAF_NREC(leaf, hdr, idx),
379                       hdr->cls->nrec_size * (leaf->nrec - idx));
380     } /* end else */
381 
382     /* Make callback to store record in native form */
383     if ((hdr->cls->store)(H5B2_LEAF_NREC(leaf, hdr, idx), udata) < 0)
384         HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node")
385 
386     /* Mark the node as dirty */
387     leaf_flags |= H5AC__DIRTIED_FLAG;
388 
389     /* Update record count for node pointer to current node */
390     curr_node_ptr->all_nrec++;
391     curr_node_ptr->node_nrec++;
392 
393     /* Update record count for current node */
394     leaf->nrec++;
395 
396     /* Check for new record being the min or max for the tree */
397     /* (Don't use 'else' for the idx check, to allow for root leaf node) */
398     if (H5B2_POS_MIDDLE != curr_pos) {
399         if (idx == 0) {
400             if (H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) {
401                 if (hdr->min_native_rec == NULL)
402                     if (NULL == (hdr->min_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
403                         HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL,
404                                     "memory allocation failed for v2 B-tree min record info")
405                 H5MM_memcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
406             } /* end if */
407         }     /* end if */
408         if (idx == (unsigned)(leaf->nrec - 1)) {
409             if (H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) {
410                 if (hdr->max_native_rec == NULL)
411                     if (NULL == (hdr->max_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
412                         HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL,
413                                     "memory allocation failed for v2 B-tree max record info")
414                 H5MM_memcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
415             } /* end if */
416         }     /* end if */
417     }         /* end if */
418 
419 done:
420     /* Release the B-tree leaf node (marked as dirty) */
421     if (leaf) {
422         /* Shadow the node if doing SWMR writes */
423         if (hdr->swmr_write && (leaf_flags & H5AC__DIRTIED_FLAG))
424             if (H5B2__shadow_leaf(leaf, curr_node_ptr) < 0)
425                 HDONE_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf B-tree node")
426 
427         /* Unprotect leaf node */
428         if (H5AC_unprotect(hdr->f, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, leaf_flags) < 0)
429             HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")
430     } /* end if */
431 
432     FUNC_LEAVE_NOAPI(ret_value)
433 } /* H5B2__insert_leaf() */
434 
435 /*-------------------------------------------------------------------------
436  * Function:	H5B2__update_leaf
437  *
438  * Purpose:	Insert or modify a record in a B-tree leaf node.
439  *		If the record exists already, it is modified as if H5B2_modify
440  *		was called).  If it doesn't exist, it is inserted as if
441  *		H5B2_insert was called.
442  *
443  * Return:	Non-negative on success/Negative on failure
444  *
445  * Programmer:	Quincey Koziol
446  *		Dec 23 2015
447  *
448  *-------------------------------------------------------------------------
449  */
450 herr_t
H5B2__update_leaf(H5B2_hdr_t * hdr,H5B2_node_ptr_t * curr_node_ptr,H5B2_update_status_t * status,H5B2_nodepos_t curr_pos,void * parent,void * udata,H5B2_modify_t op,void * op_data)451 H5B2__update_leaf(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr, H5B2_update_status_t *status,
452                   H5B2_nodepos_t curr_pos, void *parent, void *udata, H5B2_modify_t op, void *op_data)
453 {
454     H5B2_leaf_t *leaf;                            /* Pointer to leaf node */
455     unsigned     leaf_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting the leaf node */
456     int          cmp        = -1;                 /* Comparison value of records */
457     unsigned     idx        = 0;                  /* Location of record which matches key */
458     herr_t       ret_value  = SUCCEED;            /* Return value */
459 
460     FUNC_ENTER_PACKAGE
461 
462     /* Check arguments. */
463     HDassert(hdr);
464     HDassert(curr_node_ptr);
465     HDassert(H5F_addr_defined(curr_node_ptr->addr));
466 
467     /* Lock current B-tree node */
468     if (NULL == (leaf = H5B2__protect_leaf(hdr, parent, curr_node_ptr, FALSE, H5AC__NO_FLAGS_SET)))
469         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
470 
471     /* Sanity check number of records */
472     HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec);
473     HDassert(leaf->nrec == curr_node_ptr->node_nrec);
474 
475     /* Check for inserting into empty leaf */
476     if (leaf->nrec == 0)
477         idx = 0;
478     else {
479         /* Find correct location to insert this record */
480         if (H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0)
481             HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records")
482 
483         /* Check for inserting a record */
484         if (0 != cmp) {
485             /* Check if the leaf node is full */
486             if (curr_node_ptr->node_nrec == hdr->node_info[0].split_nrec) {
487                 /* Indicate that the leaf is full, but we need to insert */
488                 *status = H5B2_UPDATE_INSERT_CHILD_FULL;
489 
490                 /* Let calling routine handle insertion */
491                 HGOTO_DONE(SUCCEED)
492             } /* end if */
493 
494             /* Adjust index to leave room for record to insert */
495             if (cmp > 0)
496                 idx++;
497 
498             /* Make room for new record */
499             if (idx < leaf->nrec)
500                 HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx + 1), H5B2_LEAF_NREC(leaf, hdr, idx),
501                           hdr->cls->nrec_size * (leaf->nrec - idx));
502         } /* end if */
503     }     /* end else */
504 
505     /* Check for modifying existing record */
506     if (0 == cmp) {
507         hbool_t changed = FALSE; /* Whether the 'modify' callback changed the record */
508 
509         /* Make callback for current record */
510         if ((op)(H5B2_LEAF_NREC(leaf, hdr, idx), op_data, &changed) < 0) {
511             /* Make certain that the callback didn't modify the value if it failed */
512             HDassert(changed == FALSE);
513 
514             HGOTO_ERROR(H5E_BTREE, H5E_CANTMODIFY, FAIL,
515                         "'modify' callback failed for B-tree update operation")
516         } /* end if */
517 
518         /* Mark the node as dirty if it changed */
519         leaf_flags |= (changed ? H5AC__DIRTIED_FLAG : 0);
520 
521         /* Indicate that the record was modified */
522         *status = H5B2_UPDATE_MODIFY_DONE;
523     } /* end if */
524     else {
525         /* Must have a leaf node with enough space to insert a record now */
526         HDassert(curr_node_ptr->node_nrec < hdr->node_info[0].max_nrec);
527 
528         /* Make callback to store record in native form */
529         if ((hdr->cls->store)(H5B2_LEAF_NREC(leaf, hdr, idx), udata) < 0)
530             HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, FAIL, "unable to insert record into leaf node")
531 
532         /* Mark the node as dirty */
533         leaf_flags |= H5AC__DIRTIED_FLAG;
534 
535         /* Indicate that the record was inserted */
536         *status = H5B2_UPDATE_INSERT_DONE;
537 
538         /* Update record count for node pointer to current node */
539         curr_node_ptr->all_nrec++;
540         curr_node_ptr->node_nrec++;
541 
542         /* Update record count for current node */
543         leaf->nrec++;
544     } /* end else */
545 
546     /* Check for new record being the min or max for the tree */
547     /* (Don't use 'else' for the idx check, to allow for root leaf node) */
548     if (H5B2_POS_MIDDLE != curr_pos) {
549         if (idx == 0) {
550             if (H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) {
551                 if (hdr->min_native_rec == NULL)
552                     if (NULL == (hdr->min_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
553                         HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL,
554                                     "memory allocation failed for v2 B-tree min record info")
555                 H5MM_memcpy(hdr->min_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
556             } /* end if */
557         }     /* end if */
558         if (idx == (unsigned)(leaf->nrec - 1)) {
559             if (H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) {
560                 if (hdr->max_native_rec == NULL)
561                     if (NULL == (hdr->max_native_rec = H5MM_malloc(hdr->cls->nrec_size)))
562                         HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL,
563                                     "memory allocation failed for v2 B-tree max record info")
564                 H5MM_memcpy(hdr->max_native_rec, H5B2_LEAF_NREC(leaf, hdr, idx), hdr->cls->nrec_size);
565             } /* end if */
566         }     /* end if */
567     }         /* end if */
568 
569 done:
570     /* Release the B-tree leaf node */
571     if (leaf) {
572         /* Check if we should shadow this node */
573         if (hdr->swmr_write && (leaf_flags & H5AC__DIRTIED_FLAG)) {
574             /* Attempt to shadow the node if doing SWMR writes */
575             if (H5B2__shadow_leaf(leaf, curr_node_ptr) < 0)
576                 HDONE_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf B-tree node")
577 
578             /* Change the state to "shadowed" if only modified currently */
579             /* (Triggers parent to be marked dirty) */
580             if (*status == H5B2_UPDATE_MODIFY_DONE)
581                 *status = H5B2_UPDATE_SHADOW_DONE;
582         } /* end if */
583 
584         /* Unprotect leaf node */
585         if (H5AC_unprotect(hdr->f, H5AC_BT2_LEAF, curr_node_ptr->addr, leaf, leaf_flags) < 0)
586             HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")
587     } /* end if */
588 
589     FUNC_LEAVE_NOAPI(ret_value)
590 } /* H5B2__update_leaf() */
591 
592 /*-------------------------------------------------------------------------
593  * Function:	H5B2__swap_leaf
594  *
595  * Purpose:	Swap a record in a node with a record in a leaf node
596  *
597  * Return:	Success:	Non-negative
598  *
599  *		Failure:	Negative
600  *
601  * Programmer:	Quincey Koziol
602  *		Mar  4 2005
603  *
604  *-------------------------------------------------------------------------
605  */
606 herr_t
H5B2__swap_leaf(H5B2_hdr_t * hdr,uint16_t depth,H5B2_internal_t * internal,unsigned * internal_flags_ptr,unsigned idx,void * swap_loc)607 H5B2__swap_leaf(H5B2_hdr_t *hdr, uint16_t depth, H5B2_internal_t *internal, unsigned *internal_flags_ptr,
608                 unsigned idx, void *swap_loc)
609 {
610     const H5AC_class_t *child_class;              /* Pointer to child node's class info */
611     haddr_t             child_addr = HADDR_UNDEF; /* Address of child node */
612     void *              child      = NULL;        /* Pointer to child node */
613     uint8_t *           child_native;             /* Pointer to child's native records */
614     herr_t              ret_value = SUCCEED;      /* Return value */
615 
616     FUNC_ENTER_PACKAGE
617 
618     /* Check arguments. */
619     HDassert(hdr);
620     HDassert(internal);
621     HDassert(internal_flags_ptr);
622     HDassert(idx <= internal->nrec);
623 
624     /* Check for the kind of B-tree node to swap */
625     if (depth > 1) {
626         H5B2_internal_t *child_internal; /* Pointer to internal node */
627 
628         /* Setup information for unlocking child node */
629         child_class = H5AC_BT2_INT;
630 
631         /* Lock B-tree child nodes */
632         if (NULL ==
633             (child_internal = H5B2__protect_internal(hdr, internal, &internal->node_ptrs[idx],
634                                                      (uint16_t)(depth - 1), FALSE, H5AC__NO_FLAGS_SET)))
635             HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree internal node")
636         child_addr = internal->node_ptrs[idx].addr;
637 
638         /* More setup for accessing child node information */
639         child        = child_internal;
640         child_native = child_internal->int_native;
641     } /* end if */
642     else {
643         H5B2_leaf_t *child_leaf; /* Pointer to leaf node */
644 
645         /* Setup information for unlocking child nodes */
646         child_class = H5AC_BT2_LEAF;
647 
648         /* Lock B-tree child node */
649         if (NULL == (child_leaf = H5B2__protect_leaf(hdr, internal, &internal->node_ptrs[idx], FALSE,
650                                                      H5AC__NO_FLAGS_SET)))
651             HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
652         child_addr = internal->node_ptrs[idx].addr;
653 
654         /* More setup for accessing child node information */
655         child        = child_leaf;
656         child_native = child_leaf->leaf_native;
657     } /* end else */
658 
659     /* Swap records (use disk page as temporary buffer) */
660     H5MM_memcpy(hdr->page, H5B2_NAT_NREC(child_native, hdr, 0), hdr->cls->nrec_size);
661     H5MM_memcpy(H5B2_NAT_NREC(child_native, hdr, 0), swap_loc, hdr->cls->nrec_size);
662     H5MM_memcpy(swap_loc, hdr->page, hdr->cls->nrec_size);
663 
664     /* Mark parent as dirty */
665     *internal_flags_ptr |= H5AC__DIRTIED_FLAG;
666 
667 #ifdef H5B2_DEBUG
668     H5B2__assert_internal((hsize_t)0, hdr, internal);
669     if (depth > 1)
670         H5B2__assert_internal(internal->node_ptrs[idx].all_nrec, hdr, (H5B2_internal_t *)child);
671     else
672         H5B2__assert_leaf(hdr, (H5B2_leaf_t *)child);
673 #endif /* H5B2_DEBUG */
674 
675 done:
676     /* Unlock child node */
677     if (child && H5AC_unprotect(hdr->f, child_class, child_addr, child, H5AC__DIRTIED_FLAG) < 0)
678         HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree child node")
679 
680     FUNC_LEAVE_NOAPI(ret_value)
681 } /* end H5B2__swap_leaf() */
682 
683 /*-------------------------------------------------------------------------
684  * Function:    H5B2__shadow_leaf
685  *
686  * Purpose:     "Shadow" a leaf node - copy it to a new location, leaving
687  *              the data in the old location intact (for now).  This is
688  *              done when writing in SWMR mode to ensure that readers do
689  *              not see nodes that are out of date with respect to each
690  *              other and thereby inconsistent.
691  *
692  * Return:      Non-negative on success/Negative on failure
693  *
694  * Programmer:  Neil Fortner
695  *              Apr 27 2012
696  *
697  *-------------------------------------------------------------------------
698  */
699 static herr_t
H5B2__shadow_leaf(H5B2_leaf_t * leaf,H5B2_node_ptr_t * curr_node_ptr)700 H5B2__shadow_leaf(H5B2_leaf_t *leaf, H5B2_node_ptr_t *curr_node_ptr)
701 {
702     H5B2_hdr_t *hdr;                 /* B-tree header */
703     herr_t      ret_value = SUCCEED; /* Return value */
704 
705     FUNC_ENTER_STATIC
706 
707     /*
708      * Check arguments.
709      */
710     HDassert(leaf);
711     HDassert(curr_node_ptr);
712     HDassert(H5F_addr_defined(curr_node_ptr->addr));
713     hdr = leaf->hdr;
714     HDassert(hdr);
715     HDassert(hdr->swmr_write);
716 
717     /* We only need to shadow the node if it has not been shadowed since the
718      * last time the header was flushed, as otherwise it will be unreachable by
719      * the readers so there will be no need to shadow.  To check if it has been
720      * shadowed, compare the epoch of this node and the header.  If this node's
721      * epoch is <= to the header's, it hasn't been shadowed yet. */
722     if (leaf->shadow_epoch <= hdr->shadow_epoch) {
723         haddr_t new_node_addr; /* Address to move node to */
724 
725         /*
726          * We must clone the old node so readers with an out-of-date version of
727          * the parent can still see the correct number of children, via the
728          * shadowed node.  Remove it from cache but do not mark it free on disk.
729          */
730         /* Allocate space for the cloned node */
731         if (HADDR_UNDEF == (new_node_addr = H5MF_alloc(hdr->f, H5FD_MEM_BTREE, (hsize_t)hdr->node_size)))
732             HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, FAIL, "unable to allocate file space to move B-tree node")
733 
734         /* Move the location of the old child on the disk */
735         if (H5AC_move_entry(hdr->f, H5AC_BT2_LEAF, curr_node_ptr->addr, new_node_addr) < 0)
736             HGOTO_ERROR(H5E_BTREE, H5E_CANTMOVE, FAIL, "unable to move B-tree node")
737         curr_node_ptr->addr = new_node_addr;
738 
739         /* Should free the space in the file, but this is not supported by
740          * SWMR_WRITE code yet - QAK, 2016/12/01
741          */
742 
743         /* Set shadow epoch for node ahead of header */
744         leaf->shadow_epoch = hdr->shadow_epoch + 1;
745     } /* end if */
746 
747 done:
748     FUNC_LEAVE_NOAPI(ret_value)
749 } /* end H5B2__shadow_leaf() */
750 
751 /*-------------------------------------------------------------------------
752  * Function:	H5B2__remove_leaf
753  *
754  * Purpose:	Removes a record from a B-tree leaf node.
755  *
756  * Return:	Non-negative on success/Negative on failure
757  *
758  * Programmer:	Quincey Koziol
759  *		Mar  3 2005
760  *
761  *-------------------------------------------------------------------------
762  */
763 herr_t
H5B2__remove_leaf(H5B2_hdr_t * hdr,H5B2_node_ptr_t * curr_node_ptr,H5B2_nodepos_t curr_pos,void * parent,void * udata,H5B2_remove_t op,void * op_data)764 H5B2__remove_leaf(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos, void *parent,
765                   void *udata, H5B2_remove_t op, void *op_data)
766 {
767     H5B2_leaf_t *leaf;                            /* Pointer to leaf node */
768     haddr_t      leaf_addr  = HADDR_UNDEF;        /* Leaf address on disk */
769     unsigned     leaf_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting leaf node */
770     unsigned     idx        = 0;                  /* Location of record which matches key */
771     int          cmp;                             /* Comparison value of records */
772     herr_t       ret_value = SUCCEED;             /* Return value */
773 
774     FUNC_ENTER_PACKAGE
775 
776     /* Check arguments. */
777     HDassert(hdr);
778     HDassert(curr_node_ptr);
779     HDassert(H5F_addr_defined(curr_node_ptr->addr));
780 
781     /* Lock current B-tree node */
782     if (NULL == (leaf = H5B2__protect_leaf(hdr, parent, curr_node_ptr, FALSE, H5AC__NO_FLAGS_SET)))
783         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
784     leaf_addr = curr_node_ptr->addr;
785 
786     /* Sanity check number of records */
787     HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec);
788     HDassert(leaf->nrec == curr_node_ptr->node_nrec);
789 
790     /* Find correct location to remove this record */
791     if (H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native, udata, &idx, &cmp) < 0)
792         HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records")
793     if (cmp != 0)
794         HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record is not in B-tree")
795 
796     /* Check for invalidating the min/max record for the tree */
797     if (H5B2_POS_MIDDLE != curr_pos) {
798         /* (Don't use 'else' for the idx check, to allow for root leaf node) */
799         if (idx == 0) {
800             if (H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) {
801                 if (hdr->min_native_rec)
802                     hdr->min_native_rec = H5MM_xfree(hdr->min_native_rec);
803             } /* end if */
804         }     /* end if */
805         if (idx == (unsigned)(leaf->nrec - 1)) {
806             if (H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) {
807                 if (hdr->max_native_rec)
808                     hdr->max_native_rec = H5MM_xfree(hdr->max_native_rec);
809             } /* end if */
810         }     /* end if */
811     }         /* end if */
812 
813     /* Make 'remove' callback if there is one */
814     if (op)
815         if ((op)(H5B2_LEAF_NREC(leaf, hdr, idx), op_data) < 0)
816             HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record into leaf node")
817 
818     /* Update number of records in node */
819     leaf->nrec--;
820 
821     if (leaf->nrec > 0) {
822         /* Shadow the node if doing SWMR writes */
823         if (hdr->swmr_write) {
824             if (H5B2__shadow_leaf(leaf, curr_node_ptr) < 0)
825                 HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
826             leaf_addr = curr_node_ptr->addr;
827         } /* end if */
828 
829         /* Pack record out of leaf */
830         if (idx < leaf->nrec)
831             HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx), H5B2_LEAF_NREC(leaf, hdr, (idx + 1)),
832                       hdr->cls->nrec_size * (leaf->nrec - idx));
833 
834         /* Mark leaf node as dirty also */
835         leaf_flags |= H5AC__DIRTIED_FLAG;
836     } /* end if */
837     else {
838         /* Let the cache know that the object is deleted */
839         leaf_flags |= H5AC__DELETED_FLAG;
840         if (!hdr->swmr_write)
841             leaf_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
842 
843         /* Reset address of parent node pointer */
844         curr_node_ptr->addr = HADDR_UNDEF;
845     } /* end else */
846 
847     /* Update record count for parent of leaf node */
848     curr_node_ptr->node_nrec--;
849 
850 done:
851     /* Release the B-tree leaf node */
852     if (leaf && H5AC_unprotect(hdr->f, H5AC_BT2_LEAF, leaf_addr, leaf, leaf_flags) < 0)
853         HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")
854 
855     FUNC_LEAVE_NOAPI(ret_value)
856 } /* H5B2__remove_leaf() */
857 
858 /*-------------------------------------------------------------------------
859  * Function:	H5B2__remove_leaf_by_idx
860  *
861  * Purpose:	Removes a record from a B-tree leaf node, according to the
862  *              offset in the B-tree records.
863  *
864  * Return:	Non-negative on success/Negative on failure
865  *
866  * Programmer:	Quincey Koziol
867  *		Nov 14 2006
868  *
869  *-------------------------------------------------------------------------
870  */
871 herr_t
H5B2__remove_leaf_by_idx(H5B2_hdr_t * hdr,H5B2_node_ptr_t * curr_node_ptr,H5B2_nodepos_t curr_pos,void * parent,unsigned idx,H5B2_remove_t op,void * op_data)872 H5B2__remove_leaf_by_idx(H5B2_hdr_t *hdr, H5B2_node_ptr_t *curr_node_ptr, H5B2_nodepos_t curr_pos,
873                          void *parent, unsigned idx, H5B2_remove_t op, void *op_data)
874 {
875     H5B2_leaf_t *leaf;                            /* Pointer to leaf node */
876     haddr_t      leaf_addr  = HADDR_UNDEF;        /* Leaf address on disk */
877     unsigned     leaf_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting leaf node */
878     herr_t       ret_value  = SUCCEED;            /* Return value */
879 
880     FUNC_ENTER_PACKAGE
881 
882     /* Check arguments. */
883     HDassert(hdr);
884     HDassert(curr_node_ptr);
885     HDassert(H5F_addr_defined(curr_node_ptr->addr));
886 
887     /* Lock B-tree leaf node */
888     if (NULL == (leaf = H5B2__protect_leaf(hdr, parent, curr_node_ptr, FALSE, H5AC__NO_FLAGS_SET)))
889         HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
890     leaf_addr = curr_node_ptr->addr;
891 
892     /* Sanity check number of records */
893     HDassert(curr_node_ptr->all_nrec == curr_node_ptr->node_nrec);
894     HDassert(leaf->nrec == curr_node_ptr->node_nrec);
895     HDassert(idx < leaf->nrec);
896 
897     /* Check for invalidating the min/max record for the tree */
898     if (H5B2_POS_MIDDLE != curr_pos) {
899         /* (Don't use 'else' for the idx check, to allow for root leaf node) */
900         if (idx == 0) {
901             if (H5B2_POS_LEFT == curr_pos || H5B2_POS_ROOT == curr_pos) {
902                 if (hdr->min_native_rec)
903                     hdr->min_native_rec = H5MM_xfree(hdr->min_native_rec);
904             } /* end if */
905         }     /* end if */
906         if (idx == (unsigned)(leaf->nrec - 1)) {
907             if (H5B2_POS_RIGHT == curr_pos || H5B2_POS_ROOT == curr_pos) {
908                 if (hdr->max_native_rec)
909                     hdr->max_native_rec = H5MM_xfree(hdr->max_native_rec);
910             } /* end if */
911         }     /* end if */
912     }         /* end if */
913 
914     /* Make 'remove' callback if there is one */
915     if (op)
916         if ((op)(H5B2_LEAF_NREC(leaf, hdr, idx), op_data) < 0)
917             HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to remove record into leaf node")
918 
919     /* Update number of records in node */
920     leaf->nrec--;
921 
922     if (leaf->nrec > 0) {
923         /* Shadow the node if doing SWMR writes */
924         if (hdr->swmr_write) {
925             if (H5B2__shadow_leaf(leaf, curr_node_ptr) < 0)
926                 HGOTO_ERROR(H5E_BTREE, H5E_CANTCOPY, FAIL, "unable to shadow leaf node")
927             leaf_addr = curr_node_ptr->addr;
928         } /* end if */
929 
930         /* Pack record out of leaf */
931         if (idx < leaf->nrec)
932             HDmemmove(H5B2_LEAF_NREC(leaf, hdr, idx), H5B2_LEAF_NREC(leaf, hdr, (idx + 1)),
933                       hdr->cls->nrec_size * (leaf->nrec - idx));
934 
935         /* Mark leaf node as dirty also */
936         leaf_flags |= H5AC__DIRTIED_FLAG;
937     } /* end if */
938     else {
939         /* Let the cache know that the object is deleted */
940         leaf_flags |= H5AC__DELETED_FLAG;
941         if (!hdr->swmr_write)
942             leaf_flags |= H5AC__DIRTIED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
943 
944         /* Reset address of parent node pointer */
945         curr_node_ptr->addr = HADDR_UNDEF;
946     } /* end else */
947 
948     /* Update record count for parent of leaf node */
949     curr_node_ptr->node_nrec--;
950 
951 done:
952     /* Release the B-tree leaf node */
953     if (leaf && H5AC_unprotect(hdr->f, H5AC_BT2_LEAF, leaf_addr, leaf, leaf_flags) < 0)
954         HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release leaf B-tree node")
955 
956     FUNC_LEAVE_NOAPI(ret_value)
957 } /* H5B2__remove_leaf_by_idx() */
958 
959 /*-------------------------------------------------------------------------
960  * Function:	H5B2__leaf_free
961  *
962  * Purpose:	Destroys a B-tree leaf node in memory.
963  *
964  * Return:	Non-negative on success/Negative on failure
965  *
966  * Programmer:	Quincey Koziol
967  *		Feb 2 2005
968  *
969  *-------------------------------------------------------------------------
970  */
971 herr_t
H5B2__leaf_free(H5B2_leaf_t * leaf)972 H5B2__leaf_free(H5B2_leaf_t *leaf)
973 {
974     herr_t ret_value = SUCCEED; /* Return value */
975 
976     FUNC_ENTER_PACKAGE
977 
978     /*
979      * Check arguments.
980      */
981     HDassert(leaf);
982 
983     /* Release leaf's native key buffer */
984     if (leaf->leaf_native)
985         leaf->leaf_native = (uint8_t *)H5FL_FAC_FREE(leaf->hdr->node_info[0].nat_rec_fac, leaf->leaf_native);
986 
987     /* Decrement ref. count on B-tree header */
988     if (H5B2__hdr_decr(leaf->hdr) < 0)
989         HGOTO_ERROR(H5E_BTREE, H5E_CANTDEC, FAIL, "can't decrement ref. count on B-tree header")
990 
991     /* Sanity check */
992     HDassert(NULL == leaf->top_proxy);
993 
994     /* Free B-tree leaf node info */
995     leaf = H5FL_FREE(H5B2_leaf_t, leaf);
996 
997 done:
998     FUNC_LEAVE_NOAPI(ret_value)
999 } /* end H5B2__leaf_free() */
1000 
1001 #ifdef H5B2_DEBUG
1002 
1003 /*-------------------------------------------------------------------------
1004  * Function:	H5B2__assert_leaf
1005  *
1006  * Purpose:	Verify than a leaf node is mostly sane
1007  *
1008  * Return:	Non-negative on success, negative on failure
1009  *
1010  * Programmer:	Quincey Koziol
1011  *		Feb 19 2005
1012  *
1013  *-------------------------------------------------------------------------
1014  */
1015 H5_ATTR_PURE herr_t
H5B2__assert_leaf(const H5B2_hdr_t H5_ATTR_NDEBUG_UNUSED * hdr,const H5B2_leaf_t H5_ATTR_NDEBUG_UNUSED * leaf)1016 H5B2__assert_leaf(const H5B2_hdr_t H5_ATTR_NDEBUG_UNUSED *hdr, const H5B2_leaf_t H5_ATTR_NDEBUG_UNUSED *leaf)
1017 {
1018     /* General sanity checking on node */
1019     HDassert(leaf->nrec <= hdr->node_info->split_nrec);
1020 
1021     return (0);
1022 } /* end H5B2__assert_leaf() */
1023 
1024 /*-------------------------------------------------------------------------
1025  * Function:	H5B2__assert_leaf2
1026  *
1027  * Purpose:	Verify than a leaf node is mostly sane
1028  *
1029  * Return:	Non-negative on success, negative on failure
1030  *
1031  * Programmer:	Quincey Koziol
1032  *		Feb 19 2005
1033  *
1034  *-------------------------------------------------------------------------
1035  */
1036 H5_ATTR_PURE herr_t
H5B2__assert_leaf2(const H5B2_hdr_t H5_ATTR_NDEBUG_UNUSED * hdr,const H5B2_leaf_t H5_ATTR_NDEBUG_UNUSED * leaf,const H5B2_leaf_t H5_ATTR_UNUSED * leaf2)1037 H5B2__assert_leaf2(const H5B2_hdr_t H5_ATTR_NDEBUG_UNUSED *hdr, const H5B2_leaf_t H5_ATTR_NDEBUG_UNUSED *leaf,
1038                    const H5B2_leaf_t H5_ATTR_UNUSED *leaf2)
1039 {
1040     /* General sanity checking on node */
1041     HDassert(leaf->nrec <= hdr->node_info->split_nrec);
1042 
1043     return (0);
1044 } /* end H5B2__assert_leaf2() */
1045 #endif /* H5B2_DEBUG */
1046