diff options
Diffstat (limited to 'src/H5HFhdr.c')
-rw-r--r-- | src/H5HFhdr.c | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c new file mode 100644 index 0000000..04d3959 --- /dev/null +++ b/src/H5HFhdr.c @@ -0,0 +1,458 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5HFhdr.c + * Apr 10 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Heap header routines for fractal heaps. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HF_PACKAGE /*suppress error about including H5HFpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HFpkg.h" /* Fractal heaps */ +#include "H5Vprivate.h" /* Vectors and arrays */ + +/****************/ +/* Local Macros */ +/****************/ + +/* Limit on the size of the max. direct block size */ +/* (This is limited to 32-bits currently, because I think it's unlikely to + * need to be larger, the 32-bit limit for H5V_log2_of2(n), and + * some offsets/sizes are encoded with a maxiumum of 32-bits - QAK) + */ +#define H5HL_MAX_DIRECT_SIZE_LIMIT ((hsize_t)2 * 1024 * 1024 * 1024) + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_alloc + * + * Purpose: Allocate shared fractal heap header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 21 2006 + * + *------------------------------------------------------------------------- + */ +H5HF_t * +H5HF_hdr_alloc(H5F_t *f) +{ + H5HF_t *fh = NULL; /* Shared fractal heap header */ + H5HF_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_alloc) + + /* + * Check arguments. + */ + HDassert(f); + + /* Allocate space for the shared information */ + if(NULL == (fh = H5FL_CALLOC(H5HF_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap shared header") + + /* Set the internal parameters for the heap */ + fh->f = f; + fh->sizeof_size = H5F_SIZEOF_SIZE(f); + fh->sizeof_addr = H5F_SIZEOF_ADDR(f); + + /* Set the return value */ + ret_value = fh; + +done: + if(!ret_value) + if(fh) + (void)H5HF_cache_hdr_dest(f, fh); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_alloc() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_free_space + * + * Purpose: Compute direct block free space, for indirect blocks of + * different sizes. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 21 2006 + * + *------------------------------------------------------------------------- + */ +static hsize_t +H5HF_hdr_compute_free_space(H5HF_t *hdr, hsize_t iblock_size) +{ + hsize_t acc_heap_size; /* Accumumated heap space */ + hsize_t acc_dblock_free; /* Accumumated direct block free space */ + unsigned curr_row; /* Current row in block */ + hsize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_compute_free_space) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(iblock_size > hdr->man_dtable.cparam.max_direct_size); + + /* Set the free space in direct blocks */ + acc_heap_size = 0; + acc_dblock_free = 0; + curr_row = 0; + while(acc_heap_size < iblock_size) { + acc_heap_size += hdr->man_dtable.row_block_size[curr_row] * + hdr->man_dtable.cparam.width; + acc_dblock_free += hdr->man_dtable.row_dblock_free[curr_row] * + hdr->man_dtable.cparam.width; + curr_row++; + } /* end while */ + + /* Set return value */ + ret_value = acc_dblock_free; + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_compute_free_space() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_finish_init + * + * Purpose: Finish initializing info in shared heap header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 21 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_finish_init(H5HF_t *hdr) +{ + size_t u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_finish_init) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Compute/cache some values */ + hdr->heap_off_size = H5HF_SIZEOF_OFFSET_BITS(hdr->man_dtable.cparam.max_index); + if(H5HF_dtable_init(&hdr->man_dtable) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize doubling table info") + + /* Create the free-list structure for the heap */ + if(NULL == (hdr->flist = H5HF_flist_create(hdr->man_dtable.cparam.max_direct_size, H5HF_free_section_free_cb))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free list info") + + /* Set the size of heap IDs */ + hdr->id_len = hdr->heap_off_size + MIN(hdr->man_dtable.max_dir_blk_off_size, + ((H5V_log2_gen((hsize_t)hdr->standalone_size) + 7) / 8)); + + /* Set the free space in direct blocks */ + for(u = 0; u < hdr->man_dtable.max_root_rows; u++) { + if(u < hdr->man_dtable.max_direct_rows) + hdr->man_dtable.row_dblock_free[u] = hdr->man_dtable.row_block_size[u] - + (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, hdr->man_dtable.row_block_size[u]) + + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); + else + hdr->man_dtable.row_dblock_free[u] = H5HF_hdr_compute_free_space(hdr, hdr->man_dtable.row_block_size[u]); +#ifdef QAK +HDfprintf(stderr, "%s: row_block_size[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_size[u]); +HDfprintf(stderr, "%s: row_block_off[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_block_off[u]); +HDfprintf(stderr, "%s: row_dblock_free[%Zu] = %Hu\n", FUNC, u, hdr->man_dtable.row_dblock_free[u]); +#endif /* QAK */ + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_finish_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_init + * + * Purpose: Initialize shared fractal heap header for new heap + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 21 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_init(H5HF_t *fh, haddr_t fh_addr, H5HF_create_t *cparam) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_init) + + /* + * Check arguments. + */ + HDassert(fh); + HDassert(cparam); + +#ifndef NDEBUG + /* Check for valid parameters */ + if(!POWER_OF_TWO(cparam->managed.width) || cparam->managed.width == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "width not power of two") + if(!POWER_OF_TWO(cparam->managed.start_block_size) || cparam->managed.start_block_size == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "starting block size not power of two") + if(!POWER_OF_TWO(cparam->managed.max_direct_size) || + (cparam->managed.max_direct_size == 0 || cparam->managed.max_direct_size > H5HL_MAX_DIRECT_SIZE_LIMIT)) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") + if(cparam->managed.max_direct_size < cparam->standalone_size) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not large enough to hold all managed blocks") + if(cparam->managed.max_index > (8 * fh->sizeof_size) || cparam->managed.max_index == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") +#endif /* NDEBUG */ + + /* Set the creation parameters for the heap */ + fh->heap_addr = fh_addr; + fh->addrmap = cparam->addrmap; + fh->standalone_size = cparam->standalone_size; + HDmemcpy(&(fh->man_dtable.cparam), &(cparam->managed), sizeof(H5HF_dtable_cparam_t)); + + /* Set root table address */ + fh->man_dtable.table_addr = HADDR_UNDEF; + + /* Note that the shared info is dirty (it's not written to the file yet) */ + fh->dirty = TRUE; + + /* Make shared heap info reference counted */ + if(H5HF_hdr_finish_init(fh) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't create ref-count wrapper for shared fractal heap header") + +done: + if(ret_value < 0) + if(fh) + (void)H5HF_cache_hdr_dest(NULL, fh); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_incr + * + * Purpose: Increment reference count on shared heap header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_incr(H5HF_t *hdr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_incr) + + /* Sanity check */ + HDassert(hdr); + +/* XXX: When "un-evictable" feature is finished, mark the header as + * unevictable on the first block to share it. - QAK + */ + + /* Increment reference count on shared header */ + hdr->rc++; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_hdr_incr() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_decr + * + * Purpose: Decrement reference count on shared heap header + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_decr(H5HF_t *hdr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_decr) + + /* Sanity check */ + HDassert(hdr); + + /* Decrement reference count on shared header */ + hdr->rc--; + +/* XXX: When "un-evictable" feature is finished, mark the header as + * evictable when the ref. count drops to zero. - QAK + */ +/* XXX: Take this call out after "un-evictable" flag is working */ + H5HF_cache_hdr_dest_real(hdr); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_hdr_decr() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_dirty + * + * Purpose: Mark heap header as dirty + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 27 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_dirty(hid_t dxpl_id, H5HF_t *hdr) +{ + H5HF_t *tmp_hdr; /* Temporary pointer to heap header */ + hbool_t is_protected; /* Whether the indirect block is protected */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_dirty) +#ifdef QAK +HDfprintf(stderr, "%s: Marking heap header as dirty\n", FUNC); +#endif /* QAK */ + + /* Sanity check */ + HDassert(hdr); + +/* XXX: When "un-evictable" feature is finished, just mark the header as dirty + * in the cache, instead of this protect -> unprotect kludge - QAK + */ + /* Protect the header */ + is_protected = hdr->cache_info.is_protected; + if(!is_protected) { +#ifdef QAK +HDfprintf(stderr, "%s: hdr->heap_addr = %a\n", FUNC, hdr->heap_addr); +#endif /* QAK */ + if(NULL == (tmp_hdr = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + HDassert(hdr == tmp_hdr); + } /* end if */ + + /* Set the dirty flags for the heap header */ + hdr->dirty = TRUE; + + /* Release the heap header (marked as dirty) */ + if(!is_protected) { + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_HDR, hdr->heap_addr, tmp_hdr, H5AC__DIRTIED_FLAG) < 0) + HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_dirty() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_hdr_extend_heap + * + * Purpose: Extend heap to cover more space + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Apr 10 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_extend_heap(H5HF_t *hdr, hsize_t new_size, hsize_t extra_free) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_extend_heap) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(new_size >= hdr->total_size); + + /* Set the total space in heap */ + hdr->total_size = new_size; + hdr->man_size = new_size; + + /* Increment the free space in direct blocks */ + hdr->total_man_free += extra_free; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_hdr_extend_heap() */ + |