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: H5B2int.c
17 * Feb 27 2006
18 * Quincey Koziol
19 *
20 * Purpose: Internal routines for managing v2 B-trees.
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 #include "H5VMprivate.h" /* Vectors and arrays */
40
41 /****************/
42 /* Local Macros */
43 /****************/
44
45 /* Number of records that fit into leaf node */
46 #define H5B2_NUM_LEAF_REC(n, r) (((n)-H5B2_LEAF_PREFIX_SIZE) / (r))
47
48 /* Uncomment this macro to enable extra sanity checking */
49 /* #define H5B2_DEBUG */
50
51 /******************/
52 /* Local Typedefs */
53 /******************/
54
55 /********************/
56 /* Package Typedefs */
57 /********************/
58
59 /********************/
60 /* Local Prototypes */
61 /********************/
62
63 /*********************/
64 /* Package Variables */
65 /*********************/
66
67 /*****************************/
68 /* Library Private Variables */
69 /*****************************/
70
71 /*******************/
72 /* Local Variables */
73 /*******************/
74
75 /* Declare a free list to manage the H5B2_hdr_t struct */
76 H5FL_DEFINE_STATIC(H5B2_hdr_t);
77
78 /* Declare a free list to manage B-tree node pages to/from disk */
79 H5FL_BLK_DEFINE_STATIC(node_page);
80
81 /* Declare a free list to manage the 'size_t' sequence information */
82 H5FL_SEQ_DEFINE_STATIC(size_t);
83
84 /* Declare a free list to manage the 'H5B2_node_info_t' sequence information */
85 H5FL_SEQ_DEFINE(H5B2_node_info_t);
86
87 /*-------------------------------------------------------------------------
88 * Function: H5B2__hdr_init
89 *
90 * Purpose: Allocate & initialize B-tree header info
91 *
92 * Return: Non-negative on success/Negative on failure
93 *
94 * Programmer: Quincey Koziol
95 * Feb 2 2005
96 *
97 *-------------------------------------------------------------------------
98 */
99 herr_t
H5B2__hdr_init(H5B2_hdr_t * hdr,const H5B2_create_t * cparam,void * ctx_udata,uint16_t depth)100 H5B2__hdr_init(H5B2_hdr_t *hdr, const H5B2_create_t *cparam, void *ctx_udata, uint16_t depth)
101 {
102 size_t sz_max_nrec; /* Temporary variable for range checking */
103 unsigned u_max_nrec_size; /* Temporary variable for range checking */
104 unsigned u; /* Local index variable */
105 herr_t ret_value = SUCCEED; /* Return value */
106
107 FUNC_ENTER_PACKAGE
108
109 /*
110 * Check arguments.
111 */
112 HDassert(hdr);
113 HDassert(cparam);
114 HDassert(cparam->cls);
115 HDassert((cparam->cls->crt_context && cparam->cls->dst_context) ||
116 (NULL == cparam->cls->crt_context && NULL == cparam->cls->dst_context));
117 HDassert(cparam->node_size > 0);
118 HDassert(cparam->rrec_size > 0);
119 HDassert(cparam->merge_percent > 0 && cparam->merge_percent <= 100);
120 HDassert(cparam->split_percent > 0 && cparam->split_percent <= 100);
121 HDassert(cparam->merge_percent < (cparam->split_percent / 2));
122
123 /* Assign dynamic information */
124 hdr->depth = depth;
125
126 /* Assign user's information */
127 hdr->split_percent = cparam->split_percent;
128 hdr->merge_percent = cparam->merge_percent;
129 hdr->node_size = cparam->node_size;
130 hdr->rrec_size = cparam->rrec_size;
131
132 /* Assign common type information */
133 hdr->cls = cparam->cls;
134
135 /* Allocate "page" for node I/O */
136 if (NULL == (hdr->page = H5FL_BLK_MALLOC(node_page, hdr->node_size)))
137 HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "memory allocation failed")
138 HDmemset(hdr->page, 0, hdr->node_size);
139
140 /* Allocate array of node info structs */
141 if (NULL == (hdr->node_info = H5FL_SEQ_MALLOC(H5B2_node_info_t, (size_t)(hdr->depth + 1))))
142 HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "memory allocation failed")
143
144 /* Initialize leaf node info */
145 sz_max_nrec = H5B2_NUM_LEAF_REC(hdr->node_size, hdr->rrec_size);
146 H5_CHECKED_ASSIGN(hdr->node_info[0].max_nrec, unsigned, sz_max_nrec, size_t)
147 hdr->node_info[0].split_nrec = (hdr->node_info[0].max_nrec * hdr->split_percent) / 100;
148 hdr->node_info[0].merge_nrec = (hdr->node_info[0].max_nrec * hdr->merge_percent) / 100;
149 hdr->node_info[0].cum_max_nrec = hdr->node_info[0].max_nrec;
150 hdr->node_info[0].cum_max_nrec_size = 0;
151 if (NULL ==
152 (hdr->node_info[0].nat_rec_fac = H5FL_fac_init(hdr->cls->nrec_size * hdr->node_info[0].max_nrec)))
153 HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't create node native key block factory")
154 hdr->node_info[0].node_ptr_fac = NULL;
155
156 /* Allocate array of pointers to internal node native keys */
157 /* (uses leaf # of records because its the largest) */
158 if (NULL == (hdr->nat_off = H5FL_SEQ_MALLOC(size_t, (size_t)hdr->node_info[0].max_nrec)))
159 HGOTO_ERROR(H5E_BTREE, H5E_NOSPACE, FAIL, "memory allocation failed")
160
161 /* Initialize offsets in native key block */
162 /* (uses leaf # of records because its the largest) */
163 for (u = 0; u < hdr->node_info[0].max_nrec; u++)
164 hdr->nat_off[u] = hdr->cls->nrec_size * u;
165
166 /* Compute size to store # of records in each node */
167 /* (uses leaf # of records because its the largest) */
168 u_max_nrec_size = H5VM_limit_enc_size((uint64_t)hdr->node_info[0].max_nrec);
169 H5_CHECKED_ASSIGN(hdr->max_nrec_size, uint8_t, u_max_nrec_size, unsigned)
170 HDassert(hdr->max_nrec_size <= H5B2_SIZEOF_RECORDS_PER_NODE);
171
172 /* Initialize internal node info */
173 if (depth > 0) {
174 for (u = 1; u < (unsigned)(depth + 1); u++) {
175 sz_max_nrec = H5B2_NUM_INT_REC(hdr, u);
176 H5_CHECKED_ASSIGN(hdr->node_info[u].max_nrec, unsigned, sz_max_nrec, size_t)
177 HDassert(hdr->node_info[u].max_nrec <= hdr->node_info[u - 1].max_nrec);
178
179 hdr->node_info[u].split_nrec = (hdr->node_info[u].max_nrec * hdr->split_percent) / 100;
180 hdr->node_info[u].merge_nrec = (hdr->node_info[u].max_nrec * hdr->merge_percent) / 100;
181
182 hdr->node_info[u].cum_max_nrec =
183 ((hdr->node_info[u].max_nrec + 1) * hdr->node_info[u - 1].cum_max_nrec) +
184 hdr->node_info[u].max_nrec;
185 u_max_nrec_size = H5VM_limit_enc_size((uint64_t)hdr->node_info[u].cum_max_nrec);
186 H5_CHECKED_ASSIGN(hdr->node_info[u].cum_max_nrec_size, uint8_t, u_max_nrec_size, unsigned)
187
188 if (NULL == (hdr->node_info[u].nat_rec_fac =
189 H5FL_fac_init(hdr->cls->nrec_size * hdr->node_info[u].max_nrec)))
190 HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL, "can't create node native key block factory")
191 if (NULL == (hdr->node_info[u].node_ptr_fac =
192 H5FL_fac_init(sizeof(H5B2_node_ptr_t) * (hdr->node_info[u].max_nrec + 1))))
193 HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, FAIL,
194 "can't create internal 'branch' node node pointer block factory")
195 } /* end for */
196 } /* end if */
197
198 /* Determine if we are doing SWMR writes. Only enable for data chunks for now. */
199 hdr->swmr_write = (H5F_INTENT(hdr->f) & H5F_ACC_SWMR_WRITE) > 0 &&
200 (hdr->cls->id == H5B2_CDSET_ID || hdr->cls->id == H5B2_CDSET_FILT_ID);
201
202 /* Reset the shadow epoch */
203 hdr->shadow_epoch = 0;
204
205 /* Create the callback context, if the callback exists */
206 if (hdr->cls->crt_context)
207 if (NULL == (hdr->cb_ctx = (*hdr->cls->crt_context)(ctx_udata)))
208 HGOTO_ERROR(H5E_BTREE, H5E_CANTCREATE, FAIL, "unable to create v2 B-tree client callback context")
209
210 done:
211 if (ret_value < 0)
212 if (H5B2__hdr_free(hdr) < 0)
213 HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, FAIL, "unable to free shared v2 B-tree info")
214
215 FUNC_LEAVE_NOAPI(ret_value)
216 } /* end H5B2__hdr_init() */
217
218 /*-------------------------------------------------------------------------
219 * Function: H5B2__hdr_alloc
220 *
221 * Purpose: Allocate B-tree header
222 *
223 * Return: Non-negative on success/Negative on failure
224 *
225 * Programmer: Quincey Koziol
226 * Oct 27 2009
227 *
228 *-------------------------------------------------------------------------
229 */
230 H5B2_hdr_t *
H5B2__hdr_alloc(H5F_t * f)231 H5B2__hdr_alloc(H5F_t *f)
232 {
233 H5B2_hdr_t *hdr = NULL; /* v2 B-tree header */
234 H5B2_hdr_t *ret_value = NULL; /* Return value */
235
236 FUNC_ENTER_PACKAGE
237
238 /*
239 * Check arguments.
240 */
241 HDassert(f);
242
243 /* Allocate space for the shared information */
244 if (NULL == (hdr = H5FL_CALLOC(H5B2_hdr_t)))
245 HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, NULL, "memory allocation failed for B-tree header")
246
247 /* Assign non-zero information */
248 hdr->f = f;
249 hdr->sizeof_addr = H5F_SIZEOF_ADDR(f);
250 hdr->sizeof_size = H5F_SIZEOF_SIZE(f);
251 hdr->hdr_size = H5B2_HEADER_SIZE_HDR(hdr);
252 hdr->root.addr = HADDR_UNDEF;
253
254 /* Set return value */
255 ret_value = hdr;
256
257 done:
258
259 FUNC_LEAVE_NOAPI(ret_value)
260 } /* end H5B2__hdr_alloc() */
261
262 /*-------------------------------------------------------------------------
263 * Function: H5B2__hdr_create
264 *
265 * Purpose: Create new fractal heap header
266 *
267 * Return: Non-negative on success/Negative on failure
268 *
269 * Programmer: Quincey Koziol
270 * Mar 21 2006
271 *
272 *-------------------------------------------------------------------------
273 */
274 haddr_t
H5B2__hdr_create(H5F_t * f,const H5B2_create_t * cparam,void * ctx_udata)275 H5B2__hdr_create(H5F_t *f, const H5B2_create_t *cparam, void *ctx_udata)
276 {
277 H5B2_hdr_t *hdr = NULL; /* The new v2 B-tree header information */
278 hbool_t inserted = FALSE; /* Whether the header was inserted into cache */
279 haddr_t ret_value = HADDR_UNDEF; /* Return value */
280
281 FUNC_ENTER_PACKAGE
282
283 /*
284 * Check arguments.
285 */
286 HDassert(f);
287 HDassert(cparam);
288
289 /* Allocate v2 B-tree header */
290 if (NULL == (hdr = H5B2__hdr_alloc(f)))
291 HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, HADDR_UNDEF, "allocation failed for B-tree header")
292
293 /* Initialize shared B-tree info */
294 if (H5B2__hdr_init(hdr, cparam, ctx_udata, (uint16_t)0) < 0)
295 HGOTO_ERROR(H5E_BTREE, H5E_CANTINIT, HADDR_UNDEF, "can't create shared B-tree info")
296
297 /* Allocate space for the header on disk */
298 if (HADDR_UNDEF == (hdr->addr = H5MF_alloc(f, H5FD_MEM_BTREE, (hsize_t)hdr->hdr_size)))
299 HGOTO_ERROR(H5E_BTREE, H5E_CANTALLOC, HADDR_UNDEF, "file allocation failed for B-tree header")
300
301 /* Create 'top' proxy for extensible array entries */
302 if (hdr->swmr_write)
303 if (NULL == (hdr->top_proxy = H5AC_proxy_entry_create()))
304 HGOTO_ERROR(H5E_BTREE, H5E_CANTCREATE, HADDR_UNDEF, "can't create v2 B-tree proxy")
305
306 /* Cache the new B-tree node */
307 if (H5AC_insert_entry(f, H5AC_BT2_HDR, hdr->addr, hdr, H5AC__NO_FLAGS_SET) < 0)
308 HGOTO_ERROR(H5E_BTREE, H5E_CANTINSERT, HADDR_UNDEF, "can't add B-tree header to cache")
309 inserted = TRUE;
310
311 /* Add header as child of 'top' proxy */
312 if (hdr->top_proxy)
313 if (H5AC_proxy_entry_add_child(hdr->top_proxy, f, hdr) < 0)
314 HGOTO_ERROR(H5E_BTREE, H5E_CANTSET, HADDR_UNDEF,
315 "unable to add v2 B-tree header as child of array proxy")
316
317 /* Set address of v2 B-tree header to return */
318 ret_value = hdr->addr;
319
320 done:
321 if (!H5F_addr_defined(ret_value))
322 if (hdr) {
323 /* Remove from cache, if inserted */
324 if (inserted)
325 if (H5AC_remove_entry(hdr) < 0)
326 HDONE_ERROR(H5E_BTREE, H5E_CANTREMOVE, HADDR_UNDEF,
327 "unable to remove v2 B-tree header from cache")
328
329 /* Release header's disk space */
330 if (H5F_addr_defined(hdr->addr) &&
331 H5MF_xfree(f, H5FD_MEM_BTREE, hdr->addr, (hsize_t)hdr->hdr_size) < 0)
332 HDONE_ERROR(H5E_BTREE, H5E_CANTFREE, HADDR_UNDEF, "unable to free v2 B-tree header")
333
334 /* Destroy header */
335 if (H5B2__hdr_free(hdr) < 0)
336 HDONE_ERROR(H5E_BTREE, H5E_CANTRELEASE, HADDR_UNDEF, "unable to release v2 B-tree header")
337 } /* end if */
338
339 FUNC_LEAVE_NOAPI(ret_value)
340 } /* end H5B2__hdr_create() */
341
342 /*-------------------------------------------------------------------------
343 * Function: H5B2__hdr_incr
344 *
345 * Purpose: Increment reference count on B-tree header
346 *
347 * Return: Non-negative on success/Negative on failure
348 *
349 * Programmer: Quincey Koziol
350 * Oct 13 2009
351 *
352 *-------------------------------------------------------------------------
353 */
354 herr_t
H5B2__hdr_incr(H5B2_hdr_t * hdr)355 H5B2__hdr_incr(H5B2_hdr_t *hdr)
356 {
357 herr_t ret_value = SUCCEED; /* Return value */
358
359 FUNC_ENTER_PACKAGE
360
361 /* Sanity checks */
362 HDassert(hdr);
363
364 /* Mark header as un-evictable when a B-tree node is depending on it */
365 if (hdr->rc == 0)
366 if (H5AC_pin_protected_entry(hdr) < 0)
367 HGOTO_ERROR(H5E_BTREE, H5E_CANTPIN, FAIL, "unable to pin v2 B-tree header")
368
369 /* Increment reference count on B-tree header */
370 hdr->rc++;
371
372 done:
373 FUNC_LEAVE_NOAPI(ret_value)
374 } /* end H5B2__hdr_incr() */
375
376 /*-------------------------------------------------------------------------
377 * Function: H5B2__hdr_decr
378 *
379 * Purpose: Decrement reference count on B-tree header
380 *
381 * Return: Non-negative on success/Negative on failure
382 *
383 * Programmer: Quincey Koziol
384 * Oct 13 2009
385 *
386 *-------------------------------------------------------------------------
387 */
388 herr_t
H5B2__hdr_decr(H5B2_hdr_t * hdr)389 H5B2__hdr_decr(H5B2_hdr_t *hdr)
390 {
391 herr_t ret_value = SUCCEED; /* Return value */
392
393 FUNC_ENTER_PACKAGE
394
395 /* Sanity check */
396 HDassert(hdr);
397 HDassert(hdr->rc > 0);
398
399 /* Decrement reference count on B-tree header */
400 hdr->rc--;
401
402 /* Mark header as evictable again when no nodes depend on it */
403 if (hdr->rc == 0)
404 if (H5AC_unpin_entry(hdr) < 0)
405 HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPIN, FAIL, "unable to unpin v2 B-tree header")
406
407 done:
408 FUNC_LEAVE_NOAPI(ret_value)
409 } /* end H5B2__hdr_decr() */
410
411 /*-------------------------------------------------------------------------
412 * Function: H5B2__hdr_fuse_incr
413 *
414 * Purpose: Increment file reference count on shared v2 B-tree header
415 *
416 * Return: SUCCEED (Can't fail)
417 *
418 * Programmer: Quincey Koziol
419 * Oct 27 2009
420 *
421 *-------------------------------------------------------------------------
422 */
423 herr_t
H5B2__hdr_fuse_incr(H5B2_hdr_t * hdr)424 H5B2__hdr_fuse_incr(H5B2_hdr_t *hdr)
425 {
426 FUNC_ENTER_NOAPI_NOINIT_NOERR
427
428 /* Sanity check */
429 HDassert(hdr);
430
431 /* Increment file reference count on shared header */
432 hdr->file_rc++;
433
434 FUNC_LEAVE_NOAPI(SUCCEED)
435 } /* end H5B2__hdr_fuse_incr() */
436
437 /*-------------------------------------------------------------------------
438 * Function: H5B2__hdr_fuse_decr
439 *
440 * Purpose: Decrement file reference count on shared v2 B-tree header
441 *
442 * Return: The file's reference count after the decrement. (Can't fail)
443 *
444 * Programmer: Quincey Koziol
445 * Oct 27 2009
446 *
447 *-------------------------------------------------------------------------
448 */
449 size_t
H5B2__hdr_fuse_decr(H5B2_hdr_t * hdr)450 H5B2__hdr_fuse_decr(H5B2_hdr_t *hdr)
451 {
452 FUNC_ENTER_NOAPI_NOINIT_NOERR
453
454 /* Sanity check */
455 HDassert(hdr);
456 HDassert(hdr->file_rc);
457
458 /* Decrement file reference count on shared header */
459 hdr->file_rc--;
460
461 FUNC_LEAVE_NOAPI(hdr->file_rc)
462 } /* end H5B2__hdr_fuse_decr() */
463
464 /*-------------------------------------------------------------------------
465 * Function: H5B2__hdr_dirty
466 *
467 * Purpose: Mark B-tree header as dirty
468 *
469 * Return: Non-negative on success/Negative on failure
470 *
471 * Programmer: Quincey Koziol
472 * Oct 13 2009
473 *
474 *-------------------------------------------------------------------------
475 */
476 herr_t
H5B2__hdr_dirty(H5B2_hdr_t * hdr)477 H5B2__hdr_dirty(H5B2_hdr_t *hdr)
478 {
479 herr_t ret_value = SUCCEED; /* Return value */
480
481 FUNC_ENTER_PACKAGE
482
483 /* Sanity check */
484 HDassert(hdr);
485
486 /* Mark B-tree header as dirty in cache */
487 if (H5AC_mark_entry_dirty(hdr) < 0)
488 HGOTO_ERROR(H5E_BTREE, H5E_CANTMARKDIRTY, FAIL, "unable to mark v2 B-tree header as dirty")
489
490 done:
491 FUNC_LEAVE_NOAPI(ret_value)
492 } /* end H5B2__hdr_dirty() */
493
494 /*-------------------------------------------------------------------------
495 * Function: H5B2__hdr_protect
496 *
497 * Purpose: Convenience wrapper around protecting v2 B-tree header
498 *
499 * Return: Non-NULL pointer to header on success/NULL on failure
500 *
501 * Programmer: Quincey Koziol
502 * Dec 18 2015
503 *
504 *-------------------------------------------------------------------------
505 */
506 H5B2_hdr_t *
H5B2__hdr_protect(H5F_t * f,haddr_t hdr_addr,void * ctx_udata,unsigned flags)507 H5B2__hdr_protect(H5F_t *f, haddr_t hdr_addr, void *ctx_udata, unsigned flags)
508 {
509 H5B2_hdr_cache_ud_t udata; /* User data for cache callbacks */
510 H5B2_hdr_t * hdr = NULL; /* v2 B-tree header */
511 H5B2_hdr_t * ret_value = NULL; /* Return value */
512
513 FUNC_ENTER_PACKAGE
514
515 /* Sanity check */
516 HDassert(f);
517 HDassert(H5F_addr_defined(hdr_addr));
518
519 /* only the H5AC__READ_ONLY_FLAG may appear in flags */
520 HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
521
522 /* Set up user data for cache callbacks */
523 udata.f = f;
524 udata.addr = hdr_addr;
525 udata.ctx_udata = ctx_udata;
526
527 /* Protect the header */
528 if (NULL == (hdr = (H5B2_hdr_t *)H5AC_protect(f, H5AC_BT2_HDR, hdr_addr, &udata, flags)))
529 HGOTO_ERROR(H5E_BTREE, H5E_CANTPROTECT, NULL, "unable to load v2 B-tree header, address = %llu",
530 (unsigned long long)hdr_addr)
531 hdr->f = f; /* (Must be set again here, in case the header was already in the cache -QAK) */
532
533 /* Create top proxy, if it doesn't exist */
534 if (hdr->swmr_write && NULL == hdr->top_proxy) {
535 /* Create 'top' proxy for v2 B-tree entries */
536 if (NULL == (hdr->top_proxy = H5AC_proxy_entry_create()))
537 HGOTO_ERROR(H5E_BTREE, H5E_CANTCREATE, NULL, "can't create v2 B-tree proxy")
538
539 /* Add header as child of 'top' proxy */
540 if (H5AC_proxy_entry_add_child(hdr->top_proxy, f, hdr) < 0)
541 HGOTO_ERROR(H5E_BTREE, H5E_CANTSET, NULL, "unable to add v2 B-tree header as child of proxy")
542 } /* end if */
543
544 /* Set return value */
545 ret_value = hdr;
546
547 done:
548 /* Clean up on error */
549 if (!ret_value) {
550 /* Release the header, if it was protected */
551 if (hdr && H5AC_unprotect(hdr->f, H5AC_BT2_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0)
552 HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, NULL,
553 "unable to unprotect v2 B-tree header, address = %llu", (unsigned long long)hdr_addr)
554 } /* end if */
555
556 FUNC_LEAVE_NOAPI(ret_value)
557 } /* end H5B2__hdr_protect() */
558
559 /*-------------------------------------------------------------------------
560 * Function: H5B2__hdr_unprotect
561 *
562 * Purpose: Convenience wrapper around unprotecting v2 B-tree header
563 *
564 * Return: Non-negative on success/Negative on failure
565 *
566 * Programmer: Quincey Koziol
567 * Dec 18 2015
568 *
569 *-------------------------------------------------------------------------
570 */
571 herr_t
H5B2__hdr_unprotect(H5B2_hdr_t * hdr,unsigned cache_flags)572 H5B2__hdr_unprotect(H5B2_hdr_t *hdr, unsigned cache_flags)
573 {
574 herr_t ret_value = SUCCEED; /* Return value */
575
576 FUNC_ENTER_PACKAGE
577
578 /* Sanity check */
579 HDassert(hdr);
580
581 /* Unprotect the header */
582 if (H5AC_unprotect(hdr->f, H5AC_BT2_HDR, hdr->addr, hdr, cache_flags) < 0)
583 HGOTO_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL,
584 "unable to unprotect v2 B-tree header, address = %llu", (unsigned long long)hdr->addr)
585
586 done:
587 FUNC_LEAVE_NOAPI(ret_value)
588 } /* end H5B2__hdr_unprotect() */
589
590 /*-------------------------------------------------------------------------
591 * Function: H5B2__hdr_free
592 *
593 * Purpose: Free B-tree header info
594 *
595 * Return: Non-negative on success/Negative on failure
596 *
597 * Programmer: Quincey Koziol
598 * Feb 2 2005
599 *
600 *-------------------------------------------------------------------------
601 */
602 herr_t
H5B2__hdr_free(H5B2_hdr_t * hdr)603 H5B2__hdr_free(H5B2_hdr_t *hdr)
604 {
605 herr_t ret_value = SUCCEED; /* Return value */
606
607 FUNC_ENTER_PACKAGE
608
609 /* Sanity check */
610 HDassert(hdr);
611
612 /* Destroy the callback context */
613 if (hdr->cb_ctx) {
614 if ((*hdr->cls->dst_context)(hdr->cb_ctx) < 0)
615 HGOTO_ERROR(H5E_BTREE, H5E_CANTRELEASE, FAIL, "can't destroy v2 B-tree client callback context")
616 hdr->cb_ctx = NULL;
617 } /* end if */
618
619 /* Free the B-tree node buffer */
620 if (hdr->page)
621 hdr->page = H5FL_BLK_FREE(node_page, hdr->page);
622
623 /* Free the array of offsets into the native key block */
624 if (hdr->nat_off)
625 hdr->nat_off = H5FL_SEQ_FREE(size_t, hdr->nat_off);
626
627 /* Release the node info */
628 if (hdr->node_info) {
629 unsigned u; /* Local index variable */
630
631 /* Destroy free list factories */
632 for (u = 0; u < (unsigned)(hdr->depth + 1); u++) {
633 if (hdr->node_info[u].nat_rec_fac)
634 if (H5FL_fac_term(hdr->node_info[u].nat_rec_fac) < 0)
635 HGOTO_ERROR(H5E_BTREE, H5E_CANTRELEASE, FAIL,
636 "can't destroy node's native record block factory")
637 if (hdr->node_info[u].node_ptr_fac)
638 if (H5FL_fac_term(hdr->node_info[u].node_ptr_fac) < 0)
639 HGOTO_ERROR(H5E_BTREE, H5E_CANTRELEASE, FAIL,
640 "can't destroy node's node pointer block factory")
641 } /* end for */
642
643 /* Free the array of node info structs */
644 hdr->node_info = H5FL_SEQ_FREE(H5B2_node_info_t, hdr->node_info);
645 } /* end if */
646
647 /* Release the min & max record info, if set */
648 if (hdr->min_native_rec)
649 hdr->min_native_rec = H5MM_xfree(hdr->min_native_rec);
650 if (hdr->max_native_rec)
651 hdr->max_native_rec = H5MM_xfree(hdr->max_native_rec);
652
653 /* Destroy the 'top' proxy */
654 if (hdr->top_proxy) {
655 if (H5AC_proxy_entry_dest(hdr->top_proxy) < 0)
656 HGOTO_ERROR(H5E_BTREE, H5E_CANTRELEASE, FAIL, "unable to destroy v2 B-tree 'top' proxy")
657 hdr->top_proxy = NULL;
658 } /* end if */
659
660 /* Free B-tree header info */
661 hdr = H5FL_FREE(H5B2_hdr_t, hdr);
662
663 done:
664 FUNC_LEAVE_NOAPI(ret_value)
665 } /* end H5B2__hdr_free() */
666
667 /*-------------------------------------------------------------------------
668 * Function: H5B2__hdr_delete
669 *
670 * Purpose: Delete a v2 B-tree, starting with the header
671 *
672 * Return: Non-negative on success/Negative on failure
673 *
674 * Programmer: Quincey Koziol
675 * Oct 15 2009
676 *
677 *-------------------------------------------------------------------------
678 */
679 herr_t
H5B2__hdr_delete(H5B2_hdr_t * hdr)680 H5B2__hdr_delete(H5B2_hdr_t *hdr)
681 {
682 unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting v2 B-tree header */
683 herr_t ret_value = SUCCEED; /* Return value */
684
685 FUNC_ENTER_PACKAGE
686
687 /* Sanity check */
688 HDassert(hdr);
689
690 #ifndef NDEBUG
691 {
692 unsigned hdr_status = 0; /* v2 B-tree header's status in the metadata cache */
693
694 /* Check the v2 B-tree header's status in the metadata cache */
695 if (H5AC_get_entry_status(hdr->f, hdr->addr, &hdr_status) < 0)
696 HGOTO_ERROR(H5E_BTREE, H5E_CANTGET, FAIL,
697 "unable to check metadata cache status for v2 B-tree header")
698
699 /* Sanity checks on v2 B-tree header */
700 HDassert(hdr_status & H5AC_ES__IN_CACHE);
701 HDassert(hdr_status & H5AC_ES__IS_PROTECTED);
702 } /* end block */
703 #endif /* NDEBUG */
704
705 /* Delete all nodes in B-tree */
706 if (H5F_addr_defined(hdr->root.addr))
707 if (H5B2__delete_node(hdr, hdr->depth, &hdr->root, hdr, hdr->remove_op, hdr->remove_op_data) < 0)
708 HGOTO_ERROR(H5E_BTREE, H5E_CANTDELETE, FAIL, "unable to delete B-tree nodes")
709
710 /* Indicate that the heap header should be deleted & file space freed */
711 cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG | H5AC__FREE_FILE_SPACE_FLAG;
712
713 done:
714 /* Unprotect the header with appropriate flags */
715 if (H5B2__hdr_unprotect(hdr, cache_flags) < 0)
716 HDONE_ERROR(H5E_BTREE, H5E_CANTUNPROTECT, FAIL, "unable to release v2 B-tree header")
717
718 FUNC_LEAVE_NOAPI(ret_value)
719 } /* end H5B2__hdr_delete() */
720