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