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