diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5.c | 1 | ||||
-rw-r--r-- | src/H5AC.c | 1 | ||||
-rw-r--r-- | src/H5ACprivate.h | 3 | ||||
-rw-r--r-- | src/H5Cpkg.h | 2 | ||||
-rw-r--r-- | src/H5D.c | 2 | ||||
-rw-r--r-- | src/H5Edefin.h | 1 | ||||
-rw-r--r-- | src/H5Einit.h | 5 | ||||
-rw-r--r-- | src/H5Epubgen.h | 2 | ||||
-rw-r--r-- | src/H5Eterm.h | 1 | ||||
-rw-r--r-- | src/H5F.c | 8 | ||||
-rw-r--r-- | src/H5FDpublic.h | 12 | ||||
-rw-r--r-- | src/H5FS.c | 1887 | ||||
-rw-r--r-- | src/H5FScache.c | 426 | ||||
-rw-r--r-- | src/H5FSdbg.c | 231 | ||||
-rw-r--r-- | src/H5FSpkg.h | 127 | ||||
-rw-r--r-- | src/H5FSprivate.h | 120 | ||||
-rw-r--r-- | src/H5FSpublic.h | 53 | ||||
-rw-r--r-- | src/H5HF.c | 67 | ||||
-rw-r--r-- | src/H5HFcache.c | 118 | ||||
-rw-r--r-- | src/H5HFdbg.c | 330 | ||||
-rw-r--r-- | src/H5HFdblock.c | 447 | ||||
-rw-r--r-- | src/H5HFflist.c | 614 | ||||
-rw-r--r-- | src/H5HFhdr.c | 100 | ||||
-rw-r--r-- | src/H5HFiblock.c | 691 | ||||
-rw-r--r-- | src/H5HFint.c | 465 | ||||
-rw-r--r-- | src/H5HFiter.c | 2 | ||||
-rw-r--r-- | src/H5HFpkg.h | 189 | ||||
-rw-r--r-- | src/H5HFprivate.h | 11 | ||||
-rw-r--r-- | src/H5HFsection.c | 595 | ||||
-rw-r--r-- | src/H5HFspace.c | 291 | ||||
-rw-r--r-- | src/H5HFtest.c | 31 | ||||
-rw-r--r-- | src/H5err.txt | 1 | ||||
-rw-r--r-- | src/H5private.h | 1 | ||||
-rwxr-xr-x | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/Makefile.in | 50 |
35 files changed, 4773 insertions, 2118 deletions
@@ -231,6 +231,7 @@ H5_term_library(void) * that depend on them. -QAK */ if(pending==0) { + pending += DOWN(FS); pending += DOWN(AC); pending += DOWN(Z); pending += DOWN(FD); @@ -482,6 +482,7 @@ static const char * H5AC_entry_type_names[H5AC_NTYPES] = "fractal heap headers", "fractal heap direct blocks", "fractal heap indirect blocks", + "free space headers", "test entry" /* for testing only -- not used for actual files */ }; diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index 6234a5e..6638be4 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -49,10 +49,11 @@ typedef enum { H5AC_BT2_HDR_ID, /*v2 B-tree header */ H5AC_BT2_INT_ID, /*v2 B-tree internal node */ H5AC_BT2_LEAF_ID, /*v2 B-tree leaf node */ - H5AC_TEST_ID, /*test entry -- not used for actual files */ H5AC_FHEAP_HDR_ID, /*fractal heap header */ H5AC_FHEAP_DBLOCK_ID, /*fractal heap direct block */ H5AC_FHEAP_IBLOCK_ID, /*fractal heap indirect block */ + H5AC_FSPACE_HDR_ID, /*free space header */ + H5AC_TEST_ID, /*test entry -- not used for actual files */ H5AC_NTYPES /* Number of types, must be last */ } H5AC_type_t; diff --git a/src/H5Cpkg.h b/src/H5Cpkg.h index 8d9a5a6..12fcfe5 100644 --- a/src/H5Cpkg.h +++ b/src/H5Cpkg.h @@ -695,7 +695,7 @@ ****************************************************************************/ #define H5C__H5C_T_MAGIC 0x005CAC0E -#define H5C__MAX_NUM_TYPE_IDS 12 +#define H5C__MAX_NUM_TYPE_IDS 13 #define H5C__PREFIX_LEN 32 struct H5C_t @@ -4034,7 +4034,7 @@ H5D_flush(const H5F_t *f, hid_t dxpl_id, unsigned flags) /* Check args */ assert(f); - /* Update layout message for compact dataset */ + /* Retrieve the # of outstanding dataset IDs */ num_dsets=H5F_get_obj_count(f, H5F_OBJ_DATASET); /* Check for something to do */ diff --git a/src/H5Edefin.h b/src/H5Edefin.h index 75dc2ce..f5bcbcf 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -46,6 +46,7 @@ hid_t H5E_TST_g = FAIL; /* Ternary Search Trees */ hid_t H5E_ARGS_g = FAIL; /* Invalid arguments to routine */ hid_t H5E_ERROR_g = FAIL; /* Error API */ hid_t H5E_PLINE_g = FAIL; /* Data filters */ +hid_t H5E_FSPACE_g = FAIL; /* File Free Space */ hid_t H5E_CACHE_g = FAIL; /* Object cache */ /* Minor error IDs */ diff --git a/src/H5Einit.h b/src/H5Einit.h index ee1a5cf..72d581c 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -153,6 +153,11 @@ if((msg = H5E_create_msg(cls, H5E_MAJOR, "Data filters"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_PLINE_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_FSPACE_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MAJOR, "File Free Space"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_FSPACE_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") assert(H5E_CACHE_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MAJOR, "Object cache"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index a05e5ed..001346f 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -49,6 +49,7 @@ #define H5E_ARGS (H5OPEN H5E_ARGS_g) #define H5E_ERROR (H5OPEN H5E_ERROR_g) #define H5E_PLINE (H5OPEN H5E_PLINE_g) +#define H5E_FSPACE (H5OPEN H5E_FSPACE_g) #define H5E_CACHE (H5OPEN H5E_CACHE_g) H5_DLLVAR hid_t H5E_DATASET_g; /* Dataset */ H5_DLLVAR hid_t H5E_FUNC_g; /* Function entry/exit */ @@ -76,6 +77,7 @@ H5_DLLVAR hid_t H5E_TST_g; /* Ternary Search Trees */ H5_DLLVAR hid_t H5E_ARGS_g; /* Invalid arguments to routine */ H5_DLLVAR hid_t H5E_ERROR_g; /* Error API */ H5_DLLVAR hid_t H5E_PLINE_g; /* Data filters */ +H5_DLLVAR hid_t H5E_FSPACE_g; /* File Free Space */ H5_DLLVAR hid_t H5E_CACHE_g; /* Object cache */ /*********************/ diff --git a/src/H5Eterm.h b/src/H5Eterm.h index f2968f1..1b28d16 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -47,6 +47,7 @@ H5E_TST_g= H5E_ARGS_g= H5E_ERROR_g= H5E_PLINE_g= +H5E_FSPACE_g= H5E_CACHE_g= (-1); /* Reset minor error IDs */ @@ -27,6 +27,7 @@ #include "H5Fpkg.h" /* File access */ #include "H5FDprivate.h" /* File drivers */ #include "H5FLprivate.h" /* Free lists */ +#include "H5FSprivate.h" /* File free space */ #include "H5Gprivate.h" /* Groups */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ @@ -2332,6 +2333,13 @@ H5F_flush(H5F_t *f, hid_t dxpl_id, H5F_scope_t scope, unsigned flags) if (H5F_flush(f->mtab.child[i].file, dxpl_id, scope, flags) < 0) nerrors++; + /* Flush any cached free space info */ + /* (Make certain that this is before the metadata cache flush, so the + * updated free space info in the metadata cache gets flushed out to disk) + */ + if (H5FS_flush(f, dxpl_id, flags) < 0) + HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush free space info") + /* Flush any cached dataset storage raw data */ if (H5D_flush(f, dxpl_id, flags) < 0) HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush dataset cache") diff --git a/src/H5FDpublic.h b/src/H5FDpublic.h index cbfedba..3ba7275 100644 --- a/src/H5FDpublic.h +++ b/src/H5FDpublic.h @@ -59,6 +59,18 @@ typedef enum H5FD_mem_t { #define H5FD_MEM_FHEAP_IBLOCK H5FD_MEM_OHDR #define H5FD_MEM_FHEAP_DBLOCK H5FD_MEM_LHEAP +/* Map "free space" header blocks to 'ohdr' type file memory, since its + * a fair amount of work to add a new kind of file memory and they are similar + * enough to object headers and probably too minor to deserve their own type. + * + * Map "free space" serialized sections to 'lheap' type file memory, since they + * are similar enough to local heap info. + * + * -QAK + */ +#define H5FD_MEM_FSPACE_HDR H5FD_MEM_OHDR +#define H5FD_MEM_FSPACE_SECTS H5FD_MEM_LHEAP + /* * A free-list map which maps all types of allocation requests to a single * free list. This is useful for drivers that don't really care about diff --git a/src/H5FS.c b/src/H5FS.c new file mode 100644 index 0000000..7ed766f --- /dev/null +++ b/src/H5FS.c @@ -0,0 +1,1887 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Tuesday, May 2, 2006 + * + * Purpose: File free space functions. + * + * Note: (Used to be in the H5HFflist.c file, prior to the date above) + * + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5FS_PACKAGE /*suppress error about including H5FSpkg */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5FS_init_interface + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FSpkg.h" /* File free space */ +#include "H5MFprivate.h" /* File memory management */ +#include "H5Vprivate.h" /* Vectors and arrays */ + +/****************/ +/* Local Macros */ +/****************/ + +/* File free space format version #'s */ +#define H5FS_SECTS_VERSION 0 /* Serialized sections */ + +/* Default starting size of section buffer */ +#define H5FS_SECT_SIZE_DEFAULT 64 + +/* Max. height of the skip list holding free list nodes */ +#define H5FS_DEFAULT_SKIPLIST_HEIGHT 16 + +/* Size of the free space serialized sections on disk */ +#define H5FS_SECTS_PREFIX_SIZE(f) ( \ + /* General metadata fields */ \ + H5FS_METADATA_PREFIX_SIZE \ + \ + /* Free space serialized sections specific fields */ \ + + H5F_SIZEOF_ADDR(f) /* Address of free space header for these sections */ \ + ) + +/******************/ +/* Local Typedefs */ +/******************/ + +/* Free space node for free space sections of the same size */ +typedef struct H5FS_node_t { + hsize_t sect_size; /* Size of all sections on list */ + H5SL_t *sect_list; /* Skip list to hold pointers to actual free list section node */ +} H5FS_node_t; + +/* Free space section bin info */ +typedef struct H5FS_bin_t { + size_t sect_count; /* Total # of sections in this bin */ + H5SL_t *bin_list; /* Skip list of differently sized sections */ +} H5FS_bin_t; + +/* User data for skip list iterator callback for syncing section info */ +typedef struct { + H5F_t *f; /* Pointer to the file */ + hid_t dxpl_id; /* Dataset transfer property list */ +} H5FS_iter_ud1_t; + +/* User data for skip list iterator callback for iterating over section size nodes when syncing */ +typedef struct { + H5FS_t *fspace; /* Free space manager info */ + uint8_t **p; /* Pointer to address of buffer pointer to serialize with */ + unsigned sect_cnt_size; /* # of bytes to encode section size counts in */ +} H5FS_iter_ud2_t; + +/* User data for skip list iterator callback for iterating over section size nodes */ +typedef struct { + H5FS_t *fspace; /* Free space manager info */ + H5FS_operator_t op; /* Operator for the iteration */ + void *op_data; /* Information to pass to the operator */ +} H5FS_iter_ud3_t; + + +/********************/ +/* Package Typedefs */ +/********************/ + +/* Main free space info */ +struct H5FS_t { + /* Stored values (from header) */ + H5FS_hdr_t *hdr; /* Pointer to header info */ + + /* Computed/cached values */ + haddr_t addr; /* Address of free space header on disk */ + unsigned nbins; /* Number of bins */ + size_t serial_size; /* Total serialized size of all section nodes */ + size_t size_count; /* Number of differently sized sections */ + unsigned sect_prefix_size; /* Size of the section serialization prefix (in bytes) */ + unsigned sect_off_size; /* Size of a section offset (in bytes) */ + unsigned sect_len_size; /* Size of a section length (in bytes) */ + hbool_t using_bins; /* Flag to indicate that all nodes are in the bins */ + hbool_t dirty; /* Space information is dirty */ + + /* Memory data structures (not stored directly) */ + H5FS_section_class_t *sect_cls; /* Array of section classes for this free list */ + H5FS_section_info_t *single; /* Section information when free list has only one free section */ + H5SL_operator_t node_free_op; /* Callback for freeing nodes when free list is destroyed */ + H5FS_bin_t *bins; /* Array of lists of lists of free sections */ +}; + + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5FS_open_add(H5FS_t *fspace); +static herr_t H5FS_open_remove(H5FS_t *fspace); +static herr_t H5FS_init(H5FS_t *fspace); +static herr_t H5FS_node_free_cb(void *item, void *key, void *op_data); +static herr_t H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); +static herr_t H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); +static herr_t H5FS_add_bin_node(H5FS_t *fspace, H5FS_section_info_t *node); +static htri_t H5FS_find_bin_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node); +static herr_t H5FS_serialize_sect_cb(void *_item, void UNUSED *key, void *_udata); +static herr_t H5FS_serialize_node_cb(void *_item, void UNUSED *key, void *_udata); +static size_t H5FS_serialize_size(H5FS_t *fspace); +static herr_t H5FS_serialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); +static herr_t H5FS_deserialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); +static herr_t H5FS_flush_cb(void *_item, void *key, void *_udata); + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Declare a free list to manage the H5FS_section_class_t sequence information */ +H5FL_SEQ_DEFINE(H5FS_section_class_t); + +/* Declare a free list to manage the H5FS_hdr_t struct */ +H5FL_DEFINE(H5FS_hdr_t); + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Skip list to track open free space managers */ +H5SL_t *H5FS_open_g = NULL; + +/* Declare a free list to manage the H5FS_t struct */ +H5FL_DEFINE_STATIC(H5FS_t); + +/* Declare a free list to manage the H5FS_node_t struct */ +H5FL_DEFINE_STATIC(H5FS_node_t); + +/* Declare a free list to manage the H5FS_bin_t sequence information */ +H5FL_SEQ_DEFINE_STATIC(H5FS_bin_t); + +/* Declare a free list to manage free space section data to/from disk */ +H5FL_BLK_DEFINE_STATIC(sect_block); + + + +/*------------------------------------------------------------------------- + * Function: H5FS_init_interface + * + * Purpose: Initialize static free space memory structures + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_init_interface(void) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_init_interface) + + /* Create the skip list to track open free space managers */ + HDassert(H5FS_open_g == NULL); + if(NULL == (H5FS_open_g = H5SL_create(H5SL_TYPE_HADDR, 0.5, H5FS_DEFAULT_SKIPLIST_HEIGHT))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for tracking open free space managers") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_init_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_term_interface + * + * Purpose: Terminate this interface. + * + * Return: Success: Positive if anything was done that might + * affect other interfaces; zero otherwise. + * + * Failure: Negative. + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +int +H5FS_term_interface(void) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_term_interface) + + if(H5_interface_initialize_g) { + /* Release the open free space manager list */ + HDassert(H5FS_open_g); + + /* All the free space managers should be shut down by now */ + HDassert(H5SL_count(H5FS_open_g) == 0); + + /* Close the skip list to track the open free space managers */ + H5SL_close(H5FS_open_g); + H5FS_open_g = NULL; + + /* Interface has been shut down */ + H5_interface_initialize_g = 0; + } /* end if */ + + FUNC_LEAVE_NOAPI(0) +} /* end H5FS_term_interface() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_open_add + * + * Purpose: Add a free space manager to the list of open ones + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_open_add(H5FS_t *fspace) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_open_add) + + /* Check arguments. */ + HDassert(fspace); + + /* Add the free space manager to the list of open managers */ + if(H5SL_insert(H5FS_open_g, fspace, &fspace->addr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space manager into skip list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_open_add() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_open_remove + * + * Purpose: Remove a free space manager from the list of open ones + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_open_remove(H5FS_t *fspace) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_open_remove) + + /* Check arguments. */ + HDassert(fspace); + + /* Remove the free space manager from the list of open managers */ + if(NULL == H5SL_remove(H5FS_open_g, &fspace->addr)) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDELETE, FAIL, "can't remove free space manager from skip list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_open_remove() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_init + * + * Purpose: Initialize free space memory structures + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, April 18, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_init(H5FS_t *fspace) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_init) + + /* Check arguments. */ + HDassert(fspace); + + /* Initialize free space memory structures */ + fspace->single = NULL; + fspace->bins = NULL; + fspace->using_bins = FALSE; + fspace->serial_size = 0; + fspace->size_count = 0; + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5FS_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_create + * + * Purpose: Allocate & initialize file free space info + * + * Return: Success: Pointer to free space structure + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * Tuesday, March 7, 2006 + * + *------------------------------------------------------------------------- + */ +H5FS_t * +H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create, + H5SL_operator_t node_free_op, size_t nclasses, + H5FS_section_class_t *classes, const void *cls_init_udata) +{ + H5FS_t *fspace = NULL; /* New free space structure */ + H5FS_hdr_t *fs_hdr = NULL; /* New free space header */ + size_t u; /* Local index variable */ + H5FS_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_create, NULL) + + /* Check arguments. */ + HDassert(fs_addr); + HDassert(fs_create->shrink_percent); + HDassert(fs_create->shrink_percent < fs_create->expand_percent); + HDassert(fs_create->max_sect_size); + HDassert(nclasses == 0 || classes); + + /* + * Allocate free space structure + */ + if(NULL == (fspace = H5FL_CALLOC(H5FS_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space free list") + + /* Set immutable free list parameters */ + fspace->node_free_op = node_free_op; + fspace->sect_cls = classes; + + /* Initialize the section classes for this free space list */ + for(u = 0; u < nclasses; u++) { + /* Call the class initialization routine, if there is one */ + if(fspace->sect_cls[u].init) + if((fspace->sect_cls[u].init)(&fspace->sect_cls[u], cls_init_udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "unable to initialize section class") + } /* end for */ + + /* Allocate space for the free space header */ + if(HADDR_UNDEF == (fspace->addr = H5MF_alloc(f, H5FD_MEM_FSPACE_HDR, dxpl_id, (hsize_t)H5FS_HEADER_SIZE(f)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space header") + *fs_addr = fspace->addr; + + /* Construct the free space header */ + if(NULL == (fs_hdr = H5FL_MALLOC(H5FS_hdr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HDmemset(&fs_hdr->cache_info, 0, sizeof(H5AC_info_t)); + + /* Initialize information for header */ + fs_hdr->tot_space = 0; + fs_hdr->sect_count = 0; + fs_hdr->nclasses = nclasses; + fs_hdr->client = fs_create->client; + fs_hdr->shrink_percent = fs_create->shrink_percent; + fs_hdr->expand_percent = fs_create->expand_percent; + fs_hdr->max_sect_addr = fs_create->max_sect_addr; + fs_hdr->max_sect_size = fs_create->max_sect_size; + + /* Allocate space for the free space sections */ + fs_hdr->alloc_sect_size = H5FS_SECT_SIZE_DEFAULT; +#ifdef QAK +HDfprintf(stderr, "%s: fs_hdr->alloc_sect_size = %Hu\n", FUNC, fs_hdr->alloc_sect_size); +#endif /* QAK */ + if(HADDR_UNDEF == (fs_hdr->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fs_hdr->alloc_sect_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "file allocation failed for free space sections") + + /* Cache the new free space header */ + if(H5AC_set(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, fs_hdr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to cache") + fs_hdr = NULL; + + /* Lock the free space header into memory */ + if(NULL == (fs_hdr = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to load free space header") + + /* Point free space wrapper at header and pin it in the cache */ + fspace->hdr = fs_hdr; + if(H5AC_pin_protected_entry(f, fs_hdr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space header") + + /* Unlock free space header, now pinned */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fspace->addr, fs_hdr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, NULL, "unable to release free space header") + fs_hdr = NULL; + + /* Set modifiable free space parameters */ + fspace->nbins = H5V_log2_gen(fspace->hdr->max_sect_size); + fspace->sect_prefix_size = H5FS_SECTS_PREFIX_SIZE(f); + fspace->sect_off_size = (fspace->hdr->max_sect_addr + 7) / 8; + fspace->sect_len_size = (H5V_log2_gen(fspace->hdr->max_sect_size) + 7) / 8; + H5FS_init(fspace); +#ifdef QAK +HDfprintf(stderr, "%s: fspace->nbins = %u\n", FUNC, fspace->nbins); +HDfprintf(stderr, "%s: fspace->sect_off_size = %u, fspace->sect_len_size = %u\n", FUNC, fspace->sect_off_size, fspace->sect_len_size); +#endif /* QAK */ + + /* Set current space used for free space sections (for no sections) */ + fspace->hdr->sect_size = H5FS_serialize_size(fspace); +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_size); +#endif /* QAK */ + + /* Flag the free space as dirty */ + fspace->dirty = TRUE; + + /* Add the free space manager to the list of open free space managers */ + if(H5FS_open_add(fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space header to open list") + + /* Set return value */ + ret_value = fspace; + +done: + if(!ret_value) { + if(fspace) + if(H5FS_close(f, dxpl_id, fspace) < 0) + HDONE_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "unable to release free space info") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_open + * + * Purpose: Open an existing file free space info structure on disk + * + * Return: Success: Pointer to free space structure + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * Tuesday, May 2, 2006 + * + *------------------------------------------------------------------------- + */ +H5FS_t * +H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, H5SL_operator_t node_free_op, + size_t nclasses, H5FS_section_class_t *classes, const void *cls_init_udata) +{ + H5FS_hdr_t *fs_hdr = NULL; /* Free space header loaded from file */ + H5FS_t *fspace = NULL; /* New free space structure */ + size_t u; /* Local index variable */ + H5FS_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_open, NULL) +#ifdef QAK +HDfprintf(stderr, "%s: Opening free space manager\n", FUNC); +#endif /* QAK */ + + /* Check arguments. */ + HDassert(H5F_addr_defined(fs_addr)); + HDassert(nclasses == 0 || classes); + + /* Allocate free space structure */ + if(NULL == (fspace = H5FL_MALLOC(H5FS_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space free list") + + /* Protect the free space header */ + if(NULL == (fs_hdr = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, NULL, "unable to protect free space header") + + /* Point free space wrapper at header and pin it in the cache */ + fspace->hdr = fs_hdr; + if(H5AC_pin_protected_entry(f, fs_hdr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTPIN, NULL, "unable to pin free space header") + + /* Release the free space header */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fs_hdr, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, NULL, "unable to release free space header") + fs_hdr = NULL; + + /* Set immutable free list parameters */ + fspace->addr = fs_addr; + fspace->node_free_op = node_free_op; + HDassert(fspace->hdr->nclasses == nclasses); + fspace->sect_cls = classes; + + /* Initialize the section classes for this free space list */ + for(u = 0; u < nclasses; u++) { + /* Call the class initialization routine, if there is one */ + if(fspace->sect_cls[u].init) + if((fspace->sect_cls[u].init)(&fspace->sect_cls[u], cls_init_udata) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "unable to initialize section class") + } /* end for */ + + /* Set modifiable free space parameters */ + fspace->nbins = H5V_log2_gen(fspace->hdr->max_sect_size); + fspace->sect_prefix_size = H5FS_SECTS_PREFIX_SIZE(f); + fspace->sect_off_size = (fspace->hdr->max_sect_addr + 7) / 8; + fspace->sect_len_size = (H5V_log2_gen(fspace->hdr->max_sect_size) + 7) / 8; + H5FS_init(fspace); +#ifdef QAK +HDfprintf(stderr, "%s: fspace->nbins = %u\n", FUNC, fspace->nbins); +HDfprintf(stderr, "%s: fspace->sect_off_size = %u, fspace->sect_len_size = %u\n", FUNC, fspace->sect_off_size, fspace->sect_len_size); +#endif /* QAK */ + + /* The free space is clean, currently */ + fspace->dirty = FALSE; + + /* Go get all the sections */ + if(H5FS_deserialize_bins(f, dxpl_id, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, NULL, "can't deserialize sections") + + /* Add the free space manager to the list of open free space managers */ + if(H5FS_open_add(fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINIT, NULL, "can't add free space manager to open list") + + /* Set return value */ + ret_value = fspace; + +done: + if(!ret_value) { + if(fspace) + if(H5FS_close(f, dxpl_id, fspace) < 0) + HDONE_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "unable to release free space info") + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_open() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_sect_increase + * + * Purpose: Increase the size of the serialized free space section info + * on disk + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) +{ + hsize_t new_size; /* New size of space for serialized sections */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_increase) + + /* Check arguments. */ + HDassert(f); + HDassert(fspace); + HDassert(fspace->hdr); + + /* Increment # of sections on free space list */ + fspace->hdr->sect_count++; + + /* Update the free space sections' serialized size */ + fspace->hdr->sect_size = H5FS_serialize_size(fspace); + +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_size); +HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr->alloc_sect_size); +#endif /* QAK */ + if(fspace->hdr->sect_size > fspace->hdr->alloc_sect_size) { +/* Currently, the old block data is "thrown away" after the space is reallocated, +* so avoid data copy in H5MF_realloc() call by just free'ing the space and +* allocating new space. +* +* This also keeps the file smaller, by freeing the space and then +* allocating new space, instead of vice versa (in H5MF_realloc). +* +* QAK - 5/ 8/2006 +*/ + /* Free previous indirect block disk space */ + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, (hsize_t)fspace->hdr->alloc_sect_size)<0) + HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, FAIL, "unable to free free space sections") + + /* Compute new size */ + new_size = fspace->hdr->alloc_sect_size; + while(new_size < fspace->hdr->sect_size) + new_size *= (double)fspace->hdr->expand_percent / 100.0; + fspace->hdr->alloc_sect_size = new_size; + + /* Allocate space for the new indirect block on disk */ + if(HADDR_UNDEF == (fspace->hdr->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, (hsize_t)fspace->hdr->alloc_sect_size))) + HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_sect_increase() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_sect_decrease + * + * Purpose: Decrease the size of the serialized free space section info + * on disk + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) +{ + hsize_t decrease_threshold; /* Size threshold for decreasing serialized section size */ + hsize_t new_size; /* New size of space for serialized sections */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_decrease) + + /* Check arguments. */ + HDassert(f); + HDassert(fspace); + HDassert(fspace->hdr); + + /* Decrement # of sections on free space list */ + fspace->hdr->sect_count--; + +/* XXX: Should check for only one section in bins & convert to single section */ + /* Drop back to using a "single" node when the bins are empty. */ + if(fspace->hdr->sect_count == 0) + fspace->using_bins = FALSE; + + /* Update the free space sections' serialized size */ + fspace->hdr->sect_size = H5FS_serialize_size(fspace); + + /* Compute the threshold for decreasing the sections' serialized size */ + decrease_threshold = (fspace->hdr->alloc_sect_size * (double)fspace->hdr->shrink_percent) / 100.0; + +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_size); +HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr->alloc_sect_size); +#endif /* QAK */ + if(fspace->hdr->alloc_sect_size > H5FS_SECT_SIZE_DEFAULT && + fspace->hdr->sect_size < decrease_threshold) { +/* Currently, the old block data is "thrown away" after the space is reallocated, +* so avoid data copy in H5MF_realloc() call by just free'ing the space and +* allocating new space. +* +* This also keeps the file smaller, by freeing the space and then +* allocating new space, instead of vice versa (in H5MF_realloc). +* +* QAK - 5/ 8/2006 +*/ + /* Free previous indirect block disk space */ + if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, (hsize_t)fspace->hdr->alloc_sect_size)<0) + HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, FAIL, "unable to free free space sections") + + /* Compute new size */ + while(fspace->hdr->sect_size < decrease_threshold) { + new_size = decrease_threshold; + + decrease_threshold *= (double)fspace->hdr->shrink_percent / 100.0; + } /* end while */ + if(new_size < H5FS_SECT_SIZE_DEFAULT) + new_size = H5FS_SECT_SIZE_DEFAULT; + fspace->hdr->alloc_sect_size = new_size; + + /* Allocate space for the new indirect block on disk */ + if(HADDR_UNDEF == (fspace->hdr->sect_addr = H5MF_alloc(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, (hsize_t)fspace->hdr->alloc_sect_size))) + HGOTO_ERROR(H5E_STORAGE, H5E_NOSPACE, FAIL, "file allocation failed for free space sections") + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_sect_decrease() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_add_bin_node + * + * Purpose: Add a section of free space in a direct block to the free list + * bins + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, March 20, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_add_bin_node(H5FS_t *fspace, H5FS_section_info_t *node) +{ + H5FS_node_t *fspace_node = NULL; /* Pointer to free space node of the correct size */ + unsigned bin; /* Bin to put the free space section in */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_add_bin_node) +#ifdef QAK +HDfprintf(stderr, "%s: node->size = %Hu, node->addr = %a\n", FUNC, node->size, node->addr); +#endif /* QAK */ + + /* Check arguments. */ + HDassert(fspace); + HDassert(node); + HDassert(H5F_addr_defined(node->addr)); + HDassert(node->size); + + /* Determine correct bin which holds items of the section's size */ + bin = H5V_log2_gen(node->size); + HDassert(bin < fspace->nbins); + if(fspace->bins[bin].bin_list == NULL) { + if(NULL == (fspace->bins[bin].bin_list = H5SL_create(H5SL_TYPE_HSIZE, 0.5, H5FS_DEFAULT_SKIPLIST_HEIGHT))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for free space nodes") + } /* end if */ + else { + /* Check for node list of the correct size already */ + fspace_node = H5SL_search(fspace->bins[bin].bin_list, &node->size); + } /* end else */ + + /* Check if we need to create a new skip list for nodes of this size */ + if(fspace_node == NULL) { + /* Allocate new free list size node */ + if(NULL == (fspace_node = H5FL_MALLOC(H5FS_node_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for free space node") + + /* Initialize the free list size node */ + fspace_node->sect_size = node->size; + if(NULL == (fspace_node->sect_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, H5FS_DEFAULT_SKIPLIST_HEIGHT))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for free space nodes") + + /* Insert new free space size node into bin's list */ + if(H5SL_insert(fspace->bins[bin].bin_list, fspace_node, &fspace_node->sect_size) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list") + + /* Increment number of section sizes */ + fspace->size_count++; + } /* end if */ + + /* Increment # of section in bin */ + /* (Different from the # of items in the bin's skiplist, since each node on + * the bin's skiplist is also a skiplist...) + */ +#ifdef QAK +HDfprintf(stderr, "%s: fspace->bins[%u].sect_count = %Zu\n", FUNC, bin, fspace->bins[bin].sect_count); +#endif /* QAK */ + fspace->bins[bin].sect_count++; + + /* Increment amount of space required to serialize all sections */ +#ifdef QAK +HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size); +HDfprintf(stderr, "%s: fspace->sect_cls[node->cls->type].serial_size = %Zu\n", FUNC, fspace->sect_cls[node->cls->type].serial_size); +#endif /* QAK */ + fspace->serial_size += fspace->sect_cls[node->cls->type].serial_size; + + /* Insert free space node into correct skip list */ + if(H5SL_insert(fspace_node->sect_list, node, &node->addr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_add_bin_node() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_add + * + * Purpose: Add a section of free space in a direct block to the free list + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, March 7, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *node) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_add, FAIL) + +#ifdef QAK +HDfprintf(stderr, "%s: node->size = %Hu, node->addr = %a\n", FUNC, node->size, node->addr); +#endif /* QAK */ + + /* Check arguments. */ + HDassert(fspace); + HDassert(node); + HDassert(H5F_addr_defined(node->addr)); + HDassert(node->size); + + /* Check for special cases of # of sections on free list */ +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +#endif /* QAK */ + if(fspace->hdr->sect_count == 0) { + HDassert(fspace->single == NULL); + + /* Capture single section's information */ + fspace->single = node; + + /* Increment amount of space required to serialize all sections */ + fspace->serial_size += fspace->sect_cls[node->cls->type].serial_size; + + /* Increment number of section sizes */ + fspace->size_count++; + } /* end if */ + else { + /* Have a single section, put it into the bins */ +/* XXX: Take out the "&& !fspace->using_bins" when bins converted back into single section */ + if(fspace->hdr->sect_count == 1 && !fspace->using_bins) { + HDassert(fspace->single); + + /* Decrement amount of space required to serialize all sections */ + /* (will be re-incremented in the 'add bin node' routine) */ + fspace->serial_size -= fspace->sect_cls[fspace->single->cls->type].serial_size; + + /* Check if we should allocate the bins */ + if(fspace->bins == NULL) + /* Allocate the bins for free space sizes */ + if(NULL == (fspace->bins = H5FL_SEQ_CALLOC(H5FS_bin_t, fspace->nbins))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for free space bins") + + /* Insert the current single section into the bins */ + if(H5FS_add_bin_node(fspace, fspace->single) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list") + fspace->single = NULL; + + /* Decrement number of section sizes */ + /* (will be re-incremented in the 'add bin node' routine) */ + fspace->size_count--; + + /* Using bins for storing nodes now */ + fspace->using_bins = TRUE; + } /* end if */ + HDassert(fspace->single == NULL); + + /* Put new section into bins */ + if(H5FS_add_bin_node(fspace, node) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into skip list") + } /* end else */ + + /* Update section info & check if we need more room for the serialized free space sections */ + if(H5FS_sect_increase(f, dxpl_id, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk") + + /* Increment amount of free space managed */ + fspace->hdr->tot_space += node->size; + + /* Mark free space sections as changed */ + fspace->dirty = TRUE; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_add() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_find_bin_node + * + * Purpose: Locate a section of free space (in existing free space list + * bins) that is large enough to fulfill request. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, March 20, 2006 + * + *------------------------------------------------------------------------- + */ +static htri_t +H5FS_find_bin_node(H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node) +{ + H5FS_node_t *fspace_node; /* Free list size node */ + unsigned bin; /* Bin to put the free space section in */ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_find_bin_node) + + /* Check arguments. */ + HDassert(fspace); + HDassert(fspace->bins); + HDassert(request > 0); + HDassert(node); + + /* Determine correct bin which holds items of at least the section's size */ + bin = H5V_log2_gen(request); + HDassert(bin < fspace->nbins); + while(bin < fspace->nbins && fspace->bins[bin].bin_list == NULL) + bin++; + + /* Find the first free space section that is large enough to fulfill request */ + /* (Since the bins use skip lists to track the sizes of the address-ordered + * lists, this is actually a "best fit" algorithm) + */ +#ifdef QAK +HDfprintf(stderr, "%s: fspace->nbins = %u\n", FUNC, fspace->nbins); +HDfprintf(stderr, "%s: bin = %u\n", FUNC, bin); +#endif /* QAK */ + if(bin < fspace->nbins) + do { + /* Look for large enough free space section in this bin */ + if(fspace->bins[bin].bin_list) + /* Check for large enough list of sections on list */ + if((fspace_node = H5SL_greater(fspace->bins[bin].bin_list, &request))) { + /* Take first node off of the list (ie. node w/lowest address) */ + if(NULL == (*node = H5SL_remove_first(fspace_node->sect_list))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDELETE, FAIL, "can't remove free space node from skip list") + + /* Check for no more nodes on list of that size */ + if(H5SL_count(fspace_node->sect_list) == 0) { + H5FS_node_t *tmp_fspace_node; /* Free space list size node */ + + /* Remove size tracking list from bin */ + tmp_fspace_node = H5SL_remove(fspace->bins[bin].bin_list, &fspace_node->sect_size); + if(tmp_fspace_node == NULL || tmp_fspace_node != fspace_node) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDELETE, FAIL, "can't remove free space node from skip list") + + /* Destroy skip list for size tracking node */ + if(H5SL_close(fspace_node->sect_list) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy size tracking node's skip list") + + /* Release free space list node */ + H5FL_FREE(H5FS_node_t, fspace_node); + + /* Decrement number of section sizes */ + fspace->size_count--; + } /* end if */ + + /* Decrement the # of sections in this bin */ + /* (Different from the # of items in the bin's skiplist, since each node on + * the bin's skiplist is also a skiplist...) + */ + fspace->bins[bin].sect_count--; +#ifdef QAK +HDfprintf(stderr, "%s: fspace->bins[%u].sect_count = %Zu\n", FUNC, bin, fspace->bins[bin].sect_count); +#endif /* QAK */ + + /* Decrement amount of space required to serialize all sections */ + fspace->serial_size -= fspace->sect_cls[(*node)->cls->type].serial_size; +#ifdef QAK +HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size); +HDfprintf(stderr, "%s: fspace->sect_cls[(*node)->cls->type].serial_size = %Zu\n", FUNC, fspace->sect_cls[(*node)->cls->type].serial_size); +#endif /* QAK */ + + HGOTO_DONE(TRUE) + } /* end if */ + + /* Advance to next larger bin */ + bin++; + } while(bin < fspace->nbins); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_find_bin_node() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_find + * + * Purpose: Locate a section of free space (in existing free space list) that + * is large enough to fulfill request. + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, March 7, 2006 + * + *------------------------------------------------------------------------- + */ +htri_t +H5FS_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node) +{ + htri_t ret_value = FALSE; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_find, FAIL) + +#ifdef QAK +HDfprintf(stderr, "%s: request = %Hu\n", FUNC, request); +#endif /* QAK */ + + /* Check arguments. */ + HDassert(fspace); + HDassert(request); + HDassert(node); + + /* Check for any sections on free space list */ +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +#endif /* QAK */ + if(fspace->hdr->sect_count > 0) { + /* Check for single section */ +/* XXX: Take out the "&& !fspace->using_bins" when bins converted back into single section */ + if(fspace->hdr->sect_count == 1 && !fspace->using_bins) { + HDassert(fspace->single); + + /* See if single section is large enough */ + if(fspace->single->size >= request) { + /* Use 'single' section */ + *node = fspace->single; + fspace->single = NULL; + + /* Decrement amount of space required to serialize all sections */ + fspace->serial_size -= fspace->sect_cls[(*node)->cls->type].serial_size; + + /* Decrement number of section sizes */ + fspace->size_count--; + + /* Found a good section */ + ret_value = TRUE; + } /* end if */ + else + HGOTO_DONE(FALSE) + } /* end if */ + else { + HDassert(fspace->single == NULL); + + /* Look for node in bins */ + if((ret_value = H5FS_find_bin_node(fspace, request, node)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "can't remove section from bins") + } /* end else */ + + /* Decrement # of sections on free list, if we found an object */ + if(ret_value > 0) { + /* Update section info & check if we need less room for the serialized free space sections */ + if(H5FS_sect_decrease(f, dxpl_id, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk") + + /* Decrement amount of free space managed */ + fspace->hdr->tot_space -= (*node)->size; + + /* Mark free space sections as changed */ + fspace->dirty = TRUE; + } /* end if */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_find() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_node_free_cb + * + * Purpose: Free a size-tracking node for a bin + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Saturday, March 11, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_node_free_cb(void *item, void UNUSED *key, void *op_data) +{ + H5FS_node_t *fspace_node = (H5FS_node_t *)item; /* Temporary pointer to free space list node */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_node_free_cb) + + HDassert(fspace_node); + + /* Release the skip list for sections of this size */ + H5SL_destroy(fspace_node->sect_list, (H5SL_operator_t)op_data, NULL); + + /* Release free space list node */ + H5FL_FREE(H5FS_node_t, fspace_node); + + FUNC_LEAVE_NOAPI(0) +} /* H5FS_node_free_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_serialize_sect_cb + * + * Purpose: Skip list iterator callback to serialize free space sections + * of a particular size + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_serialize_sect_cb(void *_item, void UNUSED *key, void *_udata) +{ + H5FS_section_info_t *sect_info = (H5FS_section_info_t *)_item; /* Free space section to work on */ + H5FS_iter_ud2_t *udata = (H5FS_iter_ud2_t *)_udata; /* Callback info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_serialize_sect_cb) + + /* Check arguments. */ + HDassert(sect_info); + HDassert(udata->fspace); + HDassert(udata->p); + + /* The address of the section */ + UINT64ENCODE_VAR(*udata->p, sect_info->addr, udata->fspace->sect_off_size); +#ifdef QAK +HDfprintf(stderr, "%s: sect_info->addr = %a\n", FUNC, sect_info->addr); +#endif /* QAK */ + + /* The type of this section */ + *(*udata->p)++ = (uint8_t)sect_info->cls->type; +#ifdef QAK +HDfprintf(stderr, "%s: sect_info->cls->type = %u\n", FUNC, (unsigned)sect_info->cls->type); +#endif /* QAK */ + + /* Call 'serialize' callback for this section */ + if(sect_info->cls->serialize) { + if((*sect_info->cls->serialize)(sect_info, *udata->p) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize section") + + /* Update offset in serialization buffer */ + (*udata->p) += sect_info->cls->serial_size; + } /* end if */ + else + HDassert(sect_info->cls->serial_size == 0); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_serialize_sect_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_serialize_node_cb + * + * Purpose: Skip list iterator callback to serialize free space sections + * in a bin + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_serialize_node_cb(void *_item, void UNUSED *key, void *_udata) +{ + H5FS_node_t *fspace_node = (H5FS_node_t *)_item; /* Free space size node to work on */ + H5FS_iter_ud2_t *udata = (H5FS_iter_ud2_t *)_udata; /* Callback info */ + size_t node_count; /* Number of sections of this size */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_serialize_node_cb) + + /* Check arguments. */ + HDassert(fspace_node); + HDassert(udata->fspace); + HDassert(udata->p); + + /* The number of sections of this node's size */ + node_count = H5SL_count(fspace_node->sect_list); + HDassert(node_count); + UINT64ENCODE_VAR(*udata->p, node_count, udata->sect_cnt_size); +#ifdef QAK +HDfprintf(stderr, "%s: node_count = %Zu\n", FUNC, node_count); +#endif /* QAK */ + + /* The size of the sections for this node */ + UINT64ENCODE_VAR(*udata->p, fspace_node->sect_size, udata->fspace->sect_len_size); +#ifdef QAK +HDfprintf(stderr, "%s: sect_size = %Hu\n", FUNC, fspace_node->sect_size); +#endif /* QAK */ + + /* Iterate through all the sections of this size */ + HDassert(fspace_node->sect_list); + if(H5SL_iterate(fspace_node->sect_list, H5FS_serialize_sect_cb, udata) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_serialize_node_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_serialize_size + * + * Purpose: Determine serialized size of all sections in free space manager + * + * Return: Success: non-negative + * + * Failure: (can't fail) + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static size_t +H5FS_serialize_size(H5FS_t *fspace) +{ + size_t sect_buf_size; /* Section buffer size */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_serialize_size) + + /* Check arguments. */ + HDassert(fspace); + + /* Compute the size of the buffer required to serialize all the sections */ + + /* Serialized sections prefix */ + sect_buf_size = fspace->sect_prefix_size; + + /* Count for each differently sized section */ + sect_buf_size += fspace->size_count * MAX(1, ((H5V_log2_gen(fspace->hdr->sect_count) + 7) / 8)); + + /* Size for each differently sized section */ + sect_buf_size += fspace->size_count * fspace->sect_len_size; + + /* Offsets of each section in address space */ + sect_buf_size += fspace->hdr->sect_count * fspace->sect_off_size; + + /* Class of each section */ + sect_buf_size += fspace->hdr->sect_count * 1; + + /* Extra space required to serialize each section */ + sect_buf_size += fspace->serial_size; + + FUNC_LEAVE_NOAPI(sect_buf_size) +} /* H5FS_serialize_size() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_serialize_bins + * + * Purpose: Serialize all bins into proper form on disk + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_serialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) +{ + H5FS_iter_ud2_t udata; /* User data for callbacks */ + uint8_t *sect_buf = NULL; /* Buffer for sections */ + uint8_t *p; /* Pointer into raw data buffer */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_serialize_bins) + + /* Check arguments. */ + HDassert(f); + HDassert(fspace); + HDassert(fspace->dirty); + +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size); +#endif /* QAK */ + + /* Allocate space for the buffer to serialize the sections into */ + if(NULL == (sect_buf = H5FL_BLK_MALLOC(sect_block, (size_t)fspace->hdr->sect_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Serialize free sections into buffer available */ + p = sect_buf; + + /* Magic number */ + HDmemcpy(p, H5FS_SECTS_MAGIC, H5FS_SIZEOF_MAGIC); + p += H5FS_SIZEOF_MAGIC; + + /* Version # */ + *p++ = H5FS_SECTS_VERSION; + + /* Metadata status flags */ +/* XXX: Set this? */ + *p++ = 0; + + /* Metadata checksum */ +/* XXX: Set this! (After all the metadata is in the buffer) */ + HDmemset(p, 0, 4); + p += 4; + + /* Address of free space header for these sections */ + H5F_addr_encode(f, &p, fspace->addr); + + /* Set up user data for iterator */ + udata.fspace = fspace; + udata.p = &p; + udata.sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->sect_count) + 7) / 8); +#ifdef QAK +HDfprintf(stderr, "%s: udata.sect_cnt_size = %u\n", FUNC, udata.sect_cnt_size); +#endif /* QAK */ + + /* Serialize sections, if there are any */ + if(fspace->hdr->sect_count) { + /* Check for whether to serialize a single section */ +/* XXX: Take out the "&& !fspace->using_bins" when bins converted back into single section */ + if(fspace->hdr->sect_count == 1 && !fspace->using_bins) { +#ifdef QAK +HDfprintf(stderr, "%s: Serializing single section\n", FUNC); +#endif /* QAK */ + /* Sanity check */ + HDassert(fspace->single != NULL); + + /* The number of sections */ + UINT64ENCODE_VAR(p, 1, udata.sect_cnt_size); + + /* The size of the section */ + UINT64ENCODE_VAR(p, fspace->single->size, fspace->sect_len_size); + + /* Serialize the single node */ + if(H5FS_serialize_sect_cb(fspace->single, NULL, &udata) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize single section") + } /* end if */ + else { + unsigned bin; /* Current bin we are on */ + + /* Iterate over all the bins */ +#ifdef QAK +HDfprintf(stderr, "%s: Serializing section bins\n", FUNC); +#endif /* QAK */ + for(bin = 0; bin < fspace->nbins; bin++) { + /* Check if there are any sections in this bin */ + if(fspace->bins[bin].bin_list) { + /* Iterate over list of section size nodes for bin */ + if(H5SL_iterate(fspace->bins[bin].bin_list, H5FS_serialize_node_cb, &udata) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section size nodes") + } /* end if */ + } /* end for */ + } /* end else */ + } /* end if */ + + /* Sanity check */ + HDassert((size_t)(p - sect_buf) == fspace->hdr->sect_size); +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_size); +#endif /* QAK */ + + /* Write buffer to disk */ + HDassert(fspace->hdr->sect_size <= fspace->hdr->alloc_sect_size); +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr->alloc_sect_size); +#endif /* QAK */ + if(H5F_block_write(f, H5FD_MEM_FSPACE_SECTS, fspace->hdr->sect_addr, (size_t)fspace->hdr->sect_size, dxpl_id, sect_buf) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space sections to disk") + +done: + if(sect_buf) + H5FL_BLK_FREE(sect_block, sect_buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_serialize_bins() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_deserialize_bins + * + * Purpose: Deserialize all bins from disk + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_deserialize_bins(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) +{ + haddr_t fs_addr; /* Free space header address */ + uint32_t metadata_chksum; /* Metadata checksum value */ + uint8_t *sect_buf = NULL; /* Buffer for sections */ + const uint8_t *p; /* Pointer into raw data buffer */ + size_t old_sect_size; /* Section size */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_deserialize_bins) + + /* Check arguments. */ + HDassert(f); + HDassert(fspace); + + /* Allocate space for the buffer to serialize the sections into */ + old_sect_size = fspace->hdr->sect_size; +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_size); +#endif /* QAK */ + if(NULL == (sect_buf = H5FL_BLK_MALLOC(sect_block, (size_t)fspace->hdr->sect_size))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + /* Read buffer from disk */ + if(H5F_block_read(f, H5FD_MEM_FSPACE_SECTS, fspace->hdr->sect_addr, (size_t)fspace->hdr->sect_size, dxpl_id, sect_buf) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_READERROR, FAIL, "can't read free space sections") + + /* Deserialize free sections from buffer available */ + p = sect_buf; + + /* Magic number */ + if(HDmemcmp(p, H5FS_SECTS_MAGIC, H5FS_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "wrong free space sections signature") + p += H5FS_SIZEOF_MAGIC; + + /* Version */ + if(*p++ != H5FS_SECTS_VERSION) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "wrong free space sections version") + + /* Metadata flags (unused, currently) */ +/* XXX: Plan out metadata flags (including "read-only duplicate" feature) */ + if(*p++ != 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "unknown metadata flag in free space sections") + + /* Metadata checksum (unused, currently) */ + UINT32DECODE(p, metadata_chksum); +/* XXX: Verify checksum */ + if(metadata_chksum != 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "incorrect metadata checksum for free space sections") + + /* Address of free space header for these sections */ + H5F_addr_decode(f, &p, &fs_addr); + if(H5F_addr_ne(fs_addr, fspace->addr)) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "incorrect header address for free space sections") + + /* Check for any serialized sections */ + if(fspace->hdr->sect_count > 0) { + hsize_t old_sect_count; /* Section count from header */ + unsigned sect_cnt_size; /* The size of the section size counts */ + + /* Compute the size of the section counts */ + sect_cnt_size = MAX(1, (H5V_log2_gen(fspace->hdr->sect_count) + 7) / 8); +#ifdef QAK +HDfprintf(stderr, "%s: sect_cnt_size = %u\n", FUNC, sect_cnt_size); +HDfprintf(stderr, "%s: fspace->sect_len_size = %u\n", FUNC, fspace->sect_len_size); +#endif /* QAK */ + + /* Reset the section count, the "add" routine will update it */ + old_sect_count = fspace->hdr->sect_count; +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +#endif /* QAK */ + fspace->hdr->sect_count = 0; + + /* Walk through the buffer, deserializing sections */ + do { + hsize_t sect_size; /* Current section size */ + size_t node_count; /* # of sections of this size */ + size_t u; /* Local index variable */ + + /* The number of sections of this node's size */ + UINT64DECODE_VAR(p, node_count, sect_cnt_size); +#ifdef QAK +HDfprintf(stderr, "%s: node_count = %Zu\n", FUNC, node_count); +#endif /* QAK */ + HDassert(node_count); + + /* The size of the sections for this node */ + UINT64DECODE_VAR(p, sect_size, fspace->sect_len_size); +#ifdef QAK +HDfprintf(stderr, "%s: sect_size = %Hu\n", FUNC, sect_size); +#endif /* QAK */ + HDassert(sect_size); + + /* Loop over nodes of this size */ + for(u = 0; u < node_count; u++) { + H5FS_section_info_t *new_sect; /* Section that was deserialized */ + haddr_t sect_addr; /* Address of free space section in the address space */ + unsigned sect_type; /* Type of free space section */ + + /* The address of the section */ + UINT64DECODE_VAR(p, sect_addr, fspace->sect_off_size); +#ifdef QAK +HDfprintf(stderr, "%s: sect_addr = %a\n", FUNC, sect_addr); +#endif /* QAK */ + + /* The type of this section */ + sect_type = *p++; +#ifdef QAK +HDfprintf(stderr, "%s: sect_type = %u\n", FUNC, sect_type); +#endif /* QAK */ + + /* Call 'deserialize' callback for this section */ + HDassert(fspace->sect_cls[sect_type].deserialize); + if((*fspace->sect_cls[sect_type].deserialize)(fspace->sect_cls, p, sect_addr, sect_size, &new_sect) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTDECODE, FAIL, "can't deserialize section") + HDassert(new_sect); + + /* Update offset in serialization buffer */ + p += new_sect->cls->serial_size; + + /* Insert section in free space manager */ + if(H5FS_add(f, dxpl_id, fspace, new_sect) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to free space manager") + } /* end for */ + } while(p < (sect_buf + old_sect_size)); + + /* Sanity check */ + HDassert((size_t)(p - sect_buf) == old_sect_size); + HDassert(old_sect_size == fspace->hdr->sect_size); + HDassert(old_sect_count == fspace->hdr->sect_count); + } /* end if */ + +done: + if(sect_buf) + H5FL_BLK_FREE(sect_block, sect_buf); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_deserialize_bins() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_iterate_sect_cb + * + * Purpose: Skip list iterator callback to iterate over free space sections + * of a particular size + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Saturday, May 13, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_iterate_sect_cb(void *_item, void UNUSED *key, void *_udata) +{ + H5FS_section_info_t *sect_info = (H5FS_section_info_t *)_item; /* Free space section to work on */ + H5FS_iter_ud3_t *udata = (H5FS_iter_ud3_t *)_udata; /* Callback info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_iterate_sect_cb) + + /* Check arguments. */ + HDassert(sect_info); + HDassert(udata->fspace); + HDassert(udata->op); + + /* Make callback for this section */ + if((*udata->op)(sect_info, udata->op_data) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "iteration callback failed") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_iterate_sect_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_iterate_node_cb + * + * Purpose: Skip list iterator callback to iterate over free space sections + * in a bin + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Saturday, May 13, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_iterate_node_cb(void *_item, void UNUSED *key, void *_udata) +{ + H5FS_node_t *fspace_node = (H5FS_node_t *)_item; /* Free space size node to work on */ + H5FS_iter_ud3_t *udata = (H5FS_iter_ud3_t *)_udata; /* Callback info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_iterate_node_cb) + + /* Check arguments. */ + HDassert(fspace_node); + HDassert(udata->fspace); + HDassert(udata->op); + + /* Iterate through all the sections of this size */ + HDassert(fspace_node->sect_list); + if(H5SL_iterate(fspace_node->sect_list, H5FS_iterate_sect_cb, udata) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section nodes") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_iterate_node_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_iterate + * + * Purpose: Iterate over all the sections managed + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Saturday, May 13, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_iterate(H5FS_t *fspace, H5FS_operator_t op, void *op_data) +{ + H5FS_iter_ud3_t udata; /* User data for callbacks */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_iterate) + + /* Check arguments. */ + HDassert(fspace); + HDassert(op); + +#ifdef QAK +HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count); +#endif /* QAK */ + + /* Set up user data for iterator */ + udata.fspace = fspace; + udata.op = op; + udata.op_data = op_data; + + /* Iterate over sections, if there are any */ + if(fspace->hdr->sect_count) { + /* Check for whether to iterate over a single section */ +/* XXX: Take out the "&& !fspace->using_bins" when bins converted back into single section */ + if(fspace->hdr->sect_count == 1 && !fspace->using_bins) { +#ifdef QAK +HDfprintf(stderr, "%s: Iterating over a single section\n", FUNC); +#endif /* QAK */ + /* Sanity check */ + HDassert(fspace->single != NULL); + + /* "Iterate" over the single node */ + if(H5FS_iterate_sect_cb(fspace->single, NULL, &udata) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't 'iterate' over single section") + } /* end if */ + else { + unsigned bin; /* Current bin we are on */ + + /* Iterate over all the bins */ +#ifdef QAK +HDfprintf(stderr, "%s: Iterate over section bins\n", FUNC); +#endif /* QAK */ + for(bin = 0; bin < fspace->nbins; bin++) { + /* Check if there are any sections in this bin */ + if(fspace->bins[bin].bin_list) { + /* Iterate over list of section size nodes for bin */ + if(H5SL_iterate(fspace->bins[bin].bin_list, H5FS_iterate_node_cb, &udata) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't iterate over section size nodes") + } /* end if */ + } /* end for */ + } /* end else */ + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_iterate() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_flush_cb + * + * Purpose: Skip list iterator callback to syncronize free space sections + * in a free space manager with their serialized form for the + * metadata cache + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_flush_cb(void *_item, void UNUSED *key, void *_udata) +{ + H5FS_t *fspace = (H5FS_t *)_item; /* Free space manager to syncronize */ + H5FS_iter_ud1_t *udata = (H5FS_iter_ud1_t *)_udata; /* Callback info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_flush_cb, FAIL) + + /* Check arguments. */ + HDassert(fspace); + HDassert(udata->f); + + /* Serialize the bins for this free space manager, if they are dirty */ + if(fspace->dirty) + if(H5FS_serialize_bins(udata->f, udata->dxpl_id, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize bins") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_flush_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_flush + * + * Purpose: Syncronize free space sections in all the free space + * managers with their serialized form for the metadata cache + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 8, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_flush(H5F_t *f, hid_t dxpl_id, unsigned UNUSED flags) +{ + H5FS_iter_ud1_t udata; /* Callback info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_flush, FAIL) + + /* Check arguments. */ + HDassert(f); + + /* Set up callback information */ + udata.f = f; + udata.dxpl_id = dxpl_id; + + /* Iterate over open free space managers, to syncronize their section information */ + HDassert(H5FS_open_g); + if(H5SL_iterate(H5FS_open_g, H5FS_flush_cb, &udata) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't syncronize section info") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_close + * + * Purpose: Destroy & deallocate free list structure, serializing sections + * in the bins + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Tuesday, March 7, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace) +{ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_close, FAIL) + + /* Check arguments. */ + HDassert(f); + HDassert(fspace); + + /* Remove the free space manager from the list of open free space managers */ + if(H5FS_open_remove(fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove free space header from open list") + + /* Serialize the sections in the bins, if necessary */ + if(fspace->dirty) + if(H5FS_serialize_bins(f, dxpl_id, fspace) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTSERIALIZE, FAIL, "can't syncronize bins") + + /* Check for single section to free */ +/* XXX: Take out the "&& !fspace->using_bins" when bins converted back into single section */ + if(fspace->hdr->sect_count == 1 && !fspace->using_bins) { + HDassert(fspace->single != NULL); + fspace->node_free_op(fspace->single, &fspace->single->addr, NULL); + fspace->single = NULL; + } /* end if */ + HDassert(fspace->single == NULL); + + /* Release bins for skip lists */ + if(fspace->bins) { + /* Clear out lists of nodes */ + for(u = 0; u < fspace->nbins; u++) + if(fspace->bins[u].bin_list) { + H5SL_destroy(fspace->bins[u].bin_list, H5FS_node_free_cb, (void *)fspace->node_free_op); + fspace->bins[u].bin_list = NULL; + } /* end if */ + + H5FL_SEQ_FREE(H5FS_bin_t, fspace->bins); + } /* end if */ + + /* Unpin the free space header in the cache */ + if(H5AC_unpin_entry(f, fspace->hdr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPIN, FAIL, "unable to unpin free space header") + + /* Free free space info */ + H5FL_FREE(H5FS_t, fspace); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_close() */ + diff --git a/src/H5FScache.c b/src/H5FScache.c new file mode 100644 index 0000000..c87cdc0 --- /dev/null +++ b/src/H5FScache.c @@ -0,0 +1,426 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5FScache.c + * May 2 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Implement file free space metadata cache methods. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5FS_PACKAGE /*suppress error about including H5FSpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FSpkg.h" /* File free space */ + +/****************/ +/* Local Macros */ +/****************/ + +/* File free space format version #'s */ +#define H5FS_HDR_VERSION 0 /* Header */ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + +/* Metadata cache callbacks */ +static H5FS_hdr_t *H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *udata, void *udata2); +static herr_t H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_hdr_t *hdr); +static herr_t H5FS_cache_hdr_clear(H5F_t *f, H5FS_hdr_t *hdr, hbool_t destroy); +static herr_t H5FS_cache_hdr_size(const H5F_t *f, const H5FS_hdr_t *hdr, size_t *size_ptr); + +/*********************/ +/* Package Variables */ +/*********************/ + +/* H5FS header inherits cache-like properties from H5AC */ +const H5AC_class_t H5AC_FSPACE_HDR[1] = {{ + H5AC_FSPACE_HDR_ID, + (H5AC_load_func_t)H5FS_cache_hdr_load, + (H5AC_flush_func_t)H5FS_cache_hdr_flush, + (H5AC_dest_func_t)H5FS_cache_hdr_dest, + (H5AC_clear_func_t)H5FS_cache_hdr_clear, + (H5AC_size_func_t)H5FS_cache_hdr_size, +}}; + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + +/* Declare a free list to manage free space header data to/from disk */ +H5FL_BLK_DEFINE_STATIC(header_block); + + + +/*------------------------------------------------------------------------- + * Function: H5FS_cache_hdr_load + * + * Purpose: Loads a free space header from the disk. + * + * Return: Success: Pointer to a new free space header + * + * Failure: NULL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +static H5FS_hdr_t * +H5FS_cache_hdr_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void UNUSED *udata1, void UNUSED *udata2) +{ + H5FS_hdr_t *hdr = NULL; /* Free space header info */ + size_t size; /* Header size */ + uint8_t *buf = NULL; /* Temporary buffer */ + const uint8_t *p; /* Pointer into raw data buffer */ + uint32_t metadata_chksum; /* Metadata checksum value */ + H5FS_hdr_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_hdr_load) +#ifdef QAK +HDfprintf(stderr, "%s: Load free space header, addr = %a\n", FUNC, addr); +#endif /* QAK */ + + /* Check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + + /* Allocate space for the free space header */ + if(NULL == (hdr = H5FL_MALLOC(H5FS_hdr_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + HDmemset(&hdr->cache_info, 0, sizeof(H5AC_info_t)); + + /* Compute the size of the free space header on disk */ + size = H5FS_HEADER_SIZE(f); + + /* Allocate temporary buffer */ + if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") + + /* Read header from disk */ + if(H5F_block_read(f, H5FD_MEM_FSPACE_HDR, addr, size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_READERROR, NULL, "can't read free space header") + + p = buf; + + /* Magic number */ + if(HDmemcmp(p, H5FS_HDR_MAGIC, H5FS_SIZEOF_MAGIC)) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space header signature") + p += H5FS_SIZEOF_MAGIC; + + /* Version */ + if(*p++ != H5FS_HDR_VERSION) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "wrong free space header version") + + /* Metadata flags (unused, currently) */ +/* XXX: Plan out metadata flags (including "read-only duplicate" feature) */ + if(*p++ != 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "unknown metadata flag in free space header") + + /* Metadata checksum (unused, currently) */ + UINT32DECODE(p, metadata_chksum); +/* XXX: Verify checksum */ + if(metadata_chksum != 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "incorrect metadata checksum for free space header") + + /* Client ID */ + hdr->client = *p++; + if(hdr->client >= H5FS_NUM_CLIENT_ID) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, NULL, "unknown client ID in free space header") + + /* Total space tracked */ + H5F_DECODE_LENGTH(f, p, hdr->tot_space); + + /* # of free space sections tracked */ + H5F_DECODE_LENGTH(f, p, hdr->sect_count); + + /* # of section classes */ + UINT16DECODE(p, hdr->nclasses); + + /* Shrink percent */ + UINT16DECODE(p, hdr->shrink_percent); + + /* Expand percent */ + UINT16DECODE(p, hdr->expand_percent); + + /* Size of address space free space sections are within (log2 of actual value) */ + UINT16DECODE(p, hdr->max_sect_addr); + + /* Max. size of section to track */ + H5F_DECODE_LENGTH(f, p, hdr->max_sect_size); + + /* Address of serialized free space sections */ + H5F_addr_decode(f, &p, &hdr->sect_addr); + + /* Size of serialized free space sections */ + H5F_DECODE_LENGTH(f, p, hdr->sect_size); + + /* Allocated size of serialized free space sections */ + H5F_DECODE_LENGTH(f, p, hdr->alloc_sect_size); + + HDassert((size_t)(p - buf) == size); + + /* Set return value */ + ret_value = hdr; + +done: + if(buf) + H5FL_BLK_FREE(header_block, buf); + if(!ret_value && hdr) + (void)H5FS_cache_hdr_dest(f, hdr); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FS_cache_hdr_load() */ /*lint !e818 Can't make udata a pointer to const */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_cache_hdr_flush + * + * Purpose: Flushes a dirty free space header to disk. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5FS_hdr_t *hdr) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_hdr_flush) +#ifdef QAK +HDfprintf(stderr, "%s: Flushing free space header, addr = %a, destroy = %u\n", FUNC, addr, (unsigned)destroy); +#endif /* QAK */ + + /* check arguments */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(hdr); + + if(hdr->cache_info.is_dirty) { + uint8_t *buf = NULL; /* Temporary raw data buffer */ + uint8_t *p; /* Pointer into raw data buffer */ + size_t size; /* Header size on disk */ + + /* Compute the size of the free space header on disk */ + size = H5FS_HEADER_SIZE(f); + + /* Allocate temporary buffer */ + if((buf = H5FL_BLK_MALLOC(header_block, size)) == NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") + + p = buf; + + /* Magic number */ + HDmemcpy(p, H5FS_HDR_MAGIC, H5FS_SIZEOF_MAGIC); + p += H5FS_SIZEOF_MAGIC; + + /* Version # */ + *p++ = H5FS_HDR_VERSION; + + /* Metadata status flags */ +/* XXX: Set this? */ + *p++ = 0; + + /* Metadata checksum */ +/* XXX: Set this! (After all the metadata is in the buffer) */ + HDmemset(p, 0, 4); + p += 4; + + /* Client ID */ + *p++ = hdr->client; + + /* Total space tracked */ + H5F_ENCODE_LENGTH(f, p, hdr->tot_space); + + /* # of free space sections tracked */ + H5F_ENCODE_LENGTH(f, p, hdr->sect_count); + + /* # of section classes */ + UINT16ENCODE(p, hdr->nclasses); + + /* Shrink percent */ + UINT16ENCODE(p, hdr->shrink_percent); + + /* Expand percent */ + UINT16ENCODE(p, hdr->expand_percent); + + /* Size of address space free space sections are within (log2 of actual value) */ + UINT16ENCODE(p, hdr->max_sect_addr); + + /* Max. size of section to track */ + H5F_ENCODE_LENGTH(f, p, hdr->max_sect_size); + + /* Address of serialized free space sections */ + H5F_addr_encode(f, &p, hdr->sect_addr); + + /* Size of serialized free space sections */ + H5F_ENCODE_LENGTH(f, p, hdr->sect_size); + + /* Allocated size of serialized free space sections */ + H5F_ENCODE_LENGTH(f, p, hdr->alloc_sect_size); + + /* Write the free space header. */ + HDassert((size_t)(p - buf) == size); + if(H5F_block_write(f, H5FD_MEM_FSPACE_HDR, addr, size, dxpl_id, buf) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFLUSH, FAIL, "unable to save free space header to disk") + + H5FL_BLK_FREE(header_block, buf); + + hdr->cache_info.is_dirty = FALSE; + } /* end if */ + + if(destroy) + if(H5FS_cache_hdr_dest(f, hdr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space header") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5FS_cache_hdr_flush() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_cache_hdr_dest + * + * Purpose: Destroys a free space header in memory. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +/* ARGSUSED */ +herr_t +H5FS_cache_hdr_dest(H5F_t UNUSED *f, H5FS_hdr_t *hdr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_cache_hdr_dest) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Free the shared info itself */ + H5FL_FREE(H5FS_hdr_t, hdr); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5FS_cache_hdr_dest() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_cache_hdr_clear + * + * Purpose: Mark a free space header in memory as non-dirty. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_cache_hdr_clear(H5F_t *f, H5FS_hdr_t *hdr, hbool_t destroy) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5FS_cache_hdr_clear) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Reset the dirty flag. */ + hdr->cache_info.is_dirty = FALSE; + + if(destroy) + if(H5FS_cache_hdr_dest(f, hdr) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to destroy free space header") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FS_cache_hdr_clear() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_cache_hdr_size + * + * Purpose: Compute the size in bytes of a free space header + * on disk, and return it in *size_ptr. On failure, + * the value of *size_ptr is undefined. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FS_cache_hdr_size(const H5F_t *f, const H5FS_hdr_t *hdr, size_t *size_ptr) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_cache_hdr_size) + + /* check arguments */ + HDassert(f); + HDassert(hdr); + HDassert(size_ptr); + + /* Set size value */ + *size_ptr = H5FS_HEADER_SIZE(f); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5FS_cache_hdr_size() */ + diff --git a/src/H5FSdbg.c b/src/H5FSdbg.c new file mode 100644 index 0000000..dcbc846 --- /dev/null +++ b/src/H5FSdbg.c @@ -0,0 +1,231 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5FSdbg.c + * May 9 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Dump debugging information about a free space manager + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5FS_PACKAGE /*suppress error about including H5FSpkg */ +#define H5HF_DEBUGGING /* Need access to fractal heap debugging routines */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FSpkg.h" /* File free space */ +#include "H5HFprivate.h" /* Fractal heaps */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + +/*------------------------------------------------------------------------- + * Function: H5FS_hdr_debug + * + * Purpose: Prints debugging info about a free space header. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 9 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth) +{ + H5FS_hdr_t *hdr = NULL; /* Free space header info */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_hdr_debug, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + /* + * Load the free space header. + */ + if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "unable to load free space header") + + /* Print opening message */ + HDfprintf(stream, "%*sFree Space Header...\n", indent, ""); + + /* + * Print the values. + */ + HDfprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, + "Free space client:", + (hdr->client == H5FS_CLIENT_FHEAP_ID ? "Fractal heap" : "Unknown")); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Total free space tracked:", + hdr->tot_space); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Number of free space sections tracked:", + hdr->sect_count); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Number of free space section classes:", + hdr->nclasses); + HDfprintf(stream, "%*s%-*s %u%%\n", indent, "", fwidth, + "Shrink percent:", + hdr->shrink_percent); + HDfprintf(stream, "%*s%-*s %u%%\n", indent, "", fwidth, + "Expand percent:", + hdr->expand_percent); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "# of bits for section address space:", + hdr->max_sect_addr); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Maximum section size:", + hdr->max_sect_size); + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Serialized sections address:", + hdr->sect_addr); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Serialized sections size used:", + hdr->sect_size); + HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, + "Serialized sections size allocated:", + hdr->alloc_sect_size); + +done: + if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, addr, hdr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_PROTECT, FAIL, "unable to release free space header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FS_hdr_debug() */ + + +/*------------------------------------------------------------------------- + * Function: H5FS_sects_debug + * + * Purpose: Prints debugging info about the free space sections. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 9 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, int fwidth, + haddr_t fs_addr, haddr_t client_addr) +{ + H5FS_hdr_t *hdr = NULL; /* Free space header info */ + H5FS_client_t client; /* The client of the free space */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5FS_sects_debug, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + HDassert(H5F_addr_defined(fs_addr)); + HDassert(H5F_addr_defined(client_addr)); + + /* + * Load the free space header. + */ + if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_FSPACE, H5E_CANTLOAD, FAIL, "unable to load free space header") + + /* Retrieve the client id */ + client = hdr->client; + + /* Release the free space header */ + if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_PROTECT, FAIL, "unable to release free space header") + hdr = NULL; + + /* Print opening message */ + HDfprintf(stream, "%*sFree Space Sections...\n", indent, ""); + + /* + * Print the values. + */ + switch(client) { + case H5FS_CLIENT_FHEAP_ID: + if(H5HF_sects_debug(f, dxpl_id, client_addr, stream, indent + 3, MAX(0, fwidth - 3)) < 0) + HGOTO_ERROR(H5E_FSPACE, H5E_SYSTEM, FAIL, "unable to dump fractal heap free space sections") + break; + + default: + HDfprintf(stream, "Unknown client!\n"); + break; + } /* end switch */ + +done: + if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_FSPACE, H5E_PROTECT, FAIL, "unable to release free space header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5FS_sects_debug() */ + diff --git a/src/H5FSpkg.h b/src/H5FSpkg.h new file mode 100644 index 0000000..98a945e --- /dev/null +++ b/src/H5FSpkg.h @@ -0,0 +1,127 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Tuesday, May 2, 2006 + * + * Purpose: This file contains declarations which are visible only within + * the H5FS package. Source files outside the H5FS package should + * include H5FSprivate.h instead. + */ +#ifndef H5FS_PACKAGE +#error "Do not include this file outside the H5FS package!" +#endif + +#ifndef _H5FSpkg_H +#define _H5FSpkg_H + +/* Get package's private header */ +#include "H5FSprivate.h" /* File free space */ + +/* Other private headers needed by this file */ +#include "H5ACprivate.h" /* Metadata cache */ + +/**************************/ +/* Package Private Macros */ +/**************************/ + +/* Size of signature information (on disk) */ +#define H5FS_SIZEOF_MAGIC 4 + +/* Free space signatures */ +#define H5FS_HDR_MAGIC "FSHD" /* Header */ +#define H5FS_SECTS_MAGIC "FSSS" /* Serialized sections */ + +/* "Standard" size of prefix information for free space metadata */ +#define H5FS_METADATA_PREFIX_SIZE ( \ + 4 /* Signature */ \ + + 1 /* Version */ \ + + 1 /* Metadata flags */ \ + + 4 /* Metadata checksum */ \ + ) + +/* Size of the fractal heap header on disk */ +#define H5FS_HEADER_SIZE(f) ( \ + /* General metadata fields */ \ + H5FS_METADATA_PREFIX_SIZE \ + \ + /* Free space header specific fields */ \ + + 1 /* Client ID */ \ + + H5F_SIZEOF_SIZE(f) /* Total free space tracked */ \ + + H5F_SIZEOF_SIZE(f) /* # of sections tracked */ \ + + 2 /* Number of section classes */ \ + + 2 /* Shrink percent */ \ + + 2 /* Expand percent */ \ + + 2 /* Size of address space for sections (log2 of value) */ \ + + H5F_SIZEOF_SIZE(f) /* Max. size of section to track */ \ + + H5F_SIZEOF_ADDR(f) /* Address of serialized free space sections */ \ + + H5F_SIZEOF_SIZE(f) /* Size of serialized free space sections used */ \ + + H5F_SIZEOF_SIZE(f) /* Allocated size of serialized free space sections */ \ + ) + +/****************************/ +/* Package Private Typedefs */ +/****************************/ + +/* Free space header info */ +typedef struct H5FS_hdr_t { + /* Information for H5AC cache functions, _must_ be first field in structure */ + H5AC_info_t cache_info; + + /* Statistics */ + hsize_t tot_space; /* Total amount of space tracked */ + hsize_t sect_count; /* # of sections tracked */ + + /* Creation information */ + H5FS_client_t client; /* Type of user of this free space manager */ + unsigned nclasses; /* Number of section classes handled */ + unsigned shrink_percent; /* Percent of "normal" serialized size to shrink serialized space at */ + unsigned expand_percent; /* Percent of "normal" serialized size to expand serialized space at */ + unsigned max_sect_addr; /* Size of address space free sections are within (log2 of actual value) */ + hsize_t max_sect_size; /* Maximum size of section to track */ + + /* Serialized space information */ + haddr_t sect_addr; /* Address of the section info in the file */ + hsize_t sect_size; /* Size of the section info in the file */ + hsize_t alloc_sect_size; /* Allocated size of the section info in the file */ +} H5FS_hdr_t; + + +/*****************************/ +/* Package Private Variables */ +/*****************************/ + +/* H5FS header inherits cache-like properties from H5AC */ +H5_DLLVAR const H5AC_class_t H5AC_FSPACE_HDR[1]; + +/* Declare a free list to manage the H5FS_hdr_t struct */ +H5FL_EXTERN(H5FS_hdr_t); + + +/******************************/ +/* Package Private Prototypes */ +/******************************/ + +/* Debugging routines for dumping file structures */ +H5_DLL herr_t H5FS_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, + FILE *stream, int indent, int fwidth); +H5_DLL herr_t H5FS_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, + FILE *stream, int indent, int fwidth, haddr_t fs_addr, haddr_t client_addr); + +/* Metadata cache callbacks */ +H5_DLL herr_t H5FS_cache_hdr_dest(H5F_t *f, H5FS_hdr_t *hdr); + +#endif /* _H5FSpkg_H */ + diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h new file mode 100644 index 0000000..e6d669c --- /dev/null +++ b/src/H5FSprivate.h @@ -0,0 +1,120 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5FSprivate.h + * May 2 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Private header for library accessible file free space routines. + * + *------------------------------------------------------------------------- + */ + +#ifndef _H5FSprivate_H +#define _H5FSprivate_H + +/* Include package's public header */ +#include "H5FSpublic.h" + +/* Private headers needed by this file */ +#include "H5Fprivate.h" /* File access */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5SLprivate.h" /* Skip lists */ + +/**************************/ +/* Library Private Macros */ +/**************************/ + + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* Free space info (forward decl - defined in H5FS.c) */ +typedef struct H5FS_t H5FS_t; + +/* Forward declaration free space section info */ +typedef struct H5FS_section_info_t H5FS_section_info_t; + +/* Free space section class info */ +typedef struct H5FS_section_class_t { + unsigned type; /* Type of free space section */ + size_t serial_size; /* Size of serialized form of section */ + herr_t (*init)(struct H5FS_section_class_t *, const void *); /* Routine to initialize class-specific settings */ + herr_t (*serialize)(const H5FS_section_info_t *, uint8_t *); /* Routine to serialize a "live" section into a buffer */ + herr_t (*deserialize)(struct H5FS_section_class_t *cls, const uint8_t *, + haddr_t, hsize_t, H5FS_section_info_t **); /* Routine to deserialize a buffer into a "live" section */ + herr_t (*debug)(const H5FS_section_info_t *, FILE *, + int , int ); /* Routine to dump debugging information about a section */ +} H5FS_section_class_t; + +/* Free space section info */ +struct H5FS_section_info_t { + haddr_t addr; /* Address of free space section in the address space */ + /* (Not actually used as address, used as unique ID for free space node) */ + hsize_t size; /* Size of free space section */ + H5FS_section_class_t *cls; /* Class of free space section */ + enum { + H5FS_SECT_LIVE, /* Section has "live" memory references */ + H5FS_SECT_SERIALIZED} /* Section is in "serialized" form */ + state; /* Whether the section is in "serialized" or "live" form */ +}; + +/* Free space client IDs for identifying user of free space */ +typedef enum H5FS_client_t { + H5FS_CLIENT_FHEAP_ID = 0, /* Free space is used by fractal heap */ + H5FS_NUM_CLIENT_ID /* Number of free space client IDs (must be last) */ +} H5FS_client_t; + +/* Free space creation parameters */ +typedef struct H5FS_create_t { + H5FS_client_t client; /* Client's ID */ + unsigned shrink_percent; /* Percent of "normal" serialized size to shrink serialized space at */ + unsigned expand_percent; /* Percent of "normal" serialized size to expand serialized space at */ + unsigned max_sect_addr; /* Size of address space free sections are within (log2 of actual value) */ + hsize_t max_sect_size; /* Maximum size of section to track */ +} H5FS_create_t; + +/* Typedef for iteration operations */ +typedef herr_t (*H5FS_operator_t)(const H5FS_section_info_t *sect, + void *operator_data/*in,out*/); + + +/*****************************/ +/* Library-private Variables */ +/*****************************/ + +/* Declare a free list to manage the H5FS_section_class_t sequence information */ +H5FL_SEQ_EXTERN(H5FS_section_class_t); + + +/***************************************/ +/* Library-private Function Prototypes */ +/***************************************/ +H5_DLL H5FS_t *H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, + const H5FS_create_t *fs_create, H5SL_operator_t node_free_op, + size_t nclasses, H5FS_section_class_t *classes, const void *cls_init_udata); +H5_DLL H5FS_t *H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, + H5SL_operator_t node_free_op, size_t nclasses, + H5FS_section_class_t *classes, const void *cls_init_udata); +H5_DLL herr_t H5FS_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *node); +H5_DLL htri_t H5FS_find(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, hsize_t request, H5FS_section_info_t **node); +H5_DLL herr_t H5FS_iterate(H5FS_t *fspace, H5FS_operator_t op, void *op_data); +H5_DLL herr_t H5FS_flush(H5F_t *f, hid_t dxpl_id, unsigned flags); +H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace); + +#endif /* _H5FSprivate_H */ + diff --git a/src/H5FSpublic.h b/src/H5FSpublic.h new file mode 100644 index 0000000..dabd091 --- /dev/null +++ b/src/H5FSpublic.h @@ -0,0 +1,53 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5FSpublic.h + * May 2 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Public declarations for the file free space package. + * + *------------------------------------------------------------------------- + */ + +#ifndef _H5FSpublic_H +#define _H5FSpublic_H + +/* Public headers needed by this file */ +#include "H5public.h" + +/*****************/ +/* Public Macros */ +/*****************/ + +/*******************/ +/* Public Typedefs */ +/*******************/ + +/**********************************/ +/* Public API Function Prototypes */ +/**********************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _H5FSpublic_H */ + @@ -67,9 +67,6 @@ /* Package Variables */ /*********************/ -/* Declare a free list to manage the H5HF_hdr_t struct */ -H5FL_DEFINE(H5HF_hdr_t); - /*****************************/ /* Library Private Variables */ @@ -141,20 +138,17 @@ HDfprintf(stderr, "%s: hdr->id_len = %Zu\n", FUNC, hdr->id_len); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap info") /* Lock the heap header into memory */ -#ifdef QAK -HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr); -#endif /* QAK */ if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, NULL, NULL, H5AC_WRITE))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to load fractal heap header") - /* Point fractal heap wrapper at header */ + /* Point fractal heap wrapper at header and bump it's ref count */ fh->hdr = hdr; if(H5HF_hdr_incr(fh->hdr) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared heap header") /* Unlock heap header, now pinned */ if(H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap header") + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap header") hdr = NULL; /* Add heap to list of open objects in file */ @@ -170,7 +164,7 @@ HDfprintf(stderr, "%s: fh_addr = %a\n", FUNC, fh_addr); done: if(!ret_value) { if(fh) - (void)H5HF_close(fh); + (void)H5HF_close(fh, dxpl_id); else if(hdr) (void)H5HF_cache_hdr_dest(f, hdr); } /* end if */ @@ -253,7 +247,7 @@ done: HDONE_ERROR(H5E_HEAP, H5E_PROTECT, NULL, "unable to release fractal heap header") if(!ret_value) { if(fh) - (void)H5HF_close(fh); + (void)H5HF_close(fh, dxpl_id); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) @@ -387,6 +381,43 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_get_obj_len + * + * Purpose: Get the size of an entry in a fractal heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 9 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_get_obj_len(H5HF_t *fh, const void *_id, size_t *obj_len_p) +{ + const uint8_t *id = (const uint8_t *)_id; /* Object ID */ + + FUNC_ENTER_NOAPI_NOFUNC(H5HF_get_obj_len) + + /* + * Check arguments. + */ + HDassert(fh); + HDassert(id); + HDassert(obj_len_p); + + /* Skip over object offset */ + id += fh->hdr->heap_off_size; + + /* Retrieve the entry length */ + UINT64DECODE_VAR(id, *obj_len_p, fh->hdr->id_len); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_get_obj_len() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_read * * Purpose: Read an object from a fractal heap into a buffer @@ -456,7 +487,7 @@ done: *------------------------------------------------------------------------- */ herr_t -H5HF_close(H5HF_t *fh) +H5HF_close(H5HF_t *fh, hid_t dxpl_id) { herr_t ret_value = SUCCEED; @@ -474,19 +505,15 @@ H5HF_close(H5HF_t *fh) if(0 == fh->fo_count) { /* Remove the heap from the list of opened objects in the file */ if(H5FO_delete(fh->hdr->f, H5AC_dxpl_id, fh->hdr->heap_addr) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects") + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects") - /* Reset the free list information */ - /* (Bump the "generation" counter in case this heap header is still - * in the cache when the heap is re-opened -QAK) - */ - H5HF_flist_reset(fh->hdr->flist); - fh->hdr->fl_gen++; - fh->hdr->freelist_sync = FALSE; + /* Close the free space information */ + if(H5HF_space_close(fh->hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") /* Reset the block iterator */ if(H5HF_man_iter_reset(&fh->hdr->next_block) < 0) - HGOTO_ERROR(H5E_SYM, H5E_CANTRELEASE, FAIL, "can't reset block iterator") + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator") /* Decrement the reference count on the heap header */ if(H5HF_hdr_decr(fh->hdr) < 0) diff --git a/src/H5HFcache.c b/src/H5HFcache.c index c9d4163..1e6c1ed 100644 --- a/src/H5HFcache.c +++ b/src/H5HFcache.c @@ -321,6 +321,9 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); H5F_DECODE_LENGTH(f, p, hdr->total_man_free); H5F_DECODE_LENGTH(f, p, hdr->total_std_free); + /* Address of free section header */ + H5F_addr_decode(f, &p, &(hdr->fs_addr)); + /* Statistics information */ H5F_DECODE_LENGTH(f, p, hdr->total_size); H5F_DECODE_LENGTH(f, p, hdr->man_size); @@ -334,17 +337,11 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr); HDassert((size_t)(p - buf) == size); - /* If the heap has any blocks stored, the memory free list is out of sync */ - if(H5F_addr_defined(hdr->man_dtable.table_addr)) - hdr->freelist_sync = FALSE; - else - hdr->freelist_sync = TRUE; - /* Finish initialization of heap header */ if(H5HF_hdr_finish_init(hdr) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_CANTINIT, NULL, "can't finish initializing shared fractal heap header") #ifdef QAK -HDfprintf(stderr, "%s: hdr->flist = %p\n", FUNC, hdr->flist); +HDfprintf(stderr, "%s: hdr->fspace = %p\n", FUNC, hdr->fspace); #endif /* QAK */ /* Set return value */ @@ -431,6 +428,9 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a H5F_ENCODE_LENGTH(f, p, hdr->total_man_free); H5F_ENCODE_LENGTH(f, p, hdr->total_std_free); + /* Address of free section header */ + H5F_addr_encode(f, &p, hdr->fs_addr); + /* Statistics information */ H5F_ENCODE_LENGTH(f, p, hdr->total_size); H5F_ENCODE_LENGTH(f, p, hdr->man_size); @@ -487,9 +487,6 @@ H5HF_cache_hdr_dest(H5F_t UNUSED *f, H5HF_hdr_t *hdr) HDassert(hdr); HDassert(hdr->rc == 0); - /* Free the free list section information */ - H5HF_flist_free(hdr->flist); - /* Free the block size lookup table for the doubling table */ H5HF_dtable_dest(&hdr->man_dtable); @@ -615,8 +612,6 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, /* Set block's internal information */ dblock->size = *size; dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size); - dblock->free_list = NULL; - dblock->fl_gen = 0; /* Allocate block buffer */ /* XXX: Change to using free-list factories */ @@ -661,22 +656,11 @@ H5HF_cache_dblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_size, /* Share parent block */ if(H5HF_iblock_incr(dblock->parent) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") - - /* Retrieve this block's free space from parent */ - dblock->blk_free_space = dblock->parent->ents[dblock->par_entry].free_space; } /* end if */ - else { - /* Direct block is linked directly from heap header */ - dblock->blk_free_space = dblock->hdr->total_man_free; - } /* end else */ /* Offset of heap within the heap's address space */ UINT64DECODE_VAR(p, dblock->block_off, dblock->hdr->heap_off_size); - /* Offset of free list head */ - /* (Defer deserializing the whole free list until we actually need to modify it) */ - UINT64DECODE_VAR(p, dblock->free_list_head, dblock->blk_off_size); - /* Set return value */ ret_value = dblock; @@ -748,46 +732,8 @@ H5HF_cache_dblock_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, if(hdr->addrmap != H5HF_ABSOLUTE) HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "encoding mapped direct blocks not supported currently") - /* Offset of free list head */ - UINT64ENCODE_VAR(p, dblock->free_list_head, dblock->blk_off_size); - /* Sanity check */ - HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(hdr, dblock)); - - /* Check for dirty free list */ - if(dblock->free_list && dblock->free_list->dirty) { - H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ - - /* Loop over all free list blocks, updating their data */ - node = dblock->free_list->first; - while(node) { - /* Find first node which has enough room to describe free space */ - while(node && node->size < H5HF_MAN_ABS_DIRECT_FREE_NODE_SIZE(dblock)) - node = node->next; - - /* Check for free space node to encode */ - if(node) { - H5HF_direct_free_node_t *next_node; /* Pointer to next free list node for block */ - - /* Probe ahead for next node that is large enough to encode free space description */ - next_node = node->next; - while(next_node && next_node->size < H5HF_MAN_ABS_DIRECT_FREE_NODE_SIZE(dblock)) - next_node = next_node->next; - - /* Encode information for this node on free list */ - p = dblock->blk + node->my_offset; - UINT64ENCODE_VAR(p, node->size, dblock->blk_off_size); - UINT64ENCODE_VAR(p, (next_node ? next_node->my_offset : 0), dblock->blk_off_size); - - /* Advance to next node */ - node = node->next; - } /* end if */ - - } /* end while */ - - /* Reset the free list dirty flag */ - dblock->free_list->dirty = FALSE; - } /* end if */ + HDassert((size_t)(p - dblock->blk) == H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)); /* Write the direct block */ if(H5F_block_write(f, H5FD_MEM_FHEAP_DBLOCK, addr, (size_t)dblock->size, dxpl_id, dblock->blk) < 0) @@ -839,11 +785,6 @@ H5HF_cache_dblock_dest(H5F_t UNUSED *f, H5HF_direct_t *dblock) if(H5HF_iblock_decr(dblock->parent) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") - /* Check for free list & free it, if necessary */ - if(dblock->free_list) - if(H5HF_man_dblock_destroy_freelist(dblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't destroy free list for direct block") - /* Free block's buffer */ H5FL_BLK_FREE(direct_block, dblock->blk); @@ -880,9 +821,6 @@ H5HF_cache_dblock_clear(H5F_t *f, H5HF_direct_t *dblock, hbool_t destroy) */ HDassert(dblock); - /* Reset the free list dirty flag */ - dblock->free_list->dirty = FALSE; - /* Reset the dirty flag. */ dblock->cache_info.is_dirty = FALSE; @@ -951,9 +889,6 @@ H5HF_cache_iblock_load(H5F_t *f, hid_t dxpl_id, haddr_t addr, const void *_nrows const uint8_t *p; /* Pointer into raw data buffer */ haddr_t heap_addr; /* Address of heap header in the file */ uint32_t metadata_chksum; /* Metadata checksum value */ -#ifndef NDEBUG - hsize_t acc_child_free_space; /* Accumulated child free space */ -#endif /* NDEBUG */ size_t u; /* Local index variable */ H5HF_indirect_t *ret_value; /* Return value */ @@ -982,7 +917,6 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr); iblock->nrows = *nrows; iblock->addr = addr; iblock->dirty = FALSE; - iblock->fl_gen = 0; /* Compute size of indirect block */ iblock->size = H5HF_MAN_INDIRECT_SIZE(iblock->hdr, iblock); @@ -1031,16 +965,10 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr); if(H5HF_iblock_incr(iblock->parent) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") - /* Retrieve this block's free space from parent */ - iblock->child_free_space = iblock->parent->ents[iblock->par_entry].free_space; - /* Set max. # of rows in this block */ iblock->max_rows = iblock->nrows; } /* end if */ else { - /* Direct block is linked directly from heap header */ - iblock->child_free_space = iblock->hdr->total_man_free; - /* Set max. # of rows in this block */ iblock->max_rows = iblock->hdr->man_dtable.max_root_rows; } /* end else */ @@ -1052,29 +980,19 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr); HDassert(iblock->nrows > 0); if(NULL == (iblock->ents = H5FL_SEQ_MALLOC(H5HF_indirect_ent_t, (iblock->nrows * iblock->hdr->man_dtable.cparam.width)))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct entries") -#ifndef NDEBUG - /* Reset child free space */ - acc_child_free_space = 0; -#endif /* NDEBUG */ for(u = 0; u < (iblock->nrows * iblock->hdr->man_dtable.cparam.width); u++) { - /* Decode block address */ + /* Decode child block address */ H5F_addr_decode(f, &p, &(iblock->ents[u].addr)); - /* Decode direct & indirect blocks differently */ +#ifdef LATER + /* Decode direct & indirect blocks differently (later, when direct blocks can be compressed) */ if(u < (iblock->hdr->man_dtable.max_direct_rows * iblock->hdr->man_dtable.cparam.width)) UINT32DECODE_VAR(p, iblock->ents[u].free_space, iblock->hdr->man_dtable.max_dir_blk_off_size) - else - UINT64DECODE_VAR(p, iblock->ents[u].free_space, iblock->hdr->heap_off_size) +#endif /* LATER */ #ifdef QAK -HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a, %Hu}\n", FUNC, u, iblock->ents[u].addr, iblock->ents[u].free_space); +HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].addr); #endif /* QAK */ -#ifndef NDEBUG - acc_child_free_space += iblock->ents[u].free_space; -#endif /* NDEBUG */ } /* end for */ -#ifndef NDEBUG - HDassert(iblock->parent == NULL || acc_child_free_space == iblock->child_free_space); -#endif /* NDEBUG */ /* Sanity check */ HDassert((size_t)(p - buf) == iblock->size); @@ -1172,16 +1090,16 @@ HDfprintf(stderr, "%s: hdr->man_dtable.cparam.width = %u\n", FUNC, hdr->man_dtab /* Encode indirect block-specific fields */ for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) { #ifdef QAK -HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a, %Hu}\n", FUNC, u, iblock->ents[u].addr, iblock->ents[u].free_space); +HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].addr); #endif /* QAK */ - /* Encode block address */ + /* Encode child block address */ H5F_addr_encode(f, &p, iblock->ents[u].addr); - /* Encode direct & indirect blocks differently */ +#ifdef LATER + /* Encode direct & indirect blocks differently (when direct blocks can be compressed) */ if(u < (hdr->man_dtable.max_direct_rows * hdr->man_dtable.cparam.width)) UINT32ENCODE_VAR(p, iblock->ents[u].free_space, hdr->man_dtable.max_dir_blk_off_size) - else - UINT64ENCODE_VAR(p, iblock->ents[u].free_space, hdr->heap_off_size) +#endif /* LATER */ } /* end for */ /* Sanity check */ diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c index 6173fd8..3135590 100644 --- a/src/H5HFdbg.c +++ b/src/H5HFdbg.c @@ -28,6 +28,7 @@ /****************/ #define H5HF_PACKAGE /*suppress error about including H5HFpkg */ +#define H5HF_DEBUGGING /* Need access to fractal heap debugging routines */ /***********/ /* Headers */ @@ -48,6 +49,25 @@ /* Local Typedefs */ /******************/ +/* User data for direct block debugging iterator callback */ +typedef struct { + FILE *stream; /* Stream for output */ + int indent; /* Indention amount */ + int fwidth; /* Field width mount */ + haddr_t dblock_addr; /* Direct block's address */ + haddr_t dblock_size; /* Direct block's size */ + uint8_t *marker; /* 'Marker' array for free space */ + size_t sect_count; /* Number of free space sections in block */ + size_t amount_free; /* Amount of free space in block */ +} H5HF_debug_iter_ud1_t; + +/* User data for free space section iterator callback */ +typedef struct { + FILE *stream; /* Stream for output */ + int indent; /* Indention amount */ + int fwidth; /* Field width mount */ +} H5HF_debug_iter_ud2_t; + /********************/ /* Package Typedefs */ @@ -217,6 +237,9 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent, HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, "Number of objects in heap:", hdr->nobjs); + HDfprintf(stream, "%*s%-*s %a\n", indent, "", fwidth, + "Address of free space manager for heap:", + hdr->fs_addr); HDfprintf(stream, "%*sManaged Objects Doubling-Table Info...\n", indent, ""); H5HF_dtable_debug(&hdr->man_dtable, stream, indent + 3, MAX(0, fwidth -3)); @@ -230,6 +253,90 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_dblock_debug_cb + * + * Purpose: Detect free space within a direct block + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 13 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_dblock_debug_cb(const H5FS_section_info_t *_sect, void *_udata) +{ + const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */ + H5HF_debug_iter_ud1_t *udata = (H5HF_debug_iter_ud1_t *)_udata; /* User data for callbacks */ + haddr_t sect_start, sect_end; /* Section's beginning and ending offsets */ + haddr_t dblock_start, dblock_end; /* Direct block's beginning and ending offsets */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dblock_debug_cb) + + /* + * Check arguments. + */ + HDassert(sect); + HDassert(udata); + + /* Set up some local variables, for convenience */ + sect_start = sect->sect_info.addr; + sect_end = (sect->sect_info.addr + sect->sect_info.size) - 1; + HDassert(sect_end >= sect_start); + dblock_start = udata->dblock_addr; + dblock_end = (udata->dblock_addr + udata->dblock_size) - 1; + HDassert(dblock_end >= dblock_start); + + /* Check for overlap between free space section & direct block */ + if((sect_start <= dblock_end && sect_end >=dblock_start) || /* section within or overlaps w/beginning of direct block*/ + (sect_start <= dblock_end && sect_end >=dblock_end)) { /* section overlaps w/end of direct block */ + char temp_str[32]; /* Temporary string for formatting */ + size_t start, end; /* Start & end of the overlapping area */ + size_t len; /* Length of the overlapping area */ + size_t overlap; /* Track any overlaps */ + unsigned u; /* Local index variable */ + + /* Calculate the starting & ending */ + if(sect_start < dblock_start) + start = 0; + else + start = sect_start - dblock_start; + if(sect_end > dblock_end) + end = udata->dblock_size; + else + end = (sect_end - dblock_start) + 1; + + /* Calculate the length */ + len = end - start; + + sprintf(temp_str, "Section #%u:", udata->sect_count); + HDfprintf(udata->stream, "%*s%-*s %8Zu, %8Zu\n", udata->indent + 3, "", MAX(0, udata->fwidth - 9), + temp_str, + start, len); + udata->sect_count++; + + /* Mark this node's free space & check for overlaps w/other sections */ + overlap = 0; + for(u = start; u < end; u++) { + if(udata->marker[u]) + overlap++; + udata->marker[u] = 1; + } /* end for */ + + /* Flag overlaps */ + if (overlap) + fprintf(udata->stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n"); + else + udata->amount_free += len; + } /* end if */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5HF_dblock_debug_cb() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_dblock_debug * * Purpose: Prints debugging info about a fractal heap direct block. @@ -248,13 +355,10 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, { H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ H5HF_direct_t *dblock = NULL; /* Fractal heap direct block info */ - H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ + H5HF_debug_iter_ud1_t udata; /* User data for callbacks */ size_t blk_prefix_size; /* Size of prefix for block */ - unsigned node_count = 0; /* Number of free space nodes */ - size_t amount_free = 0; /* Amount of free space in block */ + size_t amount_free; /* Amount of free space in block */ uint8_t *marker = NULL; /* Track free space for block */ - size_t overlap; /* Number of free space overlaps */ - size_t u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5HF_dblock_debug, FAIL) @@ -282,12 +386,6 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, addr, block_size, NULL, 0, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap direct block") - /* Check for valid free list */ - if(!dblock->free_list) - if(H5HF_man_dblock_build_freelist(dblock, addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, FAIL, "can't decode free list for block") - HDassert(dblock->free_list); - /* Print opening message */ HDfprintf(stream, "%*sFractal Heap Direct Block...\n", indent, ""); @@ -300,58 +398,49 @@ H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, "Offset of direct block in heap:", dblock->block_off); - blk_prefix_size = H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(hdr, dblock); + blk_prefix_size = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, "Size of block header:", blk_prefix_size); HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, "Size of block offsets:", dblock->blk_off_size); - HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, - "Total free space in block:", - dblock->blk_free_space); - HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, - "Offset of free list head:", - dblock->free_list_head); - /* - * Traverse the free list and check that all free blocks fall within - * the block and that no two free blocks point to the same region of - * the block. */ + /* Allocate space for the free space markers */ if(NULL == (marker = H5MM_calloc(dblock->size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") - node = dblock->free_list->first; - if(node) - HDfprintf(stream, "%*sFree Blocks (offset, next offset, size):\n", indent, ""); - while(node) { - char temp_str[32]; + /* Initialize the free space information for the heap */ + if(H5HF_space_start(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") - sprintf(temp_str, "Block #%u:", node_count); - HDfprintf(stream, "%*s%-*s %8Zu, %8Zu, %8Zu\n", indent + 3, "", MAX(0, fwidth - 9), - temp_str, - node->my_offset, node->next_offset, node->size); - - if (node->my_offset + node->size > dblock->size) - fprintf(stream, "***THAT FREE BLOCK IS OUT OF BOUNDS!\n"); - else { - /* Mark this node's free space & check for overlaps w/other free space */ - for(u = overlap = 0; u < node->size; u++) { - if(marker[node->my_offset + u]) - overlap++; - marker[node->my_offset + u] = 1; - } /* end for */ - - if (overlap) - fprintf(stream, "***THAT FREE BLOCK OVERLAPPED A PREVIOUS ONE!\n"); - else - amount_free += node->size; - } /* end else */ - - /* Avance to next node */ - node = node->next; - node_count++; - } /* end while */ + /* Prepare user data for section iteration callback */ + udata.stream = stream; + udata.indent = indent; + udata.fwidth = fwidth; + udata.dblock_addr = dblock->block_off; + udata.dblock_size = block_size; + udata.marker = marker; + udata.sect_count = 0; + udata.amount_free = 0; + + /* Print header */ + HDfprintf(stream, "%*sFree Blocks (offset, size):\n", indent, ""); + + /* Iterate over the free space sections, to detect overlaps with this block */ + if(H5FS_iterate(hdr->fspace, H5HF_dblock_debug_cb, &udata) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space") + + /* Close the free space information */ + if(H5HF_space_close(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") + + /* Keep the amount of space free */ + amount_free = udata.amount_free; + + /* Check for no free space */ + if(amount_free == 0) + HDfprintf(stream, "%*s<none>\n", indent + 3, ""); HDfprintf(stream, "%*s%-*s %.2f%%\n", indent, "", fwidth, "Percent of available space for data used:", @@ -367,6 +456,7 @@ done: HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap direct block") if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, hdr_addr, hdr, H5AC__NO_FLAGS_SET) < 0) HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") + H5MM_xfree(marker); FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_dblock_debug() */ @@ -393,7 +483,6 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, H5HF_indirect_t *iblock = NULL; /* Fractal heap direct block info */ size_t dblock_size; /* Current direct block size */ char temp_str[64]; /* Temporary string, for formatting */ - hsize_t child_free_space; /* Block's children's free space */ size_t u, v; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -425,11 +514,6 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, /* Print opening message */ HDfprintf(stream, "%*sFractal Heap Indirect Block...\n", indent, ""); - /* Compute the child free space */ - child_free_space = 0; - for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) - child_free_space += iblock->ents[u].free_space; - /* * Print the values. */ @@ -439,9 +523,6 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, "Offset of indirect block in heap:", iblock->block_off); - HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth, - "Total children free space:", - child_free_space); HDfprintf(stream, "%*s%-*s %Zu\n", indent, "", fwidth, "Size of indirect block:", iblock->size); @@ -465,10 +546,9 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, size_t off = (u * hdr->man_dtable.cparam.width) + v; sprintf(temp_str, "Col #%u:", (unsigned)v); - HDfprintf(stream, "%*s%-*s %9a, %8Zu\n", indent + 6, "", MAX(0, fwidth - 6), + HDfprintf(stream, "%*s%-*s %9a\n", indent + 6, "", MAX(0, fwidth - 6), temp_str, - iblock->ents[off].addr, - iblock->ents[off].free_space); + iblock->ents[off].addr); } /* end for */ dblock_size *= 2; } /* end for */ @@ -488,10 +568,9 @@ H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, size_t off = (u * hdr->man_dtable.cparam.width) + v; sprintf(temp_str, "Col #%u:", (unsigned)v); - HDfprintf(stream, "%*s%-*s %9a, %8Hu\n", indent + 6, "", MAX(0, fwidth - 6), + HDfprintf(stream, "%*s%-*s %9a\n", indent + 6, "", MAX(0, fwidth - 6), temp_str, - iblock->ents[off].addr, - iblock->ents[off].free_space); + iblock->ents[off].addr); } /* end for */ } /* end for */ } /* end if */ @@ -509,3 +588,120 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5HF_iblock_debug() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_sects_debug_cb + * + * Purpose: Prints debugging info about a free space section for a fractal heap. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 13 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata) +{ + const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Section to dump info */ + H5HF_debug_iter_ud2_t *udata = (H5HF_debug_iter_ud2_t *)_udata; /* User data for callbacks */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sects_debug_cb) + + /* + * Check arguments. + */ + HDassert(sect); + HDassert(udata); + + /* Print generic section information */ + HDfprintf(udata->stream, "%*s%-*s %a\n", udata->indent, "", udata->fwidth, + "Section address:", + sect->sect_info.addr); + HDfprintf(udata->stream, "%*s%-*s %Hu\n", udata->indent, "", udata->fwidth, + "Section size:", + sect->sect_info.size); + HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, + "Section type:", + (sect->sect_info.cls->type == H5FS_SECT_FHEAP_SINGLE ? "single" : + (sect->sect_info.cls->type == H5FS_SECT_FHEAP_RANGE ? "range" : + (sect->sect_info.cls->type == H5FS_SECT_FHEAP_INDIRECT ? "indirect" : "unknown")))); + HDfprintf(udata->stream, "%*s%-*s %s\n", udata->indent, "", udata->fwidth, + "Section state:", + (sect->sect_info.state == H5FS_SECT_LIVE ? "live" : "serialized")); + + /* Call the section's debugging routine */ + if(sect->sect_info.cls->debug) + if((sect->sect_info.cls->debug)(_sect, udata->stream, udata->indent + 3, MAX(0, udata->fwidth - 3)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't dump section's debugging info") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sects_debug_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sects_debug + * + * Purpose: Prints debugging info about free space sections for a fractal heap. + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 9 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr, + FILE *stream, int indent, int fwidth) +{ + H5HF_hdr_t *hdr = NULL; /* Fractal heap header info */ + H5HF_debug_iter_ud2_t udata; /* User data for callbacks */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI(H5HF_sects_debug, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(fh_addr)); + HDassert(stream); + HDassert(indent >= 0); + HDassert(fwidth >= 0); + + /* + * Load the fractal heap header. + */ + if(NULL == (hdr = H5AC_protect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, NULL, NULL, H5AC_READ))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTLOAD, FAIL, "unable to load fractal heap header") + + /* Initialize the free space information for the heap */ + if(H5HF_space_start(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") + + /* Prepare user data for section iteration callback */ + udata.stream = stream; + udata.indent = indent; + udata.fwidth = fwidth; + + /* Iterate over all the free space sections */ + if(H5FS_iterate(hdr->fspace, H5HF_sects_debug_cb, &udata) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADITER, FAIL, "can't iterate over heap's free space") + + /* Close the free space information */ + if(H5HF_space_close(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") + +done: + if(hdr && H5AC_unprotect(f, dxpl_id, H5AC_FHEAP_HDR, fh_addr, hdr, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_HEAP, H5E_PROTECT, FAIL, "unable to release fractal heap header") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_sects_debug() */ + diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c index 8ac411b..8e37137 100644 --- a/src/H5HFdblock.c +++ b/src/H5HFdblock.c @@ -56,8 +56,6 @@ /********************/ /* Local Prototypes */ /********************/ -static herr_t H5HF_man_dblock_regen_freelist(H5HF_direct_t *dblock, - haddr_t dblock_addr); /*********************/ @@ -67,12 +65,6 @@ static herr_t H5HF_man_dblock_regen_freelist(H5HF_direct_t *dblock, /* Declare a free list to manage the H5HF_direct_t struct */ H5FL_DEFINE(H5HF_direct_t); -/* Declare a free list to manage the H5HF_direct_free_head_t struct */ -H5FL_DEFINE(H5HF_direct_free_head_t); - -/* Declare a free list to manage the H5HF_direct_free_node_t struct */ -H5FL_DEFINE(H5HF_direct_free_node_t); - /*****************************/ /* Library Private Variables */ @@ -103,7 +95,6 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo unsigned par_entry, size_t block_size, hsize_t block_off, haddr_t *addr_p, H5HF_free_section_t **ret_sec_node) { - H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ H5HF_free_section_t *sec_node; /* Pointer to free list section for block */ H5HF_direct_t *dblock = NULL; /* Pointer to direct block */ size_t free_space; /* Free space in new block */ @@ -145,11 +136,7 @@ HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_o dblock->size = block_size; dblock->block_off = block_off; dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(block_size); - dblock->fl_gen = hdr->fl_gen; /* New blocks have their free list generation set up correctly */ - dblock->free_list_head = H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(hdr, dblock); - dblock->blk_free_space = block_size - - (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, block_size) + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); - free_space = block_size - dblock->free_list_head; + free_space = block_size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); /* Allocate buffer for block */ /* XXX: Change to using free-list factories */ @@ -159,38 +146,19 @@ HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_o HDmemset(dblock->blk, 0, dblock->size); #endif /* H5_USING_PURIFY */ - /* Set up free list head */ - if(NULL == (dblock->free_list = H5FL_MALLOC(H5HF_direct_free_head_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head") - dblock->free_list->dirty = TRUE; - - /* Set up free list node for all unused space in block */ - if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") - - /* Set node's information */ - node->size = free_space; - node->my_offset = dblock->free_list_head; - node->next_offset = 0; - node->prev = node->next = NULL; - - /* Attach to free list head */ -/* XXX: Convert this list to a skip list? */ - dblock->free_list->first = node; - /* Allocate space for the header on disk */ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)block_size))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block") - /* Create free list section node */ + /* Create free space section node */ if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") /* Set section's information */ - sec_node->sect_addr = block_off + node->my_offset; - /* (section size is "object size", without the metadata overhead) */ - sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); - sec_node->type = H5HF_SECT_SINGLE; + sec_node->sect_info.addr = block_off + H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); + sec_node->sect_info.size = free_space; + sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_SINGLE]; + sec_node->sect_info.state = H5FS_SECT_LIVE; sec_node->u.single.parent = dblock->parent; if(dblock->parent) { if(H5HF_iblock_incr(dblock->parent) < 0) @@ -206,7 +174,7 @@ HDmemset(dblock->blk, 0, dblock->size); *ret_sec_node = sec_node; else { /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) + if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") } /* end else */ @@ -224,379 +192,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_man_dblock_build_freelist - * - * Purpose: Parse the free list information for a direct block and build - * block's free list - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Feb 28 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr) -{ - H5HF_direct_free_head_t *head = NULL; /* Pointer to free list head for block */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_build_freelist) - - /* - * Check arguments. - */ - HDassert(dblock); - - /* Allocate head of list */ - if(NULL == (head = H5FL_MALLOC(H5HF_direct_free_head_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list head") - head->dirty = FALSE; - - /* Check for any nodes on free list */ - if(dblock->free_list_head == 0) - head->first = NULL; - else { - H5HF_hdr_t *hdr; /* Pointer to shared heap header */ - H5HF_free_section_t *sec_node; /* Pointer to free list section for block */ - H5HF_direct_free_node_t *node = NULL; /* Pointer to free list node for block */ - H5HF_direct_free_node_t *prev_node; /* Pointer to previous free list node for block */ - hsize_t free_len; /* Length of free list info */ - hsize_t next_off; /* Next node offset in block */ - hsize_t prev_off; /* Prev node offset in block */ - uint8_t *p; /* Temporary pointer to free node info */ - - /* Get the pointer to the shared heap info */ - hdr = dblock->hdr; - - /* Point to first node in free list */ - p = dblock->blk + dblock->free_list_head; - - /* Decode information for first node on free list */ - UINT64DECODE_VAR(p, free_len, dblock->blk_off_size); - UINT64DECODE_VAR(p, next_off, dblock->blk_off_size); - - /* Allocate node on list */ - if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") - - /* Set node's information */ - node->size = free_len; - node->my_offset = dblock->free_list_head; - node->next_offset = next_off; - node->prev = node->next = NULL; - - /* Attach to free list head */ - head->first = node; - - /* Set block's free space */ - dblock->blk_free_space = free_len; - - /* Create free list section node */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_addr = dblock->block_off + node->my_offset; - /* (section size is "object size", without the metadata overhead) */ - sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); - sec_node->type = H5HF_SECT_SINGLE; - sec_node->u.single.parent = dblock->parent; - if(dblock->parent) { - if(H5HF_iblock_incr(dblock->parent) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - } /* end if */ - sec_node->u.single.par_entry = dblock->par_entry; - sec_node->u.single.dblock_addr = dblock_addr; - sec_node->u.single.dblock_size = dblock->size; - - /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") - - /* Set up trailing node pointer */ - prev_node = node; - prev_off = next_off; - - /* Bring in rest of node on free list */ - while(next_off != 0) { - /* Point to first node in free list */ - p = dblock->blk + next_off; - - /* Decode information for first node on free list */ - UINT64DECODE_VAR(p, free_len, dblock->blk_off_size); - UINT64DECODE_VAR(p, next_off, dblock->blk_off_size); - - /* Allocate node on list */ - if(NULL == (node = H5FL_MALLOC(H5HF_direct_free_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list node") - - /* Set node's information */ - node->size = free_len; - node->my_offset = prev_off; - node->next_offset = next_off; - node->prev = prev_node; - node->next = NULL; - - /* Adjust block's free space */ - dblock->blk_free_space += free_len; - - /* Create free list section node */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_addr = dblock->block_off + node->my_offset; - /* (section size is "object size", without the metadata overhead) */ - sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); - sec_node->type = H5HF_SECT_SINGLE; - sec_node->u.single.parent = dblock->parent; - if(dblock->parent) { - if(H5HF_iblock_incr(dblock->parent) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - } /* end if */ - sec_node->u.single.par_entry = dblock->par_entry; - sec_node->u.single.dblock_addr = dblock_addr; - sec_node->u.single.dblock_size = dblock->size; - - /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") - - /* Update trailing info */ - prev_node->next = node; - prev_off = next_off; - - /* Advance to next node */ - prev_node = node; - } /* end while */ - } /* end else */ - - /* Assign free list head to block */ - dblock->free_list = head; - -done: -/* XXX: cleanup on failure? */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_dblock_build_freelist() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_dblock_regen_freelist - * - * Purpose: Regenerate the free section information for the free space - * in a direct block's free list. - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Apr 25 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_dblock_regen_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr) -{ - H5HF_hdr_t *hdr; /* Pointer to shared heap header */ - H5HF_free_section_t *sec_node; /* Pointer to free list section for block */ - H5HF_direct_free_node_t *node; /* First node in free list */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_regen_freelist) - - /* - * Check arguments. - */ - HDassert(dblock); - HDassert(dblock->free_list); - - /* Get the pointer to the shared heap info */ - hdr = dblock->hdr; - - /* Iterate through nodes on block's free list */ - node = dblock->free_list->first; - while(node) { - /* Create free list section node */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_addr = dblock->block_off + node->my_offset; - /* (section size is "object size", without the metadata overhead) */ - sec_node->sect_size = node->size - H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); - sec_node->type = H5HF_SECT_SINGLE; - sec_node->u.single.parent = dblock->parent; - if(dblock->parent) { - if(H5HF_iblock_incr(dblock->parent) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - } /* end if */ - sec_node->u.single.par_entry = dblock->par_entry; - sec_node->u.single.dblock_addr = dblock_addr; - sec_node->u.single.dblock_size = dblock->size; - - /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") - - /* Advance to next node */ - node = node->next; - } /* end while */ - -done: -/* XXX: cleanup on failure? */ - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_dblock_regen_freelist() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_dblock_destroy_freelist - * - * Purpose: Destroy the free list information for a direct block - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Apr 22 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_man_dblock_destroy_freelist(H5HF_direct_t *dblock) -{ - H5HF_direct_free_node_t *node; /* Pointer to free list node for block */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_dblock_destroy_freelist) - - /* - * Check arguments. - */ - HDassert(dblock); - HDassert(dblock->free_list); - - /* Walk through list, freeing the nodes */ - node = dblock->free_list->first; - while(node) { - H5HF_direct_free_node_t *last_node; /* Pointer to last free list node for block */ - - /* Advance to next node */ - last_node = node; - node = node->next; - - /* Release the last node */ - H5FL_FREE(H5HF_direct_free_node_t, last_node); - } /* end while */ - - /* Release the free list head */ - H5FL_FREE(H5HF_direct_free_head_t, dblock->free_list); - - /* Reset the free list head */ - dblock->free_list = NULL; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* end H5HF_man_dblock_destroy_freelist() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_dblock_adj_free - * - * Purpose: Adjust the free space for a direct block, and it's parents - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Mar 14 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_man_dblock_adj_free(H5HF_direct_t *dblock, ssize_t amt) -{ - H5HF_hdr_t *hdr; /* Shared heap information */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_dblock_adj_free) -#ifdef QAK -HDfprintf(stderr, "%s: amt = %Zd\n", FUNC, amt); -#endif /* QAK */ - - /* - * Check arguments. - */ - HDassert(dblock); - - /* Get the pointer to the shared heap header */ - hdr = dblock->hdr; - - /* Adjust space available in block */ - HDassert(amt > 0 || dblock->blk_free_space >= (size_t)-amt); - dblock->blk_free_space += amt; - - /* Check if the parent info is set */ - if(dblock->parent) { - H5HF_indirect_t *iblock; /* Block's parent */ - - /* Get the pointer to the shared parent indirect block */ - iblock = dblock->parent; - - /* Adjust this indirect block's child free space */ -#ifdef QAK -HDfprintf(stderr, "%s: dblock->par_entry = %u\n", FUNC, dblock->par_entry); -HDfprintf(stderr, "%s: iblock->block_off = %a\n", FUNC, iblock->block_off); -HDfprintf(stderr, "%s: iblock->child_free_space = %Hu\n", FUNC, iblock->child_free_space); -HDfprintf(stderr, "%s: iblock->ents[dblock->par_entry].free_space = %Hu\n", FUNC, iblock->ents[dblock->par_entry].free_space); -#endif /* QAK */ - HDassert(amt > 0 || iblock->ents[dblock->par_entry].free_space >= (hsize_t)-amt); - iblock->ents[dblock->par_entry].free_space += amt; - HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt); - iblock->child_free_space += amt; - - /* Mark indirect block as dirty */ - if(H5HF_iblock_dirty(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - - /* Modify the free space in parent block(s) */ - while(iblock->parent) { - size_t par_entry; /* Entry in parent */ - - /* Get the pointer to the shared parent indirect block */ - par_entry = iblock->par_entry; - iblock = iblock->parent; - HDassert(iblock); - - /* Adjust this indirect block's child free space */ - HDassert(amt > 0 || iblock->ents[par_entry].free_space >= (hsize_t)-amt); - iblock->ents[par_entry].free_space += amt; - HDassert(amt > 0 || iblock->child_free_space >= (hsize_t)-amt); - iblock->child_free_space += amt; - - /* Mark indirect block as dirty */ - if(H5HF_iblock_dirty(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - } /* end while */ - } /* end if */ - - /* Update shared heap free space header */ - HDassert(amt > 0 || hdr->total_man_free >= (hsize_t)-amt); - hdr->total_man_free += amt; -#ifdef QAK -HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free); -#endif /* QAK */ - - /* Mark heap header as modified */ - if(H5HF_hdr_dirty(hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_dblock_adj_free() */ - - -/*------------------------------------------------------------------------- * Function: H5HF_man_dblock_new * * Purpose: Create a direct block large enough to hold an object of @@ -641,11 +236,9 @@ HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request); /* Adjust the size of block needed to fulfill request, with overhead */ #ifdef QAK HDfprintf(stderr, "%s: Check 1 - min_dblock_size = %Zu\n", FUNC, min_dblock_size); -HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, hdr->man_dtable.cparam.start_block_size)); -HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN = %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); +HDfprintf(stderr, "%s: H5HF_MAN_ABS_DIRECT_OVERHEAD= %u\n", FUNC, H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)); #endif /* QAK */ - if((min_dblock_size - request) < (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, min_dblock_size) - + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr))) + if((min_dblock_size - request) < H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)) min_dblock_size *= 2; #ifdef QAK HDfprintf(stderr, "%s: Check 2 - min_dblock_size = %Zu\n", FUNC, min_dblock_size); @@ -761,28 +354,6 @@ HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Zu\n", FUNC, dblock_addr if(NULL == (dblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, &dblock_size, &par_info, rw))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block") - /* Regenerate the free list information for this block, if necessary */ - /* (Only create free list information if write access is requested) */ - if(rw == H5AC_WRITE && hdr->fl_gen != dblock->fl_gen) { -#ifdef QAK -HDfprintf(stderr, "%s: building free list for direct block\n", FUNC); -#endif /* QAK */ - /* If the block has a free list from a previous generation, get rid of it */ - if(dblock->free_list) { - if(H5HF_man_dblock_regen_freelist(dblock, dblock_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, NULL, "can't regenerate free list for direct block") - } /* end if */ - else { - /* Build the free list for the block */ - if(H5HF_man_dblock_build_freelist(dblock, dblock_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't decode free list for block") - } /* end else */ - HDassert(dblock->free_list); - - /* Mark the block's free list generation as up to date now */ - dblock->fl_gen = hdr->fl_gen; - } /* end if */ - /* Set the return value */ ret_value = dblock; diff --git a/src/H5HFflist.c b/src/H5HFflist.c deleted file mode 100644 index 962f3ad..0000000 --- a/src/H5HFflist.c +++ /dev/null @@ -1,614 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * Copyright by the Board of Trustees of the University of Illinois. * - * All rights reserved. * - * * - * This file is part of HDF5. The full HDF5 copyright notice, including * - * terms governing use, modification, and redistribution, is contained in * - * the files COPYING and Copyright.html. COPYING can be found at the root * - * of the source code distribution tree; Copyright.html can be found at the * - * root level of an installed copy of the electronic HDF5 document set and * - * is linked from the top-level documents page. It can also be found at * - * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * - * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> - * Tuesday, March 7, 2006 - * - * Purpose: Fractal heap free space functions. - * - */ - -/****************/ -/* Module Setup */ -/****************/ - -#define H5HF_PACKAGE /*suppress error about including H5HFpkg */ - -/***********/ -/* Headers */ -/***********/ -#include "H5private.h" /* Generic Functions */ -#include "H5Eprivate.h" /* Error handling */ -#include "H5HFpkg.h" /* Fractal heaps */ -#include "H5Vprivate.h" /* Vectors and arrays */ - -/****************/ -/* Local Macros */ -/****************/ - -/* Max. height of the skip list holding free list nodes */ -#define H5HF_FLIST_DEFAULT_SKIPLIST_HEIGHT 16 - -/******************/ -/* Local Typedefs */ -/******************/ - -/* Structure for storing single free list section */ -typedef struct H5HF_flist_single_t { - void *node; /* Pointer to section's node */ - size_t *size_key; /* Pointer to size key for section */ - haddr_t *addr_key; /* Pointer to address key for section */ -} H5HF_flist_single_t; - -/* Free list node for free list sections of the same size */ -typedef struct H5HF_flist_node_t { - size_t sec_size; /* Size of all sections on list */ - H5SL_t *sec_list; /* Skip list to hold pointers to actual free list section node */ -} H5HF_flist_node_t; - - -/********************/ -/* Package Typedefs */ -/********************/ - -/* Main free list info */ -struct H5HF_freelist_t { - hsize_t tot_space; /* Total amount of space in free list */ - size_t sec_count; /* # of sections on free list */ - H5HF_flist_single_t single; /* Section information when free list has only one free section */ - unsigned nbins; /* Number of bins */ - H5SL_operator_t node_free_op; /* Callback for freeing nodes when free list is destroyed */ - H5SL_t **bins; /* Pointer to array of lists of free nodes */ - hbool_t using_bins; /* Flag to indicate that all nodes are in the bins */ -}; - - -/********************/ -/* Local Prototypes */ -/********************/ -static herr_t H5HF_flist_node_free_cb(void *item, void *key, void *op_data); -static herr_t H5HF_flist_init(H5HF_freelist_t *flist); - - -/*********************/ -/* Package Variables */ -/*********************/ - -/* Declare a free list to manage the H5HF_freelist_t struct */ -H5FL_DEFINE_STATIC(H5HF_freelist_t); - -/* Declare a free list to manage the H5HF_flist_node_t struct */ -H5FL_DEFINE_STATIC(H5HF_flist_node_t); - -/* Declare a free list to manage the 'H5SL_t *' sequence information */ -typedef H5SL_t *H5SL_ptr_t; -H5FL_SEQ_DEFINE_STATIC(H5SL_ptr_t); - - -/*****************************/ -/* Library Private Variables */ -/*****************************/ - - -/*******************/ -/* Local Variables */ -/*******************/ - - - -/*------------------------------------------------------------------------- - * Function: H5HF_flist_init - * - * Purpose: Initialize free list for heap - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Tuesday, April 18, 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_flist_init(H5HF_freelist_t *flist) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_flist_init) - - /* Check arguments. */ - HDassert(flist); - - /* Set free list parameters */ - flist->tot_space = 0; - flist->sec_count = 0; - flist->single.node = NULL; - flist->single.size_key = NULL; - flist->single.addr_key = NULL; - flist->bins = NULL; - flist->using_bins = FALSE; - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HF_flist_init() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_flist_create - * - * Purpose: Allocate & initialize free list for heap - * - * Return: Success: Pointer to free list structure - * - * Failure: NULL - * - * Programmer: Quincey Koziol - * Tuesday, March 7, 2006 - * - *------------------------------------------------------------------------- - */ -H5HF_freelist_t * -H5HF_flist_create(unsigned max_index_bits, H5SL_operator_t node_free_op) -{ - H5HF_freelist_t *flist; /* New free list structure */ - H5HF_freelist_t *ret_value; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_create) - - /* Check arguments. */ - - /* - * Allocate top free list structure - */ - if(NULL == (flist = H5FL_MALLOC(H5HF_freelist_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fractal heap free list") - - /* Set immutable free list parameters */ - flist->nbins = max_index_bits; - flist->node_free_op = node_free_op; - - /* Set modifiable free list parameters */ - H5HF_flist_init(flist); - - /* Set return value */ - ret_value = flist; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_flist_create() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_flist_add_bin_node - * - * Purpose: Add a section of free space in a direct block to the free list - * bins - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Monday, March 20, 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_flist_add_bin_node(H5HF_freelist_t *flist, void *node, size_t *size_key, haddr_t *addr_key) -{ - H5HF_flist_node_t *flist_node = NULL; /* Pointer to free list node of the correct size */ - unsigned bin; /* Bin to put the free space section in */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_add_bin_node) -#ifdef QAK -HDfprintf(stderr, "%s: *size_key = %Zu, *addr_key = %a\n", FUNC, *size_key, *addr_key); -#endif /* QAK */ - - /* Check arguments. */ - HDassert(flist); - HDassert(node); - HDassert(size_key); - HDassert(addr_key); - - /* Determine correct bin which holds items of the section's size */ - bin = H5V_log2_gen((hsize_t)*size_key); - HDassert(bin < flist->nbins); - if(flist->bins[bin] == NULL) { - if(NULL == (flist->bins[bin] = H5SL_create(H5SL_TYPE_SIZE, 0.5, H5HF_FLIST_DEFAULT_SKIPLIST_HEIGHT))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create skip list for free list nodes") - } /* end if */ - else { - /* Check for node list of the correct size already */ - flist_node = H5SL_search(flist->bins[bin], size_key); - } /* end else */ - - /* Check if we need to create a new skip list for nodes of this size */ - if(flist_node == NULL) { - /* Allocate new free list size node */ - if(NULL == (flist_node = H5FL_MALLOC(H5HF_flist_node_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for fractal heap free list") - - /* Initialize the free list size node */ - flist_node->sec_size = *size_key; - if(NULL == (flist_node->sec_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, H5HF_FLIST_DEFAULT_SKIPLIST_HEIGHT))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create skip list for free list nodes") - - /* Insert new free list size node into bin's list */ - if(H5SL_insert(flist->bins[bin], flist_node, &flist_node->sec_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't insert free list node into skip list") - } /* end if */ - - /* Insert free list node into correct skip list */ - if(H5SL_insert(flist_node->sec_list, node, addr_key) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't insert free list node into skip list") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_flist_add_bin_node() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_flist_add - * - * Purpose: Add a section of free space in a direct block to the free list - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Tuesday, March 7, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_flist_add(H5HF_freelist_t *flist, void *node, size_t *size_key, haddr_t *addr_key) -{ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_add) - -#ifdef QAK -HDfprintf(stderr, "%s: *size_key = %Zu, *addr_key = %a\n", FUNC, *size_key, *addr_key); -#endif /* QAK */ - - /* Check arguments. */ - HDassert(flist); - HDassert(node); - HDassert(size_key); - HDassert(addr_key); - - /* Check for special cases of # of sections on free list */ -#ifdef QAK -HDfprintf(stderr, "%s: flist->sec_count = %Zu\n", FUNC, flist->sec_count); -#endif /* QAK */ - if(flist->sec_count == 0) { - HDassert(flist->single.node == NULL); - - /* Capture single section's information */ - flist->single.node = node; - flist->single.size_key = size_key; - flist->single.addr_key = addr_key; - } /* end if */ - else { - /* Have a single section, put it into the bins */ -/* XXX: Take out the "&& !flist->using_bins" when bins converted back into single section */ - if(flist->sec_count == 1 && !flist->using_bins) { - HDassert(flist->single.node); - - /* Check if we should allocate the bins */ - if(flist->bins == NULL) - /* Allocate the bins for free space sizes */ - if(NULL == (flist->bins = H5FL_SEQ_CALLOC(H5SL_ptr_t, flist->nbins))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for free list bins") - - /* Insert the current single section into the bins */ - if(H5HF_flist_add_bin_node(flist, flist->single.node, flist->single.size_key, flist->single.addr_key) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't insert free list node into skip list") - flist->single.node = NULL; - - /* Using bins for storing nodes now */ - flist->using_bins = TRUE; - } /* end if */ - HDassert(flist->single.node == NULL); - - /* Put new section into bins */ - if(H5HF_flist_add_bin_node(flist, node, size_key, addr_key) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't insert free list node into skip list") - } /* end else */ - - /* Increment # of sections on free list */ - flist->sec_count++; - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_flist_add() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_flist_find_bin_node - * - * Purpose: Locate a section of free space (in existing free list bins) that - * is large enough to fulfill request. - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Monday, March 20, 2006 - * - *------------------------------------------------------------------------- - */ -static htri_t -H5HF_flist_find_bin_node(H5HF_freelist_t *flist, size_t request, void **node) -{ - H5HF_flist_node_t *flist_node; /* Free list size node */ - unsigned bin; /* Bin to put the free space section in */ - htri_t ret_value = FALSE; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_find_bin_node) - - /* Check arguments. */ - HDassert(flist); - HDassert(request > 0); - HDassert(node); - - /* Determine correct bin which holds items of at least the section's size */ - bin = H5V_log2_gen((hsize_t)request); - HDassert(bin < flist->nbins); - while(bin < flist->nbins && flist->bins[bin] == NULL) - bin++; - - /* Find the first free space section that is large enough to fulfill request */ - /* (Since the bins use skip lists to track the sizes of the address-ordered - * lists, this is actually a "best fit" algorithm) - */ -#ifdef QAK -HDfprintf(stderr, "%s: flist->nbins = %u\n", FUNC, flist->nbins); -HDfprintf(stderr, "%s: bin = %u\n", FUNC, bin); -#endif /* QAK */ - if(bin < flist->nbins) - do { - /* Look for large enough free list section in this bin */ - if(flist->bins[bin]) - /* Check for large enough list of sections on list */ - if((flist_node = H5SL_greater(flist->bins[bin], &request))) { - /* Take first node off of the list (ie. node w/lowest address) */ - if(NULL == (*node = H5SL_remove_first(flist_node->sec_list))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't remove free list node from skip list") - - /* Check for no more nodes on list of that size */ - if(H5SL_count(flist_node->sec_list) == 0) { - H5HF_flist_node_t *tmp_flist_node; /* Free list size node */ - - /* Remove size tracking list from bin */ - tmp_flist_node = H5SL_remove(flist->bins[bin], &flist_node->sec_size); - if(tmp_flist_node == NULL || tmp_flist_node != flist_node) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't remove free list node from skip list") - - /* Destroy skip list for size tracking node */ - if(H5SL_close(flist_node->sec_list) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCLOSEOBJ, FAIL, "can't destroy size tracking node's skip list") - - /* Release free list node */ - H5FL_FREE(H5HF_flist_node_t, flist_node); - } /* end if */ - - HGOTO_DONE(TRUE) - } /* end if */ - - /* Advance to next larger bin */ - bin++; - } while(bin < flist->nbins); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_flist_find_bin_node() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_flist_find - * - * Purpose: Locate a section of free space (in existing free list) that - * is large enough to fulfill request. - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Tuesday, March 7, 2006 - * - *------------------------------------------------------------------------- - */ -htri_t -H5HF_flist_find(H5HF_freelist_t *flist, size_t request, void **node) -{ - htri_t ret_value = FALSE; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_flist_find) - -#ifdef QAK -HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request); -#endif /* QAK */ - - /* Check arguments. */ - HDassert(flist); - HDassert(request > 0); - HDassert(node); - - /* Check for any sections on free list */ -#ifdef QAK -HDfprintf(stderr, "%s: flist->sec_count = %Zu\n", FUNC, flist->sec_count); -#endif /* QAK */ - if(flist->sec_count > 0) { - /* Check for single section */ -/* XXX: Take out the "&& !flist->using_bins" when bins converted back into single section */ - if(flist->sec_count == 1 && !flist->using_bins) { - HDassert(flist->single.node); - - /* See if single section is large enough */ - if(*(flist->single.size_key) >= request) { - *node = flist->single.node; - flist->single.node = NULL; - ret_value = TRUE; - } /* end if */ - else - HGOTO_DONE(FALSE) - } /* end if */ - else { - HDassert(flist->single.node == NULL); - - /* Look for node in bins */ - if((ret_value = H5HF_flist_find_bin_node(flist, request, node)) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "can't remove section from bins") - } /* end else */ - - /* Decrement # of sections on free list, if we found an object */ - if(ret_value > 0) { - flist->sec_count--; -/* XXX: Should check for only one section in bins & convert to single section - * This is somewhat hard because we "lose" the the size & address keys - * (The address key is actually available, but the size key is gone, unless - * we start tracking it. - * - * Drop back to using a "single" node when the bins are empty. - */ - if(flist->sec_count == 0) - flist->using_bins = FALSE; - } /* end if */ - } /* end if */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_flist_find() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_flist_node_free_cb - * - * Purpose: Free a size-tracking node for a bin - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Saturday, March 11, 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_flist_node_free_cb(void *item, void UNUSED *key, void *op_data) -{ - H5HF_flist_node_t *flist_node = (H5HF_flist_node_t *)item; /* Temporary pointer to free list node */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_flist_node_free_cb) - - HDassert(flist_node); - - /* Release the skip list for sections of this size */ - H5SL_destroy(flist_node->sec_list, (H5SL_operator_t)op_data, NULL); - - /* Release free list node */ - H5FL_FREE(H5HF_flist_node_t, flist_node); - - FUNC_LEAVE_NOAPI(0) -} /* H5HF_flist_node_free_cb() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_flist_reset - * - * Purpose: Reset free list structure by freeing all existing sections - * and restoring free list info to initial conditions. - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Tuesday, April 18, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_flist_reset(H5HF_freelist_t *flist) -{ - unsigned u; /* Local index variable */ - - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_flist_reset) - - /* Check arguments. */ - HDassert(flist); - - /* Check for single section to free */ -/* XXX: Take out the "&& !flist->using_bins" when bins converted back into single section */ - if(flist->sec_count == 1 && !flist->using_bins) { - HDassert(flist->single.node != NULL); - flist->node_free_op(flist->single.node, flist->single.addr_key, NULL); - flist->single.node = NULL; - } /* end if */ - HDassert(flist->single.node == NULL); - - /* Release bins for skip lists */ - if(flist->bins) { - /* Clear out lists of nodes */ - for(u = 0; u < flist->nbins; u++) - if(flist->bins[u]) { - H5SL_destroy(flist->bins[u], H5HF_flist_node_free_cb, (void *)flist->node_free_op); - flist->bins[u] = NULL; - } /* end if */ - - H5FL_SEQ_FREE(H5SL_ptr_t, flist->bins); - } /* end if */ - - /* Reset free list info back to initial state */ - H5HF_flist_init(flist); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HF_flist_reset() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_flist_free - * - * Purpose: Destroy & deallocate free list structure - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Tuesday, March 7, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_flist_free(H5HF_freelist_t *flist) -{ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_flist_free) - - /* Check arguments. */ - HDassert(flist); - - /* Reset free list information */ - H5HF_flist_reset(flist); - - /* Free fractal heap free list info */ - H5FL_FREE(H5HF_freelist_t, flist); - - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5HF_flist_free() */ - diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c index b598191..664a7e7 100644 --- a/src/H5HFhdr.c +++ b/src/H5HFhdr.c @@ -46,7 +46,13 @@ * need to be larger, the 32-bit limit for H5V_log2_of2(n), and * some offsets/sizes are encoded with a maxiumum of 32-bits - QAK) */ -#define H5HL_MAX_DIRECT_SIZE_LIMIT ((hsize_t)2 * 1024 * 1024 * 1024) +#define H5HF_MAX_DIRECT_SIZE_LIMIT ((hsize_t)2 * 1024 * 1024 * 1024) + +/* Limit on the width of the doubling table */ +/* (This is limited to 16-bits currently, because I think it's unlikely to + * need to be larger, and its encoded with a maxiumum of 16-bits - QAK) + */ +#define H5HF_WIDTH_LIMIT (64 * 1024) /******************/ /* Local Typedefs */ @@ -67,6 +73,9 @@ /* Package Variables */ /*********************/ +/* Declare a free list to manage the H5HF_hdr_t struct */ +H5FL_DEFINE(H5HF_hdr_t); + /*****************************/ /* Library Private Variables */ @@ -191,7 +200,7 @@ H5HF_hdr_compute_free_space(H5HF_hdr_t *hdr, hsize_t iblock_size) herr_t H5HF_hdr_finish_init(H5HF_hdr_t *hdr) { - size_t u; /* Local index variable */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_finish_init) @@ -206,17 +215,6 @@ H5HF_hdr_finish_init(H5HF_hdr_t *hdr) if(H5HF_dtable_init(&hdr->man_dtable) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize doubling table info") - /* Create the free-list structure for the heap */ - if(NULL == (hdr->flist = H5HF_flist_create(hdr->man_dtable.cparam.max_index, H5HF_free_section_free_cb))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free list info") - - /* Start the free list "generation" count */ - /* (Must be "out of sync" with starting value for indirect & direct block - * cache loading routines, in order to trigger re-building the free list - * information for each block when a heap is opened->closed->reopened -QAK) - */ - hdr->fl_gen = 1; - /* Set the size of heap IDs */ hdr->id_len = hdr->heap_off_size + MIN(hdr->man_dtable.max_dir_blk_off_size, ((H5V_log2_gen((hsize_t)hdr->standalone_size) + 7) / 8)); @@ -225,8 +223,7 @@ H5HF_hdr_finish_init(H5HF_hdr_t *hdr) for(u = 0; u < hdr->man_dtable.max_root_rows; u++) { if(u < hdr->man_dtable.max_direct_rows) hdr->man_dtable.row_dblock_free[u] = hdr->man_dtable.row_block_size[u] - - (H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(hdr, hdr->man_dtable.row_block_size[u]) - + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); + H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); else hdr->man_dtable.row_dblock_free[u] = H5HF_hdr_compute_free_space(hdr, hdr->man_dtable.row_block_size[u]); #ifdef QAK @@ -273,17 +270,28 @@ H5HF_hdr_init(H5HF_hdr_t *hdr, haddr_t fh_addr, H5HF_create_t *cparam) #ifndef NDEBUG /* Check for valid parameters */ - if(!POWER_OF_TWO(cparam->managed.width) || cparam->managed.width == 0) + if(cparam->managed.width == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "width must be greater than zero") + if(cparam->managed.width > H5HF_WIDTH_LIMIT) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "width too large") + if(!POWER_OF_TWO(cparam->managed.width)) HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "width not power of two") - if(!POWER_OF_TWO(cparam->managed.start_block_size) || cparam->managed.start_block_size == 0) + if(cparam->managed.start_block_size == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "starting block size must be greater than zero") + if(!POWER_OF_TWO(cparam->managed.start_block_size)) HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "starting block size not power of two") - if(!POWER_OF_TWO(cparam->managed.max_direct_size) || - (cparam->managed.max_direct_size == 0 || cparam->managed.max_direct_size > H5HL_MAX_DIRECT_SIZE_LIMIT)) + if(cparam->managed.max_direct_size == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size must be greater than zero") + if(cparam->managed.max_direct_size > H5HF_MAX_DIRECT_SIZE_LIMIT) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size too large") + if(!POWER_OF_TWO(cparam->managed.max_direct_size)) HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") if(cparam->managed.max_direct_size < cparam->standalone_size) HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not large enough to hold all managed blocks") - if(cparam->managed.max_index > (8 * hdr->sizeof_size) || cparam->managed.max_index == 0) - HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. direct block size not power of two") + if(cparam->managed.max_index == 0) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. heap size must be greater than zero") + if(cparam->managed.max_index > (8 * hdr->sizeof_size)) + HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "max. heap size too large for file") #endif /* NDEBUG */ /* Set the creation parameters for the heap */ @@ -292,11 +300,11 @@ H5HF_hdr_init(H5HF_hdr_t *hdr, haddr_t fh_addr, H5HF_create_t *cparam) hdr->standalone_size = cparam->standalone_size; HDmemcpy(&(hdr->man_dtable.cparam), &(cparam->managed), sizeof(H5HF_dtable_cparam_t)); - /* Set root table address */ + /* Set root table address to indicate that the heap is empty currently */ hdr->man_dtable.table_addr = HADDR_UNDEF; - /* Newly created heap's free list is always in sync in memory */ - hdr->freelist_sync = TRUE; + /* Set free list header address to indicate that the heap is empty currently */ + hdr->fs_addr = HADDR_UNDEF; /* Note that the shared info is dirty (it's not written to the file yet) */ hdr->dirty = TRUE; @@ -428,6 +436,50 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_hdr_adj_free + * + * Purpose: Adjust the free space for a heap + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 9 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_hdr_adj_free(H5HF_hdr_t *hdr, ssize_t amt) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_adj_free) +#ifdef QAK +HDfprintf(stderr, "%s: amt = %Zd\n", FUNC, amt); +#endif /* QAK */ + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Update heap header */ + HDassert(amt > 0 || hdr->total_man_free >= (hsize_t)-amt); + hdr->total_man_free += amt; +#ifdef QAK +HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free); +#endif /* QAK */ + + /* Mark heap header as modified */ + if(H5HF_hdr_dirty(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark heap header as dirty") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_hdr_adj_free() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_hdr_extend_heap * * Purpose: Extend heap to cover more space diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c index fd7b520..cdffa80 100644 --- a/src/H5HFiblock.c +++ b/src/H5HFiblock.c @@ -57,18 +57,23 @@ /* Local Prototypes */ /********************/ -/* Indirect block routines */ -static herr_t H5HF_man_iblock_skip_blocks(H5HF_hdr_t *hdr, +/* Free space section routines */ +static herr_t H5HF_man_iblock_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, haddr_t iblock_addr, unsigned start_entry, unsigned nentries); -static herr_t H5HF_man_iblock_skip_ranges(H5HF_hdr_t *hdr, +static herr_t H5HF_man_iblock_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, haddr_t iblock_addr, unsigned start_entry, unsigned nentries); -static herr_t H5HF_man_iblock_double_root(H5HF_hdr_t *hdr, hid_t dxpl_id, + +/* Root indirect block routines */ +static herr_t H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, + size_t min_dblock_size); +static herr_t H5HF_man_iblock_root_double(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size); + +/* Misc. indirect block routines */ static herr_t H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p); -static herr_t H5HF_man_iblock_build_sections(H5HF_indirect_t *iblock); /*********************/ /* Package Variables */ @@ -227,7 +232,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_man_iblock_skip_blocks(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, +H5HF_man_iblock_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, haddr_t iblock_addr, unsigned start_entry, unsigned nentries) { H5HF_free_section_t *sec_node; /* Pointer to free list section for range */ @@ -281,9 +286,10 @@ HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = % HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") /* Set section's information */ - sec_node->sect_addr = sect_off; - sec_node->sect_size = hdr->man_dtable.row_dblock_free[curr_row]; - sec_node->type = H5HF_SECT_RANGE; + sec_node->sect_info.addr = sect_off; + sec_node->sect_info.size = hdr->man_dtable.row_dblock_free[curr_row]; + sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_RANGE]; + sec_node->sect_info.state = H5FS_SECT_LIVE; sec_node->u.range.iblock = iblock; if(H5HF_iblock_incr(iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") @@ -292,7 +298,7 @@ HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = % sec_node->u.range.num_entries = row_entries; /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) + if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") /* Advance row & column position */ @@ -330,7 +336,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_man_iblock_skip_ranges(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, +H5HF_man_iblock_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock, haddr_t iblock_addr, unsigned start_entry, unsigned nentries) { H5HF_free_section_t *sec_node; /* Pointer to free list section for range */ @@ -406,12 +412,13 @@ HDfprintf(stderr, "%s: hdr->man_dtable.row_dblock_free[%u] = %Zu\n", FUNC, w, hd HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") /* Set section's information */ - sec_node->sect_addr = sect_off + hdr->man_dtable.row_block_off[w]; + sec_node->sect_info.addr = sect_off + hdr->man_dtable.row_block_off[w]; #ifdef QAK -HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr); +HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr); #endif /* QAK */ - sec_node->sect_size = hdr->man_dtable.row_dblock_free[w]; - sec_node->type = H5HF_SECT_INDIRECT; + sec_node->sect_info.size = hdr->man_dtable.row_dblock_free[w]; + sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_INDIRECT]; + sec_node->sect_info.state = H5FS_SECT_LIVE; sec_node->u.indirect.iblock = iblock; if(H5HF_iblock_incr(iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") @@ -422,7 +429,7 @@ HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr); sec_node->u.indirect.indir_nrows = num_rows; /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) + if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") } /* end for */ #ifdef QAK @@ -448,7 +455,144 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_double_root + * Function: H5HF_man_iblock_root_create + * + * Purpose: Create root indirect block + * + * Return: SUCCEED/FAIL + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_man_iblock_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size) +{ + H5HF_indirect_t *iblock; /* Pointer to indirect block */ + haddr_t iblock_addr; /* Indirect block's address */ + hsize_t acc_dblock_free; /* Accumulated free space in direct blocks */ + hbool_t have_direct_block; /* Flag to indicate a direct block already exists */ + unsigned nrows; /* Number of rows for root indirect block */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_root_create) + +#ifdef QAK +HDfprintf(stderr, "%s: Creating root indirect block\n", FUNC); +#endif /* QAK */ + + /* Check for allocating entire root indirect block initially */ + if(hdr->man_dtable.cparam.start_root_rows == 0) + nrows = hdr->man_dtable.max_root_rows; + else { + unsigned rows_needed; /* Number of rows needed to get to direct block size */ + unsigned block_row_off; /* Row offset from larger block sizes */ + + nrows = hdr->man_dtable.cparam.start_root_rows; + + block_row_off = H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size); + if(block_row_off > 0) + block_row_off++; /* Account for the pair of initial rows of the initial block size */ + rows_needed = 1 + block_row_off; + if(nrows < rows_needed) + nrows = rows_needed; + } /* end else */ +#ifdef QAK +HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); +#endif /* QAK */ + + /* Allocate root indirect block */ + if(H5HF_man_iblock_create(hdr, dxpl_id, (hsize_t)0, nrows, hdr->man_dtable.max_root_rows, &iblock_addr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block") +#ifdef QAK +HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); +#endif /* QAK */ + + /* Move current direct block (used as root) into new indirect block */ + + /* Lock new indirect block */ + if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, NULL, 0, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + + /* Check if there's already a direct block as root) */ + have_direct_block = H5F_addr_defined(hdr->man_dtable.table_addr); +#ifdef QAK +HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_block); +#endif /* QAK */ + if(have_direct_block) { + H5HF_direct_t *dblock; /* Pointer to direct block to query */ + + /* Lock first (root) direct block */ + if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, hdr->man_dtable.table_addr, hdr->man_dtable.cparam.start_block_size, iblock, 0, H5AC_WRITE))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") + + /* Point indirect block at direct block to add */ + iblock->ents[0].addr = hdr->man_dtable.table_addr; + + /* Make direct block share parent indirect block */ + dblock->parent = iblock; + dblock->par_entry = 0; + if(H5HF_iblock_incr(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") + + /* Unlock first (root) direct block */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") + dblock = NULL; + } /* end if */ + + /* Set up iterator at correct location */ + if(H5HF_man_iter_start_entry(hdr, &hdr->next_block, iblock, have_direct_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize block iterator") + + /* Check for skipping over direct blocks, in order to get to large enough block */ + if(min_dblock_size > hdr->man_dtable.cparam.start_block_size) { + /* Add skipped blocks to heap's free space */ + if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, iblock, iblock_addr, + have_direct_block, ((nrows - 1) * hdr->man_dtable.cparam.width) - have_direct_block) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") + } /* end if */ + + /* Mark indirect block as modified */ + if(H5HF_iblock_dirty(iblock) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") + + /* Unprotect root indirect block (it's pinned by the iterator though) */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__DIRTIED_FLAG) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + iblock = NULL; + + /* Point heap header at new indirect block */ + hdr->man_dtable.curr_root_rows = nrows; + hdr->man_dtable.table_addr = iblock_addr; + + /* Compute free space in direct blocks referenced from entries in root indirect block */ + acc_dblock_free = 0; + for(u = 0; u < nrows; u++) + acc_dblock_free += hdr->man_dtable.row_dblock_free[u] * hdr->man_dtable.cparam.width; + + /* Account for potential initial direct block */ + if(have_direct_block) + acc_dblock_free -= hdr->man_dtable.row_dblock_free[0]; + + /* Extend heap to cover new root indirect block */ + if(H5HF_hdr_extend_heap(hdr, hdr->man_dtable.row_block_off[nrows], acc_dblock_free) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block") + + /* Mark heap header as modified */ + if(H5HF_hdr_dirty(hdr) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark header as dirty") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_root_create() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_root_double * * Purpose: Double size of root indirect block * @@ -461,7 +605,7 @@ done: *------------------------------------------------------------------------- */ static herr_t -H5HF_man_iblock_double_root(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size) +H5HF_man_iblock_root_double(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size) { H5HF_indirect_t *iblock; /* Pointer to root indirect block */ haddr_t new_addr; /* New address of indirect block */ @@ -477,7 +621,7 @@ H5HF_man_iblock_double_root(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_si size_t u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_double_root) + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_root_double) #ifdef QAK HDfprintf(stderr, "%s: Extending root indirect block\n", FUNC); @@ -548,7 +692,7 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr); /* Check for skipping over rows and add free section for skipped rows */ if(skip_direct_rows) { /* Add skipped blocks to heap's free space */ - if(H5HF_man_iblock_skip_blocks(hdr, iblock, new_addr, + if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, iblock, new_addr, next_entry, (new_next_entry - next_entry)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space") } /* end if */ @@ -559,9 +703,7 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr); unsigned row = u / hdr->man_dtable.cparam.width; /* Row for current entry */ iblock->ents[u].addr = HADDR_UNDEF; - iblock->ents[u].free_space = hdr->man_dtable.row_dblock_free[row]; - iblock->child_free_space += iblock->ents[u].free_space; - acc_dblock_free += iblock->ents[u].free_space; + acc_dblock_free += hdr->man_dtable.row_dblock_free[row]; } /* end for */ /* Mark indirect block as dirty */ @@ -601,11 +743,11 @@ HDfprintf(stderr, "%s: acc_dblock_free = %Hu\n", FUNC, acc_dblock_free); /* Release the indirect block (marked as dirty) */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_double_root() */ +} /* end H5HF_man_iblock_root_double() */ /*------------------------------------------------------------------------- @@ -627,8 +769,10 @@ H5HF_indirect_t * H5HF_man_iblock_place_dblock(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size, size_t *entry_p, size_t *dblock_size) { +#ifdef OLD_WAY H5HF_indirect_t *iblock; /* Pointer to indirect block */ haddr_t iblock_addr; /* Indirect block's address */ +#endif /* OLD_WAY */ H5HF_indirect_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_place_dblock) @@ -644,118 +788,11 @@ HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size); /* Check for creating first indirect block */ if(hdr->man_dtable.curr_root_rows == 0) { - H5HF_direct_t *dblock; /* Pointer to direct block to query */ - hsize_t acc_dblock_free; /* Accumulated free space in direct blocks */ - hbool_t have_direct_block; /* Flag to indicate a direct block already exists */ - unsigned nrows; /* Number of rows for root indirect block */ - unsigned u; /* Local index variable */ - -#ifdef QAK -HDfprintf(stderr, "%s: creating first indirect block\n", FUNC); -#endif /* QAK */ - /* Check for allocating entire root indirect block initially */ - if(hdr->man_dtable.cparam.start_root_rows == 0) - nrows = hdr->man_dtable.max_root_rows; - else { - unsigned rows_needed; /* Number of rows needed to get to direct block size */ - unsigned block_row_off; /* Row offset from larger block sizes */ - - nrows = hdr->man_dtable.cparam.start_root_rows; - - block_row_off = H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size); - if(block_row_off > 0) - block_row_off++; /* Account for the pair of initial rows of the initial block size */ - rows_needed = 1 + block_row_off; - if(nrows < rows_needed) - nrows = rows_needed; - } /* end else */ -#ifdef QAK -HDfprintf(stderr, "%s: nrows = %u\n", FUNC, nrows); -#endif /* QAK */ - - /* Allocate root indirect block */ - if(H5HF_man_iblock_create(hdr, dxpl_id, (hsize_t)0, nrows, hdr->man_dtable.max_root_rows, &iblock_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate fractal heap indirect block") -#ifdef QAK -HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); -#endif /* QAK */ - - /* Move current direct block (used as root) into new indirect block */ - - /* Lock new indirect block */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, nrows, NULL, 0, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") - - /* Check if there's already a direct block as root) */ - have_direct_block = H5F_addr_defined(hdr->man_dtable.table_addr); -#ifdef QAK -HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_block); -#endif /* QAK */ - if(have_direct_block) { - /* Lock first (root) direct block */ - if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, hdr->man_dtable.table_addr, hdr->man_dtable.cparam.start_block_size, iblock, 0, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap direct block") - - /* Point indirect block at direct block to add */ - iblock->child_free_space += (hssize_t)(dblock->blk_free_space - iblock->ents[0].free_space); - iblock->ents[0].addr = hdr->man_dtable.table_addr; - iblock->ents[0].free_space = dblock->blk_free_space; - - /* Make direct block share parent indirect block */ - dblock->parent = iblock; - dblock->par_entry = 0; - if(H5HF_iblock_incr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block") - - /* Unlock first (root) direct block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, hdr->man_dtable.table_addr, dblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap direct block") - dblock = NULL; - } /* end if */ - - /* Set up iterator at correct location */ - if(H5HF_man_iter_start_entry(hdr, &hdr->next_block, iblock, have_direct_block) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "can't initialize block iterator") - - /* Check for skipping over direct blocks, in order to get to large enough block */ - if(min_dblock_size > hdr->man_dtable.cparam.start_block_size) { - /* Add skipped blocks to heap's free space */ - if(H5HF_man_iblock_skip_blocks(hdr, iblock, iblock_addr, - have_direct_block, ((nrows - 1) * hdr->man_dtable.cparam.width) - have_direct_block) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") - } /* end if */ - - /* Mark indirect block as modified */ - if(H5HF_iblock_dirty(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty") - - /* Unprotect root indirect block (it's pinned by the iterator though) */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") - iblock = NULL; - - /* Point heap header at new indirect block */ - hdr->man_dtable.curr_root_rows = nrows; - hdr->man_dtable.table_addr = iblock_addr; - - /* Compute free space in direct blocks referenced from entries in root indirect block */ - acc_dblock_free = 0; - for(u = 0; u < nrows; u++) - acc_dblock_free += hdr->man_dtable.row_dblock_free[u] * hdr->man_dtable.cparam.width; - - /* Account for potential initial direct block */ - if(have_direct_block) - acc_dblock_free -= hdr->man_dtable.row_dblock_free[0]; - - /* Extend heap to cover new root indirect block */ - if(H5HF_hdr_extend_heap(hdr, hdr->man_dtable.row_block_off[nrows], acc_dblock_free) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, NULL, "can't increase space to cover root direct block") - - /* Mark heap header as modified */ - if(H5HF_hdr_dirty(hdr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark header as dirty") + if(H5HF_man_iblock_root_create(hdr, dxpl_id, min_dblock_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, NULL, "unable to create root indirect block") } /* end if */ else { + H5HF_indirect_t *iblock; /* Pointer to indirect block */ hbool_t walked_up, walked_down; /* Condition variables for finding direct block location */ unsigned next_row; /* Iterator's next block row */ unsigned next_entry; /* Iterator's next block entry */ @@ -808,7 +845,7 @@ HDfprintf(stderr, "%s: min_entry = %u, skip_entries = %u\n", FUNC, min_entry, sk #endif /* QAK */ /* Add skipped direct blocks to heap's free space */ - if(H5HF_man_iblock_skip_blocks(hdr, iblock, iblock->addr, next_entry, skip_entries) < 0) + if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, iblock, iblock->addr, next_entry, skip_entries) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") /* Get information about new iterator location */ @@ -839,7 +876,7 @@ HDfprintf(stderr, "%s: Off the end of a block\n", FUNC); #ifdef QAK HDfprintf(stderr, "%s: Doubling root block\n", FUNC); #endif /* QAK */ - if(H5HF_man_iblock_double_root(hdr, dxpl_id, min_dblock_size) < 0) + if(H5HF_man_iblock_root_double(hdr, dxpl_id, min_dblock_size) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, NULL, "unable to double root indirect block") } /* end if */ else { @@ -915,7 +952,7 @@ HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry); #endif /* QAK */ /* Add skipped indirect ranges to heap's free space */ - if(H5HF_man_iblock_skip_ranges(hdr, iblock, iblock->addr, next_entry, (child_entry - next_entry)) < 0) + if(H5HF_man_iblock_skip_ranges(hdr, dxpl_id, iblock, iblock->addr, next_entry, (child_entry - next_entry)) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") } /* end if */ else { @@ -974,7 +1011,7 @@ HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = % #endif /* QAK */ /* Add skipped blocks to heap's free space */ - if(H5HF_man_iblock_skip_blocks(hdr, new_iblock, new_iblock->addr, 0, new_entry) < 0) + if(H5HF_man_iblock_skip_blocks(hdr, dxpl_id, new_iblock, new_iblock->addr, 0, new_entry) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't add skipped blocks to heap's free space") } /* end if */ @@ -988,7 +1025,7 @@ HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = % /* Unprotect child indirect block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock->addr, new_iblock, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block") } /* end else */ /* Get information about new iterator location */ @@ -1004,6 +1041,7 @@ HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = % /* Get information about iterator location */ { + H5HF_indirect_t *iblock; /* Pointer to indirect block */ unsigned next_row; /* Iterator's next block row */ unsigned next_entry; /* Iterator's next block entry */ size_t next_size; /* Size of next direct block to create */ @@ -1026,12 +1064,6 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "skipping direct block sizes not su /* Set size of direct block to create */ *dblock_size = next_size; -#ifdef OLD_WAY - /* Increment location of next block from this indirect block */ - if(H5HF_man_iter_next(hdr, &hdr->next_block, 1) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't advance fractal heap block location") -#endif /* OLD_WAY */ - /* Set return value */ ret_value = iblock; } @@ -1042,6 +1074,78 @@ done: /*------------------------------------------------------------------------- + * Function: H5HF_man_iblock_alloc_single + * + * Purpose: Update the memory information for a 'single' free section + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 8 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_man_iblock_alloc_single(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sec_node) +{ + H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */ + unsigned sec_entry; /* Entry within section indirect block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_single) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(sec_node); + HDassert(sec_node->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 */ + sec_node->u.single.parent = NULL; + sec_node->u.single.par_entry = 0; + + /* Set direct block info */ + HDassert(H5F_addr_defined(hdr->man_dtable.table_addr)); + sec_node->u.single.dblock_addr = hdr->man_dtable.table_addr; + sec_node->u.single.dblock_size = hdr->man_dtable.cparam.start_block_size; + } /* end if */ + else { + /* Look up indirect block containing direct blocks for range */ + if(H5HF_man_locate_block(hdr, dxpl_id, sec_node->sect_info.addr, FALSE, &sec_iblock, &sec_entry, H5AC_READ) < 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 information for the section */ + sec_node->u.single.parent = sec_iblock; + sec_node->u.single.par_entry = sec_entry; + + /* Set direct block info */ + sec_node->u.single.dblock_addr = sec_iblock->ents[sec_entry].addr; + sec_node->u.single.dblock_size = hdr->man_dtable.row_block_size[sec_entry / hdr->man_dtable.cparam.width]; + + /* Unlock indirect block */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, sec_iblock->addr, sec_iblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + sec_iblock = NULL; + } /* end else */ + + /* Section is "live" now */ + sec_node->sect_info.state = H5FS_SECT_LIVE; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_man_iblock_alloc_single() */ + + +/*------------------------------------------------------------------------- * Function: H5HF_man_iblock_alloc_range * * Purpose: Allocate a "single" section for an object, out of a "range" @@ -1061,7 +1165,7 @@ herr_t H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t **sec_node) { - H5HF_indirect_t *iblock; /* Pointer to indirect block */ + H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */ haddr_t dblock_addr; /* Direct block's address */ H5HF_free_section_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */ H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old section node */ @@ -1076,6 +1180,31 @@ H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id, HDassert(hdr); HDassert(sec_node && *sec_node); + /* Check for serialized section */ + if(old_sec_node->sect_info.state == H5FS_SECT_SERIALIZED) { + H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */ + unsigned sec_entry; /* Entry within section indirect block */ + + /* Look up indirect block containing direct blocks for range */ + if(H5HF_man_locate_block(hdr, dxpl_id, old_sec_node->sect_info.addr, FALSE, &sec_iblock, &sec_entry, H5AC_READ) < 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 */ + old_sec_node->u.range.iblock = sec_iblock; + + /* Unlock indirect block */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, sec_iblock->addr, sec_iblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + sec_iblock = NULL; + + /* Section is "live" now */ + old_sec_node->sect_info.state = H5FS_SECT_LIVE; + } /* end if */ + /* Compute info about range */ cur_entry = (old_sec_node->u.range.row * hdr->man_dtable.cparam.width) + old_sec_node->u.range.col; @@ -1098,7 +1227,7 @@ HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.range.row] HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect_addr); #endif /* QAK */ /* Create direct block of appropriate size */ - if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.range.row], (hsize_t)old_sec_node->sect_addr, &dblock_addr, &dblock_sec_node) < 0) + if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.range.row], (hsize_t)old_sec_node->sect_info.addr, &dblock_addr, &dblock_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") /* Hook direct block up to indirect block */ @@ -1119,14 +1248,14 @@ HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect } /* end if */ else { /* Adjust section information */ - old_sec_node->sect_addr += hdr->man_dtable.row_block_size[old_sec_node->u.range.row]; + old_sec_node->sect_info.addr += hdr->man_dtable.row_block_size[old_sec_node->u.range.row]; /* Adjust range information */ old_sec_node->u.range.col++; old_sec_node->u.range.num_entries--; /* Add section back to free space list */ - if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0) + if(H5HF_space_add(hdr, dxpl_id, old_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") } /* end else */ @@ -1178,6 +1307,31 @@ H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id, HDassert(hdr); HDassert(sec_node && *sec_node); + /* Check for serialized section */ + if(old_sec_node->sect_info.state == H5FS_SECT_SERIALIZED) { + H5HF_indirect_t *sec_iblock; /* Pointer to section indirect block */ + unsigned sec_entry; /* Entry within section indirect block */ + + /* Look up indirect block containing indirect blocks for section */ + if(H5HF_man_locate_block(hdr, dxpl_id, old_sec_node->sect_info.addr, TRUE, &sec_iblock, &sec_entry, H5AC_READ) < 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 */ + old_sec_node->u.indirect.iblock = sec_iblock; + + /* Unlock indirect block */ + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, sec_iblock->addr, sec_iblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + sec_iblock = NULL; + + /* Section is "live" now */ + old_sec_node->sect_info.state = H5FS_SECT_LIVE; + } /* end if */ + /* Compute info about range */ curr_entry = (old_sec_node->u.indirect.row * hdr->man_dtable.cparam.width) + old_sec_node->u.indirect.col; @@ -1232,7 +1386,6 @@ HDfprintf(stderr, "%s: child_iblock->child_free_space = %Hu\n", FUNC, child_iblo /* Hook child up to parent indirect block */ iblock->ents[curr_entry].addr = child_iblock_addr; - HDassert(iblock->ents[curr_entry].free_space == child_iblock->child_free_space); /* Mark parent indirect block as modified */ if(H5HF_iblock_dirty(iblock) < 0) @@ -1243,12 +1396,13 @@ HDfprintf(stderr, "%s: child_iblock->child_free_space = %Hu\n", FUNC, child_iblo dblock_entry = old_sec_node->u.indirect.indir_row * hdr->man_dtable.cparam.width; /* Create direct block of correct size */ + /* (creates a 'single' free space section also) */ #ifdef QAK HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_row = %u\n", FUNC, old_sec_node->u.indirect.indir_row); HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row] = %Hu\n", FUNC, hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]); HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect_addr); #endif /* QAK */ - if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row], (hsize_t)old_sec_node->sect_addr, &dblock_addr, &dblock_sec_node) < 0) + if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, (size_t)hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row], (hsize_t)old_sec_node->sect_info.addr, &dblock_addr, &dblock_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") /* Hook direct block up to child indirect block */ @@ -1266,10 +1420,11 @@ HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") /* Set section's information */ - range_sec_node->sect_addr = child_iblock->block_off + hdr->man_dtable.row_block_off[old_sec_node->u.indirect.indir_row] + range_sec_node->sect_info.addr = child_iblock->block_off + hdr->man_dtable.row_block_off[old_sec_node->u.indirect.indir_row] + hdr->man_dtable.row_block_size[old_sec_node->u.indirect.indir_row]; - range_sec_node->sect_size = old_sec_node->sect_size; - range_sec_node->type = H5HF_SECT_RANGE; + range_sec_node->sect_info.size = old_sec_node->sect_info.size; + range_sec_node->sect_info.cls = &hdr->sect_cls[H5FS_SECT_FHEAP_RANGE]; + range_sec_node->sect_info.state = H5FS_SECT_LIVE; range_sec_node->u.range.iblock = child_iblock; if(H5HF_iblock_incr(child_iblock) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") @@ -1278,7 +1433,7 @@ HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect range_sec_node->u.range.num_entries = hdr->man_dtable.cparam.width - 1; /* Add new free space to the global list of space */ - if(H5HF_flist_add(hdr->flist, range_sec_node, &range_sec_node->sect_size, &range_sec_node->sect_addr) < 0) + if(H5HF_space_add(hdr, dxpl_id, range_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") @@ -1295,20 +1450,20 @@ HDfprintf(stderr, "%s: old_sec_node->sect_addr = %a\n", FUNC, old_sec_node->sect } /* end if */ else { /* Adjust section information */ - old_sec_node->sect_addr += hdr->man_dtable.row_block_size[old_sec_node->u.indirect.row]; + old_sec_node->sect_info.addr += hdr->man_dtable.row_block_size[old_sec_node->u.indirect.row]; /* Adjust range information */ old_sec_node->u.indirect.col++; old_sec_node->u.indirect.num_entries--; /* Add section back to free space list */ - if(H5HF_flist_add(hdr->flist, old_sec_node, &old_sec_node->sect_size, &old_sec_node->sect_addr) < 0) + if(H5HF_space_add(hdr, dxpl_id, old_sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect block free space to global list") } /* end else */ /* Release the child indirect block (marked as dirty) */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock_addr, child_iblock, H5AC__DIRTIED_FLAG) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") /* Point 'sec_node' at new direct block section node */ *sec_node = dblock_sec_node; @@ -1319,117 +1474,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_alloc_opaque - * - * Purpose: Break up an opaque section into component sections - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Apr 25 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_man_iblock_alloc_opaque(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t **sec_node) -{ - H5HF_indirect_t *iblock; /* Pointer to indirect block */ - H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old section node */ - haddr_t child_addr; /* Child block's address */ - unsigned entry; /* Entry of child block for section */ - unsigned row; /* Row of child block for section */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_alloc_opaque) - - /* - * Check arguments. - */ - HDassert(hdr); - HDassert(sec_node && *sec_node); - - /* Get a pointer to the indirect block covering the section */ - iblock = old_sec_node->u.opaque.iblock; - HDassert(iblock); - - /* Compute info about child block */ - entry = old_sec_node->u.opaque.entry; - row = entry / hdr->man_dtable.cparam.width; - child_addr = iblock->ents[entry].addr; - - /* Check if this section's child block is direct or indirect */ - if(row < hdr->man_dtable.max_direct_rows) { - H5HF_direct_t *child_dblock; /* Direct child block */ - size_t dblock_size; /* Direct block's size */ - - /* Compute direct block info */ - dblock_size = hdr->man_dtable.row_block_size[row]; - - /* Check whether direct block exists yet */ - if(H5F_addr_defined(child_addr)) { - /* Lock child direct block */ - /* (also parses it's free space sections) */ - if(NULL == (child_dblock = H5HF_man_dblock_protect(hdr, dxpl_id, child_addr, dblock_size, iblock, entry, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") - - /* Unlock child direct block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, child_addr, child_dblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") - } /* end if */ - else { - haddr_t dblock_addr; /* Address of direct block created */ - - /* Create direct block of appropriate size */ - if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, entry, dblock_size, (hsize_t)old_sec_node->sect_addr, &dblock_addr, NULL) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block") - - /* Hook direct block up to indirect block */ - iblock->ents[entry].addr = dblock_addr; - - /* Mark indirect block as dirty */ - if(H5HF_iblock_dirty(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty") - } /* end else */ - } /* end if */ - else { - H5HF_indirect_t *child_iblock; /* Indirect child block */ - size_t iblock_nrows; /* Indirect block's size */ - - /* Compute indirect block info */ - iblock_nrows = (H5V_log2_gen(hdr->man_dtable.row_block_size[row]) - hdr->man_dtable.first_row_bits) + 1; - - /* Check whether direct block exists yet */ - if(H5F_addr_defined(child_addr)) { - /* Lock child indirect block */ - /* (also parses it's free space sections) */ - if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_addr, iblock_nrows, iblock, entry, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - - /* Release the child indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_addr, child_iblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - } /* end if */ - else { -HDfprintf(stderr, "%s: Creating indirect block from opaque section not supported\n", FUNC); -HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "Creating indirect block from opaque section not supported yet") - } /* end else */ - } /* end else */ - - /* Drop reference count on indirect block that free section is in */ - if(H5HF_iblock_decr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") - - /* Free section structure */ - H5FL_FREE(H5HF_free_section_t, old_sec_node); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_alloc_opaque() */ - - -/*------------------------------------------------------------------------- * Function: H5HF_man_iblock_create * * Purpose: Allocate & initialize a managed indirect block @@ -1447,8 +1491,7 @@ H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t block_off, unsigned nrows, unsigned max_rows, haddr_t *addr_p) { H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */ - size_t curr_row; /* Current row within indirect block */ - size_t u, v; /* Local index variable */ + size_t u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_create) @@ -1485,7 +1528,6 @@ HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows); iblock->nrows = nrows; iblock->max_rows = max_rows; iblock->dirty = TRUE; - iblock->fl_gen = hdr->fl_gen; /* New blocks have their free list generation set up correctly */ /* Compute size of buffer needed for indirect block */ iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock); @@ -1495,16 +1537,8 @@ HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows); HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for block entries") /* Initialize indirect block entry tables */ - curr_row = 0; - iblock->child_free_space = 0; - for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); /* u advanced in inner loop */) { - for(v = 0; v < hdr->man_dtable.cparam.width; v++, u++) { - iblock->ents[u].addr = HADDR_UNDEF; - iblock->ents[u].free_space = hdr->man_dtable.row_dblock_free[curr_row]; - iblock->child_free_space += iblock->ents[u].free_space; - } /* end for */ - curr_row++; - } /* end for */ + for(u = 0; u < (iblock->nrows * hdr->man_dtable.cparam.width); u++) + iblock->ents[u].addr = HADDR_UNDEF; /* Allocate space for the indirect block on disk */ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size))) @@ -1527,86 +1561,6 @@ done: /*------------------------------------------------------------------------- - * Function: H5HF_man_iblock_build_sections - * - * Purpose: Build free space sections for child blocks of an indirect block - * - * Return: SUCCEED/FAIL - * - * Programmer: Quincey Koziol - * koziol@ncsa.uiuc.edu - * Apr 25 2006 - * - *------------------------------------------------------------------------- - */ -static herr_t -H5HF_man_iblock_build_sections(H5HF_indirect_t *iblock) -{ - H5HF_free_section_t *sec_node; /* Pointer to free list section for block */ - H5HF_hdr_t *hdr; /* Heap header info */ - haddr_t curr_off; /* Offset of child block in heap */ - unsigned row, col; /* Current row & column being operated on */ - unsigned entry; /* Currenty entry being worked on */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_build_sections) - - /* - * Check arguments. - */ - HDassert(iblock); - - /* Get the heap header pointer (for convenience) */ - hdr = iblock->hdr; - - /* Set starting offset in heap */ - curr_off = iblock->block_off; - - /* Create a free space section for each child block of indirect block */ - entry = 0; -#ifdef QAK -HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", FUNC, hdr->man_alloc_size); -#endif /* QAK */ - for(row = 0; row < iblock->nrows; row++) { - for(col = 0; col < hdr->man_dtable.cparam.width; col++) { -#ifdef QAK -HDfprintf(stderr, "%s: curr_off = %a\n", FUNC, curr_off); -#endif /* QAK */ - /* Only create free space sections for blocks within the allocated size of the heap */ - if(curr_off >= hdr->man_alloc_size) - break; - - /* Allocate section node */ - if(NULL == (sec_node = H5FL_MALLOC(H5HF_free_section_t))) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct block free list section") - - /* Set section's information */ - sec_node->sect_addr = curr_off; - sec_node->sect_size = iblock->ents[entry].free_space; - sec_node->type = H5HF_SECT_OPAQUE; - sec_node->u.opaque.iblock = iblock; - sec_node->u.opaque.entry = entry; - - /* Increment reference count on indirect block */ - if(H5HF_iblock_incr(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block") - - /* Add section to free list */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add free space section to global list") - - /* Advance state */ - curr_off += hdr->man_dtable.row_block_size[row]; - entry++; - } /* end for */ - } /* end for */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_iblock_build_sections() */ - - -/*------------------------------------------------------------------------- * Function: H5HF_man_iblock_protect * * Purpose: Convenience wrapper around H5AC_protect on a indirect block @@ -1650,17 +1604,6 @@ HDfprintf(stderr, "%s: iblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock_addr if(NULL == (iblock = H5AC_protect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, &iblock_nrows, &par_info, rw))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block") - /* Regenerate the free list information for this block, if necessary */ - /* (Only create free list information if write access is requested) */ - if(rw == H5AC_WRITE && hdr->fl_gen != iblock->fl_gen) { - /* Build the free list sections for the block */ - if(H5HF_man_iblock_build_sections(iblock) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDECODE, NULL, "can't build free space sections for block") - - /* Mark the block's free list generation as up to date now */ - iblock->fl_gen = hdr->fl_gen; - } /* end if */ - /* Set the return value */ ret_value = iblock; diff --git a/src/H5HFint.c b/src/H5HFint.c index e8b380d..5b49c6d 100644 --- a/src/H5HFint.c +++ b/src/H5HFint.c @@ -57,16 +57,12 @@ /********************/ /* Local Prototypes */ /********************/ -static herr_t H5HF_man_start_freelist(H5HF_hdr_t *hdr, hid_t dxpl_id); /*********************/ /* Package Variables */ /*********************/ -/* Declare a free list to manage the H5HF_free_section_t struct */ -H5FL_DEFINE(H5HF_free_section_t); - /*****************************/ /* Library Private Variables */ @@ -80,146 +76,122 @@ H5FL_DEFINE(H5HF_free_section_t); /*------------------------------------------------------------------------- - * Function: H5HF_free_section_free_cb - * - * Purpose: Free a free section node - * - * Return: Success: non-negative - * - * Failure: negative - * - * Programmer: Quincey Koziol - * Monday, March 13, 2006 - * - *------------------------------------------------------------------------- - */ -herr_t -H5HF_free_section_free_cb(void *_sect, void UNUSED *key, void UNUSED *op_data) -{ - H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; - H5HF_indirect_t *iblock = NULL; /* Indirect block referenced */ - herr_t ret_value = 0; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_free_section_free_cb) - - HDassert(sect); - - /* Find indirect block that free section references */ - switch(sect->type) { - case H5HF_SECT_SINGLE: - iblock = sect->u.single.parent; - break; - - case H5HF_SECT_OPAQUE: - iblock = sect->u.opaque.iblock; - break; - - case H5HF_SECT_RANGE: - iblock = sect->u.range.iblock; - break; - - case H5HF_SECT_INDIRECT: - iblock = sect->u.indirect.iblock; - break; - } /* end switch */ - - /* 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 shared indirect block") - - /* Release the sections */ - H5FL_FREE(H5HF_free_section_t, sect); - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5HF_free_section_free_cb() */ - - -/*------------------------------------------------------------------------- - * Function: H5HF_man_start_freelist + * Function: H5HF_man_locate_block * - * Purpose: Start free list for existing heap, by bringing in root direct - * or indirect block and it's free space sections. + * Purpose: Locate a block in a managed heap * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * koziol@ncsa.uiuc.edu - * Apr 25 2006 + * May 8 2006 * *------------------------------------------------------------------------- */ -static herr_t -H5HF_man_start_freelist(H5HF_hdr_t *hdr, hid_t dxpl_id) +herr_t +H5HF_man_locate_block(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t obj_off, + hbool_t locate_indirect, + H5HF_indirect_t **ret_iblock, unsigned *ret_entry, + H5AC_protect_t rw) { - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT(H5HF_man_start_freelist) + haddr_t iblock_addr; /* Indirect block's address */ + H5HF_indirect_t *iblock; /* Pointer to indirect block */ + unsigned bot_row, top_row; /* Bottom & top acceptable rows */ + unsigned row, col; /* Row & column for object's block */ + size_t entry; /* Entry of block */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_man_locate_block) +#ifdef QAK +HDfprintf(stderr, "%s: obj_off = %Hu\n", FUNC, obj_off); +#endif /* QAK */ /* * Check arguments. */ HDassert(hdr); + HDassert(hdr->man_dtable.curr_root_rows); /* Only works for heaps with indirect root block */ - /* Check for empty heap */ - if(!H5F_addr_defined(hdr->man_dtable.table_addr)) { + /* Set up target bottom & top rows */ + if(locate_indirect) { + bot_row = hdr->man_dtable.max_direct_rows; + top_row = hdr->man_dtable.max_direct_rows + (H5V_log2_of2(hdr->man_dtable.cparam.width) + 1); + } /* end if */ + else { + bot_row = 0; + top_row = hdr->man_dtable.max_direct_rows; + } /* end else */ #ifdef QAK -HDfprintf(stderr, "%s: Empty heap to [not] start\n", FUNC); +HDfprintf(stderr, "%s: bot_row = %u, top_row = %u\n", FUNC, bot_row, top_row); #endif /* QAK */ - /* Nothing to do */ - ; - } /* end if */ - /* Check for root direct block */ - else if(hdr->man_dtable.curr_root_rows == 0) { - H5HF_direct_t *dblock; /* Pointer to direct block to query */ - haddr_t dblock_addr; /* Direct block address */ - size_t dblock_size; /* Direct block size */ + /* Look up row & column for object */ + if(H5HF_dtable_lookup(&hdr->man_dtable, obj_off, &row, &col) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") #ifdef QAK -HDfprintf(stderr, "%s: Root direct block to start\n", FUNC); +HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); #endif /* QAK */ - /* Bring root direct block into memory */ - /* (which will parse it's free list) */ - /* (Could create an "opaque" section for it, but it doesn't seem worthwhile) */ - dblock_addr = hdr->man_dtable.table_addr; - dblock_size = hdr->man_dtable.cparam.start_block_size; - if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, NULL, 0, H5AC_WRITE))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") - /* Unlock direct block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") - dblock = NULL; - } /* end if */ - /* Must be a root indirect block */ - else { - H5HF_indirect_t *iblock; /* Pointer to root indirect block to query */ - haddr_t iblock_addr; /* Indirect block's address */ + /* Set initial indirect block info */ + iblock_addr = hdr->man_dtable.table_addr; +#ifdef QAK +HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); +#endif /* QAK */ + + /* Lock root indirect block */ + if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0, rw))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") + /* Check for indirect block row */ + while(row < bot_row || row >= top_row) { + haddr_t new_iblock_addr; /* New indirect block's address */ + H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ + unsigned nrows; /* Number of rows in new indirect block */ + + /* Compute # of rows in child indirect block */ + nrows = (H5V_log2_gen(hdr->man_dtable.row_block_size[row]) - hdr->man_dtable.first_row_bits) + 1; + + /* Compute indirect block's entry */ + entry = (row * hdr->man_dtable.cparam.width) + col; #ifdef QAK -HDfprintf(stderr, "%s: Root indirect block to start\n", FUNC); +HDfprintf(stderr, "%s: entry = %Zu\n", FUNC, entry); #endif /* QAK */ - /* Get indirect block info */ - iblock_addr = hdr->man_dtable.table_addr; - /* Lock root indirect block */ - /* (which will parse it's free space) */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0, H5AC_WRITE))) + /* Locate child indirect block */ + new_iblock_addr = iblock->ents[entry].addr; + + /* Lock new indirect block */ + if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, nrows, iblock, entry, rw))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - /* Release the root indirect block */ + /* Release the current indirect block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - iblock = NULL; - } /* end else */ + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + + /* Switch variables to use new indirect block */ + iblock = new_iblock; + iblock_addr = new_iblock_addr; +#ifdef QAK +HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); +HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); +#endif /* QAK */ + + /* Look up row & column in new indirect block for object */ + if(H5HF_dtable_lookup(&hdr->man_dtable, (obj_off - iblock->block_off), &row, &col) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") + +#ifdef QAK +HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); +#endif /* QAK */ + } /* end while */ - /* Mark heap as being in sync now */ - hdr->freelist_sync = TRUE; + /* Set return parameters */ + *ret_entry = (row * hdr->man_dtable.cparam.width) + col; + *ret_iblock = iblock; done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5HF_man_start_freelist() */ +} /* end H5HF_man_locate_block() */ /*------------------------------------------------------------------------- @@ -241,7 +213,6 @@ H5HF_man_find(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t request, H5HF_free_section_t **sec_node/*out*/) { htri_t node_found; /* Whether an existing free list node was found */ - hbool_t search_again; /* Whether to search again for another free section */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_find) @@ -256,45 +227,9 @@ HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request); HDassert(request > 0); HDassert(sec_node); - /* Search for free space in the globel free list, until a non-opaque node is found */ - do { - /* Done searching, unless opaque node found */ - search_again = FALSE; - - /* Look for free space in global free list */ - if((node_found = H5HF_flist_find(hdr->flist, request, (void **)sec_node)) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap direct block") - - /* Check for opaque section */ - if(node_found) { - if((*sec_node)->type == H5HF_SECT_OPAQUE) { - /* Break opaque section down into component sections */ - if(H5HF_man_iblock_alloc_opaque(hdr, dxpl_id, sec_node) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up opaque free section") - - /* Search again */ - search_again = TRUE; - } /* end if */ - } /* end if */ - /* If we didn't find a node, check if we've looked in all the direct blocks in the heap for space */ - else { -#ifdef QAK -HDfprintf(stderr, "%s: hdr->freelist_sync = %u\n", FUNC, (unsigned)hdr->freelist_sync); -#endif /* QAK */ - if(!hdr->freelist_sync) { -#ifdef QAK -HDfprintf(stderr, "%s: Start free list for existing blocks in heap\n", FUNC); -#endif /* QAK */ - /* Start freelist for existing heap */ - if(H5HF_man_start_freelist(hdr, dxpl_id) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't start fractal heap free list") - - /* Search again */ - search_again = TRUE; - } /* end if */ - } /* end else */ - } while(search_again); - + /* Look for free space */ + if((node_found = H5HF_space_find(hdr, dxpl_id, (hsize_t)request, sec_node)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap") /* If we didn't find a node, go make one big enough to hold the requested block */ if(!node_found) { @@ -305,10 +240,10 @@ HDfprintf(stderr, "%s: Allocate new direct block\n", FUNC); if(H5HF_man_dblock_new(hdr, dxpl_id, request) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create fractal heap direct block") - /* Request space from the free list */ + /* Request space from the free space */ /* (Ought to be able to be filled, now) */ - if(H5HF_flist_find(hdr->flist, request, (void **)sec_node) <= 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap direct block") + if(H5HF_space_find(hdr, dxpl_id, (hsize_t)request, sec_node) <= 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap") } /* end if */ HDassert(*sec_node); #ifdef QAK @@ -354,12 +289,12 @@ H5HF_man_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sec_node, HDassert(id); /* Check for indirect section */ - if(sec_node->type == H5HF_SECT_INDIRECT) { + if(sec_node->sect_info.cls->type == H5FS_SECT_FHEAP_INDIRECT) { #ifdef QAK -HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr); -HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size); +HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr); +HDfprintf(stderr, "%s: sec_node->sect_info.size = %Zu\n", FUNC, sec_node->sect_info.size); HDfprintf(stderr, "%s: sec_node->u.indirect.iblock = %p\n", FUNC, sec_node->u.indirect.iblock); -if(sec_node->u.indirect.iblock) +if(sec_node->sect_info.state == H5FS_SECT_LIVE && sec_node->u.indirect.iblock) HDfprintf(stderr, "%s: sec_node->u.indirect.iblock->addr = %a\n", FUNC, sec_node->u.indirect.iblock->addr); HDfprintf(stderr, "%s: sec_node->u.indirect.row = %u\n", FUNC, sec_node->u.indirect.row); HDfprintf(stderr, "%s: sec_node->u.indirect.col = %u\n", FUNC, sec_node->u.indirect.col); @@ -373,12 +308,12 @@ HDfprintf(stderr, "%s: sec_node->u.indirect.indir_nrows = %u\n", FUNC, sec_node- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up indirect free section") } /* end if */ /* Check for range section */ - else if(sec_node->type == H5HF_SECT_RANGE) { + else if(sec_node->sect_info.cls->type == H5FS_SECT_FHEAP_RANGE) { #ifdef QAK -HDfprintf(stderr, "%s: sec_node->sect_addr = %a\n", FUNC, sec_node->sect_addr); -HDfprintf(stderr, "%s: sec_node->sect_size = %Zu\n", FUNC, sec_node->sect_size); +HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr); +HDfprintf(stderr, "%s: sec_node->sect_info.size = %Zu\n", FUNC, sec_node->sect_info.size); HDfprintf(stderr, "%s: sec_node->u.range.iblock = %p\n", FUNC, sec_node->u.range.iblock); -if(sec_node->u.range.iblock) +if(sec_node->sect_info.state == H5FS_SECT_LIVE && sec_node->u.range.iblock) HDfprintf(stderr, "%s: sec_node->u.range.iblock->addr = %a\n", FUNC, sec_node->u.range.iblock->addr); HDfprintf(stderr, "%s: sec_node->u.range.row = %u\n", FUNC, sec_node->u.range.row); HDfprintf(stderr, "%s: sec_node->u.range.col = %u\n", FUNC, sec_node->u.range.col); @@ -388,6 +323,14 @@ HDfprintf(stderr, "%s: sec_node->u.range.num_entries = %u\n", FUNC, sec_node->u. if(H5HF_man_iblock_alloc_range(hdr, dxpl_id, &sec_node) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't break up range free section") } /* end if */ + HDassert(sec_node->sect_info.cls->type == H5FS_SECT_FHEAP_SINGLE); + + /* Check for serialized 'single' section */ + if(sec_node->sect_info.state == H5FS_SECT_SERIALIZED) { + if(H5HF_man_iblock_alloc_single(hdr, dxpl_id, sec_node) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize direct block for single free section") + } /* end if */ + HDassert(sec_node->sect_info.state == H5FS_SECT_LIVE); /* Lock direct block */ #ifdef QAK @@ -408,71 +351,23 @@ HDfprintf(stderr, "%s: sec_node->u.single.dblock_size = %Zu\n", FUNC, sec_node-> /* Check for address mapping type */ if(hdr->addrmap == H5HF_ABSOLUTE) { - H5HF_direct_free_node_t *node; /* Block's free list node */ uint8_t *p; /* Temporary pointer to obj info in block */ - size_t obj_off; /* Offset of object within block */ - size_t full_obj_size; /* Size of object including metadata */ - size_t alloc_obj_size; /* Size of object including metadata & any free space fragment */ - size_t free_obj_size; /* Size of space to free for object */ - hbool_t whole_node = FALSE; /* Whether we've used the whole node or not */ - unsigned char free_frag_size; /* Size of free space fragment */ - - /* Locate "local" free list node for section */ -/* XXX: Change to using skip list? */ - obj_off = sec_node->sect_addr - dblock->block_off; - node = dblock->free_list->first; - while(node->my_offset != obj_off) - node = node->next; - - /* Compute full object size, with metadata for object */ - full_obj_size = obj_size + H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr); + size_t blk_off; /* Offset of object within block */ + + /* Set the offset of the object within the block */ + blk_off = sec_node->sect_info.addr - dblock->block_off; /* Sanity checks */ #ifdef QAK HDfprintf(stderr, "%s: hdr->total_man_free = %Hu\n", FUNC, hdr->total_man_free); -HDfprintf(stderr, "%s: dblock->blk_free_space = %Zu\n", FUNC, dblock->blk_free_space); HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); #endif /* QAK */ - HDassert(dblock->blk_free_space >= obj_size); - HDassert(dblock->free_list); - HDassert(node->size >= full_obj_size); + HDassert(sec_node->sect_info.size >= obj_size); - /* Check for using entire node */ - free_frag_size = 0; #ifdef QAK -HDfprintf(stderr, "%s: node->size = %Zu\n", FUNC, node->size); +HDfprintf(stderr, "%s: sec_node->sect_info.size = %Zu\n", FUNC, sec_node->sect_info.size); #endif /* QAK */ - if(node->size <= (full_obj_size + H5HF_MAN_ABS_DIRECT_FREE_NODE_SIZE(dblock))) { - /* Set the offset of the object within the block */ - obj_off = node->my_offset; - - /* Check for allocating from first node in list */ - if(node->prev == NULL) { - /* Make the next node in the free list the list head */ - dblock->free_list->first = node->next; - dblock->free_list_head = node->next_offset; - } /* end if */ - else { - H5HF_direct_free_node_t *prev_node; /* Pointer to previous free list node for block */ - - /* Excise node from list */ - prev_node = node->prev; - prev_node->next = node->next; - if(node->next) { - H5HF_direct_free_node_t *next_node; /* Pointer to next free list node for block */ - - next_node = node->next; - next_node->prev = prev_node; - prev_node->next_offset = next_node->my_offset; - } /* end if */ - else - prev_node->next_offset = 0; - } /* end if */ - - /* Set the free fragment size */ - free_frag_size = (unsigned char )(node->size - full_obj_size); - whole_node = TRUE; - + if(sec_node->sect_info.size == obj_size) { /* Drop reference count on parent indirect block of direct block that free section is in */ HDassert(dblock->parent == NULL || sec_node->u.single.parent == NULL || @@ -481,73 +376,43 @@ HDfprintf(stderr, "%s: node->size = %Zu\n", FUNC, node->size); if(H5HF_iblock_decr(sec_node->u.single.parent) < 0) HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block") - /* Release the memory for the free list node & section */ - H5FL_FREE(H5HF_direct_free_node_t, node); + /* Release the memory for the free space section */ H5FL_FREE(H5HF_free_section_t, sec_node); } /* end if */ else { - /* Allocate object from end of free space node */ - /* (so we don't have to adjust with any other node's info */ - obj_off = (node->my_offset + node->size) - full_obj_size; - node->size -= full_obj_size; - /* Adjust information for section node */ - sec_node->sect_size -= full_obj_size; + sec_node->sect_info.addr += obj_size; + sec_node->sect_info.size -= obj_size; - /* Re-insert section node onto global list */ - if(H5HF_flist_add(hdr->flist, sec_node, &sec_node->sect_size, &sec_node->sect_addr) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list") + /* Re-insert section node into heap's free space */ + if(H5HF_space_add(hdr, dxpl_id, sec_node) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space") } /* end else */ - /* Mark free list as dirty */ - dblock->free_list->dirty = TRUE; - - /* Compute the size of the space to actually allocate */ - /* (includes the metadata for the object & the free space fragment) */ - alloc_obj_size = full_obj_size + free_frag_size; - - /* Compute the size of the free space to reduce */ - /* (does not include the object prefix if this object uses a whole node) */ - free_obj_size = obj_size + (whole_node ? free_frag_size : H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(hdr)); - #ifdef QAK -HDfprintf(stderr, "%s: obj_off = %Zu\n", FUNC, obj_off); -HDfprintf(stderr, "%s: free_frag_size = %Zu\n", FUNC, free_frag_size); -HDfprintf(stderr, "%s: full_obj_size = %Zu\n", FUNC, full_obj_size); -HDfprintf(stderr, "%s: alloc_obj_size = %Zu\n", FUNC, alloc_obj_size); +HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off); #endif /* QAK */ - /* Reduce space available in parent block(s) */ - if(H5HF_man_dblock_adj_free(dblock, -(ssize_t)free_obj_size) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for direct block & parents") + /* Reduce space available in heap */ + if(H5HF_hdr_adj_free(hdr, -(ssize_t)obj_size) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap") /* Encode the object in the block */ /* Point to location for object */ - p = dblock->blk + obj_off; - - /* Encode the free fragment size */ - *p++ = free_frag_size; + p = dblock->blk + blk_off; /* Copy the object's data into the heap */ HDmemcpy(p, obj, obj_size); p += obj_size; -#ifdef H5_USING_PURIFY - /* Zero out the free space fragment */ - HDmemset(p, 0, free_frag_size); -#endif /* H5_USING_PURIFY */ -#ifndef NDEBUG - p += free_frag_size; -#endif /* NDEBUG */ - /* Sanity check */ - HDassert((size_t)(p - (dblock->blk + obj_off)) == alloc_obj_size); + HDassert((size_t)(p - (dblock->blk + blk_off)) == obj_size); /* Set the heap ID for the new object (heap offset & obj length) */ #ifdef QAK HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off); #endif /* QAK */ - UINT64ENCODE_VAR(id, (dblock->block_off + obj_off), hdr->heap_off_size); + UINT64ENCODE_VAR(id, (dblock->block_off + blk_off), hdr->heap_off_size); UINT64ENCODE_VAR(id, obj_size, hdr->id_len); } /* end if */ else { @@ -616,88 +481,27 @@ HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, obj_off, obj_len); HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") } /* end if */ else { - haddr_t iblock_addr; /* Indirect block's address */ H5HF_indirect_t *iblock; /* Pointer to indirect block */ - unsigned row, col; /* Row & column for object's block */ - size_t entry; /* Entry of block */ - - /* Look up row & column for object */ - if(H5HF_dtable_lookup(&hdr->man_dtable, obj_off, &row, &col) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") -#ifdef QAK -HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); -#endif /* QAK */ - - /* Set initial indirect block info */ - iblock_addr = hdr->man_dtable.table_addr; -#ifdef QAK -HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); -#endif /* QAK */ - - /* Lock root indirect block */ - if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock_addr, hdr->man_dtable.curr_root_rows, NULL, 0, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - - /* Check for indirect block row */ - while(row >= hdr->man_dtable.max_direct_rows) { - haddr_t new_iblock_addr; /* New indirect block's address */ - H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */ - unsigned nrows; /* Number of rows in new indirect block */ - - /* Compute # of rows in child indirect block */ - nrows = (H5V_log2_gen(hdr->man_dtable.row_block_size[row]) - hdr->man_dtable.first_row_bits) + 1; - - /* Compute indirect block's entry */ - entry = (row * hdr->man_dtable.cparam.width) + col; -#ifdef QAK -HDfprintf(stderr, "%s: entry = %Zu\n", FUNC, entry); -#endif /* QAK */ - - /* Locate child indirect block */ - new_iblock_addr = iblock->ents[entry].addr; - - /* Lock new indirect block */ - if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, nrows, iblock, entry, H5AC_READ))) - HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block") - - /* Release the current indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") - - /* Switch variables to use new indirect block */ - iblock = new_iblock; - iblock_addr = new_iblock_addr; -#ifdef QAK -HDfprintf(stderr, "%s: iblock_addr = %a\n", FUNC, iblock_addr); -HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off); -#endif /* QAK */ - - /* Look up row & column in new indirect block for object */ - if(H5HF_dtable_lookup(&hdr->man_dtable, (obj_off - iblock->block_off), &row, &col) < 0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of object") + unsigned entry; /* Entry of block */ -#ifdef QAK -HDfprintf(stderr, "%s: row = %u, col = %u\n", FUNC, row, col); -#endif /* QAK */ - } /* end while */ - - /* Compute direct block's entry */ - entry = (row * hdr->man_dtable.cparam.width) + col; + /* Look up indirect block containing direct block */ + if(H5HF_man_locate_block(hdr, dxpl_id, obj_off, FALSE, &iblock, &entry, H5AC_READ) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTCOMPUTE, FAIL, "can't compute row & column of section") #ifdef QAK HDfprintf(stderr, "%s: entry address = %a\n", FUNC, iblock->ents[entry].addr); #endif /* QAK */ /* Set direct block info */ dblock_addr = iblock->ents[entry].addr; - dblock_size = hdr->man_dtable.row_block_size[row]; + dblock_size = hdr->man_dtable.row_block_size[entry / hdr->man_dtable.cparam.width]; /* Lock direct block */ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, iblock, entry, H5AC_READ))) HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block") /* Unlock indirect block */ - if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, iblock, H5AC__NO_FLAGS_SET) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") iblock = NULL; } /* end else */ #ifdef QAK @@ -711,15 +515,12 @@ HDfprintf(stderr, "%s: dblock_addr = %a, dblock_size = %Zu\n", FUNC, dblock_addr /* Point to location for object */ p = dblock->blk + blk_off; - /* Skip over the free fragment size */ - p++; - /* Copy the object's data into the heap */ HDmemcpy(obj, p, obj_len); /* Unlock direct block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block") dblock = NULL; done: diff --git a/src/H5HFiter.c b/src/H5HFiter.c index 90f2f14..31fd6c8 100644 --- a/src/H5HFiter.c +++ b/src/H5HFiter.c @@ -233,7 +233,7 @@ HDfprintf(stderr, "%s: biter->curr->entry = %u\n", FUNC, biter->curr->entry); /* Release the current indirect block */ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, iblock_addr, iblock, H5AC__NO_FLAGS_SET) < 0) - HDONE_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") + HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block") iblock = NULL; /* See if the location falls in a direct block row */ diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h index af06770..96e5b57 100644 --- a/src/H5HFpkg.h +++ b/src/H5HFpkg.h @@ -33,7 +33,7 @@ /* Other private headers needed by this file */ #include "H5ACprivate.h" /* Metadata cache */ #include "H5FLprivate.h" /* Free Lists */ -#include "H5RCprivate.h" /* Reference counted object functions */ +#include "H5FSprivate.h" /* File free space */ #include "H5SLprivate.h" /* Skip lists */ /**************************/ @@ -77,6 +77,7 @@ + 4 /* Min. size of standalone object */ \ + (h)->sizeof_size /* Total man. free space */ \ + (h)->sizeof_size /* Total std. free entries */ \ + + (h)->sizeof_addr /* File address of free section header */ \ + (h)->sizeof_size /* Total size of heap */ \ + (h)->sizeof_size /* Size of man. space in heap */ \ + (h)->sizeof_size /* Size of alloacted man. space in heap */ \ @@ -85,32 +86,14 @@ + H5HF_DTABLE_INFO_SIZE(h) /* Size of managed obj. doubling-table info */ \ ) -/* Size of free space description in an absolute managed direct block */ -#define H5HF_MAN_ABS_DIRECT_FREE_NODE_SIZE(d) (2 * (d)->blk_off_size) - -/* Size of header for each object in an absolute managed direct block */ -#define H5HF_MAN_ABS_DIRECT_OBJ_PREFIX_LEN(h) ( \ - + 1 /* Free space fragment length */ \ - ) - /* Size of overhead for a direct block */ -#define H5HF_MAN_ABS_DIRECT_OVERHEAD_SIZE(h, s) ( \ - /* General metadata fields */ \ - H5HF_METADATA_PREFIX_SIZE \ - \ - /* Fractal heap managed, absolutely mapped direct block specific fields */ \ - + (h)->sizeof_addr /* File address of heap owning the block */ \ - + (h)->heap_off_size /* Offset of the block in the heap */ \ - + H5HF_SIZEOF_OFFSET_LEN(s) /* Offset of first descriptor in free list */ \ - ) -#define H5HF_MAN_ABS_DIRECT_OVERHEAD_DBLOCK(h, d) ( \ +#define H5HF_MAN_ABS_DIRECT_OVERHEAD(h) ( \ /* General metadata fields */ \ H5HF_METADATA_PREFIX_SIZE \ \ /* Fractal heap managed, absolutely mapped direct block specific fields */ \ + (h)->sizeof_addr /* File address of heap owning the block */ \ + (h)->heap_off_size /* Offset of the block in the heap */ \ - + (d)->blk_off_size /* Offset of first descriptor in free list */ \ ) /* Size of managed indirect block (absolute & mapped) */ @@ -121,8 +104,8 @@ /* Fractal heap managed, absolutely mapped indirect block specific fields */ \ + (h)->sizeof_addr /* File address of heap owning the block */ \ + (h)->heap_off_size /* Offset of the block in the heap */ \ - + (MIN((i)->nrows, (h)->man_dtable.max_direct_rows) * (h)->man_dtable.cparam.width * ((h)->sizeof_addr + (h)->man_dtable.max_dir_blk_off_size)) /* Size of entries for direct blocks */ \ - + ((((i)->nrows > (h)->man_dtable.max_direct_rows) ? ((i)->nrows - (h)->man_dtable.max_direct_rows) : 0) * (h)->man_dtable.cparam.width * ((h)->sizeof_addr + (h)->heap_off_size)) /* Size of entries for indirect blocks */ \ + + (MIN((i)->nrows, (h)->man_dtable.max_direct_rows) * (h)->man_dtable.cparam.width * (h)->sizeof_addr) /* Size of entries for direct blocks */ \ + + ((((i)->nrows > (h)->man_dtable.max_direct_rows) ? ((i)->nrows - (h)->man_dtable.max_direct_rows) : 0) * (h)->man_dtable.cparam.width * (h)->sizeof_addr) /* Size of entries for indirect blocks */ \ ) @@ -130,6 +113,12 @@ #define H5HF_SIZEOF_OFFSET_BITS(b) (((b) + 7) / 8) #define H5HF_SIZEOF_OFFSET_LEN(l) H5HF_SIZEOF_OFFSET_BITS(H5V_log2_of2((unsigned)(l))) +/* Free space section types for fractal heap */ +/* (values stored in free space data structures in file) */ +#define H5FS_SECT_FHEAP_SINGLE 0 /* Section is actual bytes in a direct block */ +#define H5FS_SECT_FHEAP_RANGE 1 /* Section is a range of direct blocks */ +#define H5FS_SECT_FHEAP_INDIRECT 2 /* Section is a range of _indirect_ blocks in an indirect block row */ + /****************************/ /* Package Private Typedefs */ /****************************/ @@ -189,6 +178,36 @@ typedef struct H5HF_block_iter_t { H5HF_block_loc_t *curr; /* Pointer to the current level information for iterator */ } H5HF_block_iter_t; +/* Fractal heap free space section info */ +typedef struct H5HF_free_section_t { + H5FS_section_info_t sect_info; /* Free space section information (must be first in struct) */ + union { + struct { + H5HF_indirect_t *parent; /* Indirect block parent for free section's direct block */ + unsigned par_entry; /* Entry of free section's direct block in parent indirect block */ + /* (Needed to retrieve direct block) */ + + haddr_t dblock_addr; /* Address of direct block for free section */ + size_t dblock_size; /* Size of direct block */ + /* (Needed to retrieve direct block) */ + } single; + struct { + H5HF_indirect_t *iblock; /* Indirect block for free section */ + unsigned row; /* Row for range of blocks */ + unsigned col; /* Column for range of blocks */ + unsigned num_entries; /* Number of entries covered */ + } range; + struct { + H5HF_indirect_t *iblock; /* Indirect block for free section */ + unsigned row; /* Row for range of blocks */ + unsigned col; /* Column for range of blocks */ + unsigned num_entries; /* Number of entries covered */ + unsigned indir_row; /* Row for indirect range of blocks */ + unsigned indir_nrows; /* Number of rows in indirect blocks */ + } indirect; + } u; +} H5HF_free_section_t; + /* The fractal heap header information */ /* (Each fractal heap header has certain information that is shared across all * the instances of blocks in that fractal heap) @@ -200,6 +219,7 @@ typedef struct H5HF_hdr_t { /* Shared internal information (varies during lifetime of heap) */ hsize_t total_man_free; /* Total amount of free space in managed blocks */ hsize_t total_std_free; /* Total # of free standalone ID entries */ + haddr_t fs_addr; /* Address of free space header on disk */ /* Statistics for heap */ hsize_t total_size; /* Total amount of space used by heap (managed & standalone) */ @@ -217,15 +237,11 @@ typedef struct H5HF_hdr_t { size_t sizeof_size; /* Size of file sizes */ size_t sizeof_addr; /* Size of file addresses */ size_t id_len; /* Size of heap IDs */ - H5HF_freelist_t *flist; /* Free list for objects in heap */ - unsigned fl_gen; /* Free list "generation" */ + size_t nsect_classes; /* Number of free space section classes */ + H5FS_section_class_t *sect_cls; /* Array of free space section classes */ + H5FS_t *fspace; /* Free space list for objects in heap */ + hbool_t fspace_open; /* Whether free space is ready */ H5HF_block_iter_t next_block; /* Block iterator for searching for next block with space */ - hbool_t freelist_sync; /* If the heap's free list in memory is in sync with the free list on disk */ - /* (ie. all existing blocks have been scanned - * for free space (or heap is new and there are - * no blocks with unknown free space) and new - * free space is added by adding new blocks) - */ /* Doubling table information */ /* (Partially set by user, partially derived/updated internally) */ @@ -246,7 +262,6 @@ typedef struct H5HF_hdr_t { /* Indirect block entry */ typedef struct H5HF_indirect_ent_t { haddr_t addr; /* Direct block's address */ - hsize_t free_space; /* Amount of free space in block pointed to */ /* XXX: Will need space for block size, for blocks with I/O filters */ } H5HF_indirect_ent_t; @@ -259,10 +274,8 @@ struct H5HF_indirect_t { size_t rc; /* Reference count of child blocks */ hbool_t dirty; /* Info is modified */ H5HF_hdr_t *hdr; /* Shared heap header info */ - unsigned fl_gen; /* Free list "generation" */ struct H5HF_indirect_t *parent; /* Shared parent indirect block info */ unsigned par_entry; /* Entry in parent's table */ - hsize_t child_free_space; /* Total amount of free space in children */ haddr_t addr; /* Address of this indirect block on disk */ unsigned nrows; /* Total # of rows in indirect block */ unsigned max_rows; /* Max. # of rows in indirect block */ @@ -273,22 +286,6 @@ struct H5HF_indirect_t { H5HF_indirect_ent_t *ents; /* Pointer to block entry table */ }; -/* Direct block free list node */ -typedef struct H5HF_direct_free_node_t { - /* Direct block free list info */ - size_t size; /* Size of free space */ - size_t my_offset; /* Offset of free space in block */ - size_t next_offset; /* Offset of next free space in block */ - struct H5HF_direct_free_node_t *prev; /* Previous node in free list */ - struct H5HF_direct_free_node_t *next; /* Next node in free list */ -} H5HF_direct_free_node_t; - -/* Direct block free list header */ -typedef struct H5HF_direct_free_head_t { - H5HF_direct_free_node_t *first; /* First node in free list */ - hbool_t dirty; /* Free list is modified */ -} H5HF_direct_free_head_t; - /* A fractal heap direct block */ typedef struct H5HF_direct_t { /* Information for H5AC cache functions, _must_ be first field in structure */ @@ -296,18 +293,14 @@ typedef struct H5HF_direct_t { /* Internal heap information */ H5HF_hdr_t *hdr; /* Shared heap header info */ - unsigned fl_gen; /* Free list "generation" */ H5HF_indirect_t *parent; /* Shared parent indirect block info */ unsigned par_entry; /* Entry in parent's table */ size_t size; /* Size of direct block */ unsigned blk_off_size; /* Size of offsets in the block */ - size_t blk_free_space; /* Total amount of free space in block */ - H5HF_direct_free_head_t *free_list; /* Pointer to free list for block */ uint8_t *blk; /* Pointer to buffer containing block data */ /* Stored values */ hsize_t block_off; /* Offset of the block within the heap's address space */ - size_t free_list_head; /* Offset of head of free list in block */ } H5HF_direct_t; /* Fractal heap */ @@ -325,50 +318,6 @@ typedef struct H5HF_stat_t { hsize_t nobjs; /* Number of objects in heap */ } H5HF_stat_t; -/* Fractal heap free list section info */ -typedef struct H5HF_free_section_t { - haddr_t sect_addr; /* Address of free list section in the file */ - /* (Not actually used as address, used as unique ID for free list node) */ - size_t sect_size; /* Size of free space section */ - /* (section size is "object size", without the metadata overhead, since metadata overhead varies from block to block) */ - /* (for range sections, this is the largest single section within the range) */ - enum { - H5HF_SECT_SINGLE, /* Section is actual bytes in a direct block */ - H5HF_SECT_OPAQUE, /* Section is an opaque # of bytes in child of an indirect block */ - H5HF_SECT_RANGE, /* Section is a range of direct blocks in an indirect block row */ - H5HF_SECT_INDIRECT} /* Section is a range of _indirect_ blocks in an indirect block row */ - type; /* Type of free space section */ - union { - struct { - H5HF_indirect_t *parent; /* Indirect block parent for free section's direct block */ - unsigned par_entry; /* Entry of free section's direct block in parent indirect block */ - /* (Needed to retrieve direct block) */ - - haddr_t dblock_addr; /* Address of direct block for free section */ - size_t dblock_size; /* Size of direct block */ - /* (Needed to retrieve direct block) */ - } single; - struct { - H5HF_indirect_t *iblock; /* Indirect block parent for free section's child block */ - unsigned entry; /* Entry of free section's child block in parent indirect block */ - } opaque; - struct { - H5HF_indirect_t *iblock; /* Indirect block for free section */ - unsigned row; /* Row for range of blocks */ - unsigned col; /* Column for range of blocks */ - unsigned num_entries; /* Number of entries covered */ - } range; - struct { - H5HF_indirect_t *iblock; /* Indirect block for free section */ - unsigned row; /* Row for range of blocks */ - unsigned col; /* Column for range of blocks */ - unsigned num_entries; /* Number of entries covered */ - unsigned indir_row; /* Row for indirect range of blocks */ - unsigned indir_nrows; /* Number of rows in indirect blocks */ - } indirect; - } u; -} H5HF_free_section_t; - /* Fractal heap "parent info" (for loading a block) */ typedef struct H5HF_parent_t { H5HF_hdr_t *hdr; /* Pointer to heap header info */ @@ -389,18 +338,21 @@ H5_DLLVAR const H5AC_class_t H5AC_FHEAP_DBLOCK[1]; /* H5HF indirect block inherits cache-like properties from H5AC */ H5_DLLVAR const H5AC_class_t H5AC_FHEAP_IBLOCK[1]; +/* H5HF single section inherits serializable properties from H5FS_section_class_t */ +H5_DLLVAR H5FS_section_class_t H5FS_SECT_CLS_FHEAP_SINGLE[1]; + +/* H5HF range section inherits serializable properties from H5FS_section_class_t */ +H5_DLLVAR H5FS_section_class_t H5FS_SECT_CLS_FHEAP_RANGE[1]; + +/* H5HF indirect section inherits serializable properties from H5FS_section_class_t */ +H5_DLLVAR H5FS_section_class_t H5FS_SECT_CLS_FHEAP_INDIRECT[1]; + /* Declare a free list to manage the H5HF_hdr_t struct */ H5FL_EXTERN(H5HF_hdr_t); /* Declare a free list to manage the H5HF_direct_t struct */ H5FL_EXTERN(H5HF_direct_t); -/* Declare a free list to manage the H5HF_direct_free_head_t struct */ -H5FL_EXTERN(H5HF_direct_free_head_t); - -/* Declare a free list to manage the H5HF_direct_free_node_t struct */ -H5FL_EXTERN(H5HF_direct_free_node_t); - /* Declare a free list to manage heap direct block data to/from disk */ H5FL_BLK_EXTERN(direct_block); @@ -434,6 +386,7 @@ H5_DLL unsigned H5HF_dtable_size_to_row(H5HF_dtable_t *dtable, size_t block_size H5_DLL herr_t H5HF_hdr_incr(H5HF_hdr_t *hdr); H5_DLL herr_t H5HF_hdr_decr(H5HF_hdr_t *hdr); H5_DLL herr_t H5HF_hdr_dirty(H5HF_hdr_t *hdr); +H5_DLL herr_t H5HF_hdr_adj_free(H5HF_hdr_t *hdr, ssize_t amt); H5_DLL herr_t H5HF_hdr_extend_heap(H5HF_hdr_t *hdr, hsize_t new_size, hsize_t extra_free); H5_DLL herr_t H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, hsize_t new_alloc_size, unsigned nentries); @@ -444,12 +397,12 @@ H5_DLL herr_t H5HF_iblock_decr(H5HF_indirect_t *iblock); H5_DLL herr_t H5HF_iblock_dirty(H5HF_indirect_t *iblock); H5_DLL H5HF_indirect_t * H5HF_man_iblock_place_dblock(H5HF_hdr_t *fh, hid_t dxpl_id, size_t min_dblock_size, size_t *entry_p, size_t *dblock_size); +H5_DLL herr_t H5HF_man_iblock_alloc_single(H5HF_hdr_t *hdr, hid_t dxpl_id, + H5HF_free_section_t *sec_node); H5_DLL herr_t H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t **sec_node); H5_DLL herr_t H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t **sec_node); -H5_DLL herr_t H5HF_man_iblock_alloc_opaque(H5HF_hdr_t *hdr, hid_t dxpl_id, - H5HF_free_section_t **sec_node); H5_DLL H5HF_indirect_t *H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, haddr_t iblock_addr, unsigned iblock_nrows, H5HF_indirect_t *par_iblock, unsigned par_entry, @@ -457,9 +410,6 @@ H5_DLL H5HF_indirect_t *H5HF_man_iblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, /* Direct block routines */ H5_DLL herr_t H5HF_man_dblock_new(H5HF_hdr_t *fh, hid_t dxpl_id, size_t request); -H5_DLL herr_t H5HF_man_dblock_build_freelist(H5HF_direct_t *dblock, haddr_t dblock_addr); -H5_DLL herr_t H5HF_man_dblock_destroy_freelist(H5HF_direct_t *dblock); -H5_DLL herr_t H5HF_man_dblock_adj_free(H5HF_direct_t *dblock, ssize_t amt); H5_DLL herr_t H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblock, unsigned par_entry, size_t block_size, hsize_t block_off, haddr_t *addr_p, H5HF_free_section_t **ret_sec_node); @@ -471,6 +421,9 @@ H5_DLL H5HF_direct_t *H5HF_man_dblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id, /* Routines for internal operations */ H5_DLL herr_t H5HF_free_section_free_cb(void *item, void UNUSED *key, void UNUSED *op_data); +H5_DLL herr_t H5HF_man_locate_block(H5HF_hdr_t *hdr, hid_t dxpl_id, + hsize_t obj_off, hbool_t locate_indirect, H5HF_indirect_t **par_iblock, + unsigned *par_entry, H5AC_protect_t rw); H5_DLL herr_t H5HF_man_find(H5HF_hdr_t *fh, hid_t dxpl_id, size_t request, H5HF_free_section_t **sec_node/*out*/); H5_DLL herr_t H5HF_man_insert(H5HF_hdr_t *fh, hid_t dxpl_id, @@ -480,7 +433,7 @@ H5_DLL herr_t H5HF_man_read(H5HF_hdr_t *fh, hid_t dxpl_id, hsize_t obj_off, size_t obj_len, void *obj); /* Metadata cache callbacks */ -H5_DLL herr_t H5HF_cache_hdr_dest(H5F_t *f, H5HF_hdr_t *fh); +H5_DLL herr_t H5HF_cache_hdr_dest(H5F_t *f, H5HF_hdr_t *hdr); H5_DLL herr_t H5HF_cache_dblock_dest(H5F_t *f, H5HF_direct_t *dblock); H5_DLL herr_t H5HF_cache_iblock_dest(H5F_t *f, H5HF_indirect_t *iblock); @@ -495,16 +448,6 @@ H5_DLL herr_t H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, /* Statistics routines */ H5_DLL herr_t H5HF_stat_info(H5HF_t *fh, H5HF_stat_t *stats); -/* Free list routines */ -H5_DLL H5HF_freelist_t * H5HF_flist_create(unsigned max_index_bits, - H5SL_operator_t node_free_op); -H5_DLL herr_t H5HF_flist_add(H5HF_freelist_t *flist, void *node, size_t *size_key, - haddr_t *addr_key); -H5_DLL htri_t H5HF_flist_find(H5HF_freelist_t *flist, size_t request, - void **node); -H5_DLL herr_t H5HF_flist_reset(H5HF_freelist_t *flist); -H5_DLL herr_t H5HF_flist_free(H5HF_freelist_t *flist); - /* Block iteration routines */ H5_DLL herr_t H5HF_man_iter_init(H5HF_block_iter_t *biter); H5_DLL herr_t H5HF_man_iter_start_offset(H5HF_hdr_t *hdr, hid_t dxpl_id, @@ -523,10 +466,18 @@ H5_DLL herr_t H5HF_man_iter_offset(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter, hsize_t *offset); H5_DLL hbool_t H5HF_man_iter_ready(H5HF_block_iter_t *biter); +/* Free space manipulation routines */ +H5_DLL herr_t H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id); +H5_DLL htri_t H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, + H5HF_free_section_t **node); +H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node); +H5_DLL herr_t H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id); + /* Testing routines */ #ifdef H5HF_TESTING H5_DLL herr_t H5HF_get_cparam_test(H5HF_t *fh, H5HF_create_t *cparam); H5_DLL hsize_t H5HF_get_dblock_free_test(H5HF_t *fh, unsigned row); +H5_DLL size_t H5HF_get_dblock_overhead(H5HF_t *fh); #endif /* H5HF_TESTING */ #endif /* _H5HFpkg_H */ diff --git a/src/H5HFprivate.h b/src/H5HFprivate.h index 455f426..d6b1e15 100644 --- a/src/H5HFprivate.h +++ b/src/H5HFprivate.h @@ -80,13 +80,20 @@ typedef struct H5HF_t H5HF_t; /***************************************/ H5_DLL H5HF_t *H5HF_create(H5F_t *f, hid_t dxpl_id, H5HF_create_t *cparam); H5_DLL H5HF_t *H5HF_open(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr); -H5_DLL herr_t H5HF_get_id_len(H5HF_t *fh, size_t *id_len_p); +H5_DLL herr_t H5HF_get_id_len(H5HF_t *fh, size_t *id_len_p/*out*/); H5_DLL herr_t H5HF_get_heap_addr(H5HF_t *fh, haddr_t *heap_addr); H5_DLL herr_t H5HF_insert(H5HF_t *fh, hid_t dxpl_id, size_t size, const void *obj, void *id/*out*/); +H5_DLL herr_t H5HF_get_obj_len(H5HF_t *fh, const void *id, size_t *obj_len_p/*out*/); H5_DLL herr_t H5HF_read(H5HF_t *fh, hid_t dxpl_id, const void *id, void *obj/*out*/); -H5_DLL herr_t H5HF_close(H5HF_t *fh); +H5_DLL herr_t H5HF_close(H5HF_t *fh, hid_t dxpl_id); + +/* Debugging routines */ +#ifdef H5HF_DEBUGGING +H5_DLL herr_t H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, + FILE *stream, int indent, int fwidth); +#endif /* H5HF_DEBUGGING */ #endif /* _H5HFprivate_H */ diff --git a/src/H5HFsection.c b/src/H5HFsection.c new file mode 100644 index 0000000..6cbe4cb --- /dev/null +++ b/src/H5HFsection.c @@ -0,0 +1,595 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> + * Monday, May 1, 2006 + * + * Purpose: Free space section routines for fractal heaps. + * + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HF_PACKAGE /*suppress error about including H5HFpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HFpkg.h" /* Fractal heaps */ + +/****************/ +/* Local Macros */ +/****************/ + + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ +static herr_t H5HF_sect_single_deserialize(H5FS_section_class_t *sect_cls, + const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + H5FS_section_info_t **sect); +static herr_t H5HF_sect_range_init(H5FS_section_class_t *cls, const void *udata); +static herr_t H5HF_sect_range_serialize(const H5FS_section_info_t *sect, uint8_t *buf); +static herr_t H5HF_sect_range_deserialize(H5FS_section_class_t *sect_cls, + const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + H5FS_section_info_t **sect); +static herr_t H5HF_sect_range_debug(const H5FS_section_info_t *sect, + FILE *stream, int indent, int fwidth); +static herr_t H5HF_sect_indirect_init(H5FS_section_class_t *cls, const void *udata); +static herr_t H5HF_sect_indirect_serialize(const H5FS_section_info_t *sect, uint8_t *buf); +static herr_t H5HF_sect_indirect_deserialize(H5FS_section_class_t *sect_cls, + const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + H5FS_section_info_t **sect); +static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect, + FILE *stream, int indent, int fwidth); + + +/*********************/ +/* Package Variables */ +/*********************/ + +/* Class info for "single" free space sections */ +/* (No callbacks necessary) */ +H5FS_section_class_t H5FS_SECT_CLS_FHEAP_SINGLE[1] = {{ + H5FS_SECT_FHEAP_SINGLE, + 0, + NULL, + NULL, + H5HF_sect_single_deserialize, + NULL, +}}; + +/* Class info for "range" free space sections */ +H5FS_section_class_t H5FS_SECT_CLS_FHEAP_RANGE[1] = {{ + H5FS_SECT_FHEAP_RANGE, + 0, + H5HF_sect_range_init, + H5HF_sect_range_serialize, + H5HF_sect_range_deserialize, + H5HF_sect_range_debug, +}}; + +/* Class info for "indirect" free space sections */ +H5FS_section_class_t H5FS_SECT_CLS_FHEAP_INDIRECT[1] = {{ + H5FS_SECT_FHEAP_INDIRECT, + 0, + H5HF_sect_indirect_init, + H5HF_sect_indirect_serialize, + H5HF_sect_indirect_deserialize, + H5HF_sect_indirect_debug, +}}; + +/* 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_free_section_free_cb + * + * Purpose: Free a free section node + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, March 13, 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_free_section_free_cb(void *_sect, void UNUSED *key, void UNUSED *op_data) +{ + H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; + herr_t ret_value = 0; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_free_section_free_cb) + + HDassert(sect); + + /* Check for live reference to an indirect block */ + if(sect->sect_info.state == H5FS_SECT_LIVE) { + H5HF_indirect_t *iblock; /* Indirect block referenced */ + + /* Find indirect block that free section references */ + switch(sect->sect_info.cls->type) { + case H5FS_SECT_FHEAP_SINGLE: + iblock = sect->u.single.parent; + break; + + case H5FS_SECT_FHEAP_RANGE: + iblock = sect->u.range.iblock; + break; + + case H5FS_SECT_FHEAP_INDIRECT: + iblock = sect->u.indirect.iblock; + break; + } /* end switch */ + + /* 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 shared indirect block") + } /* end if */ + + /* Release the sections */ + H5FL_FREE(H5HF_free_section_t, sect); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_free_section_free_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_node_alloc + * + * 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 herr_t +H5HF_sect_node_alloc(H5FS_section_class_t *sect_cls, unsigned sect_type, + haddr_t sect_addr, hsize_t sect_size, H5FS_section_info_t **sect) +{ + H5HF_free_section_t *new_sect; /* New section */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_node_alloc) + + /* Check arguments. */ + HDassert(H5F_addr_defined(sect_addr)); + HDassert(sect_size); + HDassert(sect); + + /* Create free list section node */ + if(NULL == (new_sect = H5FL_MALLOC(H5HF_free_section_t))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "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.cls = §_cls[sect_type]; + new_sect->sect_info.state = H5FS_SECT_SERIALIZED; + + /* Update the return parameter */ + *sect = (H5FS_section_info_t *)new_sect; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_node_alloc() */ + + +/*------------------------------------------------------------------------- + * 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 herr_t +H5HF_sect_single_deserialize(H5FS_section_class_t *sect_cls, + const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + H5FS_section_info_t **sect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_deserialize) + + /* Check arguments. */ + HDassert(buf); + HDassert(H5F_addr_defined(sect_addr)); + HDassert(sect_size); + HDassert(sect); + + /* Create free list section node */ + if(H5HF_sect_node_alloc(sect_cls, H5FS_SECT_FHEAP_SINGLE, sect_addr, sect_size, sect) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for direct block free list section") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_single_deserialize() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_range_init + * + * Purpose: Initialize the "range" class structure + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 1, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_range_init(H5FS_section_class_t *cls, const void UNUSED *udata) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_init) + + /* Check arguments. */ + HDassert(cls); + + /* Set the size of all serialized objects of this class of sections */ + cls->serial_size = 2 /* Row */ + + 2 /* Column */ + + 2; /* # of entries */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HF_sect_range_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_range_serialize + * + * Purpose: Serialize a "live" range section into a buffer + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 1, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_range_serialize(const H5FS_section_info_t *_sect, uint8_t *buf) +{ + const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_serialize) + + /* Check arguments. */ + HDassert(buf); + HDassert(sect); + + /* Range's row */ + UINT16ENCODE(buf, sect->u.range.row); + + /* Range's column */ + UINT16ENCODE(buf, sect->u.range.col); + + /* Range's # of entries */ + UINT16ENCODE(buf, sect->u.range.num_entries); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HF_sect_range_serialize() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_range_deserialize + * + * Purpose: Deserialize a buffer into a "live" range section + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 1, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_range_deserialize(H5FS_section_class_t *sect_cls, + const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + H5FS_section_info_t **sect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_deserialize) + + /* Check arguments. */ + HDassert(buf); + HDassert(H5F_addr_defined(sect_addr)); + HDassert(sect_size); + HDassert(sect); + + /* Create free list section node */ + if(H5HF_sect_node_alloc(sect_cls, H5FS_SECT_FHEAP_RANGE, sect_addr, sect_size, sect) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for direct block free list section") + + /* Range's row */ + UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.row); + + /* Range's column */ + UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.col); + + /* Range's # of entries */ + UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.num_entries); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_range_deserialize() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_range_debug + * + * Purpose: Dump debugging information about an range free space section + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Saturday, May 13, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_range_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_NOFUNC(H5HF_sect_range_debug) + + /* Check arguments. */ + HDassert(sect); + + /* Print range section information */ + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Row:", + sect->u.range.row); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Column:", + sect->u.range.col); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Number of entries:", + sect->u.range.num_entries); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HF_sect_range_debug() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_init + * + * Purpose: Initialize the "indirect" class structure + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 1, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_init(H5FS_section_class_t *cls, const void UNUSED *udata) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_init) + + /* Check arguments. */ + HDassert(cls); + + /* Set the size of all serialized objects of this class of sections */ + cls->serial_size = 2 /* Row */ + + 2 /* Column */ + + 2 /* # of entries */ + + 2 /* Indirect row */ + + 2; /* Indirect # of rows */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HF_sect_indirect_init() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_serialize + * + * Purpose: Serialize a "live" indirect section into a buffer + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Monday, May 1, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_serialize(const H5FS_section_info_t *_sect, uint8_t *buf) +{ + const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_indirect_serialize) + + /* Check arguments. */ + HDassert(buf); + HDassert(_sect); + + /* Range's row */ + UINT16ENCODE(buf, sect->u.indirect.row); + + /* Range's column */ + UINT16ENCODE(buf, sect->u.indirect.col); + + /* Range's # of entries */ + UINT16ENCODE(buf, sect->u.indirect.num_entries); + + /* Range's indirect row */ + UINT16ENCODE(buf, sect->u.indirect.indir_row); + + /* Range's indirect # of rows */ + UINT16ENCODE(buf, sect->u.indirect.indir_nrows); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* 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, May 1, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_deserialize(H5FS_section_class_t *sect_cls, + const uint8_t *buf, haddr_t sect_addr, hsize_t sect_size, + H5FS_section_info_t **sect) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_deserialize) + + /* Check arguments. */ + HDassert(buf); + HDassert(H5F_addr_defined(sect_addr)); + HDassert(sect_size); + HDassert(sect); + + /* Create free list section node */ + if(H5HF_sect_node_alloc(sect_cls, H5FS_SECT_FHEAP_INDIRECT, sect_addr, sect_size, sect) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "allocation failed for direct block free list section") + + /* Range's row */ + UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.row); + + /* Range's column */ + UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.col); + + /* Range's # of entries */ + UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.num_entries); + + /* Range's indirect row */ + UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.indir_row); + + /* Range's indirect # of rows */ + UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.indir_nrows); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_sect_indirect_deserialize() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_sect_indirect_debug + * + * Purpose: Dump debugging information about an indirect free space section + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * Saturday, May 13, 2006 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5HF_sect_indirect_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_NOFUNC(H5HF_sect_indirect_debug) + + /* 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); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Indirect row:", + sect->u.indirect.indir_row); + HDfprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, + "Indirect number of rows:", + sect->u.indirect.indir_nrows); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* H5HF_sect_indirect_debug() */ + diff --git a/src/H5HFspace.c b/src/H5HFspace.c new file mode 100644 index 0000000..7f68817 --- /dev/null +++ b/src/H5HFspace.c @@ -0,0 +1,291 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*------------------------------------------------------------------------- + * + * Created: H5HFspace.c + * May 2 2006 + * Quincey Koziol <koziol@ncsa.uiuc.edu> + * + * Purpose: Space allocation routines for fractal heaps. + * + *------------------------------------------------------------------------- + */ + +/****************/ +/* Module Setup */ +/****************/ + +#define H5HF_PACKAGE /*suppress error about including H5HFpkg */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5HFpkg.h" /* Fractal heaps */ + + +/****************/ +/* Local Macros */ +/****************/ + +#define H5HF_FSPACE_SHRINK 80 /* Percent of "normal" size to shrink serialized free space size */ +#define H5HF_FSPACE_EXPAND 120 /* Percent of "normal" size to expand serialized free space size */ + +/******************/ +/* Local Typedefs */ +/******************/ + + +/********************/ +/* Package Typedefs */ +/********************/ + + +/********************/ +/* Local Prototypes */ +/********************/ + + +/*********************/ +/* Package Variables */ +/*********************/ + + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + + +/*******************/ +/* Local Variables */ +/*******************/ + + + +/*------------------------------------------------------------------------- + * Function: H5HF_space_start + * + * Purpose: "Start up" free space for heap - open existing free space + * structure if one exists, otherwise create a new free space + * structure + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id) +{ + const H5FS_section_class_t *classes[] = { /* Free space section classes implemented for fractal heap */ + H5FS_SECT_CLS_FHEAP_SINGLE, + H5FS_SECT_CLS_FHEAP_RANGE, + H5FS_SECT_CLS_FHEAP_INDIRECT}; + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_space_start) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Allocate space for the section classes for the free list management code to use */ + hdr->nsect_classes = NELMTS(classes); + if(NULL == (hdr->sect_cls = H5FL_SEQ_MALLOC(H5FS_section_class_t, hdr->nsect_classes))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for free space section class array ") + + /* Copy the section classes for this heap */ + /* (Initialization calls will be performed by the free list code) */ + for(u = 0; u < hdr->nsect_classes; u++) { + /* Make certain that section class type can be used as an array index into this array */ + HDassert(u == classes[u]->type); + + HDmemcpy(&hdr->sect_cls[u], classes[u], sizeof(H5FS_section_class_t)); + } /* end for */ + + /* Check for creating free space info for the heap */ + if(H5F_addr_defined(hdr->fs_addr)) { + /* Open an existing free space structure for the heap */ + if(NULL == (hdr->fspace = H5FS_open(hdr->f, dxpl_id, hdr->fs_addr, + H5HF_free_section_free_cb, hdr->nsect_classes, hdr->sect_cls, hdr))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info") + } /* end if */ + else { + H5FS_create_t fs_create; /* Free space creation parameters */ + + /* Set the free space creation parameters */ + fs_create.client = H5FS_CLIENT_FHEAP_ID; + fs_create.shrink_percent = H5HF_FSPACE_SHRINK; + fs_create.expand_percent = H5HF_FSPACE_EXPAND; + fs_create.max_sect_size = hdr->man_dtable.cparam.max_direct_size; + fs_create.max_sect_addr = hdr->man_dtable.cparam.max_index; + + /* Create the free space structure for the heap */ + if(NULL == (hdr->fspace = H5FS_create(hdr->f, dxpl_id, &hdr->fs_addr, + &fs_create, H5HF_free_section_free_cb, + hdr->nsect_classes, hdr->sect_cls, hdr))) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info") + } /* end else */ + + /* Free space for heap is now open */ + hdr->fspace_open = TRUE; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_start() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_space_find + * + * Purpose: Attempt to find space in a fractal heap + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +htri_t +H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_section_t **node) +{ + htri_t node_found; /* Whether an existing free list node was found */ + htri_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_space_find) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(request); + HDassert(node); + + /* Check if the free space for the heap has been initialized */ + if(!hdr->fspace_open) + if(H5HF_space_start(hdr, dxpl_id) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space") + + /* Search for free space in the heap */ + if((node_found = H5FS_find(hdr->f, dxpl_id, hdr->fspace, request, (H5FS_section_info_t **)node)) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't locate free space in fractal heap") + + /* Set return value */ + ret_value = node_found; + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_find() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_space_add + * + * Purpose: Add a section to the free space for the heap + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_space_add) + + /* + * Check arguments. + */ + HDassert(hdr); + HDassert(node); + HDassert(hdr->fspace_open); + HDassert(hdr->fspace); + + /* Add to the free space for the heap */ + if(H5FS_add(hdr->f, dxpl_id, hdr->fspace, (H5FS_section_info_t *)node) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't add section to heap free space") + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_add() */ + + +/*------------------------------------------------------------------------- + * Function: H5HF_space_close + * + * Purpose: Close the free space for the heap + * + * Return: Success: non-negative + * + * Failure: negative + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * May 2 2006 + * + *------------------------------------------------------------------------- + */ +herr_t +H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id) +{ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5HF_space_close) + + /* + * Check arguments. + */ + HDassert(hdr); + + /* Check if the free space was ever opened */ + if(hdr->fspace_open) { + /* Sanity check */ + HDassert(hdr->fspace); + + /* Close the free space for the heap */ + if(H5FS_close(hdr->f, dxpl_id, hdr->fspace) < 0) + HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release free space info") + hdr->fspace = NULL; + + /* Release the memory for the free space section classes */ + H5FL_SEQ_FREE(H5FS_section_class_t, hdr->sect_cls); + + /* Free space is now closed */ + hdr->fspace_open = FALSE; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5HF_space_close() */ + diff --git a/src/H5HFtest.c b/src/H5HFtest.c index 4b627fd..2327fe6 100644 --- a/src/H5HFtest.c +++ b/src/H5HFtest.c @@ -132,3 +132,34 @@ H5HF_get_dblock_free_test(H5HF_t *fh, unsigned row) FUNC_LEAVE_NOAPI(ret_value) } /* H5HF_get_dblock_free_test() */ + +/*------------------------------------------------------------------------- + * Function: H5HF_get_dblock_overhead + * + * Purpose: Retrieve the size of direct block overhead + * + * Return: Success: Size of direct block overhead + * + * Failure: 0 + * + * Programmer: Quincey Koziol + * Tuesday, May 9, 2006 + * + *------------------------------------------------------------------------- + */ +size_t +H5HF_get_dblock_overhead(H5HF_t *fh) +{ + size_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_dblock_overhead) + + /* Check arguments. */ + HDassert(fh); + + /* Return direct block overhead */ + ret_value = H5HF_MAN_ABS_DIRECT_OVERHEAD(fh->hdr); + + FUNC_LEAVE_NOAPI(ret_value) +} /* H5HF_get_dblock_overhead() */ + diff --git a/src/H5err.txt b/src/H5err.txt index 014e7a7..91cdb95 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -70,6 +70,7 @@ MAJOR, H5E_TST, Ternary Search Trees MAJOR, H5E_RS, Reference Counted Strings MAJOR, H5E_ERROR, Error API MAJOR, H5E_SLIST, Skip Lists +MAJOR, H5E_FSPACE, File Free Space MAJOR, H5E_NONE_MAJOR, No error # Sections (for grouping minor errors) diff --git a/src/H5private.h b/src/H5private.h index 5ae7baf..39971eb 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -1436,6 +1436,7 @@ H5_DLL int H5AC_term_interface(void); H5_DLL int H5D_term_interface(void); H5_DLL int H5E_term_interface(void); H5_DLL int H5F_term_interface(void); +H5_DLL int H5FS_term_interface(void); H5_DLL int H5G_term_interface(void); H5_DLL int H5I_term_interface(void); H5_DLL int H5P_term_interface(void); diff --git a/src/Makefile.am b/src/Makefile.am index 0d01ec2..da84780 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -51,13 +51,15 @@ libhdf5_la_SOURCES= H5.c H5dbg.c H5A.c H5AC.c H5B.c H5Bcache.c \ H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ H5FDstream.c H5FL.c H5FO.c \ + H5FS.c H5FScache.c H5FSdbg.c \ H5G.c H5Gent.c H5Glink.c H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c \ H5Goh.c \ H5Gstab.c \ H5Gtest.c \ H5Gtraverse.c \ - H5HF.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c H5HFflist.c \ - H5HFhdr.c H5HFiblock.c H5HFint.c H5HFiter.c H5HFstat.c H5HFtest.c \ + H5HF.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \ + H5HFhdr.c H5HFiblock.c H5HFint.c H5HFiter.c H5HFsection.c \ + H5HFspace.c H5HFstat.c H5HFtest.c \ H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ H5MP.c H5MPtest.c \ H5O.c \ diff --git a/src/Makefile.in b/src/Makefile.in index 858fd9c..d930a2f 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -90,27 +90,27 @@ am_libhdf5_la_OBJECTS = H5.lo H5dbg.lo H5A.lo H5AC.lo H5B.lo \ H5Fmount.lo H5Fsfile.lo H5Fsuper.lo H5FD.lo H5FDcore.lo \ H5FDfamily.lo H5FDlog.lo H5FDmpi.lo H5FDmpio.lo \ H5FDmpiposix.lo H5FDmulti.lo H5FDsec2.lo H5FDstdio.lo \ - H5FDstream.lo H5FL.lo H5FO.lo H5G.lo H5Gent.lo H5Glink.lo \ + H5FDstream.lo H5FL.lo H5FO.lo H5FS.lo H5FScache.lo H5FSdbg.lo H5G.lo H5Gent.lo H5Glink.lo \ H5Gloc.lo H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Gstab.lo \ H5Gtest.lo H5Gtraverse.lo H5HF.lo H5HFcache.lo H5HFdbg.lo \ - H5HFdblock.lo H5HFdtable.lo H5HFflist.lo H5HFhdr.lo \ - H5HFiblock.lo H5HFint.lo H5HFiter.lo H5HFstat.lo H5HFtest.lo \ - H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo H5HP.lo H5I.lo H5MF.lo \ - H5MM.lo H5MP.lo H5MPtest.lo H5O.lo H5Oattr.lo H5Obogus.lo \ - H5Ocache.lo H5Ocont.lo H5Odtype.lo H5Oefl.lo H5Ofill.lo \ - H5Oginfo.lo H5Olayout.lo H5Olinfo.lo H5Olink.lo H5Omtime.lo \ - H5Oname.lo H5Onull.lo H5Opline.lo H5Osdspace.lo H5Oshared.lo \ - H5Ostab.lo H5P.lo H5Pacpl.lo H5Pdcpl.lo H5Pdxpl.lo H5Pfapl.lo \ - H5Pfcpl.lo H5Pgcpl.lo H5Pocpl.lo H5Ptest.lo H5R.lo H5RC.lo \ - H5RS.lo H5S.lo H5Sall.lo H5Shyper.lo H5Smpio.lo H5Snone.lo \ - H5Spoint.lo H5Sselect.lo H5Stest.lo H5SL.lo H5ST.lo H5T.lo \ - H5Tarray.lo H5Tbit.lo H5Tcommit.lo H5Tcompound.lo H5Tconv.lo \ - H5Tcset.lo H5Tenum.lo H5Tfields.lo H5Tfixed.lo H5Tfloat.lo \ - H5Tinit.lo H5Tnative.lo H5Toffset.lo H5Toh.lo H5Topaque.lo \ - H5Torder.lo H5Tpad.lo H5Tprecis.lo H5Tstrpad.lo H5Tvlen.lo \ - H5TS.lo H5V.lo H5Z.lo H5Zdeflate.lo H5Zfletcher32.lo \ - H5Znbit.lo H5Zshuffle.lo H5Zszip.lo H5Zscaleoffset.lo \ - H5Ztrans.lo + H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo \ + H5HFiblock.lo H5HFint.lo H5HFiter.lo H5HFsection.lo \ + H5HFspace.lo H5HFstat.lo H5HFtest.lo H5HG.lo H5HGdbg.lo H5HL.lo H5HLdbg.lo \ + H5HP.lo H5I.lo H5MF.lo H5MM.lo H5MP.lo H5MPtest.lo H5O.lo \ + H5Oattr.lo H5Obogus.lo H5Ocache.lo H5Ocont.lo H5Odtype.lo \ + H5Oefl.lo H5Ofill.lo H5Oginfo.lo H5Olayout.lo H5Olinfo.lo \ + H5Olink.lo H5Omtime.lo H5Oname.lo H5Onull.lo H5Opline.lo \ + H5Osdspace.lo H5Oshared.lo H5Ostab.lo H5P.lo H5Pacpl.lo \ + H5Pdcpl.lo H5Pdxpl.lo H5Pfapl.lo H5Pfcpl.lo H5Pgcpl.lo \ + H5Pocpl.lo H5Ptest.lo H5R.lo H5RC.lo H5RS.lo H5S.lo H5Sall.lo \ + H5Shyper.lo H5Smpio.lo H5Snone.lo H5Spoint.lo H5Sselect.lo \ + H5Stest.lo H5SL.lo H5ST.lo H5T.lo H5Tarray.lo H5Tbit.lo \ + H5Tcommit.lo H5Tcompound.lo H5Tconv.lo H5Tcset.lo H5Tenum.lo \ + H5Tfields.lo H5Tfixed.lo H5Tfloat.lo H5Tinit.lo H5Tnative.lo \ + H5Toffset.lo H5Toh.lo H5Topaque.lo H5Torder.lo H5Tpad.lo \ + H5Tprecis.lo H5Tstrpad.lo H5Tvlen.lo H5TS.lo H5V.lo H5Z.lo \ + H5Zdeflate.lo H5Zfletcher32.lo H5Znbit.lo H5Zshuffle.lo \ + H5Zszip.lo H5Zscaleoffset.lo H5Ztrans.lo libhdf5_la_OBJECTS = $(am_libhdf5_la_OBJECTS) PROGRAMS = $(noinst_PROGRAMS) H5detect_SOURCES = H5detect.c @@ -407,13 +407,15 @@ libhdf5_la_SOURCES = H5.c H5dbg.c H5A.c H5AC.c H5B.c H5Bcache.c \ H5FDfamily.c H5FDlog.c H5FDmpi.c H5FDmpio.c \ H5FDmpiposix.c H5FDmulti.c H5FDsec2.c H5FDstdio.c \ H5FDstream.c H5FL.c H5FO.c \ + H5FS.c H5FScache.c H5FSdbg.c \ H5G.c H5Gent.c H5Glink.c H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c \ H5Goh.c \ H5Gstab.c \ H5Gtest.c \ H5Gtraverse.c \ - H5HF.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c H5HFflist.c \ - H5HFhdr.c H5HFiblock.c H5HFint.c H5HFiter.c H5HFstat.c H5HFtest.c \ + H5HF.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \ + H5HFhdr.c H5HFiblock.c H5HFint.c H5HFiter.c H5HFsection.c \ + H5HFspace.c H5HFstat.c H5HFtest.c \ H5HG.c H5HGdbg.c H5HL.c H5HLdbg.c H5HP.c H5I.c H5MF.c H5MM.c \ H5MP.c H5MPtest.c \ H5O.c \ @@ -608,6 +610,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fmount.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsfile.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Fsuper.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FS.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FScache.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5FSdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5G.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Glink.Plo@am__quote@ @@ -624,11 +629,12 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdbg.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdblock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFdtable.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFflist.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFhdr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFiblock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFint.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFiter.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFsection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFspace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFstat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HFtest.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5HG.Plo@am__quote@ |