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