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