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 /* Programmer:  Quincey Koziol <koziol@ncsa.uiuc.edu>
15  *              Thursday, February  3, 2005
16  *
17  * Purpose:	v2 B-tree testing functions.
18  *
19  */
20 
21 
22 /****************/
23 /* Module Setup */
24 /****************/
25 
26 #include "H5B2module.h"         /* This source code file is part of the H5B2 module */
27 #define H5B2_TESTING		/*suppress warning about H5B2 testing funcs*/
28 
29 
30 /***********/
31 /* Headers */
32 /***********/
33 #include "H5private.h"		/* Generic Functions			*/
34 #include "H5B2pkg.h"		/* v2 B-trees				*/
35 #include "H5Eprivate.h"		/* Error handling		  	*/
36 
37 
38 /****************/
39 /* Local Macros */
40 /****************/
41 
42 
43 /******************/
44 /* Local Typedefs */
45 /******************/
46 
47 /* v2 B-tree client callback context */
48 typedef struct H5B2_test_ctx_t {
49     uint8_t     sizeof_size;    /* Size of file sizes */
50 } H5B2_test_ctx_t;
51 
52 
53 /********************/
54 /* Package Typedefs */
55 /********************/
56 
57 
58 /********************/
59 /* Local Prototypes */
60 /********************/
61 
62 /* v2 B-tree driver callbacks for 'test' B-trees */
63 static void *H5B2__test_crt_context(void *udata);
64 static herr_t H5B2__test_dst_context(void *ctx);
65 static herr_t H5B2__test_store(void *nrecord, const void *udata);
66 static herr_t H5B2__test_compare(const void *rec1, const void *rec2, int *result);
67 static herr_t H5B2__test_encode(uint8_t *raw, const void *nrecord, void *ctx);
68 static herr_t H5B2__test_decode(const uint8_t *raw, void *nrecord, void *ctx);
69 static herr_t H5B2__test_debug(FILE *stream, int indent, int fwidth,
70     const void *record, const void *_udata);
71 
72 /* v2 B-tree driver callbacks for 'test2' B-trees */
73 static herr_t H5B2__test2_store(void *nrecord, const void *udata);
74 static herr_t H5B2__test2_compare(const void *rec1, const void *rec2, int *result);
75 static herr_t H5B2__test2_encode(uint8_t *raw, const void *nrecord, void *ctx);
76 static herr_t H5B2__test2_decode(const uint8_t *raw, void *nrecord, void *ctx);
77 static herr_t H5B2__test2_debug(FILE *stream, int indent, int fwidth,
78     const void *record, const void *_udata);
79 
80 
81 /*********************/
82 /* Package Variables */
83 /*********************/
84 
85 /* Class structure for testing simple B-tree records */
86 const H5B2_class_t H5B2_TEST[1]={{   /* B-tree class information */
87     H5B2_TEST_ID,               /* Type of B-tree */
88     "H5B2_TEST_ID",             /* Name of B-tree class */
89     sizeof(hsize_t),            /* Size of native record */
90     H5B2__test_crt_context,      /* Create client callback context */
91     H5B2__test_dst_context,      /* Destroy client callback context */
92     H5B2__test_store,            /* Record storage callback */
93     H5B2__test_compare,          /* Record comparison callback */
94     H5B2__test_encode,           /* Record encoding callback */
95     H5B2__test_decode,           /* Record decoding callback */
96     H5B2__test_debug             /* Record debugging callback */
97 }};
98 
99 /* Class structure for testing key/value B-tree records */
100 const H5B2_class_t H5B2_TEST2[1]={{   /* B-tree class information */
101     H5B2_TEST2_ID,               /* Type of B-tree */
102     "H5B2_TEST2_ID",             /* Name of B-tree class */
103     sizeof(H5B2_test_rec_t),     /* Size of native record */
104     H5B2__test_crt_context,      /* Create client callback context */
105     H5B2__test_dst_context,      /* Destroy client callback context */
106     H5B2__test2_store,           /* Record storage callback */
107     H5B2__test2_compare,         /* Record comparison callback */
108     H5B2__test2_encode,          /* Record encoding callback */
109     H5B2__test2_decode,          /* Record decoding callback */
110     H5B2__test2_debug            /* Record debugging callback */
111 }};
112 
113 
114 /*****************************/
115 /* Library Private Variables */
116 /*****************************/
117 
118 
119 /*******************/
120 /* Local Variables */
121 /*******************/
122 
123 
124 /* Declare a free list to manage the H5B2_test_ctx_t struct */
125 H5FL_DEFINE_STATIC(H5B2_test_ctx_t);
126 
127 
128 /*-------------------------------------------------------------------------
129  * Function:	H5B2__test_crt_context
130  *
131  * Purpose:	Create client callback context
132  *
133  * Return:	Success:	non-NULL
134  *		Failure:	NULL
135  *
136  * Programmer:	Quincey Koziol
137  *              Thursday, November 26, 2009
138  *
139  *-------------------------------------------------------------------------
140  */
141 static void *
H5B2__test_crt_context(void * _f)142 H5B2__test_crt_context(void *_f)
143 {
144     H5F_t *f = (H5F_t *)_f;     /* User data for building callback context */
145     H5B2_test_ctx_t *ctx;       /* Callback context structure */
146     void *ret_value = NULL;     /* Return value */
147 
148     FUNC_ENTER_STATIC
149 
150     /* Sanity check */
151     HDassert(f);
152 
153     /* Allocate callback context */
154     if(NULL == (ctx = H5FL_MALLOC(H5B2_test_ctx_t)))
155         HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "can't allocate callback context")
156 
157     /* Determine the size of lengths in the file */
158     ctx->sizeof_size = H5F_SIZEOF_SIZE(f);
159 
160     /* Set return value */
161     ret_value = ctx;
162 
163 done:
164     FUNC_LEAVE_NOAPI(ret_value)
165 } /* H5B2__test_crt_context() */
166 
167 
168 /*-------------------------------------------------------------------------
169  * Function:	H5B2__test_dst_context
170  *
171  * Purpose:	Destroy client callback context
172  *
173  * Return:	Success:	non-negative
174  *		Failure:	negative
175  *
176  * Programmer:	Quincey Koziol
177  *              Thursday, November 26, 2009
178  *
179  *-------------------------------------------------------------------------
180  */
181 static herr_t
H5B2__test_dst_context(void * _ctx)182 H5B2__test_dst_context(void *_ctx)
183 {
184     H5B2_test_ctx_t *ctx = (H5B2_test_ctx_t *)_ctx;       /* Callback context structure */
185 
186     FUNC_ENTER_STATIC_NOERR
187 
188     /* Sanity check */
189     HDassert(ctx);
190 
191     /* Release callback context */
192     ctx = H5FL_FREE(H5B2_test_ctx_t, ctx);
193 
194     FUNC_LEAVE_NOAPI(SUCCEED)
195 } /* H5B2__test_dst_context() */
196 
197 
198 /*-------------------------------------------------------------------------
199  * Function:	H5B2__test_store
200  *
201  * Purpose:	Store native information into record for B-tree
202  *
203  * Return:	Success:	non-negative
204  *		Failure:	negative
205  *
206  * Programmer:	Quincey Koziol
207  *              Thursday, February  3, 2005
208  *
209  *-------------------------------------------------------------------------
210  */
211 static herr_t
H5B2__test_store(void * nrecord,const void * udata)212 H5B2__test_store(void *nrecord, const void *udata)
213 {
214     FUNC_ENTER_STATIC_NOERR
215 
216     *(hsize_t *)nrecord = *(const hsize_t *)udata;
217 
218     FUNC_LEAVE_NOAPI(SUCCEED)
219 } /* H5B2__test_store() */
220 
221 
222 /*-------------------------------------------------------------------------
223  * Function:	H5B2__test_compare
224  *
225  * Purpose:	Compare two native information records, according to some key
226  *
227  * Return:	<0 if rec1 < rec2
228  *              =0 if rec1 == rec2
229  *              >0 if rec1 > rec2
230  *
231  * Programmer:	Quincey Koziol
232  *              Thursday, February  3, 2005
233  *
234  *-------------------------------------------------------------------------
235  */
236 static herr_t
H5B2__test_compare(const void * rec1,const void * rec2,int * result)237 H5B2__test_compare(const void *rec1, const void *rec2, int *result)
238 {
239     FUNC_ENTER_STATIC_NOERR
240 
241     *result = (int)(*(const hssize_t *)rec1 - *(const hssize_t *)rec2);
242 
243     FUNC_LEAVE_NOAPI(SUCCEED)
244 } /* H5B2__test_compare() */
245 
246 
247 /*-------------------------------------------------------------------------
248  * Function:	H5B2__test_encode
249  *
250  * Purpose:	Encode native information into raw form for storing on disk
251  *
252  * Return:	Success:	non-negative
253  *		Failure:	negative
254  *
255  * Programmer:	Quincey Koziol
256  *              Thursday, February  3, 2005
257  *
258  *-------------------------------------------------------------------------
259  */
260 static herr_t
H5B2__test_encode(uint8_t * raw,const void * nrecord,void * _ctx)261 H5B2__test_encode(uint8_t *raw, const void *nrecord, void *_ctx)
262 {
263     H5B2_test_ctx_t *ctx = (H5B2_test_ctx_t *)_ctx;       /* Callback context structure */
264 
265     FUNC_ENTER_STATIC_NOERR
266 
267     /* Sanity check */
268     HDassert(ctx);
269 
270     H5F_ENCODE_LENGTH_LEN(raw, *(const hsize_t *)nrecord, ctx->sizeof_size);
271 
272     FUNC_LEAVE_NOAPI(SUCCEED)
273 } /* H5B2__test_encode() */
274 
275 
276 /*-------------------------------------------------------------------------
277  * Function:	H5B2__test_decode
278  *
279  * Purpose:	Decode raw disk form of record into native form
280  *
281  * Return:	Success:	non-negative
282  *		Failure:	negative
283  *
284  * Programmer:	Quincey Koziol
285  *              Friday, February  4, 2005
286  *
287  *-------------------------------------------------------------------------
288  */
289 static herr_t
H5B2__test_decode(const uint8_t * raw,void * nrecord,void * _ctx)290 H5B2__test_decode(const uint8_t *raw, void *nrecord, void *_ctx)
291 {
292     H5B2_test_ctx_t *ctx = (H5B2_test_ctx_t *)_ctx;       /* Callback context structure */
293 
294     FUNC_ENTER_STATIC_NOERR
295 
296     /* Sanity check */
297     HDassert(ctx);
298 
299     H5F_DECODE_LENGTH_LEN(raw, *(hsize_t *)nrecord, ctx->sizeof_size);
300 
301     FUNC_LEAVE_NOAPI(SUCCEED)
302 } /* H5B2__test_decode() */
303 
304 
305 /*-------------------------------------------------------------------------
306  * Function:	H5B2__test_debug
307  *
308  * Purpose:	Debug native form of record
309  *
310  * Return:	Success:	non-negative
311  *		Failure:	negative
312  *
313  * Programmer:	Quincey Koziol
314  *              Friday, February  4, 2005
315  *
316  *-------------------------------------------------------------------------
317  */
318 static herr_t
H5B2__test_debug(FILE * stream,int indent,int fwidth,const void * record,const void H5_ATTR_UNUSED * _udata)319 H5B2__test_debug(FILE *stream, int indent, int fwidth, const void *record,
320     const void H5_ATTR_UNUSED *_udata)
321 {
322     FUNC_ENTER_STATIC_NOERR
323 
324     HDassert(record);
325 
326     HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, "Record:",
327         *(const hsize_t *)record);
328 
329     FUNC_LEAVE_NOAPI(SUCCEED)
330 } /* H5B2__test_debug() */
331 
332 
333 /*-------------------------------------------------------------------------
334  * Function:	H5B2__test2_store
335  *
336  * Purpose:	Store native information into record for B-tree
337  *
338  * Return:	Success:	non-negative
339  *		Failure:	negative
340  *
341  * Programmer:	Quincey Koziol
342  *              Friday, December 25, 2015
343  *
344  *-------------------------------------------------------------------------
345  */
346 static herr_t
H5B2__test2_store(void * nrecord,const void * udata)347 H5B2__test2_store(void *nrecord, const void *udata)
348 {
349     FUNC_ENTER_STATIC_NOERR
350 
351     *(H5B2_test_rec_t *)nrecord = *(const H5B2_test_rec_t *)udata;
352 
353     FUNC_LEAVE_NOAPI(SUCCEED)
354 } /* H5B2__test2_store() */
355 
356 
357 /*-------------------------------------------------------------------------
358  * Function:	H5B2__test2_compare
359  *
360  * Purpose:	Compare two native information records, according to some key
361  *
362  * Return:	<0 if rec1 < rec2
363  *              =0 if rec1 == rec2
364  *              >0 if rec1 > rec2
365  *
366  * Programmer:	Quincey Koziol
367  *              Friday, December 25, 2015
368  *
369  *-------------------------------------------------------------------------
370  */
371 static herr_t
H5B2__test2_compare(const void * rec1,const void * rec2,int * result)372 H5B2__test2_compare(const void *rec1, const void *rec2, int *result)
373 {
374     FUNC_ENTER_STATIC_NOERR
375 
376     *result = (int)(((const H5B2_test_rec_t *)rec1)->key - ((const H5B2_test_rec_t *)rec2)->key);
377 
378     FUNC_LEAVE_NOAPI(SUCCEED)
379 } /* H5B2__test2_compare() */
380 
381 
382 /*-------------------------------------------------------------------------
383  * Function:	H5B2__test2_encode
384  *
385  * Purpose:	Encode native information into raw form for storing on disk
386  *
387  * Return:	Success:	non-negative
388  *		Failure:	negative
389  *
390  * Programmer:	Quincey Koziol
391  *              Friday, December 25, 2015
392  *
393  *-------------------------------------------------------------------------
394  */
395 static herr_t
H5B2__test2_encode(uint8_t * raw,const void * nrecord,void * _ctx)396 H5B2__test2_encode(uint8_t *raw, const void *nrecord, void *_ctx)
397 {
398     H5B2_test_ctx_t *ctx = (H5B2_test_ctx_t *)_ctx;       /* Callback context structure */
399 
400     FUNC_ENTER_STATIC_NOERR
401 
402     /* Sanity check */
403     HDassert(ctx);
404 
405     H5F_ENCODE_LENGTH_LEN(raw, ((const H5B2_test_rec_t *)nrecord)->key, ctx->sizeof_size);
406     H5F_ENCODE_LENGTH_LEN(raw, ((const H5B2_test_rec_t *)nrecord)->val, ctx->sizeof_size);
407 
408     FUNC_LEAVE_NOAPI(SUCCEED)
409 } /* H5B2__test2_encode() */
410 
411 
412 /*-------------------------------------------------------------------------
413  * Function:	H5B2__test2_decode
414  *
415  * Purpose:	Decode raw disk form of record into native form
416  *
417  * Return:	Success:	non-negative
418  *		Failure:	negative
419  *
420  * Programmer:	Quincey Koziol
421  *              Friday, December 25, 2015
422  *
423  *-------------------------------------------------------------------------
424  */
425 static herr_t
H5B2__test2_decode(const uint8_t * raw,void * nrecord,void * _ctx)426 H5B2__test2_decode(const uint8_t *raw, void *nrecord, void *_ctx)
427 {
428     H5B2_test_ctx_t *ctx = (H5B2_test_ctx_t *)_ctx;       /* Callback context structure */
429 
430     FUNC_ENTER_STATIC_NOERR
431 
432     /* Sanity check */
433     HDassert(ctx);
434 
435     H5F_DECODE_LENGTH_LEN(raw, ((H5B2_test_rec_t *)nrecord)->key, ctx->sizeof_size);
436     H5F_DECODE_LENGTH_LEN(raw, ((H5B2_test_rec_t *)nrecord)->val, ctx->sizeof_size);
437 
438     FUNC_LEAVE_NOAPI(SUCCEED)
439 } /* H5B2__test2_decode() */
440 
441 
442 /*-------------------------------------------------------------------------
443  * Function:	H5B2__test2_debug
444  *
445  * Purpose:	Debug native form of record
446  *
447  * Return:	Success:	non-negative
448  *		Failure:	negative
449  *
450  * Programmer:	Quincey Koziol
451  *              Friday, December 25, 2015
452  *
453  *-------------------------------------------------------------------------
454  */
455 static herr_t
H5B2__test2_debug(FILE * stream,int indent,int fwidth,const void * record,const void H5_ATTR_UNUSED * _udata)456 H5B2__test2_debug(FILE *stream, int indent, int fwidth, const void *record,
457     const void H5_ATTR_UNUSED *_udata)
458 {
459     FUNC_ENTER_STATIC_NOERR
460 
461     HDassert(record);
462 
463     HDfprintf(stream, "%*s%-*s (%Hu, %Hu)\n", indent, "", fwidth, "Record:",
464         ((const H5B2_test_rec_t *)record)->key,
465         ((const H5B2_test_rec_t *)record)->val);
466 
467     FUNC_LEAVE_NOAPI(SUCCEED)
468 } /* H5B2__test2_debug() */
469 
470 
471 /*-------------------------------------------------------------------------
472  * Function:	H5B2_get_root_addr_test
473  *
474  * Purpose:	Retrieve the root node's address
475  *
476  * Return:	Success:	non-negative
477  *		Failure:	negative
478  *
479  * Programmer:	Quincey Koziol
480  *              Saturday, February 26, 2005
481  *
482  *-------------------------------------------------------------------------
483  */
484 herr_t
H5B2_get_root_addr_test(H5B2_t * bt2,haddr_t * root_addr)485 H5B2_get_root_addr_test(H5B2_t *bt2, haddr_t *root_addr)
486 {
487     FUNC_ENTER_NOAPI_NOINIT_NOERR
488 
489     /* Check arguments. */
490     HDassert(bt2);
491     HDassert(root_addr);
492 
493     /* Get B-tree root addr */
494     *root_addr = bt2->hdr->root.addr;
495 
496     FUNC_LEAVE_NOAPI(SUCCEED)
497 } /* H5B2_get_root_addr_test() */
498 
499 
500 /*-------------------------------------------------------------------------
501  * Function:	H5B2_get_node_info_test
502  *
503  * Purpose:	Determine information about a node holding a record in the B-tree
504  *
505  * Return:	Success:	non-negative
506  *		Failure:	negative
507  *
508  * Programmer:	Quincey Koziol
509  *              Thursday, August 31, 2006
510  *
511  *-------------------------------------------------------------------------
512  */
513 herr_t
H5B2_get_node_info_test(H5B2_t * bt2,hid_t dxpl_id,void * udata,H5B2_node_info_test_t * ninfo)514 H5B2_get_node_info_test(H5B2_t *bt2, hid_t dxpl_id, void *udata,
515     H5B2_node_info_test_t *ninfo)
516 {
517     H5B2_hdr_t	*hdr;                   /* Pointer to the B-tree header */
518     H5B2_node_ptr_t curr_node_ptr;      /* Node pointer info for current node */
519     void        *parent = NULL;         /* Parent of current node */
520     uint16_t    depth;                  /* Current depth of the tree */
521     int         cmp;                    /* Comparison value of records */
522     unsigned    idx;                    /* Location of record which matches key */
523     herr_t	ret_value = SUCCEED;    /* Return value */
524 
525     FUNC_ENTER_NOAPI(FAIL)
526 
527     /* Check arguments. */
528     HDassert(bt2);
529 
530     /* Set the shared v2 B-tree header's file context for this operation */
531     bt2->hdr->f = bt2->f;
532 
533     /* Get the v2 B-tree header */
534     hdr = bt2->hdr;
535 
536     /* Make copy of the root node pointer to start search with */
537     curr_node_ptr = hdr->root;
538 
539         /* Set initial parent, if doing swmr writes */
540     if(hdr->swmr_write)
541         parent = hdr;
542 
543     /* Current depth of the tree */
544     depth = hdr->depth;
545 
546     /* Check for empty tree */
547     if(0 == curr_node_ptr.node_nrec)
548         HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "B-tree has no records")
549 
550     /* Walk down B-tree to find record or leaf node where record is located */
551     cmp = -1;
552     while(depth > 0 && cmp != 0) {
553         H5B2_internal_t *internal;          /* Pointer to internal node in B-tree */
554         H5B2_node_ptr_t next_node_ptr;      /* Node pointer info for next node */
555 
556         /* Lock B-tree current node */
557         if(NULL == (internal = H5B2__protect_internal(hdr, dxpl_id, parent, &curr_node_ptr, depth, FALSE, H5AC__READ_ONLY_FLAG)))
558             HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to load B-tree internal node")
559 
560         /* Unpin parent if necessary */
561         if(parent) {
562             if(parent != hdr && H5AC_unpin_entry(parent) < 0)
563                 HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
564             parent = NULL;
565         } /* end if */
566 
567         /* Locate node pointer for child */
568         if(H5B2__locate_record(hdr->cls, internal->nrec, hdr->nat_off, internal->int_native,
569                                udata, &idx, &cmp) < 0)
570             HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records")
571 
572         if(cmp > 0)
573             idx++;
574 
575         if(cmp != 0) {
576             /* Get node pointer for next node to search */
577             next_node_ptr = internal->node_ptrs[idx];
578 
579             /* Unlock current node */
580             if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, (unsigned)(hdr->swmr_write ? H5AC__PIN_ENTRY_FLAG : H5AC__NO_FLAGS_SET)) < 0)
581                 HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
582 
583             /* Keep track of parent if necessary */
584             if(hdr->swmr_write)
585                 parent = internal;
586 
587             /* Set pointer to next node to load */
588             curr_node_ptr = next_node_ptr;
589         } /* end if */
590         else {
591             /* Unlock current node */
592             if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_INT, curr_node_ptr.addr, internal, H5AC__NO_FLAGS_SET) < 0)
593                 HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
594 
595             /* Fill in information about the node */
596             ninfo->depth = depth;
597             ninfo->nrec = curr_node_ptr.node_nrec;
598 
599             /* Indicate success */
600             HGOTO_DONE(SUCCEED)
601         } /* end else */
602 
603         /* Decrement depth we're at in B-tree */
604         depth--;
605     } /* end while */
606 
607     {
608         H5B2_leaf_t *leaf;          /* Pointer to leaf node in B-tree */
609 
610         /* Lock B-tree leaf node */
611         if(NULL == (leaf = H5B2__protect_leaf(hdr, dxpl_id, parent, &curr_node_ptr, FALSE, H5AC__READ_ONLY_FLAG)))
612             HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, FAIL, "unable to protect B-tree leaf node")
613 
614         /* Unpin parent if necessary */
615         if(parent) {
616             if(parent != hdr && H5AC_unpin_entry(parent) < 0)
617                 HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
618             parent = NULL;
619         } /* end if */
620 
621         /* Locate record */
622         if(H5B2__locate_record(hdr->cls, leaf->nrec, hdr->nat_off, leaf->leaf_native,
623                                udata, &idx, &cmp) < 0)
624             HGOTO_ERROR(H5E_BTREE, H5E_CANTCOMPARE, FAIL, "can't compare btree2 records")
625 
626         /* Unlock current node */
627         if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_BT2_LEAF, curr_node_ptr.addr, leaf, H5AC__NO_FLAGS_SET) < 0)
628             HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release B-tree node")
629 
630         /* Indicate the depth that the record was found */
631         if(cmp != 0)
632             HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "record not in B-tree")
633     } /* end block */
634 
635     /* Fill in information about the leaf node */
636     ninfo->depth = depth;
637     ninfo->nrec = curr_node_ptr.node_nrec;
638 
639 done:
640     if(parent) {
641         HDassert(ret_value < 0);
642         if(parent != hdr && H5AC_unpin_entry(parent) < 0)
643             HDONE_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin parent entry")
644     } /* end if */
645 
646     FUNC_LEAVE_NOAPI(ret_value)
647 } /* H5B2_get_node_info_test() */
648 
649 
650 /*-------------------------------------------------------------------------
651  * Function:	H5B2_get_node_depth_test
652  *
653  * Purpose:	Determine the depth of a node holding a record in the B-tree
654  *
655  * Note:	Just a simple wrapper around the H5B2__get_node_info_test() routine
656  *
657  * Return:	Success:	non-negative depth of the node where the record
658  *                              was found
659  *		Failure:	negative
660  *
661  * Programmer:	Quincey Koziol
662  *              Saturday, August 26, 2006
663  *
664  *-------------------------------------------------------------------------
665  */
666 int
H5B2_get_node_depth_test(H5B2_t * bt2,hid_t dxpl_id,void * udata)667 H5B2_get_node_depth_test(H5B2_t *bt2, hid_t dxpl_id, void *udata)
668 {
669     H5B2_node_info_test_t ninfo;        /* Node information */
670     int		ret_value = -1;         /* Return information */
671 
672     FUNC_ENTER_NOAPI(FAIL)
673 
674     /* Check arguments. */
675     HDassert(bt2);
676 
677     /* Get information abou the node */
678     if(H5B2_get_node_info_test(bt2, dxpl_id, udata, &ninfo) < 0)
679         HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "error looking up node info")
680 
681     /* Set return value */
682     ret_value = (int)ninfo.depth;
683 
684 done:
685     FUNC_LEAVE_NOAPI(ret_value)
686 } /* H5B2_get_node_depth_test() */
687 
688