mirror of
https://github.com/HDFGroup/hdf5.git
synced 2024-12-15 07:40:23 +08:00
25ec07450a
and replace it with new url for COPYING file. Fix 2 lines in java error test expected output file where messages include line numbers changed by reducing the copyright header by 2 lines.
4186 lines
158 KiB
C
4186 lines
158 KiB
C
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||
* Copyright by The HDF Group. *
|
||
* 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 COPYING file, which can be found at the root of the source code *
|
||
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
|
||
* If you do not have access to either file, you may request a copy from *
|
||
* help@hdfgroup.org. *
|
||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||
|
||
/*
|
||
* Programmer: Quincey Koziol <koziol@hdfgroup.org>
|
||
* Monday, May 1, 2006
|
||
*
|
||
* Purpose: Free space section routines for fractal heaps
|
||
*
|
||
*/
|
||
|
||
/****************/
|
||
/* Module Setup */
|
||
/****************/
|
||
|
||
#include "H5HFmodule.h" /* This source code file is part of the H5HF module */
|
||
|
||
|
||
/***********/
|
||
/* Headers */
|
||
/***********/
|
||
#include "H5private.h" /* Generic Functions */
|
||
#include "H5Eprivate.h" /* Error handling */
|
||
#include "H5HFpkg.h" /* Fractal heaps */
|
||
#include "H5MMprivate.h" /* Memory management */
|
||
#include "H5VMprivate.h" /* Vectors and arrays */
|
||
|
||
/****************/
|
||
/* Local Macros */
|
||
/****************/
|
||
|
||
/* Size of serialized indirect section information */
|
||
#define H5HF_SECT_INDIRECT_SERIAL_SIZE(h) ( \
|
||
(unsigned)(h)->heap_off_size /* Indirect block's offset in "heap space" */ \
|
||
+ (unsigned)2 /* Row */ \
|
||
+ (unsigned)2 /* Column */ \
|
||
+ (unsigned)2 /* # of entries */ \
|
||
)
|
||
|
||
|
||
/******************/
|
||
/* Local Typedefs */
|
||
/******************/
|
||
|
||
/* Typedef for "class private" information for sections */
|
||
typedef struct {
|
||
H5HF_hdr_t *hdr; /* Pointer to fractal heap header */
|
||
} H5HF_sect_private_t;
|
||
|
||
|
||
/********************/
|
||
/* Package Typedefs */
|
||
/********************/
|
||
|
||
|
||
/********************/
|
||
/* Local Prototypes */
|
||
/********************/
|
||
|
||
/* Shared routines */
|
||
static herr_t H5HF_sect_init_cls(H5FS_section_class_t *cls,
|
||
H5HF_hdr_t *hdr);
|
||
static herr_t H5HF_sect_term_cls(H5FS_section_class_t *cls);
|
||
static H5HF_free_section_t *H5HF_sect_node_new(unsigned sect_type,
|
||
haddr_t sect_addr, hsize_t sect_size, H5FS_section_state_t state);
|
||
static herr_t H5HF_sect_node_free(H5HF_free_section_t *sect,
|
||
H5HF_indirect_t *parent);
|
||
|
||
/* 'single' section routines */
|
||
static herr_t H5HF_sect_single_locate_parent(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
hbool_t refresh, H5HF_free_section_t *sect);
|
||
static herr_t H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect);
|
||
|
||
/* 'single' section callbacks */
|
||
static herr_t H5HF_sect_single_add(H5FS_section_info_t **sect, unsigned *flags,
|
||
void *udata);
|
||
static H5FS_section_info_t *H5HF_sect_single_deserialize(const H5FS_section_class_t *cls,
|
||
hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
|
||
unsigned *des_flags);
|
||
static htri_t H5HF_sect_single_can_merge(const H5FS_section_info_t *sect1,
|
||
const H5FS_section_info_t *sect2, void *udata);
|
||
static herr_t H5HF_sect_single_merge(H5FS_section_info_t **sect1,
|
||
H5FS_section_info_t *sect2, void *udata);
|
||
static htri_t H5HF_sect_single_can_shrink(const H5FS_section_info_t *sect,
|
||
void *udata);
|
||
static herr_t H5HF_sect_single_shrink(H5FS_section_info_t **_sect,
|
||
void *udata);
|
||
static herr_t H5HF_sect_single_valid(const H5FS_section_class_t *cls,
|
||
const H5FS_section_info_t *sect, hid_t dxpl_id);
|
||
|
||
/* 'row' section routines */
|
||
static H5HF_free_section_t *H5HF_sect_row_create(haddr_t sect_off,
|
||
hsize_t sect_size, hbool_t is_first, unsigned row, unsigned col,
|
||
unsigned nentries, H5HF_free_section_t *under_sect);
|
||
static herr_t H5HF_sect_row_first(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect);
|
||
static herr_t H5HF_sect_row_from_single(H5HF_hdr_t *hdr,
|
||
H5HF_free_section_t *sect, H5HF_direct_t *dblock);
|
||
static herr_t H5HF_sect_row_free_real(H5HF_free_section_t *sect);
|
||
|
||
/* 'row' section callbacks */
|
||
static herr_t H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *udata);
|
||
static herr_t H5HF_sect_row_term_cls(H5FS_section_class_t *cls);
|
||
static herr_t H5HF_sect_row_serialize(const H5FS_section_class_t *cls,
|
||
const H5FS_section_info_t *sect, uint8_t *buf);
|
||
static H5FS_section_info_t *H5HF_sect_row_deserialize(const H5FS_section_class_t *cls,
|
||
hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
|
||
unsigned *des_flags);
|
||
static htri_t H5HF_sect_row_can_merge(const H5FS_section_info_t *sect1,
|
||
const H5FS_section_info_t *sect2, void *udata);
|
||
static herr_t H5HF_sect_row_merge(H5FS_section_info_t **sect1,
|
||
H5FS_section_info_t *sect2, void *udata);
|
||
static htri_t H5HF_sect_row_can_shrink(const H5FS_section_info_t *sect,
|
||
void *udata);
|
||
static herr_t H5HF_sect_row_shrink(H5FS_section_info_t **sect,
|
||
void *udata);
|
||
static herr_t H5HF_sect_row_free(H5FS_section_info_t *sect);
|
||
static herr_t H5HF_sect_row_valid(const H5FS_section_class_t *cls,
|
||
const H5FS_section_info_t *sect, hid_t dxpl_id);
|
||
static herr_t H5HF_sect_row_debug(const H5FS_section_info_t *sect,
|
||
FILE *stream, int indent, int fwidth);
|
||
|
||
/* 'indirect' section routines */
|
||
static H5HF_free_section_t *H5HF_sect_indirect_new(H5HF_hdr_t *hdr,
|
||
haddr_t sect_off, hsize_t sect_size,
|
||
H5HF_indirect_t *iblock, hsize_t iblock_off,
|
||
unsigned row, unsigned col, unsigned nentries);
|
||
static herr_t H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect, hbool_t first_child, H5HF_free_section_t **first_row_sect,
|
||
unsigned space_flags, unsigned start_row, unsigned start_col,
|
||
unsigned end_row, unsigned end_col);
|
||
static H5HF_free_section_t *H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr,
|
||
H5HF_indirect_t *iblock, H5HF_free_section_t *row_sect);
|
||
static herr_t H5HF_sect_indirect_decr(H5HF_free_section_t *sect);
|
||
static herr_t H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect);
|
||
static herr_t H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock);
|
||
static herr_t H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *row_sect, hbool_t *alloc_from_start);
|
||
static herr_t H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect, unsigned child_entry);
|
||
static herr_t H5HF_sect_indirect_first(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect);
|
||
static hbool_t H5HF_sect_indirect_is_first(H5HF_free_section_t *sect);
|
||
static H5HF_indirect_t * H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect);
|
||
static hsize_t H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect);
|
||
static H5HF_free_section_t * H5HF_sect_indirect_top(H5HF_free_section_t *sect);
|
||
static herr_t H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect1, H5HF_free_section_t *sect2);
|
||
static herr_t H5HF_sect_indirect_build_parent(H5HF_hdr_t *hdr, H5HF_free_section_t *sect);
|
||
static herr_t H5HF_sect_indirect_shrink(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect);
|
||
static herr_t H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr,
|
||
const H5HF_free_section_t *sect, uint8_t *buf);
|
||
static H5FS_section_info_t *H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr,
|
||
hid_t dxpl_id, const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
|
||
unsigned *des_flags);
|
||
static herr_t H5HF_sect_indirect_free(H5HF_free_section_t *sect);
|
||
static herr_t H5HF_sect_indirect_valid(const H5HF_hdr_t *hdr,
|
||
const H5HF_free_section_t *sect);
|
||
static herr_t H5HF_sect_indirect_debug(const H5HF_free_section_t *sect,
|
||
FILE *stream, int indent, int fwidth);
|
||
|
||
/* 'indirect' section callbacks */
|
||
static herr_t H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *udata);
|
||
static herr_t H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls);
|
||
|
||
|
||
/*********************/
|
||
/* Package Variables */
|
||
/*********************/
|
||
|
||
/* Class info for "single" free space sections */
|
||
H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{
|
||
/* Class variables */
|
||
H5HF_FSPACE_SECT_SINGLE, /* Section type */
|
||
0, /* Extra serialized size */
|
||
H5FS_CLS_MERGE_SYM, /* Class flags */
|
||
NULL, /* Class private info */
|
||
|
||
/* Class methods */
|
||
NULL, /* Initialize section class */
|
||
NULL, /* Terminate section class */
|
||
|
||
/* Object methods */
|
||
H5HF_sect_single_add, /* Add section */
|
||
NULL, /* Serialize section */
|
||
H5HF_sect_single_deserialize, /* Deserialize section */
|
||
H5HF_sect_single_can_merge, /* Can sections merge? */
|
||
H5HF_sect_single_merge, /* Merge sections */
|
||
H5HF_sect_single_can_shrink, /* Can section shrink container?*/
|
||
H5HF_sect_single_shrink, /* Shrink container w/section */
|
||
H5HF_sect_single_free, /* Free section */
|
||
H5HF_sect_single_valid, /* Check validity of section */
|
||
NULL, /* Split section node for alignment */
|
||
NULL, /* Dump debugging for section */
|
||
}};
|
||
|
||
/* Class info for "first row" free space sections */
|
||
/* (Same as "normal" row sections, except they also act as a proxy for the
|
||
* underlying indirect section
|
||
*/
|
||
H5FS_section_class_t H5HF_FSPACE_SECT_CLS_FIRST_ROW[1] = {{
|
||
/* Class variables */
|
||
H5HF_FSPACE_SECT_FIRST_ROW, /* Section type */
|
||
0, /* Extra serialized size */
|
||
H5FS_CLS_MERGE_SYM, /* Class flags */
|
||
NULL, /* Class private info */
|
||
|
||
/* Class methods */
|
||
H5HF_sect_row_init_cls, /* Initialize section class */
|
||
H5HF_sect_row_term_cls, /* Terminate section class */
|
||
|
||
/* Object methods */
|
||
NULL, /* Add section */
|
||
H5HF_sect_row_serialize, /* Serialize section */
|
||
H5HF_sect_row_deserialize, /* Deserialize section */
|
||
H5HF_sect_row_can_merge, /* Can sections merge? */
|
||
H5HF_sect_row_merge, /* Merge sections */
|
||
H5HF_sect_row_can_shrink, /* Can section shrink container?*/
|
||
H5HF_sect_row_shrink, /* Shrink container w/section */
|
||
H5HF_sect_row_free, /* Free section */
|
||
H5HF_sect_row_valid, /* Check validity of section */
|
||
NULL, /* Split section node for alignment */
|
||
H5HF_sect_row_debug, /* Dump debugging for section */
|
||
}};
|
||
|
||
/* Class info for "normal row" free space sections */
|
||
H5FS_section_class_t H5HF_FSPACE_SECT_CLS_NORMAL_ROW[1] = {{
|
||
/* Class variables */
|
||
H5HF_FSPACE_SECT_NORMAL_ROW, /* Section type */
|
||
0, /* Extra serialized size */
|
||
H5FS_CLS_MERGE_SYM|H5FS_CLS_SEPAR_OBJ|H5FS_CLS_GHOST_OBJ, /* Class flags */
|
||
NULL, /* Class private info */
|
||
|
||
/* Class methods */
|
||
H5HF_sect_row_init_cls, /* Initialize section class */
|
||
H5HF_sect_row_term_cls, /* Terminate section class */
|
||
|
||
/* Object methods */
|
||
NULL, /* Add section */
|
||
NULL, /* Serialize section */
|
||
NULL, /* Deserialize section */
|
||
NULL, /* Can sections merge? */
|
||
NULL, /* Merge sections */
|
||
NULL, /* Can section shrink container?*/
|
||
NULL, /* Shrink container w/section */
|
||
H5HF_sect_row_free, /* Free section */
|
||
H5HF_sect_row_valid, /* Check validity of section */
|
||
NULL, /* Split section node for alignment */
|
||
H5HF_sect_row_debug, /* Dump debugging for section */
|
||
}};
|
||
|
||
/* Class info for "indirect" free space sections */
|
||
/* (No object callbacks necessary - objects of this class should never be in
|
||
* section manager)
|
||
*/
|
||
H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{
|
||
/* Class variables */
|
||
H5HF_FSPACE_SECT_INDIRECT, /* Section type */
|
||
0, /* Extra serialized size */
|
||
H5FS_CLS_MERGE_SYM|H5FS_CLS_GHOST_OBJ, /* Class flags */
|
||
NULL, /* Class private info */
|
||
|
||
/* Class methods */
|
||
H5HF_sect_indirect_init_cls, /* Initialize section class */
|
||
H5HF_sect_indirect_term_cls, /* Terminate section class */
|
||
|
||
/* Object methods */
|
||
NULL, /* Add section */
|
||
NULL, /* Serialize section */
|
||
NULL, /* Deserialize section */
|
||
NULL, /* Can sections merge? */
|
||
NULL, /* Merge sections */
|
||
NULL, /* Can section shrink container?*/
|
||
NULL, /* Shrink container w/section */
|
||
NULL, /* Free section */
|
||
NULL, /* Check validity of section */
|
||
NULL, /* Split section node for alignment */
|
||
NULL, /* Dump debugging for section */
|
||
}};
|
||
|
||
/* Declare a free list to manage the H5HF_free_section_t struct */
|
||
H5FL_DEFINE(H5HF_free_section_t);
|
||
|
||
|
||
/*****************************/
|
||
/* Library Private Variables */
|
||
/*****************************/
|
||
|
||
|
||
/*******************/
|
||
/* Local Variables */
|
||
/*******************/
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_init_cls
|
||
*
|
||
* Purpose: Initialize the common class structure
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Tuesday, July 25, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_init_cls(H5FS_section_class_t *cls, H5HF_hdr_t *hdr)
|
||
{
|
||
H5HF_sect_private_t *cls_prvt; /* Pointer to class private info */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(cls);
|
||
HDassert(!cls->cls_private);
|
||
|
||
/* Allocate & initialize the class-private (i.e. private shared) information
|
||
* for this type of section
|
||
*/
|
||
if(NULL == (cls_prvt = (H5HF_sect_private_t *)H5MM_malloc(sizeof(H5HF_sect_private_t))))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
|
||
cls_prvt->hdr = hdr;
|
||
cls->cls_private = cls_prvt;
|
||
|
||
/* Increment reference count on heap header */
|
||
if(H5HF_hdr_incr(hdr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_init_cls() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_term_cls
|
||
*
|
||
* Purpose: Terminate the common class structure
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Tuesday, July 25, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_term_cls(H5FS_section_class_t *cls)
|
||
{
|
||
H5HF_sect_private_t *cls_prvt; /* Pointer to class private info */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(cls);
|
||
|
||
/* Get pointer to class private info */
|
||
cls_prvt = (H5HF_sect_private_t *)cls->cls_private;
|
||
|
||
/* Decrement reference count on heap header */
|
||
if(H5HF_hdr_decr(cls_prvt->hdr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared heap header")
|
||
|
||
/* Free the class private information */
|
||
cls->cls_private = H5MM_xfree(cls_prvt);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_term_cls() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_node_new
|
||
*
|
||
* Purpose: Allocate a free space section node of a particular type
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Saturday, May 13, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5HF_free_section_t *
|
||
H5HF_sect_node_new(unsigned sect_type, haddr_t sect_addr, hsize_t sect_size,
|
||
H5FS_section_state_t sect_state)
|
||
{
|
||
H5HF_free_section_t *new_sect; /* New section */
|
||
H5HF_free_section_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(H5F_addr_defined(sect_addr));
|
||
|
||
/* Create free list section node */
|
||
if(NULL == (new_sect = H5FL_MALLOC(H5HF_free_section_t)))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section")
|
||
|
||
/* Set the information passed in */
|
||
new_sect->sect_info.addr = sect_addr;
|
||
new_sect->sect_info.size = sect_size;
|
||
|
||
/* Set the section's class & state */
|
||
new_sect->sect_info.type = sect_type;
|
||
new_sect->sect_info.state = sect_state;
|
||
|
||
/* Set return value */
|
||
ret_value = new_sect;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_node_new() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_node_free
|
||
*
|
||
* Purpose: Free a section node
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Wednesday, May 17, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_node_free(H5HF_free_section_t *sect, H5HF_indirect_t *iblock)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
HDassert(sect);
|
||
|
||
/* Release indirect block, if there was one */
|
||
if(iblock)
|
||
if(H5HF_iblock_decr(iblock) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block")
|
||
|
||
/* Release the section */
|
||
sect = H5FL_FREE(H5HF_free_section_t, sect);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_node_free() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_new
|
||
*
|
||
* Purpose: Create a new 'single' section and return it to the caller
|
||
*
|
||
* Return: Pointer to new section on success/NULL on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* May 30 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
H5HF_free_section_t *
|
||
H5HF_sect_single_new(hsize_t sect_off, size_t sect_size,
|
||
H5HF_indirect_t *parent, unsigned par_entry)
|
||
{
|
||
H5HF_free_section_t *sect = NULL; /* 'Single' free space section to add */
|
||
H5HF_free_section_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(sect_size);
|
||
|
||
/* Create free space section node */
|
||
if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_off, (hsize_t)sect_size, H5FS_SECT_LIVE)))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for single section")
|
||
|
||
/* Set the 'single' specific fields */
|
||
sect->u.single.parent = parent;
|
||
if(sect->u.single.parent) {
|
||
if(H5HF_iblock_incr(sect->u.single.parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
|
||
} /* end if */
|
||
sect->u.single.par_entry = par_entry;
|
||
|
||
/* Set return value */
|
||
ret_value = sect;
|
||
|
||
done:
|
||
if(!ret_value && sect) {
|
||
/* Release the section */
|
||
sect = H5FL_FREE(H5HF_free_section_t, sect);
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_single_new() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_locate_parent
|
||
*
|
||
* Purpose: Locate the parent indirect block for a single section
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* October 24 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_single_locate_parent(H5HF_hdr_t *hdr, hid_t dxpl_id, hbool_t refresh,
|
||
H5HF_free_section_t *sect)
|
||
{
|
||
H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */
|
||
unsigned sec_entry; /* Entry within section indirect block */
|
||
hbool_t did_protect; /* Whether we protected the indirect block or not */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(hdr->man_dtable.curr_root_rows > 0);
|
||
HDassert(sect);
|
||
|
||
/* Look up indirect block containing direct blocks for range */
|
||
if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, &sec_entry, &did_protect, H5AC__READ_ONLY_FLAG) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
|
||
|
||
/* Increment reference count on indirect block that free section is in */
|
||
if(H5HF_iblock_incr(sec_iblock) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
|
||
|
||
/* Check for refreshing existing parent information */
|
||
if(refresh) {
|
||
if(sect->u.single.parent) {
|
||
/* Release hold on previous parent indirect block */
|
||
if(H5HF_iblock_decr(sect->u.single.parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on section's indirect block")
|
||
} /* end if */
|
||
} /* end if */
|
||
|
||
/* Set the information for the section */
|
||
sect->u.single.parent = sec_iblock;
|
||
sect->u.single.par_entry = sec_entry;
|
||
|
||
/* Unlock indirect block */
|
||
if(H5HF_man_iblock_unprotect(sec_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
|
||
sec_iblock = NULL;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_single_locate_parent() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_revive
|
||
*
|
||
* Purpose: Update the memory information for a 'single' free section
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* May 8 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
|
||
|
||
/* Check for root direct block */
|
||
if(hdr->man_dtable.curr_root_rows == 0) {
|
||
/* Set the information for the section */
|
||
HDassert(H5F_addr_defined(hdr->man_dtable.table_addr));
|
||
sect->u.single.parent = NULL;
|
||
sect->u.single.par_entry = 0;
|
||
} /* end if */
|
||
else {
|
||
/* Look up indirect block information for section */
|
||
if(H5HF_sect_single_locate_parent(hdr, dxpl_id, FALSE, sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't get section's parent info")
|
||
} /* end else */
|
||
|
||
/* Section is "live" now */
|
||
sect->sect_info.state = H5FS_SECT_LIVE;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_single_revive() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_dblock_info
|
||
*
|
||
* Purpose: Retrieve the direct block information for a single section
|
||
*
|
||
* Return: SUCCEED/FAIL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@hdfgroup.org
|
||
* October 24 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_sect_single_dblock_info(H5HF_hdr_t *hdr,
|
||
H5HF_free_section_t *sect, haddr_t *dblock_addr, size_t *dblock_size)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOERR
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
|
||
HDassert(dblock_addr);
|
||
HDassert(dblock_size);
|
||
|
||
/* Check for root direct block */
|
||
if(hdr->man_dtable.curr_root_rows == 0) {
|
||
/* Retrieve direct block info from heap header */
|
||
HDassert(H5F_addr_defined(hdr->man_dtable.table_addr));
|
||
*dblock_addr = hdr->man_dtable.table_addr;
|
||
*dblock_size = hdr->man_dtable.cparam.start_block_size;
|
||
} /* end if */
|
||
else {
|
||
/* Retrieve direct block info from parent indirect block */
|
||
*dblock_addr = sect->u.single.parent->ents[sect->u.single.par_entry].addr;
|
||
*dblock_size = hdr->man_dtable.row_block_size[sect->u.single.par_entry / hdr->man_dtable.cparam.width];
|
||
} /* end else */
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* end H5HF_sect_single_dblock_info() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_reduce
|
||
*
|
||
* Purpose: Reduce the size of a single section (possibly freeing it)
|
||
* and re-add it back to the free space manager for the heap
|
||
* (if it hasn't been freed)
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* May 31 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect, size_t amt)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
|
||
|
||
/* Check for eliminating the section */
|
||
if(sect->sect_info.size == amt) {
|
||
/* Free single section */
|
||
if(H5HF_sect_single_free((H5FS_section_info_t *)sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free single section node")
|
||
} /* end if */
|
||
else {
|
||
/* Adjust information for section */
|
||
sect->sect_info.addr += amt;
|
||
sect->sect_info.size -= amt;
|
||
|
||
/* Re-insert section node into heap's free space */
|
||
if(H5HF_space_add(hdr, dxpl_id, sect, 0) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add single section to free space manager")
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_single_reduce() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_full_dblock
|
||
*
|
||
* Purpose: Checks if a single section covers the entire direct block
|
||
* that it resides in, and converts it to a row section if so
|
||
*
|
||
* Note: Does not convert a single section to a row section if the
|
||
* single section is for a root direct block
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 27, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_single_full_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect)
|
||
{
|
||
haddr_t dblock_addr; /* Section's direct block's address */
|
||
size_t dblock_size; /* Section's direct block's size */
|
||
size_t dblock_overhead; /* Direct block's overhead */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
|
||
HDassert(hdr);
|
||
|
||
/* Retrieve direct block address from section */
|
||
if(H5HF_sect_single_dblock_info(hdr, sect, &dblock_addr, &dblock_size) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information")
|
||
|
||
/* Check for section occupying entire direct block */
|
||
/* (and not the root direct block) */
|
||
dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
|
||
if((dblock_size - dblock_overhead) == sect->sect_info.size &&
|
||
hdr->man_dtable.curr_root_rows > 0) {
|
||
H5HF_direct_t *dblock; /* Pointer to direct block for section */
|
||
|
||
if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC__NO_FLAGS_SET)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
|
||
HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr));
|
||
|
||
/* Convert 'single' section into 'row' section */
|
||
if(H5HF_sect_row_from_single(hdr, sect, dblock) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into row section")
|
||
|
||
/* Destroy direct block */
|
||
if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
|
||
dblock = NULL;
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_single_full_dblock() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_add
|
||
*
|
||
* Purpose: Perform any actions on section as it is added to free space
|
||
* manager
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 27, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_single_add(H5FS_section_info_t **_sect, unsigned *flags, void *_udata)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Don't need to check section if we are deserializing, because it should
|
||
* have already been checked when it was first added
|
||
*/
|
||
if(!(*flags & H5FS_ADD_DESERIALIZING)) {
|
||
H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
|
||
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
|
||
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
|
||
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
|
||
|
||
/* Sanity check */
|
||
HDassert(sect);
|
||
HDassert(hdr);
|
||
|
||
/* Check if single section covers entire direct block it's in */
|
||
/* (converts to row section possibly) */
|
||
if(H5HF_sect_single_full_dblock(hdr, dxpl_id, (*sect)) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't check/convert single section")
|
||
|
||
/* Set the "returned space" flag if the single section was changed
|
||
* into a row section, so the "merging & shrinking" algorithm
|
||
* gets executed in the free space manager
|
||
*/
|
||
if((*sect)->sect_info.type != H5HF_FSPACE_SECT_SINGLE)
|
||
*flags |= H5FS_ADD_RETURNED_SPACE;
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_single_add() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_deserialize
|
||
*
|
||
* Purpose: Deserialize a buffer into a "live" single section
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, May 1, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5FS_section_info_t *
|
||
H5HF_sect_single_deserialize(const H5FS_section_class_t H5_ATTR_UNUSED *cls,
|
||
hid_t H5_ATTR_UNUSED dxpl_id, const uint8_t H5_ATTR_UNUSED *buf, haddr_t sect_addr,
|
||
hsize_t sect_size, unsigned H5_ATTR_UNUSED *des_flags)
|
||
{
|
||
H5HF_free_section_t *new_sect; /* New section */
|
||
H5FS_section_info_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(H5F_addr_defined(sect_addr));
|
||
HDassert(sect_size);
|
||
|
||
/* Create free list section node */
|
||
if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_addr, sect_size, H5FS_SECT_SERIALIZED)))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section")
|
||
|
||
/* Set return value */
|
||
ret_value = (H5FS_section_info_t *)new_sect;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_single_deserialize() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_can_merge
|
||
*
|
||
* Purpose: Can two sections of this type merge?
|
||
*
|
||
* Note: Second section must be "after" first section
|
||
*
|
||
* Return: Success: non-negative (TRUE/FALSE)
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Wednesday, May 17, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static htri_t
|
||
H5HF_sect_single_can_merge(const H5FS_section_info_t *_sect1,
|
||
const H5FS_section_info_t *_sect2, void H5_ATTR_UNUSED *_udata)
|
||
{
|
||
const H5HF_free_section_t *sect1 = (const H5HF_free_section_t *)_sect1; /* Fractal heap free section */
|
||
const H5HF_free_section_t *sect2 = (const H5HF_free_section_t *)_sect2; /* Fractal heap free section */
|
||
htri_t ret_value = FALSE; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect1);
|
||
HDassert(sect2);
|
||
HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */
|
||
HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
|
||
|
||
/* Check if second section adjoins first section */
|
||
/* (This can only occur within a direct block, due to the direct block
|
||
* overhead at the beginning of a block, so no need to check if sections
|
||
* are actually within the same direct block)
|
||
*/
|
||
if(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr))
|
||
HGOTO_DONE(TRUE)
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_single_can_merge() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_merge
|
||
*
|
||
* Purpose: Merge two sections of this type
|
||
*
|
||
* Note: Second section always merges into first node
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Wednesday, May 17, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_single_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2,
|
||
void *_udata)
|
||
{
|
||
H5HF_free_section_t **sect1 = (H5HF_free_section_t **)_sect1; /* Fractal heap free section */
|
||
H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
|
||
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
|
||
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
|
||
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect1);
|
||
HDassert((*sect1)->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
|
||
HDassert(sect2);
|
||
HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
|
||
HDassert(H5F_addr_eq((*sect1)->sect_info.addr + (*sect1)->sect_info.size, sect2->sect_info.addr));
|
||
|
||
/* Add second section's size to first section */
|
||
(*sect1)->sect_info.size += sect2->sect_info.size;
|
||
|
||
/* Get rid of second section */
|
||
if(H5HF_sect_single_free((H5FS_section_info_t *)sect2) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
|
||
|
||
/* Check to see if we should revive first section */
|
||
if((*sect1)->sect_info.state != H5FS_SECT_LIVE)
|
||
if(H5HF_sect_single_revive(hdr, dxpl_id, (*sect1)) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
|
||
|
||
/* Check if single section covers entire direct block it's in */
|
||
/* (converts to row section possibly) */
|
||
if(H5HF_sect_single_full_dblock(hdr, dxpl_id, (*sect1)) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't check/convert single section")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_single_merge() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_can_shrink
|
||
*
|
||
* Purpose: Can this section shrink the container?
|
||
*
|
||
* Note: This isn't actually shrinking the heap (since that's already
|
||
* been done) as much as it's cleaning up _after_ the heap
|
||
* shrink.
|
||
*
|
||
* Return: Success: non-negative (TRUE/FALSE)
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, June 5, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static htri_t
|
||
H5HF_sect_single_can_shrink(const H5FS_section_info_t *_sect, void *_udata)
|
||
{
|
||
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */
|
||
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
|
||
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
|
||
htri_t ret_value = FALSE; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect);
|
||
|
||
/* Check for section occupying entire root direct block */
|
||
/* (We shouldn't ever have a single section that occupies an entire
|
||
* direct block, unless it's in the root direct block (because it
|
||
* would have been converted into a row section, if there was an
|
||
* indirect block that covered it)
|
||
*/
|
||
if(hdr->man_dtable.curr_root_rows == 0) {
|
||
size_t dblock_size; /* Section's direct block's size */
|
||
size_t dblock_overhead; /* Direct block's overhead */
|
||
|
||
dblock_size = hdr->man_dtable.cparam.start_block_size;
|
||
dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
|
||
if((dblock_size - dblock_overhead) == sect->sect_info.size)
|
||
HGOTO_DONE(TRUE)
|
||
} /* end if */
|
||
else {
|
||
/* We shouldn't have a situation where the 'next block' iterator
|
||
* is moved before a direct block that still has objects within it.
|
||
*/
|
||
HDassert(hdr->man_iter_off > sect->sect_info.addr);
|
||
HGOTO_DONE(FALSE)
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_single_can_shrink() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_shrink
|
||
*
|
||
* Purpose: Shrink container with section
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 17, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void H5_ATTR_UNUSED *_udata)
|
||
{
|
||
H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
|
||
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
|
||
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
|
||
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
|
||
H5HF_direct_t *dblock; /* Pointer to direct block for section */
|
||
haddr_t dblock_addr; /* Section's direct block's address */
|
||
size_t dblock_size; /* Section's direct block's size */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect);
|
||
HDassert(*sect);
|
||
HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
|
||
|
||
/* Check to see if we should revive section */
|
||
if((*sect)->sect_info.state != H5FS_SECT_LIVE)
|
||
if(H5HF_sect_single_revive(hdr, dxpl_id, (*sect)) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
|
||
|
||
/* Retrieve direct block address from section */
|
||
if(H5HF_sect_single_dblock_info(hdr, (*sect), &dblock_addr, &dblock_size) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "can't retrieve direct block information")
|
||
|
||
/* Protect the direct block for the section */
|
||
/* (should be a root direct block) */
|
||
HDassert(dblock_addr == hdr->man_dtable.table_addr);
|
||
if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr,
|
||
dblock_size, (*sect)->u.single.parent, (*sect)->u.single.par_entry, H5AC__NO_FLAGS_SET)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
|
||
HDassert(H5F_addr_eq(dblock->block_off + dblock_size, (*sect)->sect_info.addr + (*sect)->sect_info.size));
|
||
|
||
/* Destroy direct block */
|
||
if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
|
||
dblock = NULL;
|
||
|
||
/* Get rid of section */
|
||
if(H5HF_sect_single_free((H5FS_section_info_t *)*sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
|
||
|
||
/* Indicate that the section has been released */
|
||
*sect = NULL;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_single_shrink() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_free
|
||
*
|
||
* Purpose: Free a 'single' section node
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Wednesday, May 17, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_sect_single_free(H5FS_section_info_t *_sect)
|
||
{
|
||
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
|
||
H5HF_indirect_t *parent = NULL; /* Parent indirect block for section */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect);
|
||
|
||
/* Check for live reference to an indirect block */
|
||
if(sect->sect_info.state == H5FS_SECT_LIVE) {
|
||
/* Get parent indirect block, if there was one */
|
||
if(sect->u.single.parent)
|
||
parent = sect->u.single.parent;
|
||
} /* end if */
|
||
|
||
/* Release the section */
|
||
if(H5HF_sect_node_free(sect, parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_single_free() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_single_valid
|
||
*
|
||
* Purpose: Check the validity of a section
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Friday, July 21, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_single_valid(const H5FS_section_class_t H5_ATTR_UNUSED *cls, const H5FS_section_info_t *_sect, hid_t dxpl_id)
|
||
{
|
||
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Pointer to section to check */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect);
|
||
|
||
if(sect->sect_info.state == H5FS_SECT_LIVE) {
|
||
/* Check if this section is not in a direct block that is the root direct block */
|
||
/* (not enough information to check on a single section in a root direct block) */
|
||
if(sect->u.single.parent != NULL) {
|
||
H5HF_indirect_t *iblock; /* Indirect block that section's direct block resides in */
|
||
haddr_t dblock_addr; /* Direct block address */
|
||
size_t dblock_size; /* Direct block size */
|
||
size_t dblock_overhead; /* Direct block's overhead */
|
||
unsigned dblock_status = 0; /* Direct block's status in the metadata cache */
|
||
herr_t status; /* Generic status value */
|
||
|
||
/* Sanity check settings for section's direct block's parent */
|
||
iblock = sect->u.single.parent;
|
||
HDassert(H5F_addr_defined(iblock->ents[sect->u.single.par_entry].addr));
|
||
|
||
/* Retrieve direct block address from section */
|
||
/* (Casting away const OK - QAK) */
|
||
status = H5HF_sect_single_dblock_info(iblock->hdr, (H5HF_free_section_t *)sect, &dblock_addr, &dblock_size);
|
||
HDassert(status >= 0);
|
||
HDassert(H5F_addr_eq(iblock->ents[sect->u.single.par_entry].addr, dblock_addr));
|
||
HDassert(dblock_size > 0);
|
||
|
||
/* Check if the section is actually within the heap */
|
||
HDassert(sect->sect_info.addr < iblock->hdr->man_iter_off);
|
||
|
||
/* Check that the direct block has been merged correctly */
|
||
dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(iblock->hdr);
|
||
HDassert((sect->sect_info.size + dblock_overhead) < dblock_size);
|
||
|
||
/* Check the direct block's status in the metadata cache */
|
||
status = H5AC_get_entry_status(iblock->hdr->f, dblock_addr, &dblock_status);
|
||
HDassert(status >= 0);
|
||
|
||
/* If the direct block for the section isn't already protected,
|
||
* protect it here in order to check single section's sanity
|
||
* against it.
|
||
*/
|
||
if(!(dblock_status & H5AC_ES__IS_PROTECTED)) {
|
||
H5HF_direct_t *dblock; /* Direct block for section */
|
||
|
||
/* Protect the direct block for the section */
|
||
dblock = H5HF_man_dblock_protect(iblock->hdr, dxpl_id, dblock_addr, dblock_size, iblock, sect->u.single.par_entry, H5AC__READ_ONLY_FLAG);
|
||
HDassert(dblock);
|
||
|
||
/* Sanity check settings for section */
|
||
HDassert(dblock_size == dblock->size);
|
||
HDassert(dblock->size > sect->sect_info.size);
|
||
HDassert(H5F_addr_lt(dblock->block_off, sect->sect_info.addr));
|
||
HDassert(H5F_addr_ge((dblock->block_off + dblock->size),
|
||
(sect->sect_info.addr + sect->sect_info.size)));
|
||
|
||
/* Release direct block */
|
||
status = H5AC_unprotect(iblock->hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET);
|
||
HDassert(status >= 0);
|
||
} /* end if */
|
||
} /* end if */
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* H5HF_sect_single_valid() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_create
|
||
*
|
||
* Purpose: Create a new 'row' section
|
||
*
|
||
* Return: Success: pointer to new section
|
||
*
|
||
* Failure: NULL
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5HF_free_section_t *
|
||
H5HF_sect_row_create(haddr_t sect_off, hsize_t sect_size, hbool_t is_first,
|
||
unsigned row, unsigned col, unsigned nentries, H5HF_free_section_t *under_sect)
|
||
{
|
||
H5HF_free_section_t *sect = NULL; /* 'Row' section created */
|
||
H5HF_free_section_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect_size);
|
||
HDassert(nentries);
|
||
HDassert(under_sect);
|
||
|
||
/* Create 'row' free space section node */
|
||
/* ("inherits" underlying indirect section's state) */
|
||
if(NULL == (sect = H5HF_sect_node_new((unsigned)(is_first ? H5HF_FSPACE_SECT_FIRST_ROW : H5HF_FSPACE_SECT_NORMAL_ROW), sect_off, sect_size, under_sect->sect_info.state)))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for row section")
|
||
|
||
/* Set the 'row' specific fields */
|
||
sect->u.row.under = under_sect;
|
||
sect->u.row.row = row;
|
||
sect->u.row.col = col;
|
||
sect->u.row.num_entries = nentries;
|
||
sect->u.row.checked_out = FALSE;
|
||
|
||
/* Set return value */
|
||
ret_value = sect;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_create() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_from_single
|
||
*
|
||
* Purpose: Convert a 'single' section into a 'row' section
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
|
||
H5HF_direct_t *dblock)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(dblock);
|
||
|
||
/* Convert 'single' section information to 'row' section info */
|
||
sect->sect_info.addr = dblock->block_off;
|
||
sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
|
||
sect->u.row.row = dblock->par_entry / hdr->man_dtable.cparam.width;
|
||
sect->u.row.col = dblock->par_entry % hdr->man_dtable.cparam.width;
|
||
sect->u.row.num_entries = 1;
|
||
sect->u.row.checked_out = FALSE;
|
||
|
||
/* Create indirect section that underlies the row section */
|
||
if(NULL == (sect->u.row.under = H5HF_sect_indirect_for_row(hdr, dblock->parent, sect)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "serializing row section not supported yet")
|
||
|
||
/* Release single section's hold on underlying indirect block */
|
||
if(H5HF_iblock_decr(dblock->parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_row_from_single() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_revive
|
||
*
|
||
* Purpose: Update the memory information for a 'row' free section
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_sect_row_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->u.row.under);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
|
||
|
||
/* Pass along "revive" request to underlying indirect section */
|
||
/* (which will mark this section as "live") */
|
||
if(H5HF_sect_indirect_revive_row(hdr, dxpl_id, sect->u.row.under) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_row_revive() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_reduce
|
||
*
|
||
* Purpose: Reduce the size of a row section (possibly freeing it)
|
||
* and re-add it back to the free space manager for the heap
|
||
* (if it hasn't been freed)
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_sect_row_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect,
|
||
unsigned *entry_p)
|
||
{
|
||
hbool_t alloc_from_start; /* Whether to allocate from the end of the row */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
|
||
sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
|
||
HDassert(entry_p);
|
||
|
||
/* Mark the row as checked out from the free space manager */
|
||
HDassert(sect->u.row.checked_out == FALSE);
|
||
sect->u.row.checked_out = TRUE;
|
||
|
||
/* Forward row section to indirect routines, to handle reducing underlying indirect section */
|
||
alloc_from_start = FALSE;
|
||
if(H5HF_sect_indirect_reduce_row(hdr, dxpl_id, sect, &alloc_from_start) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce underlying section")
|
||
|
||
/* Determine entry allocated */
|
||
*entry_p = (sect->u.row.row * hdr->man_dtable.cparam.width) + sect->u.row.col;
|
||
if(!alloc_from_start)
|
||
*entry_p += (sect->u.row.num_entries - 1);
|
||
|
||
/* Check for eliminating the section */
|
||
if(sect->u.row.num_entries == 1) {
|
||
/* Free row section */
|
||
if(H5HF_sect_row_free((H5FS_section_info_t *)sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section node")
|
||
} /* end if */
|
||
else {
|
||
/* Check whether to allocate from the beginning or end of the row */
|
||
if(alloc_from_start) {
|
||
/* Adjust section start */
|
||
sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.row.row];
|
||
sect->u.row.col++;
|
||
} /* end else */
|
||
|
||
/* Adjust span of blocks covered */
|
||
sect->u.row.num_entries--;
|
||
|
||
/* Check the row back in */
|
||
sect->u.row.checked_out = FALSE;
|
||
|
||
/* Add 'row' section back to free space list */
|
||
if(H5HF_space_add(hdr, dxpl_id, sect, 0) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add indirect section to free space manager")
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_row_reduce() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_first
|
||
*
|
||
* Purpose: Make row a "first row"
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 10 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_first(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Sanity check */
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
|
||
|
||
/* If the row is already checked out from the free space manager, just
|
||
* change it's class directly and the free space manager will adjust when
|
||
* it is checked back in.
|
||
*/
|
||
if(sect->u.row.checked_out)
|
||
sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
|
||
else {
|
||
/* Change row section to be the "first row" */
|
||
if(H5HF_space_sect_change_class(hdr, dxpl_id, sect, H5HF_FSPACE_SECT_FIRST_ROW) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row")
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_row_first() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_get_iblock
|
||
*
|
||
* Purpose: Retrieve the indirect block for a row section
|
||
*
|
||
* Return: Pointer to indirect block on success/NULL on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 9 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
H5HF_indirect_t *
|
||
H5HF_sect_row_get_iblock(H5HF_free_section_t *sect)
|
||
{
|
||
H5HF_indirect_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW ||
|
||
sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
|
||
|
||
ret_value = H5HF_sect_indirect_get_iblock(sect->u.row.under);
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_row_get_iblock() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_init_cls
|
||
*
|
||
* Purpose: Initialize the "row" section class structure
|
||
*
|
||
* Note: Since 'row' sections are proxies for 'indirect' sections, this
|
||
* routine forwards call to 'indirect' class initialization
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_init_cls(H5FS_section_class_t *cls, void *_udata)
|
||
{
|
||
H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata; /* Fractal heap header */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(cls);
|
||
HDassert(hdr);
|
||
|
||
/* Call common class initialization */
|
||
if(H5HF_sect_init_cls(cls, hdr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize common section class")
|
||
|
||
/* First row sections actually are proxies for indirection sections on disk */
|
||
if(cls->type == H5HF_FSPACE_SECT_FIRST_ROW)
|
||
cls->serial_size = H5HF_SECT_INDIRECT_SERIAL_SIZE(hdr);
|
||
else
|
||
cls->serial_size = 0;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_init_cls() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_term_cls
|
||
*
|
||
* Purpose: Terminate the "row" section class structure
|
||
*
|
||
* Note: Since 'row' sections are proxies for 'indirect' sections, this
|
||
* routine forwards call to 'indirect' class termination
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_term_cls(H5FS_section_class_t *cls)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(cls);
|
||
|
||
/* Call common class termination */
|
||
if(H5HF_sect_term_cls(cls) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate common section class")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_term_cls() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_serialize
|
||
*
|
||
* Purpose: Serialize a "live" row section into a buffer
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_serialize(const H5FS_section_class_t *cls,
|
||
const H5FS_section_info_t *_sect, uint8_t *buf)
|
||
{
|
||
H5HF_hdr_t *hdr; /* Fractal heap header */
|
||
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect;
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(cls);
|
||
HDassert(buf);
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
|
||
HDassert(sect->sect_info.addr == sect->u.row.under->sect_info.addr);
|
||
|
||
/* Forward to indirect routine to serialize underlying section */
|
||
hdr = ((H5HF_sect_private_t *)(cls->cls_private))->hdr;
|
||
if(H5HF_sect_indirect_serialize(hdr, sect->u.row.under, buf) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize row section's underlying indirect section")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_serialize() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_deserialize
|
||
*
|
||
* Purpose: Deserialize a buffer into a "live" row section
|
||
*
|
||
* Note: Actually this routine just forwards to the 'indirect'
|
||
* deserialize routine, which creates the row section.
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Saturday, July 15, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5FS_section_info_t *
|
||
H5HF_sect_row_deserialize(const H5FS_section_class_t *cls, hid_t dxpl_id,
|
||
const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
|
||
unsigned *des_flags)
|
||
{
|
||
H5HF_hdr_t *hdr; /* Fractal heap header */
|
||
H5FS_section_info_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(cls);
|
||
HDassert(buf);
|
||
HDassert(H5F_addr_defined(sect_addr));
|
||
HDassert(sect_size);
|
||
|
||
/* Forward to indirect routine to deserialize underlying section */
|
||
hdr = ((H5HF_sect_private_t *)(cls->cls_private))->hdr;
|
||
if(NULL == (ret_value = H5HF_sect_indirect_deserialize(hdr, dxpl_id, buf,
|
||
sect_addr, sect_size, des_flags)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't deserialize row section's underlying indirect section")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_deserialize() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_can_merge
|
||
*
|
||
* Purpose: Can two sections of this type merge?
|
||
*
|
||
* Note: Second section must be "after" first section
|
||
*
|
||
* Return: Success: non-negative (TRUE/FALSE)
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static htri_t
|
||
H5HF_sect_row_can_merge(const H5FS_section_info_t *_sect1,
|
||
const H5FS_section_info_t *_sect2, void H5_ATTR_UNUSED *_udata)
|
||
{
|
||
const H5HF_free_section_t *sect1 = (const H5HF_free_section_t *)_sect1; /* Fractal heap free section */
|
||
const H5HF_free_section_t *sect2 = (const H5HF_free_section_t *)_sect2; /* Fractal heap free section */
|
||
H5HF_free_section_t *top_indir_sect1, *top_indir_sect2; /* Top indirect section for each row */
|
||
htri_t ret_value = FALSE; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect1);
|
||
HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
|
||
HDassert(sect2);
|
||
HDassert(sect1->sect_info.type == sect2->sect_info.type); /* Checks "MERGE_SYM" flag */
|
||
HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
|
||
|
||
/* Get the top indirect section underlying each row */
|
||
top_indir_sect1 = H5HF_sect_indirect_top(sect1->u.row.under);
|
||
HDassert(top_indir_sect1);
|
||
top_indir_sect2 = H5HF_sect_indirect_top(sect2->u.row.under);
|
||
HDassert(top_indir_sect2);
|
||
|
||
/* Check if second section shares the same underlying indirect block as
|
||
* the first section, but doesn't already have same underlying indirect
|
||
* section.
|
||
*/
|
||
if(top_indir_sect1 != top_indir_sect2) {
|
||
if(H5HF_sect_indirect_iblock_off(top_indir_sect1) == H5HF_sect_indirect_iblock_off(top_indir_sect2)) {
|
||
/* Check if second section adjoins first section */
|
||
if(H5F_addr_eq((top_indir_sect1->sect_info.addr + top_indir_sect1->u.indirect.span_size), top_indir_sect2->sect_info.addr))
|
||
HGOTO_DONE(TRUE)
|
||
} /* end if */
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_can_merge() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_merge
|
||
*
|
||
* Purpose: Merge two sections of this type
|
||
*
|
||
* Note: Second section always merges into first node
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_merge(H5FS_section_info_t **_sect1, H5FS_section_info_t *_sect2,
|
||
void *_udata)
|
||
{
|
||
H5HF_free_section_t **sect1 = (H5HF_free_section_t **)_sect1; /* Fractal heap free section */
|
||
H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
|
||
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
|
||
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
|
||
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect1);
|
||
HDassert((*sect1)->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
|
||
HDassert(sect2);
|
||
HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
|
||
|
||
/* Check if second section is past end of "next block" iterator */
|
||
if(sect2->sect_info.addr >= hdr->man_iter_off) {
|
||
H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */
|
||
|
||
/* Get the top indirect section underlying second row section */
|
||
top_indir_sect = H5HF_sect_indirect_top(sect2->u.row.under);
|
||
|
||
/* Shrink away underlying indirect section */
|
||
if(H5HF_sect_indirect_shrink(hdr, dxpl_id, top_indir_sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section")
|
||
} /* end if */
|
||
else {
|
||
/* Check to see if we should revive first section */
|
||
if((*sect1)->sect_info.state != H5FS_SECT_LIVE)
|
||
if(H5HF_sect_row_revive(hdr, dxpl_id, (*sect1)) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
|
||
|
||
/* Check to see if we should revive second section */
|
||
if(sect2->sect_info.state != H5FS_SECT_LIVE)
|
||
if(H5HF_sect_row_revive(hdr, dxpl_id, sect2) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
|
||
|
||
/* Merge rows' underlying indirect sections together */
|
||
if(H5HF_sect_indirect_merge_row(hdr, dxpl_id, (*sect1), sect2) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTMERGE, FAIL, "can't merge underlying indirect sections")
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_merge() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_can_shrink
|
||
*
|
||
* Purpose: Can this section shrink the container?
|
||
*
|
||
* Note: This isn't actually shrinking the heap (since that's already
|
||
* been done) as much as it's cleaning up _after_ the heap
|
||
* shrink.
|
||
*
|
||
* Return: Success: non-negative (TRUE/FALSE)
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static htri_t
|
||
H5HF_sect_row_can_shrink(const H5FS_section_info_t *_sect, void H5_ATTR_UNUSED *_udata)
|
||
{
|
||
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */
|
||
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
|
||
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
|
||
htri_t ret_value = FALSE; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
|
||
|
||
/* Check if section is past end of "next block" iterator */
|
||
if(sect->sect_info.addr >= hdr->man_iter_off)
|
||
HGOTO_DONE(TRUE)
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_can_shrink() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_shrink
|
||
*
|
||
* Purpose: Shrink container with section
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_shrink(H5FS_section_info_t **_sect, void *_udata)
|
||
{
|
||
H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
|
||
H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */
|
||
H5HF_sect_add_ud_t *udata = (H5HF_sect_add_ud_t *)_udata; /* User callback data */
|
||
H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
|
||
hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect);
|
||
HDassert(*sect);
|
||
HDassert((*sect)->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
|
||
|
||
/* Get the top indirect section underlying each row */
|
||
top_indir_sect = H5HF_sect_indirect_top((*sect)->u.row.under);
|
||
|
||
/* Shrink away underlying indirect section */
|
||
if(H5HF_sect_indirect_shrink(hdr, dxpl_id, top_indir_sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't shrink underlying indirect section")
|
||
|
||
/* Indicate that the section has been released */
|
||
*sect = NULL;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_shrink() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_free_real
|
||
*
|
||
* Purpose: Free a 'row' section node
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_free_real(H5HF_free_section_t *sect)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
HDassert(sect);
|
||
|
||
/* Release the section */
|
||
if(H5HF_sect_node_free(sect, NULL) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_free_real() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_free
|
||
*
|
||
* Purpose: Free a 'row' section node
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Thursday, July 6, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_free(H5FS_section_info_t *_sect)
|
||
{
|
||
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
HDassert(sect);
|
||
HDassert(sect->u.row.under);
|
||
|
||
/* Decrement the ref. count on the row section's underlying indirect section */
|
||
if(H5HF_sect_indirect_decr(sect->u.row.under) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't detach section node")
|
||
|
||
/* Release the section */
|
||
if(H5HF_sect_row_free_real(sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_row_free() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_valid
|
||
*
|
||
* Purpose: Check the validity of a section
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Friday, July 21, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_valid(const H5FS_section_class_t *cls, const H5FS_section_info_t *_sect,
|
||
hid_t H5_ATTR_UNUSED dxpl_id)
|
||
{
|
||
H5HF_sect_private_t *cls_prvt; /* Pointer to class private info */
|
||
const H5HF_hdr_t *hdr; /* Fractal heap header */
|
||
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Pointer to section to check */
|
||
const H5HF_free_section_t *indir_sect; /* Pointer to underlying indirect section */
|
||
unsigned indir_idx; /* Index of row in underlying indirect section's row array */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Basic sanity check */
|
||
HDassert(cls);
|
||
HDassert(sect);
|
||
|
||
/* Retrieve class private information */
|
||
cls_prvt = (H5HF_sect_private_t *)cls->cls_private;
|
||
hdr = cls_prvt->hdr;
|
||
|
||
/* Sanity checking on the row */
|
||
HDassert(sect->u.row.under);
|
||
HDassert(sect->u.row.num_entries);
|
||
HDassert(sect->u.row.checked_out == FALSE);
|
||
indir_sect = sect->u.row.under;
|
||
indir_idx = sect->u.row.row - indir_sect->u.indirect.row;
|
||
HDassert(indir_sect->u.indirect.dir_rows[indir_idx] == sect);
|
||
|
||
/* Check if the section is actually within the heap */
|
||
HDassert(sect->sect_info.addr < hdr->man_iter_off);
|
||
|
||
/* Different checking for different kinds of rows */
|
||
if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) {
|
||
H5HF_free_section_t *top_indir_sect; /* Top indirect section for row */
|
||
|
||
/* Some extra sanity checks on the row */
|
||
HDassert(sect->u.row.row == indir_sect->u.indirect.row);
|
||
|
||
/* Get the top indirect section underlying row */
|
||
top_indir_sect = H5HF_sect_indirect_top(sect->u.row.under);
|
||
|
||
/* Check that the row's underlying indirect section is valid */
|
||
H5HF_sect_indirect_valid(hdr, top_indir_sect);
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* H5HF_sect_row_valid() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_row_debug
|
||
*
|
||
* Purpose: Dump debugging information about an row free space section
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Tuesday, July 25, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_row_debug(const H5FS_section_info_t *_sect,
|
||
FILE *stream, int indent, int fwidth)
|
||
{
|
||
const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect);
|
||
|
||
/* Print indirect section information */
|
||
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
|
||
"Row:",
|
||
sect->u.row.row);
|
||
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
|
||
"Column:",
|
||
sect->u.row.col);
|
||
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
|
||
"Number of entries:",
|
||
sect->u.row.num_entries);
|
||
|
||
/* If this is a first row section display information about underlying indirect section */
|
||
if(sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW) {
|
||
/* Print indirect section header */
|
||
HDfprintf(stream, "%*s%-*s\n", indent, "", fwidth,
|
||
"Underlying indirect section:");
|
||
|
||
H5HF_sect_indirect_debug(sect->u.row.under, stream, indent + 3, MAX(0, fwidth - 3));
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* H5HF_sect_row_debug() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_iblock_off
|
||
*
|
||
* Purpose: Get the offset of the indirect block for the section
|
||
*
|
||
* Return: Offset of indirect block in "heap space" (can't fail)
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static hsize_t
|
||
H5HF_sect_indirect_iblock_off(const H5HF_free_section_t *sect)
|
||
{
|
||
hsize_t ret_value = 0; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(sect);
|
||
|
||
ret_value = sect->sect_info.state == H5FS_SECT_LIVE ? sect->u.indirect.u.iblock->block_off : sect->u.indirect.u.iblock_off;
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_iblock_off() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_top
|
||
*
|
||
* Purpose: Get the "top" indirect section
|
||
*
|
||
* Return: Pointer to the top indirect section (can't fail)
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5HF_free_section_t *
|
||
H5HF_sect_indirect_top(H5HF_free_section_t *sect)
|
||
{
|
||
H5HF_free_section_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(sect);
|
||
|
||
if(sect->u.indirect.parent)
|
||
ret_value = H5HF_sect_indirect_top(sect->u.indirect.parent);
|
||
else
|
||
ret_value = sect;
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_top() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_init_cls
|
||
*
|
||
* Purpose: Initialize the "indirect" class structure
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 3, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, void *_udata)
|
||
{
|
||
H5HF_hdr_t *hdr = (H5HF_hdr_t *)_udata; /* Fractal heap header */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(cls);
|
||
HDassert(hdr);
|
||
|
||
/* Call to common class initialization */
|
||
if(H5HF_sect_init_cls(cls, hdr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize common section class")
|
||
|
||
/* Set the size of all serialized objects of this class of sections */
|
||
cls->serial_size = H5HF_SECT_INDIRECT_SERIAL_SIZE(hdr);
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_indirect_init_cls() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_term_cls
|
||
*
|
||
* Purpose: Terminate the "indirect" class structure
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 3, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_term_cls(H5FS_section_class_t *cls)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(cls);
|
||
|
||
/* Call common class termination */
|
||
if(H5HF_sect_term_cls(cls) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't terminate common section class")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_indirect_term_cls() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_new
|
||
*
|
||
* Purpose: Create a new 'indirect' section for other routines to finish
|
||
* initializing.
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5HF_free_section_t *
|
||
H5HF_sect_indirect_new(H5HF_hdr_t *hdr, haddr_t sect_off, hsize_t sect_size,
|
||
H5HF_indirect_t *iblock, hsize_t iblock_off, unsigned row, unsigned col,
|
||
unsigned nentries)
|
||
{
|
||
H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
|
||
H5HF_free_section_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(nentries);
|
||
|
||
/* Create free space section node */
|
||
if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_off,
|
||
sect_size, (iblock ? H5FS_SECT_LIVE : H5FS_SECT_SERIALIZED))))
|
||
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for indirect section")
|
||
|
||
/* Set the 'indirect' specific fields */
|
||
if(iblock) {
|
||
sect->u.indirect.u.iblock = iblock;
|
||
sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
|
||
sect->u.indirect.u.iblock->max_rows;
|
||
if(H5HF_iblock_incr(sect->u.indirect.u.iblock) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
|
||
} /* end if */
|
||
else {
|
||
sect->u.indirect.u.iblock_off = iblock_off;
|
||
sect->u.indirect.iblock_entries = 0;
|
||
} /* end else */
|
||
sect->u.indirect.row = row;
|
||
sect->u.indirect.col = col;
|
||
sect->u.indirect.num_entries = nentries;
|
||
|
||
/* Compute span size of indirect section */
|
||
sect->u.indirect.span_size = H5HF_dtable_span_size(&hdr->man_dtable,
|
||
row, col, nentries);
|
||
HDassert(sect->u.indirect.span_size > 0);
|
||
|
||
/* This indirect section doesn't (currently) have a parent */
|
||
sect->u.indirect.parent = NULL;
|
||
sect->u.indirect.par_entry = 0;
|
||
|
||
/* Set return value */
|
||
ret_value = sect;
|
||
|
||
done:
|
||
if(!ret_value && sect) {
|
||
/* Release the section */
|
||
sect = H5FL_FREE(H5HF_free_section_t, sect);
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_new() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_for_row
|
||
*
|
||
* Purpose: Create the underlying indirect section for a new row section
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5HF_free_section_t *
|
||
H5HF_sect_indirect_for_row(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock,
|
||
H5HF_free_section_t *row_sect)
|
||
{
|
||
H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
|
||
H5HF_free_section_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(iblock);
|
||
HDassert(row_sect);
|
||
HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows);
|
||
|
||
/* Create free space section node */
|
||
if(NULL == (sect = H5HF_sect_indirect_new(hdr, row_sect->sect_info.addr,
|
||
row_sect->sect_info.size, iblock, iblock->block_off,
|
||
row_sect->u.row.row, row_sect->u.row.col, row_sect->u.row.num_entries)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section")
|
||
|
||
/* Set # of direct rows covered */
|
||
sect->u.indirect.dir_nrows = 1;
|
||
|
||
/* Allocate space for the derived row sections */
|
||
if(NULL == (sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *))))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, NULL, "allocation failed for row section pointer array")
|
||
|
||
/* Atatch the new row section to indirect section */
|
||
sect->u.indirect.dir_rows[0] = row_sect;
|
||
sect->u.indirect.rc = 1;
|
||
|
||
/* No indirect rows in current section */
|
||
sect->u.indirect.indir_nents = 0;
|
||
sect->u.indirect.indir_ents = NULL;
|
||
|
||
/* Set return value */
|
||
ret_value = sect;
|
||
|
||
done:
|
||
if(!ret_value && sect)
|
||
if(H5HF_sect_indirect_free(sect) < 0)
|
||
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "can't free indirect section node")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_for_row() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_init_rows
|
||
*
|
||
* Purpose: Initialize the derived row sections for a newly created
|
||
* indirect section
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_init_rows(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect, hbool_t first_child, H5HF_free_section_t **first_row_sect,
|
||
unsigned space_flags, unsigned start_row, unsigned start_col,
|
||
unsigned end_row, unsigned end_col)
|
||
{
|
||
hsize_t curr_off; /* Offset of new section in "heap space" */
|
||
size_t dblock_overhead; /* Direct block's overhead */
|
||
unsigned row_entries; /* # of entries in row */
|
||
unsigned row_col; /* Column within current row */
|
||
unsigned curr_entry; /* Current entry within indirect section */
|
||
unsigned curr_indir_entry; /* Current indirect entry within indirect section */
|
||
unsigned curr_row; /* Current row within indirect section */
|
||
unsigned dir_nrows; /* # of direct rows in indirect section */
|
||
unsigned u; /* Local index variable */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(sect);
|
||
HDassert(sect->u.indirect.span_size > 0);
|
||
|
||
/* Reset reference count for indirect section */
|
||
/* (Also reset the direct & indirect row pointers */
|
||
sect->u.indirect.rc = 0;
|
||
sect->u.indirect.dir_rows = NULL;
|
||
sect->u.indirect.indir_ents = NULL;
|
||
|
||
/* Set up direct block information, if necessary */
|
||
if(start_row < hdr->man_dtable.max_direct_rows) {
|
||
unsigned max_direct_row; /* Max. direct row covered */
|
||
|
||
/* Compute max. direct row covered by indirect section */
|
||
max_direct_row = MIN(end_row, (hdr->man_dtable.max_direct_rows - 1));
|
||
|
||
/* Compute # of direct rows covered */
|
||
dir_nrows = (max_direct_row - start_row) + 1;
|
||
|
||
/* Don't set the of direct rows in section yet, so sanity
|
||
* checking works (enabled in free section manager, with H5FS_DEBUG
|
||
* macro) correctly.
|
||
*/
|
||
sect->u.indirect.dir_nrows = 0;
|
||
|
||
/* Allocate space for the derived row sections */
|
||
if(NULL == (sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * dir_nrows)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
|
||
} /* end if */
|
||
else {
|
||
/* No rows of direct blocks covered, reset direct row information */
|
||
dir_nrows = 0;
|
||
sect->u.indirect.dir_nrows = 0;
|
||
} /* end else */
|
||
|
||
/* Set up indirect block information, if necessary */
|
||
if(end_row >= hdr->man_dtable.max_direct_rows) {
|
||
unsigned indirect_start_row; /* Row to start indirect entries on */
|
||
unsigned indirect_start_col; /* Column to start indirect entries on */
|
||
unsigned indirect_start_entry; /* Index of starting indirect entry */
|
||
unsigned indirect_end_entry; /* Index of ending indirect entry */
|
||
|
||
/* Compute starting indirect entry */
|
||
if(start_row < hdr->man_dtable.max_direct_rows) {
|
||
indirect_start_row = hdr->man_dtable.max_direct_rows;
|
||
indirect_start_col = 0;
|
||
} /* end if */
|
||
else {
|
||
indirect_start_row = start_row;
|
||
indirect_start_col = start_col;
|
||
} /* end else */
|
||
indirect_start_entry = (indirect_start_row * hdr->man_dtable.cparam.width)
|
||
+ indirect_start_col;
|
||
|
||
/* Compute ending indirect entry */
|
||
indirect_end_entry = (end_row * hdr->man_dtable.cparam.width) + end_col;
|
||
|
||
/* Compute # of indirect entries covered */
|
||
sect->u.indirect.indir_nents = (indirect_end_entry - indirect_start_entry) + 1;
|
||
|
||
/* Allocate space for the child indirect sections */
|
||
if(NULL == (sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * sect->u.indirect.indir_nents)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
|
||
} /* end if */
|
||
else {
|
||
/* No indirect block entries covered, reset indirect row information */
|
||
sect->u.indirect.indir_nents = 0;
|
||
} /* end else */
|
||
|
||
/* Set up initial row information */
|
||
if(start_row == end_row)
|
||
row_entries = (end_col - start_col) + 1;
|
||
else
|
||
row_entries = hdr->man_dtable.cparam.width - start_col;
|
||
row_col = start_col;
|
||
|
||
/* Loop over creating the sections covered by this indirect section */
|
||
curr_off = sect->sect_info.addr;
|
||
curr_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
|
||
curr_row = 0;
|
||
curr_indir_entry = 0;
|
||
dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
|
||
for(u = start_row; u <= end_row; u++, curr_row++) {
|
||
if(u < hdr->man_dtable.max_direct_rows) {
|
||
H5HF_free_section_t *row_sect = NULL; /* 'Row' free space section to add */
|
||
|
||
/* Create 'row' free space section node */
|
||
if(NULL == (row_sect = H5HF_sect_row_create(curr_off,
|
||
(hdr->man_dtable.row_block_size[u] - dblock_overhead), first_child, u, row_col,
|
||
row_entries, sect)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "creation failed for child row section")
|
||
|
||
/* Add new row section to array for indirect section */
|
||
sect->u.indirect.dir_rows[curr_row] = row_sect;
|
||
|
||
/* Check to see if we should grab the first row section instead of adding it immediately */
|
||
if(first_row_sect)
|
||
*first_row_sect = row_sect;
|
||
else {
|
||
/* Add new row section to free space manager for the heap */
|
||
if(H5HF_space_add(hdr, dxpl_id, row_sect, space_flags) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space")
|
||
} /* end else */
|
||
|
||
/* Increment reference count for underlying indirect section */
|
||
sect->u.indirect.rc++;
|
||
|
||
/* Advance the offset to the next section */
|
||
curr_off += row_entries * hdr->man_dtable.row_block_size[u];
|
||
|
||
/* Advance the current entry to the next row*/
|
||
curr_entry += row_entries;
|
||
|
||
/* Reset the 'first child' parameters */
|
||
first_child = FALSE;
|
||
first_row_sect = NULL;
|
||
} /* end if */
|
||
else {
|
||
H5HF_indirect_t *child_iblock; /* Child indirect block */
|
||
H5HF_free_section_t *child_sect; /* Child 'indirect' section to add */
|
||
unsigned child_nrows; /* Number of child rows in indirect blocks for this row */
|
||
unsigned child_nentries; /* Number of child entries in indirect blocks for this row */
|
||
unsigned v; /* Local index variable */
|
||
|
||
/* Compute info about row's indirect blocks for child section */
|
||
child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[u]);
|
||
child_nentries = child_nrows * hdr->man_dtable.cparam.width;
|
||
|
||
/* Add an indirect section for each indirect block in the row */
|
||
for(v = 0; v < row_entries; v++) {
|
||
hbool_t did_protect; /* Whether we protected the indirect block or not */
|
||
|
||
/* Try to get the child section's indirect block, if it's available */
|
||
if(sect->sect_info.state == H5FS_SECT_LIVE) {
|
||
haddr_t child_iblock_addr; /* Child indirect block's address on disk */
|
||
|
||
/* Get the address of the child indirect block */
|
||
if(H5HF_man_iblock_entry_addr(sect->u.indirect.u.iblock, curr_entry, &child_iblock_addr) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve child indirect block's address")
|
||
|
||
/* If the child indirect block's address is defined, protect it */
|
||
if(H5F_addr_defined(child_iblock_addr)) {
|
||
if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, child_nrows, sect->u.indirect.u.iblock, curr_entry, FALSE, H5AC__NO_FLAGS_SET, &did_protect)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
|
||
} /* end if */
|
||
else
|
||
child_iblock = NULL;
|
||
} /* end if */
|
||
else
|
||
child_iblock = NULL;
|
||
|
||
/* Create free space section node */
|
||
if(NULL == (child_sect = H5HF_sect_indirect_new(hdr, curr_off, (hsize_t)0,
|
||
child_iblock, curr_off, 0, 0, child_nentries)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
|
||
|
||
/* Initialize rows for new indirect section */
|
||
if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, child_sect,
|
||
first_child, first_row_sect, space_flags, 0, 0,
|
||
(child_nrows - 1), (hdr->man_dtable.cparam.width - 1)) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section")
|
||
|
||
/* If we have a valid child indirect block, release it now */
|
||
/* (will be pinned, if rows reference it) */
|
||
if(child_iblock)
|
||
if(H5HF_man_iblock_unprotect(child_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
|
||
|
||
/* Attach child section to this section */
|
||
child_sect->u.indirect.parent = sect;
|
||
child_sect->u.indirect.par_entry = curr_entry;
|
||
sect->u.indirect.indir_ents[curr_indir_entry] = child_sect;
|
||
sect->u.indirect.rc++;
|
||
|
||
/* Advance the offset for the next section */
|
||
curr_off += hdr->man_dtable.row_block_size[u];
|
||
|
||
/* Advance to the next entry */
|
||
curr_entry++;
|
||
curr_indir_entry++;
|
||
|
||
/* Reset the 'first child' parameters */
|
||
first_child = FALSE;
|
||
first_row_sect = NULL;
|
||
} /* end for */
|
||
} /* end else */
|
||
|
||
/* Compute the # of entries for the next row */
|
||
if(u < (end_row - 1))
|
||
row_entries = hdr->man_dtable.cparam.width;
|
||
else
|
||
row_entries = end_col + 1;
|
||
|
||
/* Reset column for all other rows */
|
||
row_col = 0;
|
||
} /* end for */
|
||
|
||
/* Set the final # of direct rows in section */
|
||
sect->u.indirect.dir_nrows = dir_nrows;
|
||
|
||
/* Make certain we've tracked the section's dependents correctly */
|
||
HDassert(sect->u.indirect.rc ==
|
||
(sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
|
||
|
||
done:
|
||
if(ret_value < 0) {
|
||
if(sect->u.indirect.indir_ents)
|
||
H5MM_xfree(sect->u.indirect.indir_ents);
|
||
if(sect->u.indirect.dir_rows)
|
||
H5MM_xfree(sect->u.indirect.dir_rows);
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_init_rows() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_add
|
||
*
|
||
* Purpose: Add a new 'indirect' section to the free space manager for this
|
||
* heap
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 3 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
herr_t
|
||
H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries)
|
||
{
|
||
H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
|
||
H5HF_free_section_t *first_row_sect = NULL; /* First row section in new indirect section */
|
||
hsize_t sect_off; /* Offset of section in heap space */
|
||
unsigned start_row; /* Start row in indirect block */
|
||
unsigned start_col; /* Start column in indirect block */
|
||
unsigned end_entry; /* End entry in indirect block */
|
||
unsigned end_row; /* End row in indirect block */
|
||
unsigned end_col; /* End column in indirect block */
|
||
unsigned u; /* Local index variable */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(iblock);
|
||
HDassert(nentries);
|
||
|
||
/* Compute starting column & row */
|
||
start_row = start_entry / hdr->man_dtable.cparam.width;
|
||
start_col = start_entry % hdr->man_dtable.cparam.width;
|
||
|
||
/* Compute end column & row */
|
||
end_entry = (start_entry + nentries) - 1;
|
||
end_row = end_entry / hdr->man_dtable.cparam.width;
|
||
end_col = end_entry % hdr->man_dtable.cparam.width;
|
||
|
||
/* Initialize information for rows skipped over */
|
||
sect_off = iblock->block_off;
|
||
for(u = 0; u < start_row; u++)
|
||
sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
|
||
sect_off += hdr->man_dtable.row_block_size[start_row] * start_col;
|
||
|
||
/* Create free space section node */
|
||
if(NULL == (sect = H5HF_sect_indirect_new(hdr, sect_off, (hsize_t)0, iblock,
|
||
iblock->block_off, start_row, start_col, nentries)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
|
||
|
||
/* Initialize rows for new indirect section */
|
||
if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, sect, TRUE, &first_row_sect,
|
||
H5FS_ADD_SKIP_VALID, start_row, start_col, end_row, end_col) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize indirect section")
|
||
HDassert(first_row_sect);
|
||
|
||
/* Now that underlying indirect section is consistent, add first row
|
||
* section to free space manager for the heap
|
||
*/
|
||
if(H5HF_space_add(hdr, dxpl_id, first_row_sect, H5FS_ADD_RETURNED_SPACE) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add row section to free space")
|
||
|
||
done:
|
||
if(ret_value < 0 && sect)
|
||
if(H5HF_sect_indirect_free(sect) < 0)
|
||
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_add() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_decr
|
||
*
|
||
* Purpose: Decrement ref. count on indirect section
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 6 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_decr(H5HF_free_section_t *sect)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(sect);
|
||
HDassert(sect->u.indirect.rc);
|
||
|
||
/* Decrement ref. count for indirect section */
|
||
sect->u.indirect.rc--;
|
||
|
||
/* If the indirect section's ref. count drops to zero, free the section */
|
||
if(sect->u.indirect.rc == 0) {
|
||
H5HF_free_section_t *par_sect; /* Parent indirect section */
|
||
|
||
/* Preserve pointer to parent indirect section when freeing this section */
|
||
par_sect = sect->u.indirect.parent;
|
||
|
||
/* Free indirect section */
|
||
if(H5HF_sect_indirect_free(sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
|
||
|
||
/* Decrement ref. count on indirect section's parent */
|
||
if(par_sect)
|
||
if(H5HF_sect_indirect_decr(par_sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section")
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_decr() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_revive_row
|
||
*
|
||
* Purpose: Update the memory information for a 'indirect' free section
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 3 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_revive_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
|
||
{
|
||
H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */
|
||
hbool_t did_protect; /* Whether we protected the indirect block or not */
|
||
unsigned u; /* Local index variable */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
|
||
|
||
/* Look up indirect block containing indirect blocks for section */
|
||
if(H5HF_man_dblock_locate(hdr, dxpl_id, sect->sect_info.addr, &sec_iblock, NULL, &did_protect, H5AC__READ_ONLY_FLAG) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section")
|
||
|
||
/* Increment reference count on indirect block that free section is in */
|
||
if(H5HF_iblock_incr(sec_iblock) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
|
||
|
||
/* Set the pointer to the section's indirect block */
|
||
sect->u.indirect.u.iblock = sec_iblock;
|
||
|
||
/* Set the number of entries in the indirect block */
|
||
sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
|
||
sect->u.indirect.u.iblock->max_rows;
|
||
|
||
/* Unlock indirect block */
|
||
if(H5HF_man_iblock_unprotect(sec_iblock, dxpl_id, H5AC__NO_FLAGS_SET, did_protect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
|
||
sec_iblock = NULL;
|
||
|
||
/* Section is "live" now */
|
||
sect->sect_info.state = H5FS_SECT_LIVE;
|
||
|
||
/* Loop over derived row sections and mark them all as 'live' now */
|
||
for(u = 0; u < sect->u.indirect.dir_nrows; u++)
|
||
sect->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_LIVE;
|
||
|
||
/* Revive parent indirect section, if there is one */
|
||
if(sect->u.indirect.parent && sect->u.indirect.parent->sect_info.state == H5FS_SECT_SERIALIZED)
|
||
if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.u.iblock->parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_revive_row() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_revive
|
||
*
|
||
* Purpose: Update the memory information for a 'indirect' free section
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 10 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *sect, H5HF_indirect_t *sect_iblock)
|
||
{
|
||
unsigned u; /* Local index variable */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_SERIALIZED);
|
||
HDassert(sect_iblock);
|
||
|
||
/* Increment reference count on indirect block that free section is in */
|
||
if(H5HF_iblock_incr(sect_iblock) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
|
||
|
||
/* Set the pointer to the section's indirect block */
|
||
sect->u.indirect.u.iblock = sect_iblock;
|
||
|
||
/* Set the number of entries in the indirect block */
|
||
sect->u.indirect.iblock_entries = hdr->man_dtable.cparam.width *
|
||
sect->u.indirect.u.iblock->max_rows;
|
||
|
||
/* Section is "live" now */
|
||
sect->sect_info.state = H5FS_SECT_LIVE;
|
||
|
||
/* Loop over derived row sections and mark them all as 'live' now */
|
||
for(u = 0; u < sect->u.indirect.dir_nrows; u++)
|
||
sect->u.indirect.dir_rows[u]->sect_info.state = H5FS_SECT_LIVE;
|
||
|
||
/* Revive parent indirect section, if there is one */
|
||
if(sect->u.indirect.parent && sect->u.indirect.parent->sect_info.state == H5FS_SECT_SERIALIZED)
|
||
if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.u.iblock->parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTREVIVE, FAIL, "can't revive indirect section")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_revive() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_reduce_row
|
||
*
|
||
* Purpose: Remove a block from an indirect section (possibly freeing it)
|
||
* and re-add it back to the free space manager for the heap
|
||
* (if it hasn't been freed)
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 10 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_reduce_row(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *row_sect,
|
||
hbool_t *alloc_from_start)
|
||
{
|
||
H5HF_free_section_t *sect; /* Indirect section underlying row section */
|
||
unsigned row_start_entry; /* Entry for first block covered in row section */
|
||
unsigned row_end_entry; /* Entry for last block covered in row section */
|
||
unsigned row_entry; /* Entry to allocate in row section */
|
||
unsigned start_entry; /* Entry for first block covered */
|
||
unsigned start_row; /* Start row in indirect block */
|
||
unsigned start_col; /* Start column in indirect block */
|
||
unsigned end_entry; /* Entry for last block covered */
|
||
unsigned end_row; /* End row in indirect block */
|
||
H5HF_free_section_t *peer_sect = NULL; /* Peer indirect section */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(row_sect);
|
||
|
||
/* Compute starting & ending information for row section */
|
||
row_start_entry = (row_sect->u.row.row * hdr->man_dtable.cparam.width) + row_sect->u.row.col;
|
||
row_end_entry = (row_start_entry + row_sect->u.row.num_entries) - 1;
|
||
|
||
/* Compute starting & ending information for indirect section */
|
||
sect = row_sect->u.row.under;
|
||
start_row = sect->u.indirect.row;
|
||
start_col = sect->u.indirect.col;
|
||
start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
|
||
end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
|
||
end_row = end_entry / hdr->man_dtable.cparam.width;
|
||
|
||
/* Additional sanity check */
|
||
HDassert(sect->u.indirect.span_size > 0);
|
||
HDassert(sect->u.indirect.iblock_entries > 0);
|
||
HDassert(sect->u.indirect.dir_nrows > 0);
|
||
HDassert(sect->u.indirect.dir_rows);
|
||
HDassert(sect->u.indirect.dir_rows[(row_sect->u.row.row - start_row)] == row_sect);
|
||
|
||
/* Check if we should allocate from end of indirect section */
|
||
if(row_end_entry == end_entry && start_row != end_row) {
|
||
*alloc_from_start = FALSE;
|
||
row_entry = row_end_entry;
|
||
} /* end if */
|
||
else {
|
||
*alloc_from_start = TRUE;
|
||
row_entry = row_start_entry;
|
||
} /* end else */
|
||
|
||
/* Check if we have a parent section to be detached from */
|
||
if(sect->u.indirect.parent) {
|
||
hbool_t is_first; /* Flag to indicate that this section is the first section in hierarchy */
|
||
|
||
/* Check if this section is the first section */
|
||
is_first = H5HF_sect_indirect_is_first(sect);
|
||
|
||
/* Remove this indirect section from parent indirect section */
|
||
if(H5HF_sect_indirect_reduce(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section")
|
||
sect->u.indirect.parent = NULL;
|
||
sect->u.indirect.par_entry = 0;
|
||
|
||
/* If we weren't the first section, set "first row" for this indirect section */
|
||
if(!is_first)
|
||
if(H5HF_sect_indirect_first(hdr, dxpl_id, sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
|
||
} /* end if */
|
||
|
||
/* Adjust indirect section's span size */
|
||
sect->u.indirect.span_size -= row_sect->sect_info.size;
|
||
|
||
/* Check how to adjust section for allocated entry */
|
||
if(sect->u.indirect.num_entries > 1) {
|
||
if(row_entry == start_entry) {
|
||
/* Adjust section start */
|
||
sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.indirect.row];
|
||
|
||
/* Adjust block coordinates of span */
|
||
sect->u.indirect.col++;
|
||
if(sect->u.indirect.col == hdr->man_dtable.cparam.width) {
|
||
HDassert(row_sect->u.row.num_entries == 1);
|
||
|
||
/* Adjust section's span information */
|
||
sect->u.indirect.row++;
|
||
sect->u.indirect.col = 0;
|
||
|
||
/* Adjust direct row information */
|
||
sect->u.indirect.dir_nrows--;
|
||
|
||
/* Adjust direct row sections for indirect section */
|
||
if(sect->u.indirect.dir_nrows > 0) {
|
||
HDassert(sect->u.indirect.dir_rows);
|
||
HDmemmove(§->u.indirect.dir_rows[0],
|
||
§->u.indirect.dir_rows[1],
|
||
sect->u.indirect.dir_nrows * sizeof(H5HF_free_section_t *));
|
||
HDassert(sect->u.indirect.dir_rows[0]);
|
||
|
||
/* Make new "first row" in indirect section */
|
||
if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW)
|
||
if(H5HF_sect_row_first(hdr, dxpl_id, sect->u.indirect.dir_rows[0]) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
|
||
} /* end if */
|
||
else {
|
||
/* Sanity check */
|
||
HDassert(sect->u.indirect.indir_nents > 0);
|
||
HDassert(sect->u.indirect.indir_ents);
|
||
|
||
/* Eliminate direct rows for this section */
|
||
sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
|
||
|
||
/* Make new "first row" in indirect section */
|
||
if(row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW)
|
||
if(H5HF_sect_indirect_first(hdr, dxpl_id, sect->u.indirect.indir_ents[0]) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section")
|
||
} /* end else */
|
||
} /* end if */
|
||
|
||
/* Adjust number of entries covered */
|
||
sect->u.indirect.num_entries--;
|
||
} /* end if */
|
||
else if(row_entry == end_entry) {
|
||
unsigned new_end_row; /* New end row for entries */
|
||
|
||
/* Sanity check */
|
||
HDassert(sect->u.indirect.indir_nents == 0);
|
||
HDassert(sect->u.indirect.indir_ents == NULL);
|
||
|
||
/* Adjust number of entries covered */
|
||
sect->u.indirect.num_entries--;
|
||
|
||
/* Check for eliminating a direct row */
|
||
new_end_row = ((start_entry + sect->u.indirect.num_entries) - 1) / hdr->man_dtable.cparam.width;
|
||
HDassert(new_end_row <= end_row);
|
||
if(new_end_row < end_row) {
|
||
HDassert(new_end_row == (end_row - 1));
|
||
sect->u.indirect.dir_nrows--;
|
||
} /* end if */
|
||
} /* end if */
|
||
else {
|
||
H5HF_indirect_t *iblock; /* Pointer to indirect block for this section */
|
||
hsize_t iblock_off; /* Section's indirect block's offset in "heap space" */
|
||
unsigned peer_nentries; /* Number of entries in new peer indirect section */
|
||
unsigned peer_dir_nrows; /* Number of direct rows in new peer indirect section */
|
||
unsigned new_start_row; /* New starting row for current indirect section */
|
||
unsigned u; /* Local index variable */
|
||
|
||
/* Sanity checks */
|
||
HDassert(row_sect->u.row.col == 0);
|
||
HDassert(row_sect->u.row.row > 0);
|
||
HDassert(row_sect->u.row.row < hdr->man_dtable.max_direct_rows);
|
||
HDassert(row_sect->u.row.num_entries == hdr->man_dtable.cparam.width);
|
||
HDassert(row_sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
|
||
|
||
/* Compute basic information about peer & current indirect sections */
|
||
new_start_row = row_sect->u.row.row;
|
||
peer_nentries = row_entry - start_entry;
|
||
peer_dir_nrows = new_start_row - start_row;
|
||
|
||
/* Get indirect block information for peer */
|
||
if(sect->sect_info.state == H5FS_SECT_LIVE) {
|
||
iblock = sect->u.indirect.u.iblock;
|
||
iblock_off = sect->u.indirect.u.iblock->block_off;
|
||
} /* end if */
|
||
else {
|
||
iblock = NULL;
|
||
iblock_off = sect->u.indirect.u.iblock_off;
|
||
} /* end else */
|
||
|
||
/* Create peer indirect section */
|
||
if(NULL == (peer_sect = H5HF_sect_indirect_new(hdr, sect->sect_info.addr,
|
||
sect->sect_info.size, iblock, iblock_off, start_row, start_col,
|
||
peer_nentries)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
|
||
|
||
/* Set up direct row & indirect entry information for peer section */
|
||
peer_sect->u.indirect.indir_nents = 0;
|
||
peer_sect->u.indirect.indir_ents = NULL;
|
||
peer_sect->u.indirect.dir_nrows = peer_dir_nrows;
|
||
if(NULL == (peer_sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_dir_nrows)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "allocation failed for row section pointer array")
|
||
|
||
/* Transfer row sections between current & peer sections */
|
||
HDmemcpy(&peer_sect->u.indirect.dir_rows[0],
|
||
§->u.indirect.dir_rows[0],
|
||
(sizeof(H5HF_free_section_t *) * peer_dir_nrows));
|
||
HDmemmove(§->u.indirect.dir_rows[0],
|
||
§->u.indirect.dir_rows[peer_dir_nrows],
|
||
(sizeof(H5HF_free_section_t *) * (sect->u.indirect.dir_nrows - peer_dir_nrows)));
|
||
sect->u.indirect.dir_nrows -= peer_dir_nrows;
|
||
HDassert(row_sect == sect->u.indirect.dir_rows[0]);
|
||
|
||
/* Re-target transferred row sections to point to new underlying indirect section */
|
||
for(u = 0; u < peer_dir_nrows; u++)
|
||
peer_sect->u.indirect.dir_rows[u]->u.row.under = peer_sect;
|
||
|
||
/* Change first row section in indirect section to be the "first row" */
|
||
/* (But we don't have to tell the free space manager about it,
|
||
* because the row section is "checked out" from the free space
|
||
* manager currently.
|
||
*/
|
||
row_sect->sect_info.type = H5HF_FSPACE_SECT_FIRST_ROW;
|
||
|
||
/* Adjust reference counts for current & peer sections */
|
||
peer_sect->u.indirect.rc = peer_dir_nrows;
|
||
sect->u.indirect.rc -= peer_dir_nrows;
|
||
|
||
/* Transfer/update cached information about indirect block */
|
||
peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries;
|
||
peer_sect->u.indirect.span_size = row_sect->sect_info.addr - peer_sect->sect_info.addr;
|
||
|
||
/* Update information for current section */
|
||
sect->sect_info.addr = row_sect->sect_info.addr + hdr->man_dtable.row_block_size[new_start_row];
|
||
sect->u.indirect.span_size -= peer_sect->u.indirect.span_size; /* (span for row section has already been removed) */
|
||
sect->u.indirect.row = new_start_row;
|
||
sect->u.indirect.col = row_sect->u.row.col + 1;
|
||
sect->u.indirect.num_entries -= (peer_nentries + 1); /* Transferred entries, plus the entry allocated out of the row */
|
||
|
||
/* Make certain we've tracked the sections' dependents correctly */
|
||
HDassert(sect->u.indirect.rc ==
|
||
(sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
|
||
HDassert(peer_sect->u.indirect.rc ==
|
||
(peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
|
||
|
||
/* Reset the peer_sect variable, to indicate that it has been hooked into the data structures correctly and shouldn't be freed */
|
||
peer_sect = NULL;
|
||
} /* end else */
|
||
} /* end if */
|
||
else {
|
||
/* Decrement count of entries & rows */
|
||
sect->u.indirect.num_entries--;
|
||
sect->u.indirect.dir_nrows--;
|
||
HDassert(sect->u.indirect.dir_nrows == 0);
|
||
|
||
/* Eliminate direct rows for this section */
|
||
sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
|
||
} /* end else */
|
||
|
||
done:
|
||
/* Free allocated peer_sect. Note that this is necessary for all failures until peer_sect is linked
|
||
* into the main free space structures (via the direct blocks), and the reference count is updated. */
|
||
if(peer_sect) {
|
||
/* Sanity check - we should only be here if an error occurred */
|
||
HDassert(ret_value < 0);
|
||
|
||
if(H5HF_sect_indirect_free(peer_sect) < 0)
|
||
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_reduce_row() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_reduce
|
||
*
|
||
* Purpose: Reduce the size of a indirect section (possibly freeing it)
|
||
* and re-add it back to the free space manager for the heap
|
||
* (if it hasn't been freed)
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 10 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect,
|
||
unsigned child_entry)
|
||
{
|
||
unsigned start_entry; /* Entry for first block covered */
|
||
unsigned start_row; /* Start row in indirect block */
|
||
unsigned start_col; /* Start column in indirect block */
|
||
unsigned end_entry; /* Entry for last block covered */
|
||
unsigned end_row; /* End row in indirect block */
|
||
H5HF_free_section_t *peer_sect = NULL; /* Peer indirect section */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->u.indirect.span_size > 0);
|
||
HDassert(sect->u.indirect.iblock_entries > 0);
|
||
|
||
/* Compute starting & ending information for indirect section */
|
||
start_row = sect->u.indirect.row;
|
||
start_col = sect->u.indirect.col;
|
||
start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
|
||
end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
|
||
end_row = end_entry / hdr->man_dtable.cparam.width;
|
||
|
||
/* Check how to adjust section for allocated entry */
|
||
if(sect->u.indirect.num_entries > 1) {
|
||
/* Check if we have a parent section to be detached from */
|
||
if(sect->u.indirect.parent) {
|
||
hbool_t is_first; /* Flag to indicate that this section is the first section in hierarchy */
|
||
|
||
/* Check if this section is the first section */
|
||
is_first = H5HF_sect_indirect_is_first(sect);
|
||
|
||
/* Reduce parent indirect section */
|
||
if(H5HF_sect_indirect_reduce(hdr, dxpl_id, sect->u.indirect.parent, sect->u.indirect.par_entry) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce parent indirect section")
|
||
sect->u.indirect.parent = NULL;
|
||
sect->u.indirect.par_entry = 0;
|
||
|
||
/* If we weren't the first section, set "first row" for this indirect section */
|
||
if(!is_first)
|
||
if(H5HF_sect_indirect_first(hdr, dxpl_id, sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for indirect section")
|
||
} /* end if */
|
||
|
||
/* Check if we can allocate from start of indirect section */
|
||
if(child_entry == start_entry) {
|
||
/* Sanity check */
|
||
HDassert(sect->u.indirect.dir_nrows == 0);
|
||
HDassert(sect->u.indirect.dir_rows == NULL);
|
||
HDassert(sect->u.indirect.indir_nents > 0);
|
||
HDassert(sect->u.indirect.indir_ents);
|
||
|
||
/* Adjust section start */
|
||
sect->sect_info.addr += hdr->man_dtable.row_block_size[start_row];
|
||
|
||
/* Adjust span of blocks covered */
|
||
sect->u.indirect.col++;
|
||
if(sect->u.indirect.col == hdr->man_dtable.cparam.width) {
|
||
sect->u.indirect.row++;
|
||
sect->u.indirect.col = 0;
|
||
} /* end if */
|
||
sect->u.indirect.num_entries--;
|
||
sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[start_row];
|
||
|
||
/* Adjust indirect entry information */
|
||
sect->u.indirect.indir_nents--;
|
||
HDmemmove(§->u.indirect.indir_ents[0],
|
||
§->u.indirect.indir_ents[1],
|
||
sect->u.indirect.indir_nents * sizeof(H5HF_free_section_t *));
|
||
HDassert(sect->u.indirect.indir_ents[0]);
|
||
|
||
/* Make new "first row" in new first indirect child section */
|
||
if(H5HF_sect_indirect_first(hdr, dxpl_id, sect->u.indirect.indir_ents[0]) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for child indirect section")
|
||
} /* end if */
|
||
else if(child_entry == end_entry) {
|
||
/* Sanity check */
|
||
HDassert(sect->u.indirect.indir_nents > 0);
|
||
HDassert(sect->u.indirect.indir_ents);
|
||
|
||
/* Adjust span of blocks covered */
|
||
sect->u.indirect.num_entries--;
|
||
sect->u.indirect.span_size -= hdr->man_dtable.row_block_size[end_row];
|
||
|
||
/* Adjust indirect entry information */
|
||
sect->u.indirect.indir_nents--;
|
||
if(sect->u.indirect.indir_nents == 0)
|
||
sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
|
||
} /* end if */
|
||
else {
|
||
H5HF_indirect_t *iblock; /* Pointer to indirect block for this section */
|
||
hsize_t iblock_off; /* Section's indirect block's offset in "heap space" */
|
||
haddr_t peer_sect_addr; /* Address of new peer section in "heap space" */
|
||
unsigned peer_nentries; /* Number of entries in new peer indirect section */
|
||
unsigned peer_start_row; /* Starting row for new peer indirect section */
|
||
unsigned peer_start_col; /* Starting column for new peer indirect section */
|
||
unsigned child_row; /* Row where child entry is located */
|
||
unsigned new_nentries; /* New number of entries for current indirect section */
|
||
unsigned u; /* Local index variable */
|
||
|
||
/* Sanity check */
|
||
HDassert(sect->u.indirect.indir_nents > 0);
|
||
HDassert(sect->u.indirect.indir_ents);
|
||
|
||
/* Compute basic information about peer & current indirect sections */
|
||
peer_nentries = end_entry - child_entry;
|
||
peer_start_row = (child_entry + 1) / hdr->man_dtable.cparam.width;
|
||
peer_start_col = (child_entry + 1) % hdr->man_dtable.cparam.width;
|
||
child_row = child_entry / hdr->man_dtable.cparam.width;
|
||
new_nentries = sect->u.indirect.num_entries - (peer_nentries + 1);
|
||
HDassert(child_row >= hdr->man_dtable.max_direct_rows);
|
||
|
||
/* Get indirect block information for peer */
|
||
if(sect->sect_info.state == H5FS_SECT_LIVE) {
|
||
iblock = sect->u.indirect.u.iblock;
|
||
iblock_off = sect->u.indirect.u.iblock->block_off;
|
||
} /* end if */
|
||
else {
|
||
iblock = NULL;
|
||
iblock_off = sect->u.indirect.u.iblock_off;
|
||
} /* end else */
|
||
|
||
/* Update the number of entries in current section & calculate it's span size */
|
||
/* (Will use this to compute the section address for the peer section */
|
||
sect->u.indirect.num_entries = new_nentries;
|
||
sect->u.indirect.span_size = H5HF_dtable_span_size(&hdr->man_dtable,
|
||
sect->u.indirect.row, sect->u.indirect.col, new_nentries);
|
||
HDassert(sect->u.indirect.span_size > 0);
|
||
|
||
/* Compute address of peer indirect section */
|
||
peer_sect_addr = sect->sect_info.addr;
|
||
peer_sect_addr += sect->u.indirect.span_size;
|
||
peer_sect_addr += hdr->man_dtable.row_block_size[child_row];
|
||
|
||
/* Create peer indirect section */
|
||
if(NULL == (peer_sect = H5HF_sect_indirect_new(hdr, peer_sect_addr,
|
||
sect->sect_info.size, iblock, iblock_off, peer_start_row,
|
||
peer_start_col, peer_nentries)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
|
||
|
||
/* Set up direct row & indirect entry information for peer section */
|
||
peer_sect->u.indirect.dir_nrows = 0;
|
||
peer_sect->u.indirect.dir_rows = NULL;
|
||
peer_sect->u.indirect.indir_nents = peer_nentries;
|
||
if(NULL == (peer_sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *) * peer_nentries)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "allocation failed for indirect section pointer array")
|
||
|
||
/* Transfer child indirect sections between current & peer sections */
|
||
HDmemcpy(&peer_sect->u.indirect.indir_ents[0],
|
||
§->u.indirect.indir_ents[sect->u.indirect.indir_nents - peer_nentries],
|
||
(sizeof(H5HF_free_section_t *) * peer_nentries));
|
||
sect->u.indirect.indir_nents -= (peer_nentries + 1); /* Transferred blocks, plus child entry */
|
||
|
||
/* Eliminate indirect entries for this section, if appropriate */
|
||
if(sect->u.indirect.indir_nents == 0)
|
||
sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
|
||
|
||
/* Re-target transferred row sections to point to new underlying indirect section */
|
||
for(u = 0; u < peer_nentries; u++)
|
||
peer_sect->u.indirect.indir_ents[u]->u.indirect.parent = peer_sect;
|
||
|
||
/* Adjust reference counts for current & peer sections */
|
||
peer_sect->u.indirect.rc = peer_nentries;
|
||
sect->u.indirect.rc -= peer_nentries;
|
||
|
||
/* Transfer cached information about indirect block */
|
||
peer_sect->u.indirect.iblock_entries = sect->u.indirect.iblock_entries;
|
||
|
||
/* Make certain we've tracked the sections' dependents correctly */
|
||
/* (Note modified on current section's ref. count, since we haven't
|
||
* detached the child section yet)
|
||
*/
|
||
HDassert((sect->u.indirect.rc - 1) ==
|
||
(sect->u.indirect.indir_nents + sect->u.indirect.dir_nrows));
|
||
HDassert(peer_sect->u.indirect.rc ==
|
||
(peer_sect->u.indirect.indir_nents + peer_sect->u.indirect.dir_nrows));
|
||
|
||
/* Make new "first row" in peer section */
|
||
if(H5HF_sect_indirect_first(hdr, dxpl_id, peer_sect->u.indirect.indir_ents[0]) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't make new 'first row' for peer indirect section")
|
||
|
||
/* Reset the peer_sect variable, to indicate that it has been hooked into the data structures correctly and shouldn't be freed */
|
||
peer_sect = NULL;
|
||
} /* end else */
|
||
} /* end if */
|
||
else {
|
||
/* Decrement count of entries & indirect entries */
|
||
sect->u.indirect.num_entries--;
|
||
sect->u.indirect.indir_nents--;
|
||
HDassert(sect->u.indirect.indir_nents == 0);
|
||
|
||
/* Eliminate indirect entries for this section */
|
||
sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
|
||
} /* end else */
|
||
|
||
/* Decrement # of sections which depend on this row */
|
||
/* (Must be last as section can be freed) */
|
||
if(H5HF_sect_indirect_decr(sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement section's ref. count ")
|
||
|
||
done:
|
||
/* Free allocated peer_sect. Note that this is necessary for all failures until peer_sect is linked
|
||
* into the main free space structures (via the direct blocks), and the reference count is updated. */
|
||
if(peer_sect) {
|
||
/* Sanity check - we should only be here if an error occurred */
|
||
HDassert(ret_value < 0);
|
||
|
||
if(H5HF_sect_indirect_free(peer_sect) < 0)
|
||
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_reduce() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_is_first
|
||
*
|
||
* Purpose: Check if indirect section is first in all parents
|
||
*
|
||
* Return: Non-negative (TRUE/FALSE) on success/<can't fail>
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 17 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static hbool_t
|
||
H5HF_sect_indirect_is_first(H5HF_free_section_t *sect)
|
||
{
|
||
hbool_t ret_value = FALSE; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Sanity check */
|
||
HDassert(sect);
|
||
|
||
/* Recurse to parent */
|
||
if(sect->u.indirect.parent) {
|
||
if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr)
|
||
ret_value = H5HF_sect_indirect_is_first(sect->u.indirect.parent);
|
||
} /* end if */
|
||
else
|
||
ret_value = TRUE;
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_is_first() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_first
|
||
*
|
||
* Purpose: Make new 'first row' for indirect section
|
||
*
|
||
* Return: Non-negative on success/Negative on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 10 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_first(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Sanity check */
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
|
||
/* Check if this indirect section has direct block rows */
|
||
if(sect->u.indirect.dir_nrows > 0) {
|
||
/* Sanity checks */
|
||
HDassert(sect->u.indirect.row == 0);
|
||
HDassert(sect->u.indirect.col == 0);
|
||
HDassert(sect->u.indirect.dir_rows);
|
||
HDassert(sect->u.indirect.dir_rows[0]);
|
||
|
||
/* Change first row section in indirect section to be the "first row" */
|
||
if(H5HF_sect_row_first(hdr, dxpl_id, sect->u.indirect.dir_rows[0]) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set row section to be first row")
|
||
} /* end if */
|
||
else {
|
||
/* Sanity checks */
|
||
HDassert(sect->u.indirect.indir_nents > 0);
|
||
HDassert(sect->u.indirect.indir_ents);
|
||
HDassert(sect->u.indirect.indir_ents[0]);
|
||
|
||
/* Forward to first child indirect section */
|
||
if(H5HF_sect_indirect_first(hdr, dxpl_id, sect->u.indirect.indir_ents[0]) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "can't set child indirect section to be first row")
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_first() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_get_iblock
|
||
*
|
||
* Purpose: Retrieve the indirect block for a indirect section
|
||
*
|
||
* Return: Pointer to indirect block on success/NULL on failure
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* koziol@ncsa.uiuc.edu
|
||
* July 9 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5HF_indirect_t *
|
||
H5HF_sect_indirect_get_iblock(H5HF_free_section_t *sect)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/*
|
||
* Check arguments.
|
||
*/
|
||
HDassert(sect);
|
||
HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
|
||
HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
|
||
|
||
FUNC_LEAVE_NOAPI(sect->u.indirect.u.iblock)
|
||
} /* end H5HF_sect_indirect_get_iblock() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_merge_row
|
||
*
|
||
* Purpose: Merge two sections of this type
|
||
*
|
||
* Note: Second section always merges into first node
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Tuesday, July 18, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_merge_row(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
H5HF_free_section_t *row_sect1, H5HF_free_section_t *row_sect2)
|
||
{
|
||
H5HF_free_section_t *sect1, *sect2; /* Indirect sections underlying row sections */
|
||
unsigned start_entry1; /* Start entry for section #1 */
|
||
unsigned start_row1, start_col1; /* Starting row & column for section #1 */
|
||
unsigned end_entry1; /* End entry for section #1 */
|
||
unsigned end_row1; /* Ending row for section #1 */
|
||
unsigned start_row2; /* Starting row for section #2 */
|
||
hbool_t merged_rows; /* Flag to indicate that rows was merged together */
|
||
unsigned u; /* Local index variable */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Sanity check parameters */
|
||
HDassert(hdr);
|
||
HDassert(row_sect1);
|
||
HDassert(row_sect1->u.row.under);
|
||
HDassert(row_sect1->sect_info.state == H5FS_SECT_LIVE);
|
||
HDassert(row_sect2);
|
||
HDassert(row_sect2->u.row.under);
|
||
HDassert(row_sect2->sect_info.state == H5FS_SECT_LIVE);
|
||
HDassert(row_sect2->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW);
|
||
|
||
/* Set up indirect section information */
|
||
sect1 = H5HF_sect_indirect_top(row_sect1->u.row.under);
|
||
HDassert(sect1);
|
||
sect2 = H5HF_sect_indirect_top(row_sect2->u.row.under);
|
||
HDassert(sect2);
|
||
|
||
/* Sanity check some assumptions about the indirect sections */
|
||
HDassert(sect1->sect_info.state == H5FS_SECT_LIVE);
|
||
HDassert(sect1->u.indirect.span_size > 0);
|
||
HDassert(sect1->u.indirect.iblock_entries > 0);
|
||
HDassert(sect2->sect_info.state == H5FS_SECT_LIVE);
|
||
HDassert(sect2->u.indirect.span_size > 0);
|
||
HDassert(sect2->u.indirect.iblock_entries > 0);
|
||
HDassert(sect1->u.indirect.iblock_entries == sect2->u.indirect.iblock_entries);
|
||
|
||
/* Set up span information */
|
||
start_row1 = sect1->u.indirect.row;
|
||
start_col1 = sect1->u.indirect.col;
|
||
start_entry1 = (start_row1 * hdr->man_dtable.cparam.width) + start_col1;
|
||
end_entry1 = (start_entry1 + sect1->u.indirect.num_entries) - 1;
|
||
end_row1 = end_entry1 / hdr->man_dtable.cparam.width;
|
||
start_row2 = sect2->u.indirect.row;
|
||
|
||
/* Check for direct sections in second section */
|
||
/* (second indirect section can be parent of indirect section for second
|
||
* row, and thus have no row sections of it's own)
|
||
*/
|
||
if(sect2->u.indirect.dir_nrows > 0) {
|
||
unsigned new_dir_nrows1; /* New value for number of direct rows in first section */
|
||
unsigned src_row2; /* Source row for copying from second section */
|
||
unsigned nrows_moved2; /* Number of rows to move from second section to first */
|
||
|
||
/* Sanity check child row assumptions */
|
||
/* (second indirect section should be at top of equal or deeper
|
||
* hier. of row/indirect sections, so if second indirect section
|
||
* has child row sections, first indirect section _must_ have
|
||
* them also)
|
||
*/
|
||
HDassert(sect1->u.indirect.dir_nrows > 0);
|
||
HDassert(sect1->u.indirect.dir_rows);
|
||
|
||
/* Check for sections sharing a row in the same underlying indirect block */
|
||
if(row_sect1->u.row.under->u.indirect.u.iblock->block_off == row_sect2->u.row.under->u.indirect.u.iblock->block_off
|
||
&& end_row1 == start_row2) {
|
||
H5HF_free_section_t *last_row_sect1; /* Last row in first indirect section */
|
||
|
||
/* Locate the last row section in first indirect section, if we don't already have it */
|
||
if(row_sect1->u.row.row != end_row1)
|
||
last_row_sect1 = sect1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows - 1];
|
||
else
|
||
last_row_sect1 = row_sect1;
|
||
HDassert(last_row_sect1);
|
||
HDassert(last_row_sect1->u.row.row == end_row1);
|
||
|
||
/* Adjust info for first row section, to absorb second row section */
|
||
HDassert((last_row_sect1->u.row.col + last_row_sect1->u.row.num_entries) == row_sect2->u.row.col);
|
||
last_row_sect1->u.row.num_entries += row_sect2->u.row.num_entries;
|
||
|
||
/* Set up parameters for transfer of rows */
|
||
src_row2 = 1;
|
||
nrows_moved2 = sect2->u.indirect.dir_nrows - 1;
|
||
new_dir_nrows1 = (sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows) - 1;
|
||
|
||
/* Indicate that the rows were merged */
|
||
merged_rows = TRUE;
|
||
} /* end if */
|
||
else {
|
||
|
||
/* Set up parameters for transfer of rows */
|
||
src_row2 = 0;
|
||
nrows_moved2 = sect2->u.indirect.dir_nrows;
|
||
new_dir_nrows1 = sect1->u.indirect.dir_nrows + sect2->u.indirect.dir_nrows;
|
||
|
||
/* Indicate that the rows were _not_ merged */
|
||
merged_rows = FALSE;
|
||
} /* end else */
|
||
|
||
/* Check if we need to move additional rows */
|
||
if(nrows_moved2 > 0) {
|
||
H5HF_free_section_t **new_dir_rows; /* Pointer to new array of direct row pointers */
|
||
|
||
/* Extend the first section's row array */
|
||
if(NULL == (new_dir_rows = (H5HF_free_section_t **)H5MM_realloc(sect1->u.indirect.dir_rows, sizeof(H5HF_free_section_t *) * new_dir_nrows1)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
|
||
sect1->u.indirect.dir_rows = new_dir_rows;
|
||
|
||
/* Transfer the second section's rows to first section */
|
||
HDmemcpy(§1->u.indirect.dir_rows[sect1->u.indirect.dir_nrows],
|
||
§2->u.indirect.dir_rows[src_row2],
|
||
(sizeof(H5HF_free_section_t *) * nrows_moved2));
|
||
|
||
/* Re-target the row sections moved from second section */
|
||
for(u = sect1->u.indirect.dir_nrows; u < new_dir_nrows1; u++)
|
||
sect1->u.indirect.dir_rows[u]->u.row.under = sect1;
|
||
|
||
/* Adjust reference counts to account for transferred rows */
|
||
sect1->u.indirect.rc += nrows_moved2;
|
||
sect2->u.indirect.rc -= nrows_moved2;
|
||
|
||
/* Update information for first section */
|
||
sect1->u.indirect.dir_nrows = new_dir_nrows1;
|
||
} /* end if */
|
||
} /* end if */
|
||
else
|
||
/* Indicate that the rows were _not_ merged */
|
||
merged_rows = FALSE;
|
||
|
||
/* Check for indirect sections in second section */
|
||
if(sect2->u.indirect.indir_nents > 0) {
|
||
unsigned new_indir_nents1; /* New value for number of indirect entries in first section */
|
||
|
||
/* Some sanity checks on second indirect section */
|
||
HDassert(sect2->u.indirect.rc > 0);
|
||
HDassert(sect2->u.indirect.indir_nents > 0);
|
||
HDassert(sect2->u.indirect.indir_ents);
|
||
|
||
/* Set up parameters for transfer of entries */
|
||
new_indir_nents1 = sect1->u.indirect.indir_nents + sect2->u.indirect.indir_nents;
|
||
|
||
/* Check if first section can just take over second section's memory buffer */
|
||
if(sect1->u.indirect.indir_ents == NULL) {
|
||
sect1->u.indirect.indir_ents = sect2->u.indirect.indir_ents;
|
||
sect2->u.indirect.indir_ents = NULL;
|
||
} /* end if */
|
||
else {
|
||
H5HF_free_section_t **new_indir_ents; /* Pointer to new array of indirect entries */
|
||
|
||
/* Extend the first section's entry array */
|
||
if(NULL == (new_indir_ents = (H5HF_free_section_t **)H5MM_realloc(sect1->u.indirect.indir_ents, sizeof(H5HF_free_section_t *) * new_indir_nents1)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for row section pointer array")
|
||
sect1->u.indirect.indir_ents = new_indir_ents;
|
||
|
||
/* Transfer the second section's entries to first section */
|
||
HDmemcpy(§1->u.indirect.indir_ents[sect1->u.indirect.indir_nents],
|
||
§2->u.indirect.indir_ents[0],
|
||
(sizeof(H5HF_free_section_t *) * sect2->u.indirect.indir_nents));
|
||
} /* end else */
|
||
|
||
/* Re-target the child indirect sections moved from second section */
|
||
for(u = sect1->u.indirect.indir_nents; u < new_indir_nents1; u++)
|
||
sect1->u.indirect.indir_ents[u]->u.indirect.parent = sect1;
|
||
|
||
/* Adjust reference counts for transferred child indirect sections */
|
||
sect1->u.indirect.rc += sect2->u.indirect.indir_nents;
|
||
sect2->u.indirect.rc -= sect2->u.indirect.indir_nents;
|
||
|
||
/* Update information for first section */
|
||
sect1->u.indirect.indir_nents = new_indir_nents1;
|
||
} /* end if */
|
||
|
||
/* Update information for first section */
|
||
sect1->u.indirect.num_entries += sect2->u.indirect.num_entries;
|
||
sect1->u.indirect.span_size += sect2->u.indirect.span_size;
|
||
|
||
/* Make certain we've tracked the first section's dependents correctly */
|
||
HDassert(sect1->u.indirect.rc ==
|
||
(sect1->u.indirect.indir_nents + sect1->u.indirect.dir_nrows));
|
||
|
||
/* Wrap up, freeing or re-inserting second row section */
|
||
/* (want this to be after the first indirection section is consistent again) */
|
||
if(merged_rows) {
|
||
/* Release second row section */
|
||
/* (indirectly releases second indirect section, since all of it's
|
||
* other dependents are gone)
|
||
*/
|
||
HDassert(sect2->u.indirect.rc == 1);
|
||
if(H5HF_sect_row_free((H5FS_section_info_t *)row_sect2) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free row section")
|
||
} /* end if */
|
||
else {
|
||
/* Decrement ref. count on second indirect section's parent */
|
||
HDassert(sect2->u.indirect.rc == 0);
|
||
if(sect2->u.indirect.parent)
|
||
if(H5HF_sect_indirect_decr(sect2->u.indirect.parent) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't decrement ref. count on parent indirect section")
|
||
|
||
/* Free second indirect section */
|
||
if(H5HF_sect_indirect_free(sect2) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
|
||
|
||
/* Re-add the second section's first row */
|
||
/* (it's already been added to first indirect section, but it's been removed
|
||
* from the free space manager and needs to be re-added)
|
||
*/
|
||
row_sect2->sect_info.type = H5HF_FSPACE_SECT_NORMAL_ROW;
|
||
if(H5HF_space_add(hdr, dxpl_id, row_sect2, H5FS_ADD_SKIP_VALID) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add second row section to free space")
|
||
} /* end else */
|
||
|
||
/* Check if we can create parent indirect section for first section */
|
||
/* (i.e. merged indirect sections cover an entire indirect block) */
|
||
if(sect1->u.indirect.iblock_entries == sect1->u.indirect.num_entries) {
|
||
/* Build parent section for fully populated indirect section */
|
||
HDassert(sect1->u.indirect.parent == NULL);
|
||
if(H5HF_sect_indirect_build_parent(hdr, sect1) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create parent for full indirect section")
|
||
} /* end if */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_merge_row() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_build_parent
|
||
*
|
||
* Purpose: Build a parent indirect section for a full indirect section
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Friday, July 21, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_build_parent(H5HF_hdr_t *hdr, H5HF_free_section_t *sect)
|
||
{
|
||
H5HF_indirect_t *par_iblock; /* Indirect block for parent section */
|
||
H5HF_free_section_t *par_sect = NULL; /* Parent indirect section */
|
||
unsigned par_row, par_col; /* Row & column in parent indirect section */
|
||
unsigned par_entry; /* Entry within parent indirect section */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Sanity check parameters */
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(sect->u.indirect.span_size > 0);
|
||
HDassert(sect->u.indirect.iblock_entries > 0);
|
||
HDassert(sect->u.indirect.iblock_entries == sect->u.indirect.num_entries);
|
||
HDassert(sect->u.indirect.u.iblock);
|
||
HDassert(sect->u.indirect.parent == NULL);
|
||
|
||
/* Get information for creating parent indirect section */
|
||
par_entry = sect->u.indirect.u.iblock->par_entry;
|
||
par_row = par_entry / hdr->man_dtable.cparam.width;
|
||
par_col = par_entry % hdr->man_dtable.cparam.width;
|
||
HDassert(par_row >= hdr->man_dtable.max_direct_rows);
|
||
par_iblock = sect->u.indirect.u.iblock->parent;
|
||
HDassert(par_iblock);
|
||
|
||
/* Create parent indirect section */
|
||
if(NULL == (par_sect = H5HF_sect_indirect_new(hdr, sect->sect_info.addr,
|
||
sect->sect_info.size, par_iblock, par_iblock->block_off,
|
||
par_row, par_col, 1)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section")
|
||
|
||
/* No rows of direct blocks covered in parent, reset direct row information */
|
||
par_sect->u.indirect.dir_nrows = 0;
|
||
par_sect->u.indirect.dir_rows = NULL;
|
||
|
||
/* Allocate space for the child indirect sections */
|
||
par_sect->u.indirect.indir_nents = 1;
|
||
if(NULL == (par_sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_malloc(sizeof(H5HF_free_section_t *))))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "allocation failed for indirect section pointer array")
|
||
|
||
/* Attach sections together */
|
||
sect->u.indirect.parent = par_sect;
|
||
sect->u.indirect.par_entry = par_entry;
|
||
par_sect->u.indirect.indir_ents[0] = sect;
|
||
par_sect->u.indirect.rc = 1;
|
||
|
||
done:
|
||
if(ret_value < 0)
|
||
if(par_sect && H5HF_sect_indirect_free(par_sect) < 0)
|
||
HDONE_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
|
||
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_build_parent() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_shrink
|
||
*
|
||
* Purpose: "Shrink" container w/section
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 24, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_shrink(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
|
||
{
|
||
unsigned u; /* Local index variable */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Sanity check parameters */
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
|
||
/* Sanity check some assumptions about the indirect section */
|
||
HDassert(sect->u.indirect.dir_nrows > 0 || sect->u.indirect.indir_nents > 0);
|
||
|
||
/* Walk through direct rows, freeing them */
|
||
for(u = 0; u < sect->u.indirect.dir_nrows; u++) {
|
||
/* Remove the normal rows from free space manager */
|
||
if(sect->u.indirect.dir_rows[u]->sect_info.type != H5HF_FSPACE_SECT_FIRST_ROW) {
|
||
HDassert(sect->u.indirect.dir_rows[u]->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
|
||
if(H5HF_space_remove(hdr, dxpl_id, sect->u.indirect.dir_rows[u]) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTREMOVE, FAIL, "can't remove section from heap free space")
|
||
} /* end if */
|
||
|
||
/* Release the row section */
|
||
if(H5HF_sect_row_free_real(sect->u.indirect.dir_rows[u]) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free child section node")
|
||
} /* end for */
|
||
|
||
/* Walk through indirect entries, freeing them (recursively) */
|
||
for(u = 0; u < sect->u.indirect.indir_nents; u++)
|
||
if(H5HF_sect_indirect_shrink(hdr, dxpl_id, sect->u.indirect.indir_ents[u]) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free child section node")
|
||
|
||
/* Free the indirect section itself */
|
||
if(H5HF_sect_indirect_free(sect) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* end H5HF_sect_indirect_shrink() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_serialize
|
||
*
|
||
* Purpose: Serialize a "live" indirect section into a buffer
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 3, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_serialize(H5HF_hdr_t *hdr, const H5HF_free_section_t *sect,
|
||
uint8_t *buf)
|
||
{
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
HDassert(buf);
|
||
|
||
/* Check if this indirect section has a parent & forward if this section is first */
|
||
if(sect->u.indirect.parent) {
|
||
if(sect->sect_info.addr == sect->u.indirect.parent->sect_info.addr)
|
||
if(H5HF_sect_indirect_serialize(hdr, sect->u.indirect.parent, buf) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTSERIALIZE, FAIL, "can't serialize indirect section's parent indirect section")
|
||
} /* end if */
|
||
else {
|
||
/* Indirect range's indirect block's block offset */
|
||
if(sect->sect_info.state == H5FS_SECT_LIVE) {
|
||
HDassert(sect->u.indirect.u.iblock);
|
||
UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock->block_off, hdr->heap_off_size);
|
||
} /* end if */
|
||
else
|
||
UINT64ENCODE_VAR(buf, sect->u.indirect.u.iblock_off, hdr->heap_off_size);
|
||
|
||
/* Indirect range's row */
|
||
UINT16ENCODE(buf, sect->u.indirect.row);
|
||
|
||
/* Indirect range's column */
|
||
UINT16ENCODE(buf, sect->u.indirect.col);
|
||
|
||
/* Indirect range's # of entries */
|
||
UINT16ENCODE(buf, sect->u.indirect.num_entries);
|
||
} /* end else */
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_indirect_serialize() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_deserialize
|
||
*
|
||
* Purpose: Deserialize a buffer into a "live" indirect section
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 3, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static H5FS_section_info_t *
|
||
H5HF_sect_indirect_deserialize(H5HF_hdr_t *hdr, hid_t dxpl_id,
|
||
const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size,
|
||
unsigned *des_flags)
|
||
{
|
||
H5HF_free_section_t *new_sect; /* New indirect section */
|
||
hsize_t iblock_off; /* Indirect block's offset */
|
||
unsigned start_row; /* Indirect section's start row */
|
||
unsigned start_col; /* Indirect section's start column */
|
||
unsigned nentries; /* Indirect section's number of entries */
|
||
unsigned start_entry; /* Start entry in indirect block */
|
||
unsigned end_entry; /* End entry in indirect block */
|
||
unsigned end_row; /* End row in indirect block */
|
||
unsigned end_col; /* End column in indirect block */
|
||
H5FS_section_info_t *ret_value = NULL; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
/* Check arguments. */
|
||
HDassert(hdr);
|
||
HDassert(buf);
|
||
HDassert(H5F_addr_defined(sect_addr));
|
||
HDassert(sect_size);
|
||
|
||
/* Indirect range's indirect block's block offset */
|
||
UINT64DECODE_VAR(buf, iblock_off, hdr->heap_off_size);
|
||
|
||
/* Indirect section's row */
|
||
UINT16DECODE(buf, start_row);
|
||
|
||
/* Indirect section's column */
|
||
UINT16DECODE(buf, start_col);
|
||
|
||
/* Indirect section's # of entries */
|
||
UINT16DECODE(buf, nentries);
|
||
|
||
/* Create free space section node */
|
||
if(NULL == (new_sect = H5HF_sect_indirect_new(hdr, sect_addr, sect_size,
|
||
NULL, iblock_off, start_row, start_col, nentries)))
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't create indirect section")
|
||
|
||
/* Compute start entry */
|
||
start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
|
||
|
||
/* Compute end column & row */
|
||
end_entry = (start_entry + nentries) - 1;
|
||
end_row = end_entry / hdr->man_dtable.cparam.width;
|
||
end_col = end_entry % hdr->man_dtable.cparam.width;
|
||
|
||
/* Initialize rows for new indirect section */
|
||
if(H5HF_sect_indirect_init_rows(hdr, dxpl_id, new_sect, TRUE, NULL,
|
||
H5FS_ADD_DESERIALIZING, new_sect->u.indirect.row, new_sect->u.indirect.col,
|
||
end_row, end_col) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize indirect section")
|
||
|
||
/* Indicate that this section shouldn't be added to free space manager's list */
|
||
*des_flags |= H5FS_DESERIALIZE_NO_ADD;
|
||
|
||
/* Set return value */
|
||
ret_value = (H5FS_section_info_t *)new_sect;
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_indirect_deserialize() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_free
|
||
*
|
||
* Purpose: Free a 'indirect' section node
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 3, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_free(H5HF_free_section_t *sect)
|
||
{
|
||
H5HF_indirect_t *iblock = NULL; /* Indirect block for section */
|
||
herr_t ret_value = SUCCEED; /* Return value */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT
|
||
|
||
HDassert(sect);
|
||
|
||
/* Release the memory for tracking direct rows */
|
||
sect->u.indirect.dir_rows = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.dir_rows);
|
||
|
||
/* Release the memory for tracking indirect entries */
|
||
sect->u.indirect.indir_ents = (H5HF_free_section_t **)H5MM_xfree(sect->u.indirect.indir_ents);
|
||
|
||
/* Check for live reference to an indirect block */
|
||
if(sect->sect_info.state == H5FS_SECT_LIVE) {
|
||
/* Get indirect block, if there was one */
|
||
if(sect->u.indirect.u.iblock)
|
||
iblock = sect->u.indirect.u.iblock;
|
||
} /* end if */
|
||
|
||
/* Release the sections */
|
||
if(H5HF_sect_node_free(sect, iblock) < 0)
|
||
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
|
||
|
||
done:
|
||
FUNC_LEAVE_NOAPI(ret_value)
|
||
} /* H5HF_sect_indirect_free() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_valid
|
||
*
|
||
* Purpose: Check the validity of a section
|
||
*
|
||
* Return: Success: non-negative
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Friday, July 21, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_valid(const H5HF_hdr_t *hdr, const H5HF_free_section_t *sect)
|
||
{
|
||
unsigned start_row; /* Row for first block covered */
|
||
unsigned start_col; /* Column for first block covered */
|
||
unsigned start_entry; /* Entry for first block covered */
|
||
unsigned end_row; /* Row for last block covered */
|
||
unsigned end_entry; /* Entry for last block covered */
|
||
unsigned u; /* Local index variable */
|
||
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Sanity check arguments */
|
||
HDassert(hdr);
|
||
HDassert(sect);
|
||
|
||
/* Compute starting entry, column & row */
|
||
start_row = sect->u.indirect.row;
|
||
start_col = sect->u.indirect.col;
|
||
start_entry = (start_row * hdr->man_dtable.cparam.width) + start_col;
|
||
|
||
/* Compute ending entry, column & row */
|
||
end_entry = (start_entry + sect->u.indirect.num_entries) - 1;
|
||
end_row = end_entry / hdr->man_dtable.cparam.width;
|
||
|
||
/* Sanity check any direct rows */
|
||
if(sect->u.indirect.dir_nrows > 0) {
|
||
unsigned dir_nrows; /* Number of direct rows in section */
|
||
unsigned max_dir_row; /* Maximum direct row in section */
|
||
|
||
/* Check for indirect rows in section */
|
||
if(end_row >= hdr->man_dtable.max_direct_rows)
|
||
max_dir_row = hdr->man_dtable.max_direct_rows - 1;
|
||
else
|
||
max_dir_row = end_row;
|
||
|
||
/* Iterate over direct rows, checking pointer references */
|
||
dir_nrows = (max_dir_row - start_row) + 1;
|
||
HDassert(dir_nrows == sect->u.indirect.dir_nrows);
|
||
for(u = 0; u < dir_nrows; u++) {
|
||
const H5HF_free_section_t *tmp_row_sect; /* Pointer to row section */
|
||
|
||
tmp_row_sect = sect->u.indirect.dir_rows[u];
|
||
HDassert(tmp_row_sect->sect_info.type == H5HF_FSPACE_SECT_FIRST_ROW
|
||
|| tmp_row_sect->sect_info.type == H5HF_FSPACE_SECT_NORMAL_ROW);
|
||
HDassert(tmp_row_sect->u.row.under == sect);
|
||
HDassert(tmp_row_sect->u.row.row == (start_row + u));
|
||
if(u > 0) {
|
||
const H5HF_free_section_t *tmp_row_sect2; /* Pointer to row section */
|
||
|
||
tmp_row_sect2 = sect->u.indirect.dir_rows[u - 1];
|
||
HDassert(tmp_row_sect2->u.row.row < tmp_row_sect->u.row.row);
|
||
HDassert(H5F_addr_lt(tmp_row_sect2->sect_info.addr, tmp_row_sect->sect_info.addr));
|
||
HDassert(tmp_row_sect2->sect_info.size <= tmp_row_sect->sect_info.size);
|
||
} /* end if */
|
||
} /* end for */
|
||
} /* end if */
|
||
|
||
/* Sanity check any indirect entries */
|
||
if(sect->u.indirect.indir_nents > 0) {
|
||
/* Basic sanity checks */
|
||
if(sect->sect_info.state == H5FS_SECT_LIVE) {
|
||
HDassert(sect->u.indirect.iblock_entries);
|
||
HDassert(sect->u.indirect.indir_nents <= sect->u.indirect.iblock_entries);
|
||
} /* end if */
|
||
HDassert(sect->u.indirect.indir_ents);
|
||
|
||
/* Sanity check each child indirect section */
|
||
for(u = 0; u < sect->u.indirect.indir_nents; u++) {
|
||
const H5HF_free_section_t *tmp_child_sect; /* Pointer to child indirect section */
|
||
|
||
tmp_child_sect = sect->u.indirect.indir_ents[u];
|
||
HDassert(tmp_child_sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
|
||
HDassert(tmp_child_sect->u.indirect.parent == sect);
|
||
if(u > 0) {
|
||
const H5HF_free_section_t *tmp_child_sect2; /* Pointer to child indirect section */
|
||
|
||
tmp_child_sect2 = sect->u.indirect.indir_ents[u - 1];
|
||
HDassert(H5F_addr_lt(tmp_child_sect2->sect_info.addr, tmp_child_sect->sect_info.addr));
|
||
} /* end if */
|
||
|
||
/* Recursively check child indirect section */
|
||
H5HF_sect_indirect_valid(hdr, tmp_child_sect);
|
||
} /* end for */
|
||
} /* end if */
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* H5HF_sect_indirect_valid() */
|
||
|
||
|
||
/*-------------------------------------------------------------------------
|
||
* Function: H5HF_sect_indirect_debug
|
||
*
|
||
* Purpose: Dump debugging information about an indirect free space section
|
||
*
|
||
* Return: Success: non-negative
|
||
*
|
||
* Failure: negative
|
||
*
|
||
* Programmer: Quincey Koziol
|
||
* Monday, July 3, 2006
|
||
*
|
||
*-------------------------------------------------------------------------
|
||
*/
|
||
static herr_t
|
||
H5HF_sect_indirect_debug(const H5HF_free_section_t *sect,
|
||
FILE *stream, int indent, int fwidth)
|
||
{
|
||
FUNC_ENTER_NOAPI_NOINIT_NOERR
|
||
|
||
/* Check arguments. */
|
||
HDassert(sect);
|
||
|
||
/* Print indirect section information */
|
||
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
|
||
"Row:",
|
||
sect->u.indirect.row);
|
||
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
|
||
"Column:",
|
||
sect->u.indirect.col);
|
||
HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth,
|
||
"Number of entries:",
|
||
sect->u.indirect.num_entries);
|
||
|
||
FUNC_LEAVE_NOAPI(SUCCEED)
|
||
} /* H5HF_sect_indirect_debug() */
|
||
|