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: H5HFdblock.c
17 * Apr 10 2006
18 * Quincey Koziol
19 *
20 * Purpose: Direct block routines for fractal heaps.
21 *
22 *-------------------------------------------------------------------------
23 */
24
25 /****************/
26 /* Module Setup */
27 /****************/
28
29 #include "H5HFmodule.h" /* This source code file is part of the H5HF module */
30
31 /***********/
32 /* Headers */
33 /***********/
34 #include "H5private.h" /* Generic Functions */
35 #include "H5Eprivate.h" /* Error handling */
36 #include "H5Fprivate.h" /* File access */
37 #include "H5HFpkg.h" /* Fractal heaps */
38 #include "H5MFprivate.h" /* File memory management */
39 #include "H5VMprivate.h" /* Vectors and arrays */
40
41 /****************/
42 /* Local Macros */
43 /****************/
44
45 /******************/
46 /* Local Typedefs */
47 /******************/
48
49 /********************/
50 /* Package Typedefs */
51 /********************/
52
53 /********************/
54 /* Local Prototypes */
55 /********************/
56
57 /*********************/
58 /* Package Variables */
59 /*********************/
60
61 /* Declare a free list to manage the H5HF_direct_t struct */
62 H5FL_DEFINE(H5HF_direct_t);
63
64 /*****************************/
65 /* Library Private Variables */
66 /*****************************/
67
68 /*******************/
69 /* Local Variables */
70 /*******************/
71
72 /*-------------------------------------------------------------------------
73 * Function: H5HF__man_dblock_create
74 *
75 * Purpose: Allocate & initialize a managed direct block
76 *
77 * Return: Pointer to new direct block on success, NULL on failure
78 *
79 * Programmer: Quincey Koziol
80 * Feb 27 2006
81 *
82 *-------------------------------------------------------------------------
83 */
84 herr_t
H5HF__man_dblock_create(H5HF_hdr_t * hdr,H5HF_indirect_t * par_iblock,unsigned par_entry,haddr_t * addr_p,H5HF_free_section_t ** ret_sec_node)85 H5HF__man_dblock_create(H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblock, unsigned par_entry, haddr_t *addr_p,
86 H5HF_free_section_t **ret_sec_node)
87 {
88 H5HF_free_section_t *sec_node; /* Pointer to free space section for block */
89 H5HF_direct_t * dblock = NULL; /* Pointer to direct block */
90 haddr_t dblock_addr; /* Direct block's address */
91 size_t free_space; /* Free space in new block */
92 herr_t ret_value = SUCCEED; /* Return value */
93
94 FUNC_ENTER_PACKAGE
95
96 /*
97 * Check arguments.
98 */
99 HDassert(hdr);
100
101 /*
102 * Allocate file and memory data structures.
103 */
104 if (NULL == (dblock = H5FL_MALLOC(H5HF_direct_t)))
105 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap direct block")
106
107 /* Reset the metadata cache info for the heap header */
108 HDmemset(&dblock->cache_info, 0, sizeof(H5AC_info_t));
109
110 /* Share common heap information */
111 dblock->hdr = hdr;
112 if (H5HF__hdr_incr(hdr) < 0)
113 HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header")
114
115 /* Set info for direct block */
116 if (par_iblock) {
117 unsigned par_row = par_entry / hdr->man_dtable.cparam.width; /* Row for block */
118
119 /* Compute offset & size, based on parent's information */
120 dblock->block_off = par_iblock->block_off;
121 dblock->block_off += hdr->man_dtable.row_block_off[par_row];
122 dblock->block_off +=
123 hdr->man_dtable.row_block_size[par_row] * (par_entry % hdr->man_dtable.cparam.width);
124 H5_CHECKED_ASSIGN(dblock->size, size_t, hdr->man_dtable.row_block_size[par_row], hsize_t);
125 } /* end if */
126 else {
127 /* Must be the root direct block */
128 dblock->block_off = 0;
129 dblock->size = hdr->man_dtable.cparam.start_block_size;
130 } /* end else */
131 dblock->file_size = 0;
132 free_space = dblock->size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
133
134 /* Allocate buffer for block */
135 /* XXX: Change to using free-list factories */
136 if ((dblock->blk = H5FL_BLK_MALLOC(direct_block, dblock->size)) == NULL)
137 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
138 HDmemset(dblock->blk, 0, dblock->size);
139
140 dblock->write_buf = NULL;
141 dblock->write_size = 0;
142
143 /* Allocate [temporary] space for the direct block on disk */
144 if (H5F_USE_TMP_SPACE(hdr->f)) {
145 if (HADDR_UNDEF == (dblock_addr = H5MF_alloc_tmp(hdr->f, (hsize_t)dblock->size)))
146 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
147 "file allocation failed for fractal heap direct block")
148 } /* end if */
149 else {
150 if (HADDR_UNDEF == (dblock_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, (hsize_t)dblock->size)))
151 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL,
152 "file allocation failed for fractal heap direct block")
153 } /* end else */
154
155 /* Attach to parent indirect block, if there is one */
156 dblock->parent = par_iblock;
157 if (dblock->parent) {
158 if (H5HF__man_iblock_attach(dblock->parent, par_entry, dblock_addr) < 0)
159 HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach direct block to parent indirect block")
160 dblock->fd_parent = par_iblock;
161 } /* end if */
162 else
163 dblock->fd_parent = hdr;
164 dblock->par_entry = par_entry;
165
166 /* Create a new 'single' section for the free space in the block */
167 if (NULL == (sec_node = H5HF__sect_single_new((dblock->block_off + H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)),
168 free_space, dblock->parent, dblock->par_entry)))
169 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for new direct block's free space")
170
171 /* Check what to do with section node */
172 if (ret_sec_node)
173 /* Pass back the pointer to the section instead of adding it to the free list */
174 *ret_sec_node = sec_node;
175 else {
176 /* Add new free space to the heap's list of space */
177 if (H5HF__space_add(hdr, sec_node, 0) < 0)
178 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
179 } /* end else */
180
181 /* Cache the new fractal heap direct block */
182 if (H5AC_insert_entry(hdr->f, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
183 HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap direct block to cache")
184
185 /* Increase the allocated heap size */
186 if (H5HF__hdr_inc_alloc(hdr, dblock->size) < 0)
187 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
188
189 /* Set the address of of direct block, if requested */
190 if (addr_p)
191 *addr_p = dblock_addr;
192
193 done:
194 if (ret_value < 0)
195 if (dblock)
196 if (H5HF__man_dblock_dest(dblock) < 0)
197 HDONE_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to destroy fractal heap direct block")
198
199 FUNC_LEAVE_NOAPI(ret_value)
200 } /* end H5HF__man_dblock_create() */
201
202 /*-------------------------------------------------------------------------
203 * Function: H5HF__man_dblock_destroy
204 *
205 * Purpose: Destroy a managed direct block
206 *
207 * Note: This routine does _not_ insert a range section for the
208 * destroyed direct block, that must be handled by the
209 * caller.
210 *
211 * Return: SUCCEED/FAIL
212 *
213 * Programmer: Quincey Koziol
214 * May 17 2006
215 *
216 *-------------------------------------------------------------------------
217 */
218 herr_t
H5HF__man_dblock_destroy(H5HF_hdr_t * hdr,H5HF_direct_t * dblock,haddr_t dblock_addr,hbool_t * parent_removed)219 H5HF__man_dblock_destroy(H5HF_hdr_t *hdr, H5HF_direct_t *dblock, haddr_t dblock_addr, hbool_t *parent_removed)
220 {
221 hsize_t dblock_size; /* Size of direct block on disk */
222 unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting indirect block */
223 herr_t ret_value = SUCCEED; /* Return value */
224
225 FUNC_ENTER_PACKAGE
226
227 /*
228 * Check arguments.
229 */
230 HDassert(hdr);
231 HDassert(dblock);
232
233 /* Check for I/O filters on this heap */
234 if (hdr->filter_len > 0) {
235 /* Check for root direct block */
236 if (dblock->parent == NULL)
237 /* Get direct block's actual size */
238 dblock_size = (hsize_t)hdr->pline_root_direct_size;
239 else {
240 H5HF_indirect_t *par_iblock; /* Parent indirect block */
241 unsigned par_entry; /* Entry in parent indirect block */
242
243 /* Get parent information */
244 par_iblock = dblock->parent;
245 par_entry = dblock->par_entry;
246
247 /* Get direct block's actual size */
248 dblock_size = (hsize_t)par_iblock->filt_ents[par_entry].size;
249 } /* end else */
250 } /* end if */
251 else
252 dblock_size = (hsize_t)dblock->size;
253
254 /* Reset the parent_removed flag */
255 if (parent_removed)
256 *parent_removed = FALSE;
257
258 /* Check for root direct block */
259 if (hdr->man_dtable.curr_root_rows == 0) {
260 /* Sanity check */
261 HDassert(hdr->man_dtable.table_addr == dblock_addr);
262 HDassert(hdr->man_dtable.cparam.start_block_size == dblock->size);
263
264 /* Sanity check block iterator */
265 HDassert(!H5HF__man_iter_ready(&hdr->next_block));
266
267 /* Reset header information back to "empty heap" state */
268 if (H5HF__hdr_empty(hdr) < 0)
269 HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty")
270 } /* end if */
271 else {
272 /* Adjust heap statistics */
273 hdr->man_alloc_size -= dblock->size;
274
275 /* Check for this direct block being the highest in the heap */
276 if ((dblock->block_off + dblock->size) == hdr->man_iter_off)
277 /* Move 'next block' iterator backwards (may shrink heap) */
278 if (H5HF__hdr_reverse_iter(hdr, dblock_addr) < 0)
279 HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reverse 'next block' iterator")
280
281 /* Detach from parent indirect block */
282 if (dblock->parent) {
283 /* Destroy flush dependency between direct block and parent */
284 if (H5AC_destroy_flush_dependency(dblock->fd_parent, dblock) < 0)
285 HGOTO_ERROR(H5E_HEAP, H5E_CANTUNDEPEND, FAIL, "unable to destroy flush dependency")
286 dblock->fd_parent = NULL;
287
288 /* If this is the last direct block for the indirect block, the
289 * indirect block will be removed when this direct block is detached
290 */
291 if (parent_removed && 1 == dblock->parent->nchildren)
292 *parent_removed = TRUE;
293
294 if (H5HF__man_iblock_detach(dblock->parent, dblock->par_entry) < 0)
295 HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach from parent indirect block");
296 dblock->parent = NULL;
297 dblock->par_entry = 0;
298 } /* end if */
299 } /* end else */
300
301 /* Indicate that the direct block should be deleted */
302 dblock->file_size = dblock_size;
303 cache_flags |= H5AC__DIRTIED_FLAG | H5AC__DELETED_FLAG;
304
305 /* If the dblock is in real file space, also tell the cache to free its file space */
306 if (!H5F_IS_TMP_ADDR(hdr->f, dblock_addr))
307 cache_flags |= H5AC__FREE_FILE_SPACE_FLAG;
308
309 done:
310 /* Unprotect the indirect block, with appropriate flags */
311 if (H5AC_unprotect(hdr->f, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, cache_flags) < 0)
312 HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
313
314 FUNC_LEAVE_NOAPI(ret_value)
315 } /* end H5HF__man_dblock_destroy() */
316
317 /*-------------------------------------------------------------------------
318 * Function: H5HF__man_dblock_new
319 *
320 * Purpose: Create a direct block large enough to hold an object of
321 * the requested size
322 *
323 * Return: SUCCEED/FAIL
324 *
325 * Programmer: Quincey Koziol
326 * Mar 13 2006
327 *
328 *-------------------------------------------------------------------------
329 */
330 herr_t
H5HF__man_dblock_new(H5HF_hdr_t * hdr,size_t request,H5HF_free_section_t ** ret_sec_node)331 H5HF__man_dblock_new(H5HF_hdr_t *hdr, size_t request, H5HF_free_section_t **ret_sec_node)
332 {
333 haddr_t dblock_addr; /* Address of new direct block */
334 size_t min_dblock_size; /* Min. size of direct block to allocate */
335 herr_t ret_value = SUCCEED; /* Return value */
336
337 FUNC_ENTER_PACKAGE
338
339 /*
340 * Check arguments.
341 */
342 HDassert(hdr);
343 HDassert(request > 0);
344
345 /* Compute the min. size of the direct block needed to fulfill the request */
346 if (request < hdr->man_dtable.cparam.start_block_size)
347 min_dblock_size = hdr->man_dtable.cparam.start_block_size;
348 else {
349 min_dblock_size = ((size_t)1) << (1 + H5VM_log2_gen((uint64_t)request));
350 HDassert(min_dblock_size <= hdr->man_dtable.cparam.max_direct_size);
351 } /* end else */
352
353 /* Adjust the size of block needed to fulfill request, with overhead */
354 if (min_dblock_size < H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr) + request)
355 min_dblock_size *= 2;
356
357 /* Check if this is the first block in the heap */
358 if (!H5F_addr_defined(hdr->man_dtable.table_addr) &&
359 min_dblock_size == hdr->man_dtable.cparam.start_block_size) {
360 /* Create new direct block at starting offset */
361 if (H5HF__man_dblock_create(hdr, NULL, 0, &dblock_addr, ret_sec_node) < 0)
362 HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
363
364 /* Point root at new direct block */
365 hdr->man_dtable.curr_root_rows = 0;
366 hdr->man_dtable.table_addr = dblock_addr;
367 if (hdr->filter_len > 0) {
368 hdr->pline_root_direct_size = hdr->man_dtable.cparam.start_block_size;
369 hdr->pline_root_direct_filter_mask = 0;
370 } /* end if */
371
372 /* Extend heap to cover new direct block */
373 if (H5HF__hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size,
374 (hssize_t)hdr->man_dtable.row_tot_dblock_free[0]) < 0)
375 HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block")
376 } /* end if */
377 /* Root entry already exists, allocate direct block from root indirect block */
378 else {
379 H5HF_indirect_t *iblock; /* Pointer to indirect block to create */
380 unsigned next_row; /* Iterator's next block row */
381 unsigned next_entry; /* Iterator's next block entry */
382 size_t next_size; /* Size of next direct block to create */
383
384 /* Update iterator to reflect any previous increments as well as allow for requested direct block size
385 */
386 if (H5HF__hdr_update_iter(hdr, min_dblock_size) < 0)
387 HGOTO_ERROR(H5E_HEAP, H5E_CANTUPDATE, FAIL, "unable to update block iterator")
388
389 /* Retrieve information about current iterator position */
390 if (H5HF__man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0)
391 HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location")
392 HDassert(next_row < iblock->nrows);
393 H5_CHECKED_ASSIGN(next_size, size_t, hdr->man_dtable.row_block_size[next_row], hsize_t);
394
395 /* Check for skipping over blocks */
396 if (min_dblock_size > next_size) {
397 HDfprintf(
398 stderr,
399 "%s: Skipping direct block sizes not supported, min_dblock_size = %zu, next_size = %zu\n",
400 FUNC, min_dblock_size, next_size);
401 HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "skipping direct block sizes not supported yet")
402 } /* end if */
403
404 /* Advance "next block" iterator to next direct block entry */
405 if (H5HF__hdr_inc_iter(hdr, (hsize_t)next_size, 1) < 0)
406 HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment 'next block' iterator")
407
408 /* Create new direct block at current location*/
409 if (H5HF__man_dblock_create(hdr, iblock, next_entry, &dblock_addr, ret_sec_node) < 0)
410 HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
411 } /* end else */
412
413 done:
414 FUNC_LEAVE_NOAPI(ret_value)
415 } /* end H5HF__man_dblock_new() */
416
417 /*-------------------------------------------------------------------------
418 * Function: H5HF__man_dblock_protect
419 *
420 * Purpose: Convenience wrapper around H5AC_protect on a direct block
421 * (Use H5AC_unprotect to unprotect it for now)
422 *
423 * Return: Pointer to direct block on success, NULL on failure
424 *
425 * Programmer: Quincey Koziol
426 * Apr 17 2006
427 *
428 *-------------------------------------------------------------------------
429 */
430 H5HF_direct_t *
H5HF__man_dblock_protect(H5HF_hdr_t * hdr,haddr_t dblock_addr,size_t dblock_size,H5HF_indirect_t * par_iblock,unsigned par_entry,unsigned flags)431 H5HF__man_dblock_protect(H5HF_hdr_t *hdr, haddr_t dblock_addr, size_t dblock_size,
432 H5HF_indirect_t *par_iblock, unsigned par_entry, unsigned flags)
433 {
434 H5HF_direct_t * dblock; /* Direct block from cache */
435 H5HF_dblock_cache_ud_t udata; /* parent and other infor for deserializing direct block */
436 H5HF_direct_t * ret_value = NULL; /* Return value */
437
438 FUNC_ENTER_PACKAGE
439
440 /*
441 * Check arguments.
442 */
443 HDassert(hdr);
444 HDassert(H5F_addr_defined(dblock_addr));
445 HDassert(dblock_size > 0);
446
447 /* only H5AC__READ_ONLY_FLAG may appear in flags */
448 HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
449
450 /* Set up parent info */
451 udata.par_info.hdr = hdr;
452 udata.par_info.iblock = par_iblock;
453 udata.par_info.entry = par_entry;
454
455 /* set up the file pointer in the user data */
456 udata.f = hdr->f;
457
458 /* set up the direct block size */
459 udata.dblock_size = dblock_size;
460
461 /* compute the on disk image size -- observe that odi_size and
462 * dblock_size will be identical if there is no filtering.
463 */
464 if (hdr->filter_len > 0) {
465 if (par_iblock == NULL) {
466 udata.odi_size = hdr->pline_root_direct_size;
467 udata.filter_mask = hdr->pline_root_direct_filter_mask;
468 } /* end if */
469 else {
470 /* Sanity check */
471 HDassert(H5F_addr_eq(par_iblock->ents[par_entry].addr, dblock_addr));
472
473 /* Set up parameters to read filtered direct block */
474 udata.odi_size = par_iblock->filt_ents[par_entry].size;
475 udata.filter_mask = par_iblock->filt_ents[par_entry].filter_mask;
476 } /* end else */
477 } /* end if */
478 else {
479 udata.odi_size = dblock_size;
480 udata.filter_mask = 0;
481 } /* end else */
482
483 /* Reset compression context info */
484 udata.decompressed = FALSE;
485 udata.dblk = NULL;
486
487 /* Protect the direct block */
488 if (NULL ==
489 (dblock = (H5HF_direct_t *)H5AC_protect(hdr->f, H5AC_FHEAP_DBLOCK, dblock_addr, &udata, flags)))
490 HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block")
491
492 /* Set the return value */
493 ret_value = dblock;
494
495 done:
496 FUNC_LEAVE_NOAPI(ret_value)
497 } /* end H5HF__man_dblock_protect() */
498
499 /*-------------------------------------------------------------------------
500 * Function: H5HF__man_dblock_locate
501 *
502 * Purpose: Locate a direct block in a managed heap
503 *
504 * Return: SUCCEED/FAIL
505 *
506 * Programmer: Quincey Koziol
507 * May 8 2006
508 *
509 *-------------------------------------------------------------------------
510 */
511 herr_t
H5HF__man_dblock_locate(H5HF_hdr_t * hdr,hsize_t obj_off,H5HF_indirect_t ** ret_iblock,unsigned * ret_entry,hbool_t * ret_did_protect,unsigned flags)512 H5HF__man_dblock_locate(H5HF_hdr_t *hdr, hsize_t obj_off, H5HF_indirect_t **ret_iblock, unsigned *ret_entry,
513 hbool_t *ret_did_protect, unsigned flags)
514 {
515 haddr_t iblock_addr; /* Indirect block's address */
516 H5HF_indirect_t *iblock; /* Pointer to indirect block */
517 hbool_t did_protect; /* Whether we protected the indirect block or not */
518 unsigned row, col; /* Row & column for object's block */
519 unsigned entry; /* Entry of block */
520 herr_t ret_value = SUCCEED; /* Return value */
521
522 FUNC_ENTER_PACKAGE
523
524 /*
525 * Check arguments.
526 */
527 HDassert(hdr);
528 HDassert(hdr->man_dtable.curr_root_rows); /* Only works for heaps with indirect root block */
529 HDassert(ret_iblock);
530 HDassert(ret_did_protect);
531
532 /* only H5AC__READ_ONLY_FLAG may appear in flags */
533 HDassert((flags & (unsigned)(~H5AC__READ_ONLY_FLAG)) == 0);
534
535 /* Look up row & column for object */
536 if (H5HF__dtable_lookup(&hdr->man_dtable, obj_off, &row, &col) < 0)
537 HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object")
538
539 /* Set initial indirect block info */
540 iblock_addr = hdr->man_dtable.table_addr;
541
542 /* Lock root indirect block */
543 if (NULL == (iblock = H5HF__man_iblock_protect(hdr, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0,
544 FALSE, flags, &did_protect)))
545 HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
546
547 /* Check for indirect block row */
548 while (row >= hdr->man_dtable.max_direct_rows) {
549 H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */
550 hbool_t new_did_protect; /* Whether we protected the indirect block or not */
551 unsigned nrows; /* Number of rows in new indirect block */
552 unsigned cache_flags = H5AC__NO_FLAGS_SET; /* Flags for unprotecting parent indirect block */
553
554 /* Compute # of rows in child indirect block */
555 nrows = (H5VM_log2_gen(hdr->man_dtable.row_block_size[row]) - hdr->man_dtable.first_row_bits) + 1;
556 HDassert(nrows < iblock->nrows); /* child must be smaller than parent */
557
558 /* Compute indirect block's entry */
559 entry = (row * hdr->man_dtable.cparam.width) + col;
560
561 /* Locate child indirect block */
562 iblock_addr = iblock->ents[entry].addr;
563
564 /* Check if we need to (re-)create the child indirect block */
565 if (!H5F_addr_defined(iblock_addr)) {
566 if (H5HF__man_iblock_create(hdr, iblock, entry, nrows, nrows, &iblock_addr) < 0)
567 HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block")
568
569 /* Indicate that the parent indirect block was modified */
570 cache_flags |= H5AC__DIRTIED_FLAG;
571 } /* end if */
572
573 /* Lock child indirect block */
574 if (NULL == (new_iblock = H5HF__man_iblock_protect(hdr, iblock_addr, nrows, iblock, entry, FALSE,
575 flags, &new_did_protect)))
576 HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
577
578 /* Release the current indirect block */
579 if (H5HF__man_iblock_unprotect(iblock, cache_flags, did_protect) < 0)
580 HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
581
582 /* Switch variables to use new indirect block */
583 iblock = new_iblock;
584 did_protect = new_did_protect;
585
586 /* Look up row & column in new indirect block for object */
587 if (H5HF__dtable_lookup(&hdr->man_dtable, (obj_off - iblock->block_off), &row, &col) < 0)
588 HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object")
589 HDassert(row < iblock->nrows); /* child must be smaller than parent */
590 } /* end while */
591
592 /* Set return parameters */
593 if (ret_entry)
594 *ret_entry = (row * hdr->man_dtable.cparam.width) + col;
595 *ret_iblock = iblock;
596 *ret_did_protect = did_protect;
597
598 done:
599 FUNC_LEAVE_NOAPI(ret_value)
600 } /* end H5HF__man_dblock_locate() */
601
602 /*-------------------------------------------------------------------------
603 * Function: H5HF__man_dblock_delete
604 *
605 * Purpose: Delete a managed direct block
606 *
607 * Note: This routine does _not_ modify any indirect block that points
608 * to this direct block, it is assumed that the whole heap is
609 * being deleted. (H5HF__man_dblock_destroy modifies the indirect
610 * block)
611 *
612 * Return: SUCCEED/FAIL
613 *
614 * Programmer: Quincey Koziol
615 * Aug 7 2006
616 *
617 *-------------------------------------------------------------------------
618 */
619 herr_t
H5HF__man_dblock_delete(H5F_t * f,haddr_t dblock_addr,hsize_t dblock_size)620 H5HF__man_dblock_delete(H5F_t *f, haddr_t dblock_addr, hsize_t dblock_size)
621 {
622 unsigned dblock_status = 0; /* Direct block's status in the metadata cache */
623 herr_t ret_value = SUCCEED; /* Return value */
624
625 FUNC_ENTER_PACKAGE
626
627 /*
628 * Check arguments.
629 */
630 HDassert(f);
631 HDassert(H5F_addr_defined(dblock_addr));
632 HDassert(dblock_size > 0);
633
634 /* Check the direct block's status in the metadata cache */
635 if (H5AC_get_entry_status(f, dblock_addr, &dblock_status) < 0)
636 HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to check metadata cache status for direct block")
637
638 /* If the direct block is in the cache, expunge it now */
639 if (dblock_status & H5AC_ES__IN_CACHE) {
640 /* Sanity checks on direct block */
641 HDassert(!(dblock_status & H5AC_ES__IS_PINNED));
642 HDassert(!(dblock_status & H5AC_ES__IS_PROTECTED));
643
644 /* Evict the direct block from the metadata cache */
645 if (H5AC_expunge_entry(f, H5AC_FHEAP_DBLOCK, dblock_addr, H5AC__NO_FLAGS_SET) < 0)
646 HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "unable to remove direct block from cache")
647 } /* end if */
648
649 /* Check if the direct block is NOT currently allocated in temp. file space */
650 /* (temp. file space does not need to be freed) */
651 if (!H5F_IS_TMP_ADDR(f, dblock_addr))
652 /* Release direct block's disk space */
653 /* (XXX: Under the best of circumstances, this block's space in the file
654 * would be freed in the H5AC_expunge_entry() call above (and the
655 * H5AC__FREE_FILE_SPACE_FLAG used there), but since the direct
656 * block structure might have a different size on disk than in
657 * the heap's 'abstract' address space, we would need to set the
658 * "file_size" field for the direct block structure. In order to
659 * do that, we'd have to protect/unprotect the direct block and
660 * that would add a bunch of unnecessary overhead to the process,
661 * so we just release the file space here, directly. -QAK)
662 */
663 if (H5MF_xfree(f, H5FD_MEM_FHEAP_DBLOCK, dblock_addr, dblock_size) < 0)
664 HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block file space")
665
666 done:
667 FUNC_LEAVE_NOAPI(ret_value)
668 } /* end H5HF__man_dblock_delete() */
669
670 /*-------------------------------------------------------------------------
671 * Function: H5HF__man_dblock_dest
672 *
673 * Purpose: Destroys a fractal heap direct block in memory.
674 *
675 * Return: Non-negative on success/Negative on failure
676 *
677 * Programmer: Quincey Koziol
678 * Feb 27 2006
679 *
680 *-------------------------------------------------------------------------
681 */
682 herr_t
H5HF__man_dblock_dest(H5HF_direct_t * dblock)683 H5HF__man_dblock_dest(H5HF_direct_t *dblock)
684 {
685 herr_t ret_value = SUCCEED; /* Return value */
686
687 FUNC_ENTER_PACKAGE
688
689 /*
690 * Check arguments.
691 */
692 HDassert(dblock);
693
694 /* Decrement reference count on shared fractal heap info */
695 HDassert(dblock->hdr != NULL);
696 if (H5HF__hdr_decr(dblock->hdr) < 0)
697 HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
698 if (dblock->parent)
699 if (H5HF__iblock_decr(dblock->parent) < 0)
700 HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL,
701 "can't decrement reference count on shared indirect block")
702
703 /* Free block's buffer */
704 dblock->blk = H5FL_BLK_FREE(direct_block, dblock->blk);
705
706 /* Free fractal heap direct block info */
707 dblock = H5FL_FREE(H5HF_direct_t, dblock);
708
709 done:
710 FUNC_LEAVE_NOAPI(ret_value)
711 } /* end H5HF__man_dblock_dest() */
712