summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5Edefin.h2
-rw-r--r--src/H5Einit.h10
-rw-r--r--src/H5Epubgen.h4
-rw-r--r--src/H5Eterm.h4
-rw-r--r--src/H5FS.c379
-rw-r--r--src/H5FSdbg.c39
-rw-r--r--src/H5FSpkg.h28
-rw-r--r--src/H5FSprivate.h43
-rw-r--r--src/H5HF.c10
-rw-r--r--src/H5HFcache.c45
-rw-r--r--src/H5HFdbg.c20
-rw-r--r--src/H5HFdblock.c184
-rw-r--r--src/H5HFdtable.c39
-rw-r--r--src/H5HFhdr.c766
-rw-r--r--src/H5HFiblock.c1107
-rw-r--r--src/H5HFint.c91
-rw-r--r--src/H5HFiter.c113
-rw-r--r--src/H5HFpkg.h101
-rw-r--r--src/H5HFprivate.h14
-rw-r--r--src/H5HFsection.c1126
-rw-r--r--src/H5HFspace.c56
-rw-r--r--src/H5HFstat.c4
-rw-r--r--src/H5HFtest.c121
-rw-r--r--src/H5err.txt2
24 files changed, 2918 insertions, 1390 deletions
diff --git a/src/H5Edefin.h b/src/H5Edefin.h
index d10ec5f..f297a50 100644
--- a/src/H5Edefin.h
+++ b/src/H5Edefin.h
@@ -74,6 +74,8 @@ hid_t H5E_CANTGETSIZE_g = FAIL; /* Unable to compute size */
hid_t H5E_CANTRESTORE_g = FAIL; /* Can't restore condition */
hid_t H5E_CANTCOMPUTE_g = FAIL; /* Can't compute value */
hid_t H5E_CANTEXTEND_g = FAIL; /* Can't extend heap's space */
+hid_t H5E_CANTATTACH_g = FAIL; /* Can't attach object */
+hid_t H5E_CANTUPDATE_g = FAIL; /* Can't update object */
/* Function entry/exit interface errors */
hid_t H5E_CANTINIT_g = FAIL; /* Unable to initialize object */
diff --git a/src/H5Einit.h b/src/H5Einit.h
index c6909d2..aedbac3 100644
--- a/src/H5Einit.h
+++ b/src/H5Einit.h
@@ -264,6 +264,16 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't extend heap's space"))==NULL)
HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
if((H5E_CANTEXTEND_g = H5I_register(H5I_ERROR_MSG, msg))<0)
HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
+assert(H5E_CANTATTACH_g==(-1));
+if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't attach object"))==NULL)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
+if((H5E_CANTATTACH_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
+assert(H5E_CANTUPDATE_g==(-1));
+if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't update object"))==NULL)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed")
+if((H5E_CANTUPDATE_g = H5I_register(H5I_ERROR_MSG, msg))<0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message")
/* Function entry/exit interface errors */
assert(H5E_CANTINIT_g==(-1));
diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h
index 01ed436..b989db7 100644
--- a/src/H5Epubgen.h
+++ b/src/H5Epubgen.h
@@ -122,9 +122,13 @@ H5_DLLVAR hid_t H5E_CANTGETSIZE_g; /* Unable to compute size */
#define H5E_CANTRESTORE (H5OPEN H5E_CANTRESTORE_g)
#define H5E_CANTCOMPUTE (H5OPEN H5E_CANTCOMPUTE_g)
#define H5E_CANTEXTEND (H5OPEN H5E_CANTEXTEND_g)
+#define H5E_CANTATTACH (H5OPEN H5E_CANTATTACH_g)
+#define H5E_CANTUPDATE (H5OPEN H5E_CANTUPDATE_g)
H5_DLLVAR hid_t H5E_CANTRESTORE_g; /* Can't restore condition */
H5_DLLVAR hid_t H5E_CANTCOMPUTE_g; /* Can't compute value */
H5_DLLVAR hid_t H5E_CANTEXTEND_g; /* Can't extend heap's space */
+H5_DLLVAR hid_t H5E_CANTATTACH_g; /* Can't attach object */
+H5_DLLVAR hid_t H5E_CANTUPDATE_g; /* Can't update object */
/* Function entry/exit interface errors */
#define H5E_CANTINIT (H5OPEN H5E_CANTINIT_g)
diff --git a/src/H5Eterm.h b/src/H5Eterm.h
index 1643db9..c2c206e 100644
--- a/src/H5Eterm.h
+++ b/src/H5Eterm.h
@@ -75,7 +75,9 @@ H5E_CANTGETSIZE_g=
/* Heap errors */
H5E_CANTRESTORE_g=
H5E_CANTCOMPUTE_g=
-H5E_CANTEXTEND_g=
+H5E_CANTEXTEND_g=
+H5E_CANTATTACH_g=
+H5E_CANTUPDATE_g=
/* Function entry/exit interface errors */
H5E_CANTINIT_g=
diff --git a/src/H5FS.c b/src/H5FS.c
index 8e6763e..87fb4dd 100644
--- a/src/H5FS.c
+++ b/src/H5FS.c
@@ -71,12 +71,6 @@ typedef struct H5FS_node_t {
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 */
@@ -102,28 +96,6 @@ typedef struct {
/* 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 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_t *merge_list; /* Skip list to hold sections for detecting merges */
- H5FS_bin_t *bins; /* Array of lists of lists of free sections */
-};
-
/********************/
/* Local Prototypes */
@@ -133,9 +105,8 @@ static herr_t H5FS_open_remove(H5FS_t *fspace);
static herr_t H5FS_init(H5FS_t *fspace);
static herr_t H5FS_sect_free_cb(void *item, void *key, void *op_data);
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 herr_t H5FS_sect_increase(H5FS_t *fspace);
+static herr_t H5FS_sect_decrease(H5FS_t *fspace);
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);
@@ -367,7 +338,7 @@ H5FS_init(H5FS_t *fspace)
*/
H5FS_t *
H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_create,
- size_t nclasses, H5FS_section_class_t *classes, const void *cls_init_udata)
+ size_t nclasses, const 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 */
@@ -390,10 +361,17 @@ H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr, const H5FS_create_t *fs_c
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space free list")
/* Set immutable free list parameters */
- fspace->sect_cls = classes;
+ if(NULL == (fspace->sect_cls = H5FL_SEQ_MALLOC(H5FS_section_class_t, nclasses)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space section class array ")
/* Initialize the section classes for this free space list */
for(u = 0; u < nclasses; u++) {
+ /* Make certain that section class type can be used as an array index into this array */
+ HDassert(u == classes[u]->type);
+
+ /* Copy the class information into the free space manager */
+ HDmemcpy(&fspace->sect_cls[u], classes[u], sizeof(H5FS_section_class_t));
+
/* Call the class initialization routine, if there is one */
if(fspace->sect_cls[u].init_cls)
if((fspace->sect_cls[u].init_cls)(&fspace->sect_cls[u], cls_init_udata) < 0)
@@ -495,7 +473,7 @@ done:
*/
H5FS_t *
H5FS_open(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr, size_t nclasses,
- H5FS_section_class_t *classes, const void *cls_init_udata)
+ const 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 */
@@ -532,10 +510,17 @@ HDfprintf(stderr, "%s: Opening free space manager\n", FUNC);
/* Set immutable free list parameters */
fspace->addr = fs_addr;
HDassert(fspace->hdr->nclasses == nclasses);
- fspace->sect_cls = classes;
+ if(NULL == (fspace->sect_cls = H5FL_SEQ_MALLOC(H5FS_section_class_t, nclasses)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for free space section class array ")
/* Initialize the section classes for this free space list */
for(u = 0; u < nclasses; u++) {
+ /* Make certain that section class type can be used as an array index into this array */
+ HDassert(u == classes[u]->type);
+
+ /* Copy the class information into the free space manager */
+ HDmemcpy(&fspace->sect_cls[u], classes[u], sizeof(H5FS_section_class_t));
+
/* Call the class initialization routine, if there is one */
if(fspace->sect_cls[u].init_cls)
if((fspace->sect_cls[u].init_cls)(&fspace->sect_cls[u], cls_init_udata) < 0)
@@ -601,14 +586,11 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
+H5FS_sect_increase(H5FS_t *fspace)
{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_increase)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_increase)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->hdr);
@@ -618,8 +600,7 @@ H5FS_sect_increase(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
/* Update the free space sections' serialized size */
fspace->hdr->sect_size = H5FS_serialize_size(fspace);
-done:
- FUNC_LEAVE_NOAPI(ret_value)
+ FUNC_LEAVE_NOAPI(SUCCEED)
} /* H5FS_sect_increase() */
@@ -639,14 +620,13 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_decrease(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
+H5FS_sect_decrease(H5FS_t *fspace)
{
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5FS_sect_decrease)
/* Check arguments. */
- HDassert(f);
HDassert(fspace);
HDassert(fspace->hdr);
@@ -884,14 +864,15 @@ H5FS_sect_unlink_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info
HGOTO_ERROR(H5E_FSPACE, H5E_NOTFOUND, FAIL, "can't find section node on size list")
/* Decrement amount of space required to serialize all sections */
- fspace->serial_size -= fspace->sect_cls[sect->cls->type].serial_size;
+ fspace->serial_size -= fspace->sect_cls[sect->type].serial_size;
#ifdef QAK
+HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
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);
+HDfprintf(stderr, "%s: fspace->sect_cls[%u].serial_size = %Zu\n", FUNC, sect->type, fspace->sect_cls[sect->type].serial_size);
#endif /* QAK */
/* Update section info & check if we need less room for the serialized free space sections */
- if(H5FS_sect_decrease(f, dxpl_id, fspace) < 0)
+ if(H5FS_sect_decrease(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk")
/* Decrement amount of free space managed */
@@ -1121,10 +1102,9 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t
HDassert(sect);
/* Add section to the address-ordered list of sections */
- if(fspace->merge_list == NULL) {
+ if(fspace->merge_list == NULL)
if(NULL == (fspace->merge_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 merging free space sections")
- } /* end if */
if(H5SL_insert(fspace->merge_list, sect, &sect->addr) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into merging skip list")
@@ -1133,10 +1113,10 @@ H5FS_sect_link_rest(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t
HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size);
HDfprintf(stderr, "%s: fspace->sect_cls[sect->cls->type].serial_size = %Zu\n", FUNC, fspace->sect_cls[sect->cls->type].serial_size);
#endif /* QAK */
- fspace->serial_size += fspace->sect_cls[sect->cls->type].serial_size;
+ fspace->serial_size += fspace->sect_cls[sect->type].serial_size;
/* Update section info & check if we need more room for the serialized free space sections */
- if(H5FS_sect_increase(f, dxpl_id, fspace) < 0)
+ if(H5FS_sect_increase(fspace) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't increase free space section size on disk")
/* Increment amount of free space managed */
@@ -1173,13 +1153,22 @@ H5FS_sect_link(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sec
HDassert(fspace);
HDassert(sect);
- /* Add node to size tracked data structures */
+ /* Add section to size tracked data structures */
+#ifdef QAK
+HDfprintf(stderr, "%s: Check 1.0 - fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
+#endif /* QAK */
if(H5FS_sect_link_size(fspace, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to size tracking data structures")
+#ifdef QAK
+HDfprintf(stderr, "%s: Check 2.0 - fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
+#endif /* QAK */
/* Update rest of free space manager data structures for section addition */
if(H5FS_sect_link_rest(f, dxpl_id, fspace, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't add section to non-size tracking data structures")
+#ifdef QAK
+HDfprintf(stderr, "%s: Check 3.0 - fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
+#endif /* QAK */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1205,7 +1194,7 @@ static herr_t
H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
H5FS_section_info_t **sect, void *op_data)
{
- H5FS_section_info_t *tmp_sect_node; /* Temporary free space section */
+ H5FS_section_class_t *sect_cls = NULL; /* Section's class */
hbool_t merged; /* Flag to indicate merge occurred */
htri_t status; /* Status value */
herr_t ret_value = SUCCEED; /* Return value */
@@ -1221,6 +1210,9 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
/* Loop until no more merging */
do {
+ H5FS_section_class_t *tmp_sect_cls; /* Temporary section's class */
+ H5FS_section_info_t *tmp_sect_node; /* Temporary free space section */
+
/* Reset 'merge occurred' flag */
merged = FALSE;
@@ -1228,27 +1220,32 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
tmp_sect_node = H5SL_less(fspace->merge_list, &(*sect)->addr);
/* Check for node before new node able to merge with new node */
- if(tmp_sect_node && tmp_sect_node->cls->can_merge) {
- /* Determine if the sections can merge */
- if((status = (*tmp_sect_node->cls->can_merge)(tmp_sect_node, *sect, op_data)) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections")
- if(status > 0) {
- /* Sanity check */
- HDassert((*sect)->cls->merge);
-
- /* Remove 'less than' node from data structures */
- if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
-
- /* Merge the two sections together */
- if((*tmp_sect_node->cls->merge)(tmp_sect_node, *sect, op_data) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections")
-
- /* Retarget section pointer to 'less than' node that was merged into */
- *sect = tmp_sect_node;
-
- /* Indicate successful merge occurred */
- merged = TRUE;
+ if(tmp_sect_node) {
+ tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; /* Use class for left-most section */
+ if(tmp_sect_cls->can_merge) {
+ /* Determine if the sections can merge */
+ if((status = (*tmp_sect_cls->can_merge)(tmp_sect_node, *sect, op_data)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections")
+ if(status > 0) {
+ /* Sanity check */
+ HDassert(tmp_sect_cls->merge);
+
+ /* Remove 'less than' node from data structures */
+ if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
+
+ /* Merge the two sections together */
+ /* (rescan the class of the node, the 'can merge' callback can change it) */
+ tmp_sect_cls = &fspace->sect_cls[tmp_sect_node->type]; /* Use class for left-most section */
+ if((*tmp_sect_cls->merge)(tmp_sect_node, *sect, op_data) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections")
+
+ /* Retarget section pointer to 'less than' node that was merged into */
+ *sect = tmp_sect_node;
+
+ /* Indicate successful merge occurred */
+ merged = TRUE;
+ } /* end if */
} /* end if */
} /* end if */
@@ -1256,31 +1253,38 @@ H5FS_sect_merge(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace,
tmp_sect_node = H5SL_greater(fspace->merge_list, &(*sect)->addr);
/* Check for node after new node able to merge with new node */
- if(tmp_sect_node && tmp_sect_node->cls->can_merge) {
- /* Determine if the sections can merge */
- if((status = (*tmp_sect_node->cls->can_merge)(*sect, tmp_sect_node, op_data)) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections")
- if(status > 0) {
- /* Sanity check */
- HDassert((*sect)->cls->merge);
-
- /* Remove 'greater than' node from data structures */
- if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
-
- /* Merge the two sections together */
- if((*(*sect)->cls->merge)(*sect, tmp_sect_node, op_data) < 0)
- HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections")
-
- /* Indicate successful merge occurred */
- merged = TRUE;
+ if(tmp_sect_node) {
+ tmp_sect_cls = &fspace->sect_cls[(*sect)->type]; /* Use class for left-most section */
+ if(tmp_sect_cls->can_merge) {
+ /* Determine if the sections can merge */
+ if((status = (*tmp_sect_cls->can_merge)(*sect, tmp_sect_node, op_data)) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't check for merging sections")
+ if(status > 0) {
+ /* Sanity check */
+ HDassert(tmp_sect_cls->merge);
+
+ /* Remove 'greater than' node from data structures */
+ if(H5FS_sect_unlink(f, dxpl_id, fspace, tmp_sect_node) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTRELEASE, FAIL, "can't remove section from internal data structures")
+
+ /* Merge the two sections together */
+ /* (rescan the class of the node, the 'can merge' callback can change it) */
+ tmp_sect_cls = &fspace->sect_cls[(*sect)->type]; /* Use class for left-most section */
+ if((*tmp_sect_cls->merge)(*sect, tmp_sect_node, op_data) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't merge two sections")
+
+ /* Indicate successful merge occurred */
+ merged = TRUE;
+ } /* end if */
} /* end if */
} /* end if */
} while(merged);
+ HDassert(*sect);
/* Check for (possibly merged) section able to shrink the size of the container */
- if((*sect)->cls->can_shrink) {
- if((status = (*(*sect)->cls->can_shrink)(*sect, op_data)) < 0)
+ sect_cls = &fspace->sect_cls[(*sect)->type];
+ if(sect_cls->can_shrink) {
+ if((status = (*sect_cls->can_shrink)(*sect, op_data)) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTSHRINK, FAIL, "can't check for shrinking container")
if(status > 0) {
#ifdef QAK
@@ -1288,7 +1292,10 @@ HDfprintf(stderr, "%s: Can shrink!\n", FUNC);
#endif /* QAK */
/* Shrink the container */
/* (callback can indicate that it has discarded the section by setting *sect to NULL) */
- if((*(*sect)->cls->shrink)(sect, op_data) < 0)
+ /* (rescan the class of the node, the 'can shrink' callback can change it) */
+ sect_cls = &fspace->sect_cls[(*sect)->type];
+ HDassert(sect_cls->shrink);
+ if((*sect_cls->shrink)(sect, op_data) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't shrink free space container")
} /* end if */
} /* end if */
@@ -1321,7 +1328,7 @@ H5FS_add(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace, H5FS_section_info_t *sect,
FUNC_ENTER_NOAPI(H5FS_add, FAIL)
#ifdef QAK
-HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->cls->type = %u\n", FUNC, sect->size, sect->addr, sect->cls->type);
+HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a, sect->type = %u\n", FUNC, sect->size, sect->addr, sect->type);
#endif /* QAK */
/* Check arguments. */
@@ -1341,11 +1348,17 @@ HDfprintf(stderr, "%s: Returning space\n", FUNC);
HGOTO_ERROR(H5E_FSPACE, H5E_CANTMERGE, FAIL, "can't merge sections")
} /* end if */
- /* Add new (possibly merged or even discarded) node to free sections */
+ /* Add new (possibly merged) node to free sections data structures */
+ /* (If section has been completely merged away or discarded, 'sect' will
+ * be NULL at this point - QAK)
+ */
if(sect)
if(H5FS_sect_link(f, dxpl_id, fspace, sect) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space section into skip list")
+#ifdef QAK
+HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
+#endif /* QAK */
/* Mark free space sections as changed */
/* (if we're not deserializing all the sections) */
if(!(flags & H5FS_ADD_DESERIALIZING))
@@ -1517,16 +1530,18 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_sect_free_cb(void *_sect, void UNUSED *key, void UNUSED *op_data)
+H5FS_sect_free_cb(void *_sect, void UNUSED *key, void *op_data)
{
- H5FS_section_info_t *sect = (H5FS_section_info_t *)_sect;
+ H5FS_section_info_t *sect = (H5FS_section_info_t *)_sect; /* Section to free */
+ const H5FS_t *fspace = (const H5FS_t *)op_data; /* Free space manager for section */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FS_sect_free_cb)
HDassert(sect);
+ HDassert(fspace);
/* Call the 'free' method for the section's class */
- (*sect->cls->free)(sect);
+ (*fspace->sect_cls[sect->type].free)(sect);
FUNC_LEAVE_NOAPI(0)
} /* H5FS_sect_free_cb() */
@@ -1547,16 +1562,17 @@ H5FS_sect_free_cb(void *_sect, void UNUSED *key, void UNUSED *op_data)
*-------------------------------------------------------------------------
*/
static herr_t
-H5FS_node_free_cb(void *item, void UNUSED *key, void UNUSED *op_data)
+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);
+ HDassert(op_data);
/* Release the skip list for sections of this size */
- H5SL_destroy(fspace_node->sect_list, H5FS_sect_free_cb, NULL);
+ H5SL_destroy(fspace_node->sect_list, H5FS_sect_free_cb, op_data);
/* Release free space list node */
H5FL_FREE(H5FS_node_t, fspace_node);
@@ -1583,39 +1599,41 @@ H5FS_node_free_cb(void *item, void UNUSED *key, void UNUSED *op_data)
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_section_class_t *sect_cls; /* Class of section */
+ H5FS_section_info_t *sect= (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(sect);
HDassert(udata->fspace);
HDassert(udata->p);
/* The address of the section */
- UINT64ENCODE_VAR(*udata->p, sect_info->addr, udata->fspace->sect_off_size);
+ UINT64ENCODE_VAR(*udata->p, sect->addr, udata->fspace->sect_off_size);
#ifdef QAK
-HDfprintf(stderr, "%s: sect_info->addr = %a\n", FUNC, sect_info->addr);
+HDfprintf(stderr, "%s: sect->addr = %a\n", FUNC, sect->addr);
#endif /* QAK */
/* The type of this section */
- *(*udata->p)++ = (uint8_t)sect_info->cls->type;
+ *(*udata->p)++ = (uint8_t)sect->type;
#ifdef QAK
-HDfprintf(stderr, "%s: sect_info->cls->type = %u\n", FUNC, (unsigned)sect_info->cls->type);
+HDfprintf(stderr, "%s: sect->type = %u\n", FUNC, (unsigned)sect->type);
#endif /* QAK */
/* Call 'serialize' callback for this section */
- if(sect_info->cls->serialize) {
- if((*sect_info->cls->serialize)(sect_info, *udata->p) < 0)
+ sect_cls = &udata->fspace->sect_cls[sect->type];
+ if(sect_cls->serialize) {
+ if((*sect_cls->serialize)(sect, *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;
+ (*udata->p) += sect_cls->serial_size;
} /* end if */
else
- HDassert(sect_info->cls->serial_size == 0);
+ HDassert(sect_cls->serial_size == 0);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1765,7 +1783,10 @@ HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size);
/* Check for existing serialized sections on disk to release */
if(H5F_addr_defined(fspace->hdr->sect_addr)) {
/* Free previous serialized sections disk space */
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, (hsize_t)fspace->hdr->alloc_sect_size)<0)
+#ifdef QAK
+HDfprintf(stderr, "%s: Releasing space for serialized sections\n", FUNC);
+#endif /* QAK */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, fspace->hdr->alloc_sect_size)<0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, FAIL, "unable to release free space sections")
/* Reset address and size of serialized sections on disk */
@@ -1780,6 +1801,9 @@ HDfprintf(stderr, "%s: fspace->serial_size = %Zu\n", FUNC, fspace->serial_size);
fspace->hdr->alloc_sect_size = (size_t)fspace->hdr->sect_size * (double)fspace->hdr->expand_percent / 100.0;
/* Allocate space for the new serialized sections on disk */
+#ifdef QAK
+HDfprintf(stderr, "%s: Allocating space for serialized sections\n", FUNC);
+#endif /* QAK */
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 */
@@ -1800,7 +1824,7 @@ HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr-
* QAK - 5/ 8/2006
*/
/* Free previous serialized sections disk space */
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, (hsize_t)fspace->hdr->alloc_sect_size)<0)
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, fspace->hdr->alloc_sect_size)<0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, FAIL, "unable to free free space sections")
/* Compute new size */
@@ -1810,6 +1834,9 @@ HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr-
fspace->hdr->alloc_sect_size = new_size;
/* Allocate space for the new serialized sections on disk */
+#ifdef QAK
+HDfprintf(stderr, "%s: Allocating space for larger serialized sections, fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_size);
+#endif /* QAK */
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 */
@@ -1836,7 +1863,7 @@ HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr-
* QAK - 5/ 8/2006
*/
/* Free previous serialized sections disk space */
- if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, (hsize_t)fspace->hdr->alloc_sect_size)<0)
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fspace->hdr->sect_addr, fspace->hdr->alloc_sect_size)<0)
HGOTO_ERROR(H5E_STORAGE, H5E_CANTFREE, FAIL, "unable to free free space sections")
/* Compute new size */
@@ -1850,6 +1877,9 @@ HDfprintf(stderr, "%s: fspace->hdr->alloc_sect_size = %Hu\n", FUNC, fspace->hdr-
fspace->hdr->alloc_sect_size = new_size;
/* Allocate space for the new serialized sections on disk */
+#ifdef QAK
+HDfprintf(stderr, "%s: Allocating space for smaller serialized sections\n", FUNC);
+#endif /* QAK */
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 */
@@ -1900,6 +1930,9 @@ HDfprintf(stderr, "%s: Serializing single section\n", FUNC);
/* The size of the section */
UINT64ENCODE_VAR(p, fspace->single->size, fspace->sect_len_size);
+#ifdef QAK
+HDfprintf(stderr, "%s: fspace->single->size = %Hu\n", FUNC, fspace->single->size);
+#endif /* QAK */
/* Serialize the single node */
if(H5FS_serialize_sect_cb(fspace->single, NULL, &udata) < 0)
@@ -2020,8 +2053,9 @@ HDfprintf(stderr, "%s: fspace->hdr->sect_size = %Hu\n", FUNC, fspace->hdr->sect_
/* 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 */
+ hsize_t old_sect_count; /* Section count from header */
+ hsize_t old_tot_space; /* Total space managed 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);
@@ -2032,10 +2066,13 @@ HDfprintf(stderr, "%s: fspace->sect_len_size = %u\n", FUNC, fspace->sect_len_siz
/* Reset the section count, the "add" routine will update it */
old_sect_count = fspace->hdr->sect_count;
+ old_tot_space = fspace->hdr->tot_space;
#ifdef QAK
HDfprintf(stderr, "%s: fspace->hdr->sect_count = %Hu\n", FUNC, fspace->hdr->sect_count);
+HDfprintf(stderr, "%s: fspace->hdr->tot_space = %Hu\n", FUNC, fspace->hdr->tot_space);
#endif /* QAK */
fspace->hdr->sect_count = 0;
+ fspace->hdr->tot_space = 0;
/* Walk through the buffer, deserializing sections */
do {
@@ -2077,12 +2114,11 @@ HDfprintf(stderr, "%s: sect_type = %u\n", FUNC, sect_type);
/* 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)
+ if(NULL == (new_sect = (*fspace->sect_cls[sect_type].deserialize)(p, sect_addr, sect_size)))
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;
+ p += fspace->sect_cls[sect_type].serial_size;
/* Insert section in free space manager */
if(H5FS_add(f, dxpl_id, fspace, new_sect, H5FS_ADD_DESERIALIZING, NULL) < 0)
@@ -2094,6 +2130,7 @@ HDfprintf(stderr, "%s: sect_type = %u\n", FUNC, sect_type);
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);
+ HDassert(old_tot_space == fspace->hdr->tot_space);
} /* end if */
done:
@@ -2254,6 +2291,39 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FS_get_sect_count
+ *
+ * Purpose: Retrieve the number of sections managed
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, May 30, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_get_sect_count(const H5FS_t *fspace, hsize_t *nsects)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FS_get_sect_count, FAIL)
+
+ /* Check arguments. */
+ HDassert(fspace);
+ HDassert(nsects);
+
+ /* Get the section count */
+ *nsects = fspace->hdr->sect_count;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_get_sect_count() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FS_flush_cb
*
* Purpose: Skip list iterator callback to syncronize free space sections
@@ -2333,6 +2403,64 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FS_delete
+ *
+ * Purpose: Delete a free space manager on disk
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, May 30, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr)
+{
+ H5FS_hdr_t *fs_hdr = NULL; /* Free space header loaded from file */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FS_delete, FAIL)
+#ifdef QAK
+HDfprintf(stderr, "%s: Deleting free space manager\n", FUNC);
+#endif /* QAK */
+
+ /* Check arguments. */
+ HDassert(f);
+ HDassert(H5F_addr_defined(fs_addr));
+
+ /* Protect the free space header */
+ if(NULL == (fs_hdr = H5AC_protect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, NULL, NULL, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTPROTECT, FAIL, "unable to protect free space header")
+
+ /* Delete serialized section storage, if there are any */
+#ifdef QAK
+HDfprintf(stderr, "%s: fs_hdr->sect_addr = %a\n", FUNC, fs_hdr->sect_addr);
+#endif /* QAK */
+ if(fs_hdr->sect_count > 0) {
+ HDassert(H5F_addr_defined(fs_hdr->sect_addr));
+ HDassert(fs_hdr->sect_size > 0);
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_SECTS, dxpl_id, fs_hdr->sect_addr, fs_hdr->alloc_sect_size)<0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space sections")
+ } /* end if */
+
+ /* Release header's disk space */
+ if(H5MF_xfree(f, H5FD_MEM_FSPACE_HDR, dxpl_id, fs_addr, (hsize_t)H5FS_HEADER_SIZE(f))<0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTFREE, FAIL, "unable to release free space header")
+
+ /* Release the free space header */
+ if(H5AC_unprotect(f, dxpl_id, H5AC_FSPACE_HDR, fs_addr, fs_hdr, H5AC__DELETED_FLAG) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_CANTUNPROTECT, FAIL, "unable to release free space header")
+ fs_hdr = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5FS_delete() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FS_close
*
* Purpose: Destroy & deallocate free list structure, serializing sections
@@ -2370,7 +2498,8 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
/* Check for single section to free */
if(fspace->single) {
- fspace->single->cls->free(fspace->single);
+ /* Call the 'free' callback for the section */
+ (*fspace->sect_cls[fspace->single->type].free)(fspace->single);
fspace->single = NULL;
} /* end if */
HDassert(fspace->single == NULL);
@@ -2380,7 +2509,7 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
/* 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, NULL);
+ H5SL_destroy(fspace->bins[u].bin_list, H5FS_node_free_cb, fspace);
fspace->bins[u].bin_list = NULL;
} /* end if */
@@ -2388,15 +2517,17 @@ H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace)
} /* end if */
/* Release skip list for merging sections */
- if(fspace->merge_list) {
+ if(fspace->merge_list)
if(H5SL_close(fspace->merge_list) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCLOSEOBJ, FAIL, "can't destroy section merging skip list")
- } /* 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")
+ /* Release the memory for the free space section classes */
+ fspace->sect_cls = H5FL_SEQ_FREE(H5FS_section_class_t, fspace->sect_cls);
+
/* Free free space info */
H5FL_FREE(H5FS_t, fspace);
diff --git a/src/H5FSdbg.c b/src/H5FSdbg.c
index dcbc846..a946cf0 100644
--- a/src/H5FSdbg.c
+++ b/src/H5FSdbg.c
@@ -158,6 +158,45 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FS_sect_debug
+ *
+ * Purpose: Prints debugging info about a free space section.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5FS_sect_debug(const H5FS_t *fspace, const H5FS_section_info_t *sect, FILE *stream, int indent, int fwidth)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5FS_sect_debug, FAIL)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(fspace);
+ HDassert(sect);
+ HDassert(stream);
+ HDassert(indent >= 0);
+ HDassert(fwidth >= 0);
+
+ /* Call the section's debugging routine */
+ if(fspace->sect_cls[sect->type].debug)
+ if((fspace->sect_cls[sect->type].debug)(sect, stream, indent, fwidth) < 0)
+ HGOTO_ERROR(H5E_FSPACE, H5E_BADITER, FAIL, "can't dump section's debugging info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FS_sect_debug() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FS_sects_debug
*
* Purpose: Prints debugging info about the free space sections.
diff --git a/src/H5FSpkg.h b/src/H5FSpkg.h
index 98a945e..0f9aaad 100644
--- a/src/H5FSpkg.h
+++ b/src/H5FSpkg.h
@@ -98,6 +98,34 @@ typedef struct H5FS_hdr_t {
hsize_t alloc_sect_size; /* Allocated size of the section info in the file */
} H5FS_hdr_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;
+
+/* 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 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_t *merge_list; /* Skip list to hold sections for detecting merges */
+ H5FS_bin_t *bins; /* Array of lists of lists of free sections */
+};
+
/*****************************/
/* Package Private Variables */
diff --git a/src/H5FSprivate.h b/src/H5FSprivate.h
index 3b9311b..281bb57 100644
--- a/src/H5FSprivate.h
+++ b/src/H5FSprivate.h
@@ -54,7 +54,7 @@
/* Library Private Typedefs */
/****************************/
-/* Free space info (forward decl - defined in H5FS.c) */
+/* Free space info (forward decl - defined in H5FSpkg.h) */
typedef struct H5FS_t H5FS_t;
/* Forward declaration free space section info */
@@ -71,28 +71,27 @@ typedef struct H5FS_section_class_t {
/* Object methods */
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 */
- htri_t (*can_merge)(const H5FS_section_info_t *, const H5FS_section_info_t *,
- void *); /* Routine to determine if two nodes are mergable */
+ H5FS_section_info_t *(*deserialize)(const uint8_t *, haddr_t, hsize_t); /* Routine to deserialize a buffer into a "live" section */
+ htri_t (*can_merge)(H5FS_section_info_t *, H5FS_section_info_t *, void *); /* Routine to determine if two nodes are mergable */
herr_t (*merge)(H5FS_section_info_t *, H5FS_section_info_t *, void *); /* Routine to merge two nodes */
- htri_t (*can_shrink)(H5FS_section_info_t *, void *); /* Routine to determine if node can shrink container */
+ htri_t (*can_shrink)(H5FS_section_info_t *, void *); /* Routine to determine if node can shrink container */
herr_t (*shrink)(H5FS_section_info_t **, void *); /* Routine to shrink container */
- herr_t (*free)(H5FS_section_info_t *); /* Routine to free node */
- herr_t (*debug)(const H5FS_section_info_t *, FILE *,
- int , int ); /* Routine to dump debugging information about a section */
+ herr_t (*free)(H5FS_section_info_t *); /* Routine to free node */
+ herr_t (*debug)(const H5FS_section_info_t *, FILE *, int , int ); /* Routine to dump debugging information about a section */
} H5FS_section_class_t;
+/* State of section ("live" or "serialized") */
+typedef enum H5FS_section_state_t {
+ H5FS_SECT_LIVE, /* Section has "live" memory references */
+ H5FS_SECT_SERIALIZED /* Section is in "serialized" form */
+} H5FS_section_state_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 */
+ haddr_t addr; /* Address of free space section in the address space */
+ hsize_t size; /* Size of free space section */
+ unsigned type; /* Type of free space section (i.e. class) */
+ H5FS_section_state_t state; /* Whether the section is in "serialized" or "live" form */
};
/* Free space client IDs for identifying user of free space */
@@ -128,16 +127,22 @@ H5FL_SEQ_EXTERN(H5FS_section_class_t);
/***************************************/
H5_DLL H5FS_t *H5FS_create(H5F_t *f, hid_t dxpl_id, haddr_t *fs_addr,
const H5FS_create_t *fs_create, size_t nclasses,
- H5FS_section_class_t *classes, const void *cls_init_udata);
+ const 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,
- size_t nclasses, H5FS_section_class_t *classes, const void *cls_init_udata);
+ size_t nclasses, const 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, unsigned flags, void *op_data);
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_get_sect_count(const H5FS_t *fspace, hsize_t *nsects);
H5_DLL herr_t H5FS_flush(H5F_t *f, hid_t dxpl_id, unsigned flags);
+H5_DLL herr_t H5FS_delete(H5F_t *f, hid_t dxpl_id, haddr_t fs_addr);
H5_DLL herr_t H5FS_close(H5F_t *f, hid_t dxpl_id, H5FS_t *fspace);
+/* Debugging routines for dumping file structures */
+H5_DLL herr_t H5FS_sect_debug(const H5FS_t *fspace, const H5FS_section_info_t *sect,
+ FILE *stream, int indent, int fwidth);
+
#endif /* _H5FSprivate_H */
diff --git a/src/H5HF.c b/src/H5HF.c
index fcbb9cc..f30eb16 100644
--- a/src/H5HF.c
+++ b/src/H5HF.c
@@ -568,10 +568,20 @@ H5HF_close(H5HF_t *fh, hid_t dxpl_id)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't remove group from list of open objects")
/* Close the free space information */
+ /* (Can't put this in header "destroy" routine, because it has
+ * pointers to indirect blocks in the heap, which would create
+ * a reference loop and the objects couldn't be removed from
+ * the metadata cache - QAK)
+ */
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 */
+ /* (Can't put this in header "destroy" routine, because it has
+ * pointers to indirect blocks in the heap, which would create
+ * a reference loop and the objects couldn't be removed from
+ * the metadata cache - QAK)
+ */
if(H5HF_man_iter_reset(&fh->hdr->next_block) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator")
diff --git a/src/H5HFcache.c b/src/H5HFcache.c
index 8b59876..d896a3e 100644
--- a/src/H5HFcache.c
+++ b/src/H5HFcache.c
@@ -328,6 +328,7 @@ HDfprintf(stderr, "%s: Load heap header, addr = %a\n", FUNC, addr);
H5F_DECODE_LENGTH(f, p, hdr->total_size);
H5F_DECODE_LENGTH(f, p, hdr->man_size);
H5F_DECODE_LENGTH(f, p, hdr->man_alloc_size);
+ H5F_DECODE_LENGTH(f, p, hdr->man_iter_off);
H5F_DECODE_LENGTH(f, p, hdr->std_size);
H5F_DECODE_LENGTH(f, p, hdr->nobjs);
@@ -435,6 +436,7 @@ HDfprintf(stderr, "%s: Flushing heap header, addr = %a, destroy = %u\n", FUNC, a
H5F_ENCODE_LENGTH(f, p, hdr->total_size);
H5F_ENCODE_LENGTH(f, p, hdr->man_size);
H5F_ENCODE_LENGTH(f, p, hdr->man_alloc_size);
+ H5F_ENCODE_LENGTH(f, p, hdr->man_iter_off);
H5F_ENCODE_LENGTH(f, p, hdr->std_size);
H5F_ENCODE_LENGTH(f, p, hdr->nobjs);
@@ -917,7 +919,7 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
iblock->rc = 0;
iblock->nrows = *nrows;
iblock->addr = addr;
- iblock->dirty = FALSE;
+ iblock->nchildren = 0;
/* Compute size of indirect block */
iblock->size = H5HF_MAN_INDIRECT_SIZE(iblock->hdr, iblock);
@@ -985,6 +987,12 @@ HDfprintf(stderr, "%s: Load indirect block, addr = %a\n", FUNC, addr);
/* Decode child block address */
H5F_addr_decode(f, &p, &(iblock->ents[u].addr));
+ /* Count child blocks */
+ if(H5F_addr_defined(iblock->ents[u].addr)) {
+ iblock->nchildren++;
+ iblock->max_child = u;
+ } /* end if */
+
#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))
@@ -995,8 +1003,9 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add
#endif /* QAK */
} /* end for */
- /* Sanity check */
+ /* Sanity checks */
HDassert((size_t)(p - buf) == iblock->size);
+ HDassert(iblock->nchildren); /* indirect blocks w/no children should have been deleted */
/* Set return value */
ret_value = iblock;
@@ -1042,13 +1051,14 @@ HDfprintf(stderr, "%s: Flushing indirect block, addr = %a, destroy = %u\n", FUNC
HDassert(iblock);
if(iblock->cache_info.is_dirty) {
- H5HF_hdr_t *hdr; /* Shared fractal heap information */
- uint8_t *buf = NULL; /* Temporary buffer */
- uint8_t *p; /* Pointer into raw data buffer */
- size_t u; /* Local index variable */
-
- /* Sanity check */
- HDassert(iblock->dirty);
+ H5HF_hdr_t *hdr; /* Shared fractal heap information */
+ uint8_t *buf = NULL; /* Temporary buffer */
+ uint8_t *p; /* Pointer into raw data buffer */
+#ifndef NDEBUG
+ unsigned nchildren = 0; /* Track # of children */
+ unsigned max_child = 0; /* Track max. child entry used */
+#endif /* NDEBUG */
+ size_t u; /* Local index variable */
/* Get the pointer to the shared heap header */
hdr = iblock->hdr;
@@ -1096,6 +1106,15 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add
/* Encode child block address */
H5F_addr_encode(f, &p, iblock->ents[u].addr);
+#ifndef NDEBUG
+ /* Count child blocks */
+ if(H5F_addr_defined(iblock->ents[u].addr)) {
+ nchildren++;
+ if(u > max_child)
+ max_child = u;
+ } /* end if */
+#endif /* NDEBUG */
+
#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))
@@ -1105,6 +1124,10 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add
/* Sanity check */
HDassert((size_t)(p - buf) == iblock->size);
+#ifndef NDEBUG
+ HDassert(nchildren == iblock->nchildren);
+ HDassert(max_child == iblock->max_child);
+#endif /* NDEBUG */
/* Write the indirect block */
if(H5F_block_write(f, H5FD_MEM_FHEAP_IBLOCK, addr, iblock->size, dxpl_id, buf) < 0)
@@ -1114,7 +1137,6 @@ HDfprintf(stderr, "%s: iblock->ents[%Zu] = {%a}\n", FUNC, u, iblock->ents[u].add
H5FL_BLK_FREE(indirect_block, buf);
/* Reset dirty flags */
- iblock->dirty = FALSE;
iblock->cache_info.is_dirty = FALSE;
} /* end if */
@@ -1153,9 +1175,8 @@ H5HF_cache_iblock_dest(H5F_t UNUSED *f, H5HF_indirect_t *iblock)
*/
HDassert(iblock);
HDassert(iblock->rc == 0);
- HDassert(!iblock->dirty);
#ifdef QAK
-HDfprintf(stderr, "%s: Destroying indirect block\n", "H5HF_cache_iblock_dest");
+HDfprintf(stderr, "%s: Destroying indirect block\n", FUNC);
#endif /* QAK */
/* Decrement reference count on shared info */
diff --git a/src/H5HFdbg.c b/src/H5HFdbg.c
index 81faf1e..c8945fd 100644
--- a/src/H5HFdbg.c
+++ b/src/H5HFdbg.c
@@ -63,6 +63,7 @@ typedef struct {
/* User data for free space section iterator callback */
typedef struct {
+ H5FS_t *fspace; /* Free space manager */
FILE *stream; /* Stream for output */
int indent; /* Indention amount */
int fwidth; /* Field width mount */
@@ -232,9 +233,12 @@ H5HF_hdr_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream, int indent,
"Total managed space data block size:",
hdr->man_size);
HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
- "Total managed space allocated data block size:",
+ "Total managed space allocated:",
hdr->man_alloc_size);
HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
+ "Offset of managed space iterator:",
+ hdr->man_iter_off);
+ HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
"Total standalone space data block size:",
hdr->std_size);
HDfprintf(stream, "%*s%-*s %Hu\n", indent, "", fwidth,
@@ -628,17 +632,16 @@ H5HF_sects_debug_cb(const H5FS_section_info_t *_sect, void *_udata)
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"))));
+ (sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE ? "single" :
+ (sect->sect_info.type == H5HF_FSPACE_SECT_RANGE ? "range" :
+ (sect->sect_info.type == H5HF_FSPACE_SECT_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")
+ /* Dump section-specific debugging information */
+ if(H5FS_sect_debug(udata->fspace, _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)
@@ -688,6 +691,7 @@ H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t fh_addr,
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
/* Prepare user data for section iteration callback */
+ udata.fspace = hdr->fspace;
udata.stream = stream;
udata.indent = indent;
udata.fwidth = fwidth;
diff --git a/src/H5HFdblock.c b/src/H5HFdblock.c
index 88c4e90..a4f1815 100644
--- a/src/H5HFdblock.c
+++ b/src/H5HFdblock.c
@@ -92,8 +92,7 @@ H5FL_DEFINE(H5HF_direct_t);
*/
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)
+ unsigned par_entry, haddr_t *addr_p, H5HF_free_section_t **ret_sec_node)
{
H5HF_free_section_t *sec_node; /* Pointer to free space section for block */
H5HF_direct_t *dblock = NULL; /* Pointer to direct block */
@@ -106,7 +105,6 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo
* Check arguments.
*/
HDassert(hdr);
- HDassert(block_size > 0);
HDassert(addr_p);
/*
@@ -124,49 +122,49 @@ H5HF_man_dblock_create(hid_t dxpl_id, H5HF_hdr_t *hdr, H5HF_indirect_t *par_iblo
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header")
/* Set info for direct block */
-#ifdef QAK
-HDfprintf(stderr, "%s: size = %Zu, block_off = %Hu\n", FUNC, block_size, block_off);
-#endif /* QAK */
- dblock->parent = par_iblock;
- if(dblock->parent) {
- if(H5HF_iblock_incr(par_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ if(par_iblock) {
+ unsigned par_row = par_entry / hdr->man_dtable.cparam.width; /* Row for block */
+
+ /* Compute offset & size, based on parent's information */
+ dblock->block_off = par_iblock->block_off;
+ dblock->block_off += hdr->man_dtable.row_block_off[par_row];
+ dblock->block_off += hdr->man_dtable.row_block_size[par_row] * (par_entry % hdr->man_dtable.cparam.width);
+ dblock->size = hdr->man_dtable.row_block_size[par_row];
} /* end if */
- dblock->par_entry = par_entry;
- dblock->size = block_size;
- dblock->block_off = block_off;
- dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(block_size);
- free_space = block_size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
+ else {
+ /* Must be the root direct block */
+ dblock->block_off = 0;
+ dblock->size = hdr->man_dtable.cparam.start_block_size;
+ } /* end else */
+ dblock->blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dblock->size);
+ free_space = dblock->size - H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
/* Allocate buffer for block */
/* XXX: Change to using free-list factories */
- if((dblock->blk = H5FL_BLK_MALLOC(direct_block, block_size)) == NULL)
+ if((dblock->blk = H5FL_BLK_MALLOC(direct_block, dblock->size)) == NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
#ifdef H5_USING_PURIFY
HDmemset(dblock->blk, 0, dblock->size);
#endif /* H5_USING_PURIFY */
/* 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)))
+ if(HADDR_UNDEF == (*addr_p = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, (hsize_t)dblock->size)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap direct block")
+#ifdef QAK
+HDfprintf(stderr, "%s: direct block address = %a\n", FUNC, *addr_p);
+#endif /* QAK */
- /* 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_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)
- 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 = *addr_p;
- sec_node->u.single.dblock_size = block_size;
+ /* Attach to parent indirect block, if there is one */
+ dblock->parent = par_iblock;
+ if(dblock->parent)
+ if(H5HF_man_iblock_attach(dblock->parent, par_entry, *addr_p) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach direct block to parent indirect block")
+ dblock->par_entry = par_entry;
+
+ /* Create a new 'single' section for the free space in the block */
+ if(NULL == (sec_node = H5HF_sect_single_new((dblock->block_off + H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr)),
+ free_space, dblock->parent, dblock->par_entry, *addr_p, dblock->size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for new direct block's free space")
/* Check what to do with section node */
if(ret_sec_node)
@@ -182,6 +180,10 @@ HDmemset(dblock->blk, 0, dblock->size);
if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, *addr_p, dblock, H5AC__NO_FLAGS_SET) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add fractal heap direct block to cache")
+ /* Increase the allocated heap size */
+ if(H5HF_hdr_inc_alloc(hdr, dblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
+
done:
if(ret_value < 0)
if(dblock)
@@ -196,6 +198,10 @@ done:
*
* Purpose: Destroy a managed direct block
*
+ * Note: This routine does _not_ insert a range section for the
+ * destroyed direct block, that must be handled by the
+ * caller.
+ *
* Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
@@ -230,6 +236,10 @@ HDfprintf(stderr, "%s: root direct block\n", FUNC);
/* Sanity check block iterator */
HDassert(!H5HF_man_iter_ready(&hdr->next_block));
+ /* Reset root pointer information */
+ hdr->man_dtable.curr_root_rows = 0;
+ hdr->man_dtable.table_addr = HADDR_UNDEF;
+
/* Reset header information back to "empty heap" state */
if(H5HF_hdr_empty(hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty")
@@ -239,21 +249,51 @@ HDfprintf(stderr, "%s: root direct block\n", FUNC);
HDfprintf(stderr, "%s: root indirect block\n", FUNC);
#endif /* QAK */
-/* Remove from parent indirect block */
+ /* Detach from parent indirect block */
+ if(H5HF_man_iblock_detach(dblock->parent, dxpl_id, dblock->par_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach from parent indirect block")
+ dblock->parent = NULL;
+ dblock->par_entry = 0;
-/* If this is the last block in the heap, move block iterator backwards */
+ /* Adjust heap statistics */
+ hdr->man_alloc_size -= dblock->size;
-/* Detect the last direct block (of the starting block size) and make it the root direct block */
-
-HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "destroying non-root direct block not supported yet")
+#ifdef QAK
+HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off);
+HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off);
+#endif /* QAK */
+ /* Check for this direct block being the highest in the heap */
+ if((dblock->block_off + dblock->size) == hdr->man_iter_off) {
+ /* Move 'next block' iterator backwards (may shrink heap) */
+ if(H5HF_hdr_reverse_iter(hdr, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reverse 'next block' iterator")
+ } /* end if */
+#if 0
+ else {
+ unsigned par_row, par_col; /* Row & column in parent indirect block */
+
+ /* Compute row & column in parent indirect block */
+ par_row = dblock->par_entry / hdr->man_dtable.cparam.width;
+ par_col = dblock->par_entry % hdr->man_dtable.cparam.width;
+
+ /* Add a 'range' section for the space in the destroyed block */
+ if(H5HF_sect_range_add(hdr, dxpl_id, dblock->block_off, hdr->man_dtable.row_dblock_free[par_row],
+ dblock->parent, par_row, par_col, 1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINSERT, FAIL, "can't create range section for direct block being destroyed")
+ } /* end else */
+#endif /* 0 */
} /* end else */
/* Release direct block's disk space */
+#ifdef QAK
+HDfprintf(stderr, "%s: Before releasing direct block's space, dblock_addr = %a\n", FUNC, dblock_addr);
+#endif /* QAK */
if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_DBLOCK, dxpl_id, dblock_addr, (hsize_t)dblock->size)<0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap direct block")
/* Remove direct block from metadata cache */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__DELETED_FLAG) < 0)
+ /* (direct block "destroy" callback will be called by cache) */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
dblock = NULL;
@@ -277,11 +317,10 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_man_dblock_new(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t request)
+H5HF_man_dblock_new(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t request,
+ H5HF_free_section_t **ret_sec_node)
{
haddr_t dblock_addr; /* Address of new direct block */
- hsize_t dblock_off; /* Direct block offset in heap address space */
- size_t dblock_size; /* Size of new direct block */
size_t min_dblock_size; /* Min. size of direct block to allocate */
herr_t ret_value = SUCCEED; /* Return value */
@@ -319,13 +358,11 @@ HDfprintf(stderr, "%s: Check 2 - min_dblock_size = %Zu\n", FUNC, min_dblock_size
if(!H5F_addr_defined(hdr->man_dtable.table_addr) &&
min_dblock_size == hdr->man_dtable.cparam.start_block_size) {
/* Create new direct block at starting offset */
- dblock_size = hdr->man_dtable.cparam.start_block_size;
- dblock_off = 0;
- if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, dblock_size, dblock_off, &dblock_addr, NULL) < 0)
+ if(H5HF_man_dblock_create(dxpl_id, hdr, NULL, 0, &dblock_addr, ret_sec_node) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
#ifdef QAK
-HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
+HDfprintf(stderr, "%s: root direct block, dblock_addr = %a\n", FUNC, dblock_addr);
#endif /* QAK */
/* Point root at new direct block */
@@ -333,49 +370,50 @@ HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
hdr->man_dtable.table_addr = dblock_addr;
/* Extend heap to cover new direct block */
- if(H5HF_hdr_extend_heap(hdr, (hsize_t)dblock_size, hdr->man_dtable.row_dblock_free[0]) < 0)
+ if(H5HF_hdr_adjust_heap(hdr, (hsize_t)hdr->man_dtable.cparam.start_block_size, (hssize_t)hdr->man_dtable.row_dblock_free[0]) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "can't increase space to cover root direct block")
} /* end if */
- /* Root entry already exists, go get indirect block for new direct block */
+ /* Root entry already exists, allocate direct block from root indirect block */
else {
H5HF_indirect_t *iblock; /* Pointer to indirect block to create */
- size_t dblock_entry; /* Direct entry for new direct 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 */
+
+ /* Update iterator to reflect any previous increments as well as allow for requested direct block size */
+ if(H5HF_hdr_update_iter(hdr, dxpl_id, min_dblock_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUPDATE, FAIL, "unable to update block iterator")
+
+ /* Retrieve information about current iterator position */
+ if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location")
+ HDassert(next_row < iblock->nrows);
+ next_size = hdr->man_dtable.row_block_size[next_row];
+
+ /* Check for skipping over blocks */
+ if(min_dblock_size > next_size) {
+HDfprintf(stderr, "%s: Skipping direct block sizes not supported, min_dblock_size = %Zu, next_size = %Zu\n", FUNC, min_dblock_size, next_size);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "skipping direct block sizes not supported yet")
+ } /* end if */
+
+ /* Advance "next block" iterator to next direct block entry */
+ if(H5HF_hdr_inc_iter(hdr, (hsize_t)next_size, 1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment 'next block' iterator")
- /* Find indirect block with room for block of correct size */
- if(NULL == (iblock = H5HF_man_iblock_place_dblock(hdr, dxpl_id, min_dblock_size, &dblock_entry, &dblock_size)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to locate indirect block with space for direct block")
#ifdef QAK
HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr);
-HDfprintf(stderr, "%s: dblock_entry = %Zu\n", FUNC, dblock_entry);
-HDfprintf(stderr, "%s: dblock_size = %Zu\n", FUNC, dblock_size);
+HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
#endif /* QAK */
- /* Compute the direct block's offset in the heap's address space */
- dblock_off = iblock->block_off;
- dblock_off += hdr->man_dtable.row_block_off[dblock_entry / hdr->man_dtable.cparam.width];
- dblock_off += hdr->man_dtable.row_block_size[dblock_entry / hdr->man_dtable.cparam.width] * (dblock_entry % hdr->man_dtable.cparam.width);
-
/* Create new direct block at current location*/
- if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, dblock_entry, dblock_size, dblock_off, &dblock_addr, NULL) < 0)
+ if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, next_entry, &dblock_addr, ret_sec_node) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap direct block")
-
#ifdef QAK
HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
#endif /* QAK */
-
- /* Point indirect block at new direct block */
- iblock->ents[dblock_entry].addr = dblock_addr;
-
- /* 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")
} /* end else */
- /* Advance the allocated heap size/new block iterator */
- if(H5HF_hdr_inc_alloc(hdr, dblock_off + dblock_size, 1) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_dblock_new() */
diff --git a/src/H5HFdtable.c b/src/H5HFdtable.c
index e51b45b..1461cd7 100644
--- a/src/H5HFdtable.c
+++ b/src/H5HFdtable.c
@@ -103,11 +103,11 @@ H5HF_dtable_init(H5HF_dtable_t *dtable)
HDassert(dtable);
/* Compute/cache some values */
- dtable->first_row_bits = H5V_log2_of2(dtable->cparam.start_block_size) +
- H5V_log2_of2(dtable->cparam.width);
+ dtable->start_bits = H5V_log2_of2(dtable->cparam.start_block_size);
+ dtable->first_row_bits = dtable->start_bits + H5V_log2_of2(dtable->cparam.width);
dtable->max_root_rows = (dtable->cparam.max_index - dtable->first_row_bits) + 1;
- dtable->max_direct_rows = (H5V_log2_of2(dtable->cparam.max_direct_size) -
- H5V_log2_of2(dtable->cparam.start_block_size)) + 2;
+ dtable->max_direct_bits = H5V_log2_of2(dtable->cparam.max_direct_size);
+ dtable->max_direct_rows = (dtable->max_direct_bits - dtable->start_bits) + 2;
dtable->num_id_first_row = dtable->cparam.start_block_size * dtable->cparam.width;
dtable->max_dir_blk_off_size = H5HF_SIZEOF_OFFSET_LEN(dtable->cparam.max_direct_size);
@@ -245,3 +245,34 @@ H5HF_dtable_size_to_row(H5HF_dtable_t *dtable, size_t block_size)
FUNC_LEAVE_NOAPI(row)
} /* end H5HF_dtable_size_to_row() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_dtable_size_to_rows
+ *
+ * Purpose: Compute # of rows of indirect block of a given size
+ *
+ * Return: Non-negative on success (can't fail)
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5HF_dtable_size_to_rows(H5HF_dtable_t *dtable, hsize_t size)
+{
+ unsigned rows; /* # of rows required for indirect block */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_dtable_size_to_rows)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(dtable);
+
+ rows = (H5V_log2_gen(size) - dtable->first_row_bits) + 1;
+
+ FUNC_LEAVE_NOAPI(rows)
+} /* end H5HF_dtable_size_to_rows() */
+
diff --git a/src/H5HFhdr.c b/src/H5HFhdr.c
index 05d0a77..836d1e6 100644
--- a/src/H5HFhdr.c
+++ b/src/H5HFhdr.c
@@ -68,6 +68,10 @@
/* Local Prototypes */
/********************/
+/* Free space section routines */
+static herr_t H5HF_hdr_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries);
+
/*********************/
/* Package Variables */
@@ -426,7 +430,7 @@ HDfprintf(stderr, "%s: Marking heap header as dirty\n", FUNC);
HDassert(hdr);
/* Mark header as dirty in cache */
- if(H5AC_mark_pinned_entry_dirty(hdr->f, hdr, FALSE, 0) < 0)
+ if(H5AC_mark_pinned_or_protected_entry_dirty(hdr->f, hdr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark fractal heap header as dirty")
/* Set the dirty flags for the heap header */
@@ -482,9 +486,9 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HF_hdr_extend_heap
+ * Function: H5HF_hdr_adjust_heap
*
- * Purpose: Extend heap to cover more space
+ * Purpose: Adjust heap space
*
* Return: Non-negative on success/Negative on failure
*
@@ -495,25 +499,31 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_hdr_extend_heap(H5HF_hdr_t *hdr, hsize_t new_size, hsize_t extra_free)
+H5HF_hdr_adjust_heap(H5HF_hdr_t *hdr, hsize_t new_size, hssize_t extra_free)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_extend_heap)
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_adjust_heap)
/*
* Check arguments.
*/
HDassert(hdr);
- HDassert(new_size >= hdr->total_size);
/* Set the total space in heap */
hdr->total_size = new_size;
hdr->man_size = new_size;
- /* Increment the free space in direct blocks */
+ /* Adjust the free space in direct blocks */
hdr->total_man_free += extra_free;
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5HF_hdr_extend_heap() */
+ /* 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_hdr_adjust_heap() */
/*-------------------------------------------------------------------------
@@ -525,37 +535,752 @@ H5HF_hdr_extend_heap(H5HF_hdr_t *hdr, hsize_t new_size, hsize_t extra_free)
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * Apr 24 2006
+ * May 23 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, size_t alloc_size)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_hdr_inc_alloc)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(alloc_size);
+
+ /* Update the "allocated" size within the heap */
+ hdr->man_alloc_size += alloc_size;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", "H5HF_hdr_inc_alloc", hdr->man_alloc_size);
+#endif /* QAK */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_hdr_inc_alloc() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_hdr_start_iter
+ *
+ * Purpose: Start "next block" iterator at an offset/entry in the heap
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
*
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, hsize_t new_alloc_size, unsigned nentries)
+H5HF_hdr_start_iter(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, hsize_t curr_off, unsigned curr_entry)
{
herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_inc_alloc)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_start_iter)
/*
* Check arguments.
*/
HDassert(hdr);
- HDassert(new_alloc_size >= hdr->man_alloc_size);
+ HDassert(iblock);
+
+ /* Set up "next block" iterator at correct location */
+ if(H5HF_man_iter_start_entry(hdr, &hdr->next_block, iblock, curr_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize block iterator")
+
+ /* Set the offset of the iterator in the heap */
+ hdr->man_iter_off = curr_off;
- /* Advance the iterator for the current location with in the indirect block */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_hdr_start_iter() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_hdr_reset_iter
+ *
+ * Purpose: Reset "next block" iterator
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_hdr_reset_iter(H5HF_hdr_t *hdr, hsize_t curr_off)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_reset_iter)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+
+ /* Reset "next block" iterator */
+ if(H5HF_man_iter_reset(&hdr->next_block) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator")
+
+ /* Set the offset of the iterator in the heap */
+ hdr->man_iter_off = curr_off;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_hdr_reset_iter() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_hdr_skip_blocks
+ *
+ * Purpose: Add skipped direct blocks to free space for heap
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Apr 3 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_hdr_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock,
+ unsigned start_entry, unsigned nentries)
+{
+ hsize_t sect_off; /* Offset of free section in heap */
+ unsigned curr_row; /* Current row in indirect block */
+ unsigned curr_col; /* Current column in indirect block */
+ unsigned u; /* Local index variables */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_blocks)
+#ifdef QAK
+HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(iblock);
+ HDassert(nentries);
+
+ /* Compute starting column & row */
+ curr_row = start_entry / hdr->man_dtable.cparam.width;
+ curr_col = start_entry % hdr->man_dtable.cparam.width;
+
+ /* Initialize information for rows skipped over */
+ sect_off = iblock->block_off;
+ for(u = 0; u < curr_row; u++)
+ sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
+ sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col;
+#ifdef QAK
+HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
+#endif /* QAK */
+
+ /* Loop over the blocks to skip */
+ for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) {
+ unsigned row_entries; /* Number of entries in a particular row */
+
+ /* Compute number of entries in (possible partial) current row */
+ row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u);
+#ifdef QAK
+HDfprintf(stderr, "%s: u = %u\n", FUNC, u);
+HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
+HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = %Hu\n", FUNC, row_entries, curr_row, hdr->man_dtable.row_dblock_free[curr_row]);
+#endif /* QAK */
+
+ /* Add 'range' section for blocks skipped in this row */
+ if(H5HF_sect_range_add(hdr, dxpl_id, sect_off, hdr->man_dtable.row_dblock_free[curr_row],
+ iblock, curr_row, curr_col, row_entries) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create range section for indirect block's free space")
+
+ /* Advance row & column position */
+ sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row];
+ curr_row++;
+ curr_col = 0; /* (first partial row aligns this) */
+
+ /* Increment index variable */
+ u += row_entries;
+ } /* end for */
+#ifdef QAK
+HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
+#endif /* QAK */
+
+ /* Advance the new block iterator */
+ if(H5HF_hdr_inc_iter(hdr, (sect_off - hdr->man_iter_off), nentries) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_hdr_skip_blocks() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_hdr_skip_ranges
+ *
+ * Purpose: Add skipped indirect ranges to free space for heap
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Apr 4 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_hdr_skip_ranges(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *iblock,
+ unsigned start_entry, unsigned nentries)
+{
+ hsize_t sect_off; /* Offset of free section in heap */
+ size_t row_dblock_free_space; /* Size of free space for row of direct blocks in a row */
+ size_t acc_row_dblock_free_space; /* Accumulated size of free space for row of direct blocks in a row */
+ unsigned curr_row; /* Current row in indirect block */
+ unsigned curr_col; /* Current column in indirect block */
+ unsigned u, w; /* Local index variables */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_skip_ranges)
+#ifdef QAK
+HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(iblock);
+ HDassert(nentries);
+
+ /* Compute starting column & row */
+ curr_row = start_entry / hdr->man_dtable.cparam.width;
+ curr_col = start_entry % hdr->man_dtable.cparam.width;
+#ifdef QAK
+HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
+#endif /* QAK */
+
+ /* Initialize information for rows skipped over */
+ sect_off = iblock->block_off;
+ for(u = 0; u < curr_row; u++)
+ sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
+ sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col;
+#ifdef QAK
+HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
+#endif /* QAK */
+
+ /* Loop over the blocks to skip */
+ for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) {
+ unsigned row_entries; /* Number of entries in a particular row */
+ unsigned num_rows; /* Number of rows in indirect blocks referenced */
+
+ /* Compute number of rows in indirect blocks covered by entry */
+ num_rows = (H5V_log2_of2((uint32_t)hdr->man_dtable.row_block_size[curr_row]) -
+ H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) - 1;
+
+ /* Compute number of entries in (possible partial) current row */
+ row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u);
+#ifdef QAK
+HDfprintf(stderr, "%s: u = %u\n", FUNC, u);
+HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
+HDfprintf(stderr, "%s: row_entries = %u, num_rows = %u\n", FUNC, row_entries, num_rows);
+#endif /* QAK */
+
+ /* Loop over rows in indirect blocks covered */
+ acc_row_dblock_free_space = 0;
+ for(w = 0; w < num_rows; w++) {
+
+ /* Compute free space in direct blocks for this row */
+ row_dblock_free_space = hdr->man_dtable.cparam.width * hdr->man_dtable.row_dblock_free[w];
+ acc_row_dblock_free_space += row_dblock_free_space;
+#ifdef QAK
+HDfprintf(stderr, "%s: w = %u\n", FUNC, w);
+HDfprintf(stderr, "%s: hdr->man_dtable.row_dblock_free[%u] = %Zu\n", FUNC, w, hdr->man_dtable.row_dblock_free[w]);
+#endif /* QAK */
+
+ /* Add "indirect" free space section for blocks in this row */
+
+ /* Create free list section node for blocks skipped over */
+ if(H5HF_sect_indirect_add(hdr, dxpl_id, (sect_off + hdr->man_dtable.row_block_off[w]),
+ hdr->man_dtable.row_dblock_free[w], iblock, curr_row, curr_col, row_entries, w, num_rows) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create indirect section for indirect block's free space")
+ } /* end for */
+#ifdef QAK
+HDfprintf(stderr, "%s: acc_row_dblock_free_space = %Zu\n", FUNC, acc_row_dblock_free_space);
+#endif /* QAK */
+
+ /* Advance row & column position */
+ sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row];
+ curr_row++;
+ curr_col = 0; /* (first partial row aligns this) */
+
+ /* Advance outer loop index */
+ u += row_entries;
+ } /* end for */
+#ifdef QAK
+HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
+#endif /* QAK */
+
+ /* Advance the new block iterator */
+ if(H5HF_hdr_inc_iter(hdr, (sect_off - hdr->man_iter_off), nentries) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_hdr_skip_ranges() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_hdr_update_iter
+ *
+ * Purpose: Update state of heap to account for current iterator
+ * position.
+ *
+ * Note: Creates necessary indirect blocks
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Mar 14 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_hdr_update_iter(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_update_iter)
+#ifdef QAK
+HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(min_dblock_size > 0);
+
+ /* Check for creating first indirect block */
+ if(hdr->man_dtable.curr_root_rows == 0) {
+ if(H5HF_man_iblock_root_create(hdr, dxpl_id, min_dblock_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "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 */
+ unsigned min_dblock_row; /* Minimum row for direct block size request */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: searching root indirect block\n", FUNC);
+#endif /* QAK */
+ /* Compute min. row for direct block requested */
+ min_dblock_row = H5HF_dtable_size_to_row(&hdr->man_dtable, min_dblock_size);
+#ifdef QAK
+HDfprintf(stderr, "%s: min_dblock_size = %Zu, min_dblock_row = %u\n", FUNC, min_dblock_size, min_dblock_row);
+#endif /* QAK */
+
+ /* Initialize block iterator, if necessary */
+ if(!H5HF_man_iter_ready(&hdr->next_block)) {
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off);
+#endif /* QAK */
+ /* Start iterator with previous offset of iterator */
+ if(H5HF_man_iter_start_offset(hdr, dxpl_id, &hdr->next_block, hdr->man_iter_off) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to set block iterator location")
+ } /* end if */
+
+ /* Get information about current iterator location */
+ if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location")
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Check 1.0\n", FUNC);
+HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
+HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
+HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
+HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
+#endif /* QAK */
+ /* Check for skipping over blocks in the current block */
+ if(min_dblock_row > next_row && next_row < iblock->nrows) {
+ unsigned min_entry; /* Min entry for direct block requested */
+ unsigned skip_entries; /* Number of entries to skip in the current block */
+
+ /* Compute the number of entries to skip in the current block */
+ min_entry = min_dblock_row * hdr->man_dtable.cparam.width;
+ if(min_dblock_row >= iblock->nrows)
+ skip_entries = (iblock->nrows * hdr->man_dtable.cparam.width) - next_entry;
+ else
+ skip_entries = min_entry - next_entry;
+#ifdef QAK
+HDfprintf(stderr, "%s: min_entry = %u, skip_entries = %u\n", FUNC, min_entry, skip_entries);
+#endif /* QAK */
+
+ /* Add skipped direct blocks to heap's free space */
+ if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, next_entry, skip_entries) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space")
+
+ /* Get information about new iterator location */
+ if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location")
+ } /* end if */
+
+ do {
+ /* Reset conditions for leaving loop */
+ walked_up = walked_down = FALSE;
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Check 2.0\n", FUNC);
+HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
+HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
+HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
+HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
+#endif /* QAK */
+
+ /* Check for walking off end of indirect block */
+ /* (walk up iterator) */
+ while(next_row >= iblock->nrows) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Off the end of a block\n", FUNC);
+#endif /* QAK */
+ /* Check for needing to expand root indirect block */
+ if(iblock->parent == NULL) {
+#ifdef QAK
+HDfprintf(stderr, "%s: Doubling root block\n", FUNC);
+#endif /* QAK */
+ if(H5HF_man_iblock_root_double(hdr, dxpl_id, min_dblock_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTEXTEND, FAIL, "unable to double root indirect block")
+ } /* end if */
+ else {
+#ifdef QAK
+HDfprintf(stderr, "%s: Walking up a level\n", FUNC);
+#endif /* QAK */
+ /* Move iterator up one level */
+ if(H5HF_man_iter_up(&hdr->next_block) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location")
+
+ /* Increment location of next block at this level */
+ if(H5HF_man_iter_next(hdr, &hdr->next_block, 1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't advance fractal heap block location")
+ } /* end else */
+
+ /* Get information about new iterator location */
+ if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location")
+
+ /* Indicate that we walked up */
+ walked_up = TRUE;
+ } /* end while */
+#ifdef QAK
+HDfprintf(stderr, "%s: Check 3.0\n", FUNC);
+HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
+HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
+HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
+HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
+#endif /* QAK */
+
+ /* Check for walking into child indirect block */
+ /* (walk down iterator) */
+ if(next_row >= hdr->man_dtable.max_direct_rows) {
+ unsigned child_nrows; /* Number of rows in new indirect block */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Walking down into child indirect block\n", FUNC);
+#endif /* QAK */
+#ifdef QAK
+HDfprintf(stderr, "%s: Check 3.1\n", FUNC);
+HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
+HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
+HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
+HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
+#endif /* QAK */
+ HDassert(!H5F_addr_defined(iblock->ents[next_entry].addr));
+
+ /* Compute # of rows in next child indirect block to use */
+ child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[next_row]);
+#ifdef QAK
+HDfprintf(stderr, "%s: child_nrows = %u\n", FUNC, child_nrows);
+#endif /* QAK */
+
+ /* Check for skipping over indirect blocks */
+ /* (that don't have direct blocks large enough to hold direct block size requested) */
+ if(hdr->man_dtable.row_block_size[child_nrows - 1] < min_dblock_size) {
+ unsigned child_rows_needed; /* Number of rows needed to hold direct block */
+ unsigned child_entry; /* Entry of child indirect block */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Skipping indirect block row that is too small\n", FUNC);
+#endif /* QAK */
+ /* Compute # of rows needed in child indirect block */
+ child_rows_needed = (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) + 2;
+ HDassert(child_rows_needed > child_nrows);
+ child_entry = (next_row + (child_rows_needed - child_nrows)) * hdr->man_dtable.cparam.width;
+ if(child_entry > (iblock->nrows * hdr->man_dtable.cparam.width))
+ child_entry = iblock->nrows * hdr->man_dtable.cparam.width;
+#ifdef QAK
+HDfprintf(stderr, "%s: child_rows_needed = %u\n", FUNC, child_rows_needed);
+HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry);
+#endif /* QAK */
+
+ /* Add skipped indirect ranges to heap's free space */
+ if(H5HF_hdr_skip_ranges(hdr, dxpl_id, iblock, next_entry, (child_entry - next_entry)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space")
+ } /* end if */
+ else {
+ H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */
+ haddr_t new_iblock_addr; /* New indirect block's address */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: Allocating new child indirect block\n", FUNC);
+#endif /* QAK */
+ /* Allocate new indirect block */
+ if(H5HF_man_iblock_create(hdr, dxpl_id, iblock, next_entry, child_nrows, child_nrows, &new_iblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block")
+
+ /* Lock new indirect block */
+ if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, child_nrows, iblock, next_entry, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
+
+ /* Move iterator down one level */
+ if(H5HF_man_iter_down(&hdr->next_block, new_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location")
+
+ /* Check for skipping over rows and add free section for skipped rows */
+ if(min_dblock_size > hdr->man_dtable.cparam.start_block_size) {
+ unsigned new_entry; /* Entry of direct block which is large enough */
+
+ /* Compute entry for direct block size requested */
+ new_entry = hdr->man_dtable.cparam.width * min_dblock_row;
+#ifdef QAK
+HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = %u\n", FUNC, new_entry);
+#endif /* QAK */
+
+ /* Add skipped blocks to heap's free space */
+ if(H5HF_hdr_skip_blocks(hdr, dxpl_id, new_iblock, 0, new_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't add skipped blocks to heap's free space")
+ } /* end if */
+
+ /* Unprotect child indirect block */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock->addr, new_iblock, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+ } /* end else */
+
+ /* Get information about new iterator location */
+ if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL, &next_entry, &iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator location")
+
+ /* Indicate that we walked down */
+ walked_down = TRUE;
+ } /* end if */
+ } while(walked_down || walked_up);
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_hdr_update_iter() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_hdr_inc_iter
+ *
+ * Purpose: Advance "next block" iterator
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 23 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_hdr_inc_iter(H5HF_hdr_t *hdr, hsize_t adv_size, unsigned nentries)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_inc_iter)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(nentries);
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu, adv_size = %Hu\n", FUNC, hdr->man_iter_off, adv_size);
+#endif /* QAK */
+
+ /* Advance the iterator for the current location within the indirect block */
if(hdr->next_block.curr)
if(H5HF_man_iter_next(hdr, &hdr->next_block, nentries) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location")
- /* Update the "allocated" size within the heap */
- hdr->man_alloc_size = new_alloc_size;
+ /* Increment the offset of the iterator in the heap */
+ hdr->man_iter_off += adv_size;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_hdr_inc_iter() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_hdr_reverse_iter
+ *
+ * Purpose: Walk "next block" iterator backwards until the correct
+ * location to allocate next block from is found
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_hdr_reverse_iter(H5HF_hdr_t *hdr, hid_t dxpl_id)
+{
+ H5HF_indirect_t *iblock; /* Indirect block where iterator is located */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_hdr_reverse_iter)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+
+ /* Initialize block iterator, if necessary */
+ if(!H5HF_man_iter_ready(&hdr->next_block))
+ /* Start iterator with previous offset of iterator */
+ if(H5HF_man_iter_start_offset(hdr, dxpl_id, &hdr->next_block, hdr->man_iter_off) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "unable to set block iterator location")
+
+ /* Get information about current iterator location */
+ if(H5HF_man_iter_curr(&hdr->next_block, NULL, NULL, NULL, &iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator information")
#ifdef QAK
-HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", FUNC, hdr->man_alloc_size);
+HDfprintf(stderr, "%s: iblock->nchildren = %u\n", FUNC, iblock->nchildren);
+HDfprintf(stderr, "%s: iblock->parent = %p\n", FUNC, iblock->parent);
#endif /* QAK */
+ /* Walk backwards through heap, looking for direct block to place iterator after */
+
+ /* Walk up the levels in the heap until we find an indirect block with children */
+ while(iblock->nchildren == 0 && iblock->parent) {
+ /* Move iterator to parent of current block */
+ if(H5HF_man_iter_up(&hdr->next_block) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location")
+
+ /* Detach from parent indirect block */
+ if(H5HF_man_iblock_detach(iblock->parent, dxpl_id, iblock->par_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach from parent indirect block")
+ iblock->parent = NULL;
+ iblock->par_entry = 0;
+ } /* end while */
+
+ /* If there's children in this indirect block, walk backwards to find last child */
+ if(iblock->nchildren) {
+ unsigned curr_entry; /* Current entry for iterator */
+ unsigned row; /* Row for entry */
+ hbool_t walked_down; /* Loop flag */
+
+ /* Get information about current iterator location */
+ if(H5HF_man_iter_curr(&hdr->next_block, NULL, NULL, &curr_entry, NULL) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, FAIL, "unable to retrieve current block iterator information")
+#ifdef QAK
+HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry);
+#endif /* QAK */
+
+ /* Move current iterator position backwards once */
+ curr_entry--;
+
+ /* Search backwards for direct block to latch onto */
+ do {
+ int tmp_entry; /* Temp. entry for iterator (use signed value to detect errors) */
+
+ /* Reset loop flag */
+ walked_down = FALSE;
+
+ /* Walk backwards through entries, until we find one that has a child */
+ /* (Account for root indirect block shrinking) */
+ tmp_entry = MIN(curr_entry, ((iblock->nrows * hdr->man_dtable.cparam.width) - 1));
+#ifdef QAK
+HDfprintf(stderr, "%s: tmp_entry = %d\n", FUNC, tmp_entry);
+HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
+#endif /* QAK */
+ while(!H5F_addr_defined(iblock->ents[tmp_entry].addr)) {
+ tmp_entry--;
+ HDassert(tmp_entry >= 0);
+ } /* end while */
+#ifdef QAK
+HDfprintf(stderr, "%s: check 2.0 - tmp_entry = %d\n", FUNC, tmp_entry);
+#endif /* QAK */
+ curr_entry = tmp_entry;
+
+ /* Check if entry is for a direct block */
+ row = curr_entry / hdr->man_dtable.cparam.width;
+ if(row < hdr->man_dtable.max_direct_rows) {
+ /* Increment entry to empty location */
+ curr_entry++;
+
+ /* Set the current location of the iterator to next entry after the existing direct block */
+ if(H5HF_man_iter_set_entry(hdr, &hdr->next_block, curr_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "unable to set current block iterator location")
+
+ /* Update iterator offset */
+ hdr->man_iter_off = iblock->block_off;
+ hdr->man_iter_off += hdr->man_dtable.row_block_off[curr_entry / hdr->man_dtable.cparam.width];
+ hdr->man_iter_off += hdr->man_dtable.row_block_size[curr_entry / hdr->man_dtable.cparam.width] * (curr_entry % hdr->man_dtable.cparam.width);
+ } /* end if */
+ else {
+ H5HF_indirect_t *child_iblock; /* Pointer to child indirect block */
+ unsigned child_nrows; /* # of rows in child block */
+
+ /* Compute # of rows in next child indirect block to use */
+ child_nrows = H5HF_dtable_size_to_rows(&hdr->man_dtable, hdr->man_dtable.row_block_size[row]);
+
+ /* Lock child indirect block */
+ if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, iblock->ents[curr_entry].addr, child_nrows, iblock, curr_entry, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
+
+ /* Set the current location of the iterator */
+ if(H5HF_man_iter_set_entry(hdr, &hdr->next_block, curr_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSET, FAIL, "unable to set current block iterator location")
+
+ /* Walk down into child indirect block (pins child block) */
+ if(H5HF_man_iter_down(&hdr->next_block, child_iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, FAIL, "unable to advance current block iterator location")
+
+ /* Update iterator location */
+ iblock = child_iblock;
+ curr_entry = (child_iblock->nrows * hdr->man_dtable.cparam.width) - 1;
+
+ /* Unprotect child indirect block */
+ if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, child_iblock->addr, child_iblock, H5AC__NO_FLAGS_SET) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+
+ /* Note that we walked down */
+ walked_down = TRUE;
+ } /* end else */
+ } while(walked_down);
+ } /* end if */
+ else {
+ /* Reset header information back to "empty heap" state */
+ if(H5HF_hdr_empty(hdr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't make heap empty")
+ } /* end else */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_hdr_inc_alloc() */
+} /* end H5HF_hdr_reverse_iter() */
/*-------------------------------------------------------------------------
@@ -584,13 +1309,10 @@ HDfprintf(stderr, "%s: Reseting heap header to empty\n", FUNC);
/* Sanity check */
HDassert(hdr);
- /* Reset root pointer information */
- hdr->man_dtable.curr_root_rows = 0;
- hdr->man_dtable.table_addr = HADDR_UNDEF;
-
/* Shrink heap size */
hdr->total_size = hdr->std_size;
hdr->man_size = 0;
+ hdr->man_alloc_size = 0;
/* Reset the free space in direct blocks */
hdr->total_man_free = 0;
diff --git a/src/H5HFiblock.c b/src/H5HFiblock.c
index f3d7029..652ae54 100644
--- a/src/H5HFiblock.c
+++ b/src/H5HFiblock.c
@@ -56,24 +56,9 @@
/********************/
/* Local Prototypes */
/********************/
+static herr_t H5HF_man_iblock_root_halve(H5HF_indirect_t *root_iblock, hid_t dxpl_id);
+static herr_t H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id);
-/* 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, hid_t dxpl_id,
- H5HF_indirect_t *iblock, haddr_t iblock_addr,
- unsigned start_entry, unsigned nentries);
-
-/* 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);
/*********************/
/* Package Variables */
@@ -160,10 +145,40 @@ H5HF_iblock_decr(H5HF_indirect_t *iblock)
iblock->rc--;
/* Mark block as evictable again when no child blocks depend on it */
- if(iblock->rc == 0)
+ if(iblock->rc == 0) {
+ H5HF_indirect_t *tmp_iblock; /* Temporary pointer to indirect block */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: indirect block ref. count at zero, iblock->addr = %a\n", FUNC, iblock->addr);
+#endif /* QAK */
+ /* Lock indirect block */
+ if(iblock->nchildren == 0) {
+ if(NULL == (tmp_iblock = H5HF_man_iblock_protect(iblock->hdr, H5AC_dxpl_id, iblock->addr, iblock->nrows, NULL, 0, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
+ HDassert(tmp_iblock == iblock);
+ } /* end if */
+
if(H5AC_unpin_entry(iblock->hdr->f, iblock) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPIN, FAIL, "unable to unpin fractal heap indirect block")
+/* XXX: If the indirect block has no children, delete indirect block's entry
+ * from cache.
+ */
+ if(iblock->nchildren == 0) {
+ /* Check for deleting root indirect block (and no root direct block) */
+ if(iblock->block_off == 0 && iblock->hdr->man_dtable.curr_root_rows > 0) {
+ /* Reset root pointer information */
+ iblock->hdr->man_dtable.curr_root_rows = 0;
+ iblock->hdr->man_dtable.table_addr = HADDR_UNDEF;
+ } /* end if */
+
+ /* Unlock indirect block with delete flag */
+ if(H5AC_unprotect(iblock->hdr->f, H5AC_dxpl_id, H5AC_FHEAP_IBLOCK, iblock->addr, tmp_iblock, H5AC__DIRTIED_FLAG|H5AC__DELETED_FLAG) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap indirect block")
+ tmp_iblock = NULL;
+ } /* end if */
+ } /* end if */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_iblock_decr() */
@@ -195,23 +210,9 @@ HDfprintf(stderr, "%s: Marking indirect block as dirty\n", FUNC);
/* Sanity check */
HDassert(iblock);
-/* XXX: Need to mark a protected block as dirty eventually also... */
-{
- unsigned entry_status; /* Indirect block entry status */
-
- if(H5AC_get_entry_status(iblock->hdr->f, iblock->addr, &entry_status) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to query fractal heap indirect block status")
- HDassert(entry_status & H5AC_ES__IN_CACHE);
-
- if(!(entry_status & H5AC_ES__IS_PROTECTED)) {
- /* Mark indirect block as dirty in cache */
- if(H5AC_mark_pinned_entry_dirty(iblock->hdr->f, iblock, FALSE, 0) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark fractal heap indirect block as dirty")
- } /* end if */
-}
-
- /* Set the dirty flag for the indirect block */
- iblock->dirty = TRUE;
+ /* Mark indirect block as dirty in cache */
+ if(H5AC_mark_pinned_or_protected_entry_dirty(iblock->hdr->f, iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMARKDIRTY, FAIL, "unable to mark fractal heap indirect block as dirty")
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -219,245 +220,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HF_man_iblock_skip_blocks
- *
- * Purpose: Add skipped direct blocks to free space for heap
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Apr 3 2006
- *
- *-------------------------------------------------------------------------
- */
-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)
-{
- H5HF_free_section_t *sec_node; /* Pointer to free list section for range */
- hsize_t sect_off; /* Offset of free section in heap */
- unsigned curr_row; /* Current row in indirect block */
- unsigned curr_col; /* Current column in indirect block */
- unsigned u; /* Local index variables */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_skip_blocks)
-#ifdef QAK
-HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries);
-#endif /* QAK */
-
- /*
- * Check arguments.
- */
- HDassert(hdr);
- HDassert(iblock);
- HDassert(H5F_addr_defined(iblock_addr));
-
- /* Compute starting column & row */
- curr_row = start_entry / hdr->man_dtable.cparam.width;
- curr_col = start_entry % hdr->man_dtable.cparam.width;
-
- /* Initialize information for rows skipped over */
- sect_off = iblock->block_off;
- for(u = 0; u < curr_row; u++)
- sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
- sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col;
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Loop over the blocks to skip */
- for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) {
- unsigned row_entries; /* Number of entries in a particular row */
-
- /* Compute number of entries in (possible partial) current row */
- row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u);
-#ifdef QAK
-HDfprintf(stderr, "%s: u = %u\n", FUNC, u);
-HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
-HDfprintf(stderr, "%s: row_entries = %u, hdr->man_dtable.row_dblock_free[%u] = %Hu\n", FUNC, row_entries, curr_row, hdr->man_dtable.row_dblock_free[curr_row]);
-#endif /* QAK */
-
- /* Add free space section for blocks in this row */
-
- /* Create free list section node for blocks skipped over */
- 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_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")
- sec_node->u.range.row = curr_row;
- sec_node->u.range.col = curr_col;
- sec_node->u.range.num_entries = row_entries;
-
- /* Add new free space to the global list of space */
- 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 */
- sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row];
- curr_row++;
- curr_col = 0; /* (first partial row aligns this) */
-
- /* Increment index variable */
- u += row_entries;
- } /* end for */
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Advance the allocated heap size/new block iterator */
- if(H5HF_hdr_inc_alloc(hdr, sect_off, nentries) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_man_iblock_skip_blocks() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_man_iblock_skip_ranges
- *
- * Purpose: Add skipped indirect ranges to free space for heap
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Apr 4 2006
- *
- *-------------------------------------------------------------------------
- */
-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)
-{
- H5HF_free_section_t *sec_node; /* Pointer to free list section for range */
- hsize_t sect_off; /* Offset of free section in heap */
- size_t row_dblock_free_space; /* Size of free space for row of direct blocks in a row */
- size_t acc_row_dblock_free_space; /* Accumulated size of free space for row of direct blocks in a row */
- unsigned curr_row; /* Current row in indirect block */
- unsigned curr_col; /* Current column in indirect block */
- unsigned u, w; /* Local index variables */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_skip_ranges)
-#ifdef QAK
-HDfprintf(stderr, "%s: start_entry = %u, nentries = %u\n", FUNC, start_entry, nentries);
-#endif /* QAK */
-
- /*
- * Check arguments.
- */
- HDassert(hdr);
- HDassert(iblock);
- HDassert(H5F_addr_defined(iblock_addr));
-
- /* Compute starting column & row */
- curr_row = start_entry / hdr->man_dtable.cparam.width;
- curr_col = start_entry % hdr->man_dtable.cparam.width;
-#ifdef QAK
-HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
-#endif /* QAK */
-
- /* Initialize information for rows skipped over */
- sect_off = iblock->block_off;
- for(u = 0; u < curr_row; u++)
- sect_off += hdr->man_dtable.row_block_size[u] * hdr->man_dtable.cparam.width;
- sect_off += hdr->man_dtable.row_block_size[curr_row] * curr_col;
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Loop over the blocks to skip */
- for(u = start_entry; u < (start_entry + nentries); /* u is advanced in loop */) {
- unsigned row_entries; /* Number of entries in a particular row */
- unsigned num_rows; /* Number of rows in indirect blocks referenced */
-
- /* Compute number of rows in indirect blocks covered by entry */
- num_rows = (H5V_log2_of2((uint32_t)hdr->man_dtable.row_block_size[curr_row]) -
- H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) - 1;
-
- /* Compute number of entries in (possible partial) current row */
- row_entries = MIN(hdr->man_dtable.cparam.width - curr_col, (start_entry + nentries) - u);
-#ifdef QAK
-HDfprintf(stderr, "%s: u = %u\n", FUNC, u);
-HDfprintf(stderr, "%s: curr_col = %u, curr_row = %u\n", FUNC, curr_col, curr_row);
-HDfprintf(stderr, "%s: row_entries = %u, num_rows = %u\n", FUNC, row_entries, num_rows);
-#endif /* QAK */
-
- /* Loop over rows in indirect blocks covered */
- acc_row_dblock_free_space = 0;
- for(w = 0; w < num_rows; w++) {
-
- /* Compute free space in direct blocks for this row */
- row_dblock_free_space = hdr->man_dtable.cparam.width * hdr->man_dtable.row_dblock_free[w];
- acc_row_dblock_free_space += row_dblock_free_space;
-#ifdef QAK
-HDfprintf(stderr, "%s: w = %u\n", FUNC, w);
-HDfprintf(stderr, "%s: hdr->man_dtable.row_dblock_free[%u] = %Zu\n", FUNC, w, hdr->man_dtable.row_dblock_free[w]);
-#endif /* QAK */
-
- /* Add "indirect" free space section for blocks in this row */
-
- /* Create free list section node for blocks skipped over */
- 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_info.addr = sect_off + hdr->man_dtable.row_block_off[w];
-#ifdef QAK
-HDfprintf(stderr, "%s: sec_node->sect_info.addr = %a\n", FUNC, sec_node->sect_info.addr);
-#endif /* QAK */
- 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")
- sec_node->u.indirect.row = curr_row;
- sec_node->u.indirect.col = curr_col;
- sec_node->u.indirect.num_entries = row_entries;
- sec_node->u.indirect.indir_row = w;
- sec_node->u.indirect.indir_nrows = num_rows;
-
- /* Add new free space to the global list of space */
- 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
-HDfprintf(stderr, "%s: acc_row_dblock_free_space = %Zu\n", FUNC, acc_row_dblock_free_space);
-#endif /* QAK */
-
- /* Advance row & column position */
- sect_off += row_entries * hdr->man_dtable.row_block_size[curr_row];
- curr_row++;
- curr_col = 0; /* (first partial row aligns this) */
-
- /* Advance outer loop index */
- u += row_entries;
- } /* end for */
-#ifdef QAK
-HDfprintf(stderr, "%s: sect_off = %Zu\n", FUNC, sect_off);
-#endif /* QAK */
-
- /* Advance the allocated heap size/new block iterator */
- if(H5HF_hdr_inc_alloc(hdr, sect_off, nentries) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't increase allocated heap size")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_man_iblock_skip_ranges() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5HF_man_iblock_root_create
*
* Purpose: Create root indirect block
@@ -470,7 +232,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
+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 */
@@ -508,7 +270,7 @@ 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)
+ if(H5HF_man_iblock_create(hdr, dxpl_id, NULL, 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);
@@ -532,30 +294,27 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl
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 */
+ /* Attach direct block to new root 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")
+ if(H5HF_man_iblock_attach(iblock, 0, hdr->man_dtable.table_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach root direct block to parent indirect block")
- /* Unlock first (root) direct block */
+ /* Unlock first (previously the 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)
+ /* Start iterator at correct location */
+ if(H5HF_hdr_start_iter(hdr, iblock, (hsize_t)(have_direct_block ? hdr->man_dtable.cparam.start_block_size : 0), 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)
+ if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, 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 */
@@ -582,13 +341,9 @@ HDfprintf(stderr, "%s: have_direct_block = %u\n", FUNC, (unsigned)have_direct_bl
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)
+ if(H5HF_hdr_adjust_heap(hdr, hdr->man_dtable.row_block_off[nrows], (hssize_t)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() */
@@ -607,7 +362,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-static herr_t
+herr_t
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 */
@@ -665,7 +420,7 @@ HDfprintf(stderr, "%s: new_next_entry = %u\n", FUNC, new_next_entry);
#endif /* QAK */
/* 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
+* to 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
@@ -674,8 +429,8 @@ HDfprintf(stderr, "%s: new_next_entry = %u\n", FUNC, new_next_entry);
* QAK - 3/14/2006
*/
/* Free previous indirect block disk space */
- if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size)<0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block")
+ if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space")
/* Compute size of buffer needed for new indirect block */
iblock->nrows = new_nrows;
@@ -695,8 +450,8 @@ 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, dxpl_id, iblock, new_addr,
- next_entry, (new_next_entry - next_entry)) < 0)
+ if(H5HF_hdr_skip_blocks(hdr, dxpl_id, iblock, 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 */
@@ -714,9 +469,11 @@ HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr);
HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
/* Move object in cache, if it actually was relocated */
- if(H5F_addr_ne(iblock->addr, new_addr))
+ if(H5F_addr_ne(iblock->addr, new_addr)) {
if(H5AC_rename(hdr->f, H5AC_FHEAP_IBLOCK, iblock->addr, new_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTSPLIT, FAIL, "unable to move fractal heap root indirect block")
+ iblock->addr = new_addr;
+ } /* end if */
/* Update other shared header info */
hdr->man_dtable.curr_root_rows = new_nrows;
@@ -728,363 +485,186 @@ HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows - 1] = %Hu\n", FU
HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows]);
HDfprintf(stderr, "%s: acc_dblock_free = %Hu\n", FUNC, acc_dblock_free);
#endif /* QAK */
- if(H5HF_hdr_extend_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], acc_dblock_free) < 0)
+ if(H5HF_hdr_adjust_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], (hssize_t)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")
-
-/* XXX: Sanity check until can rename pinned entry in metadata cache */
-#ifndef NDEBUG
-{
-H5HF_indirect_t *old_root_iblock = iblock;
-#endif /* NDEBUG */
-
- /* Lock root indirect block (again) */
- if(NULL == (iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_addr, hdr->man_dtable.curr_root_rows, NULL, 0, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
- iblock->addr = new_addr;
-
-#ifndef NDEBUG
- HDassert(old_root_iblock == iblock);
-}
-#endif /* NDEBUG */
-
- /* Update the indirect block pointer in iterator */
- /* (pins the indirect block after it's in the new location) */
- if(H5HF_man_iter_update_iblock(&hdr->next_block, iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTMODIFY, FAIL, "unable to update indirect block for block iterator")
-
- /* Release the indirect block (marked as dirty) */
- 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")
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_root_double() */
/*-------------------------------------------------------------------------
- * Function: H5HF_man_iblock_place_dblock
- *
- * Purpose: Find indirect block with location for placing a direct block
+ * Function: H5HF_man_iblock_root_halve
*
- * Note: Creates necessary indirect blocks
+ * Purpose: Halve size of root indirect block
*
- * Return: Pointer to indirect block on success, NULL on failure
+ * Return: SUCCEED/FAIL
*
* Programmer: Quincey Koziol
* koziol@ncsa.uiuc.edu
- * Mar 14 2006
+ * Jun 12 2006
*
*-------------------------------------------------------------------------
*/
-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)
+static herr_t
+H5HF_man_iblock_root_halve(H5HF_indirect_t *iblock, hid_t dxpl_id)
{
- H5HF_indirect_t *ret_value; /* Return value */
+ H5HF_hdr_t *hdr = iblock->hdr; /* Pointer to heap header */
+ haddr_t new_addr; /* New address of indirect block */
+ hsize_t acc_dblock_free; /* Accumulated free space in direct blocks */
+ unsigned max_child_row; /* Row for max. child entry */
+ unsigned new_nrows; /* New # of rows */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_place_dblock)
-#ifdef QAK
-HDfprintf(stderr, "%s: min_dblock_size = %Zu\n", FUNC, min_dblock_size);
-#endif /* QAK */
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_root_halve)
- /*
- * Check arguments.
- */
+ /* Sanity check */
+ HDassert(iblock);
+ HDassert(iblock->parent == NULL);
HDassert(hdr);
- HDassert(min_dblock_size > 0);
-
- /* Check for creating first indirect block */
- if(hdr->man_dtable.curr_root_rows == 0) {
- 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 */
- unsigned min_dblock_row; /* Minimum row for direct block size request */
#ifdef QAK
-HDfprintf(stderr, "%s: searching root indirect block\n", FUNC);
+HDfprintf(stderr, "%s: Reducing root indirect block\n", FUNC);
#endif /* QAK */
- /* Compute min. row for direct block requested */
- min_dblock_row = H5HF_dtable_size_to_row(&hdr->man_dtable, min_dblock_size);
-#ifdef QAK
-HDfprintf(stderr, "%s: min_dblock_size = %Zu, min_dblock_row = %u\n", FUNC, min_dblock_size, min_dblock_row);
-#endif /* QAK */
-
- /* Initialize block iterator, if necessary */
- if(!H5HF_man_iter_ready(&hdr->next_block)) {
-#ifdef QAK
-HDfprintf(stderr, "%s: hdr->man_alloc_size = %Hu\n", FUNC, hdr->man_alloc_size);
-#endif /* QAK */
- /* Start iterator with offset of allocated space */
- if(H5HF_man_iter_start_offset(hdr, dxpl_id, &hdr->next_block, hdr->man_alloc_size) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, NULL, "unable to set block iterator location")
- } /* end if */
- /* Get information about current iterator location */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
+ /* Compute maximum row used by child of indirect block */
+ max_child_row = iblock->max_child / hdr->man_dtable.cparam.width;
+ /* Compute new # of rows in root indirect block */
+ new_nrows = 1 << (1 + H5V_log2_gen((hsize_t)max_child_row));
#ifdef QAK
-HDfprintf(stderr, "%s: Check 1.0\n", FUNC);
-HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
+HDfprintf(stderr, "%s: new_nrows = %u\n", FUNC, new_nrows);
HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
#endif /* QAK */
- /* Check for skipping over blocks in the current block */
- if(min_dblock_row > next_row && next_row < iblock->nrows) {
- unsigned min_entry; /* Min entry for direct block requested */
- unsigned skip_entries; /* Number of entries to skip in the current block */
-
- /* Compute the number of entries to skip in the current block */
- min_entry = min_dblock_row * hdr->man_dtable.cparam.width;
- if(min_dblock_row >= iblock->nrows)
- skip_entries = (iblock->nrows * hdr->man_dtable.cparam.width) - next_entry;
- else
- skip_entries = min_entry - next_entry;
-#ifdef QAK
-HDfprintf(stderr, "%s: min_entry = %u, skip_entries = %u\n", FUNC, min_entry, skip_entries);
-#endif /* QAK */
-
- /* Add skipped direct blocks to heap's free space */
- 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 */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
- } /* end if */
+/* Currently, the old block data is "thrown away" after the space is reallocated,
+* to 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 - 6/12/2006
+*/
+ /* Free previous indirect block disk space */
+ if(H5MF_xfree(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block file space")
- do {
- /* Reset conditions for leaving loop */
- walked_up = walked_down = FALSE;
+ /* Compute free space in rows to delete */
+ acc_dblock_free = 0;
+ for(u = new_nrows; u < iblock->nrows; u++)
+ acc_dblock_free += hdr->man_dtable.row_dblock_free[u] * hdr->man_dtable.cparam.width;
-#ifdef QAK
-HDfprintf(stderr, "%s: Check 2.0\n", FUNC);
-HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
-HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
-#endif /* QAK */
+ /* Compute size of buffer needed for new indirect block */
+ iblock->nrows = new_nrows;
+ iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock);
- /* Check for walking off end of indirect block */
- /* (walk up iterator) */
- while(next_row >= iblock->nrows) {
-#ifdef QAK
-HDfprintf(stderr, "%s: Off the end of a block\n", FUNC);
-#endif /* QAK */
- /* Check for needing to expand root indirect block */
- if(iblock->parent == NULL) {
-#ifdef QAK
-HDfprintf(stderr, "%s: Doubling root block\n", FUNC);
-#endif /* QAK */
- 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 {
-#ifdef QAK
-HDfprintf(stderr, "%s: Walking up a level\n", FUNC);
-#endif /* QAK */
- /* Move iterator up one level */
- if(H5HF_man_iter_up(&hdr->next_block) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, NULL, "unable to advance current block iterator location")
-
- /* Increment location of next block at this level */
- 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")
- } /* end else */
-
- /* Get information about new iterator location */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
-
- /* Indicate that we walked up */
- walked_up = TRUE;
- } /* end while */
+ /* Allocate space for the new indirect block on disk */
+ if(HADDR_UNDEF == (new_addr = H5MF_alloc(hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, (hsize_t)iblock->size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
#ifdef QAK
-HDfprintf(stderr, "%s: Check 3.0\n", FUNC);
-HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
-HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
+HDfprintf(stderr, "%s: new_addr = %a\n", FUNC, new_addr);
#endif /* QAK */
- /* Check for walking into child indirect block */
- /* (walk down iterator) */
- if(next_row >= hdr->man_dtable.max_direct_rows) {
- hsize_t next_size; /* Size of next direct block to create */
- unsigned child_nrows; /* Number of rows in new indirect block */
+ /* Re-allocate direct block entry table */
+ if(NULL == (iblock->ents = H5FL_SEQ_REALLOC(H5HF_indirect_ent_t, iblock->ents, (iblock->nrows * hdr->man_dtable.cparam.width))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for direct entries")
-#ifdef QAK
-HDfprintf(stderr, "%s: Walking down into child indirect block\n", FUNC);
-#endif /* QAK */
-#ifdef QAK
-HDfprintf(stderr, "%s: Check 3.1\n", FUNC);
-HDfprintf(stderr, "%s: iblock = %p\n", FUNC, iblock);
-HDfprintf(stderr, "%s: iblock->nrows = %u\n", FUNC, iblock->nrows);
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
-#endif /* QAK */
- HDassert(!H5F_addr_defined(iblock->ents[next_entry].addr));
+ /* Move object in cache, if it actually was relocated */
+ if(H5F_addr_ne(iblock->addr, new_addr)) {
+ if(H5AC_rename(hdr->f, H5AC_FHEAP_IBLOCK, iblock->addr, new_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSPLIT, FAIL, "unable to move fractal heap root indirect block")
+ iblock->addr = new_addr;
+ } /* end if */
- /* Compute # of rows in next child indirect block to use */
- next_size = hdr->man_dtable.row_block_size[next_row];
- child_nrows = (H5V_log2_gen(next_size) - hdr->man_dtable.first_row_bits) + 1;
-#ifdef QAK
-HDfprintf(stderr, "%s: child_nrows = %u\n", FUNC, child_nrows);
-#endif /* QAK */
+ /* 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")
- /* Check for skipping over indirect blocks */
- /* (that don't have direct blocks large enough to hold direct block size requested) */
- if(hdr->man_dtable.row_block_size[child_nrows - 1] < min_dblock_size) {
- unsigned child_rows_needed; /* Number of rows needed to hold direct block */
- unsigned child_entry; /* Entry of child indirect block */
+ /* Update other shared header info */
+ hdr->man_dtable.curr_root_rows = new_nrows;
+ hdr->man_dtable.table_addr = new_addr;
+ /* Shrink heap to only cover new root indirect block */
#ifdef QAK
-HDfprintf(stderr, "%s: Skipping indirect block row that is too small\n", FUNC);
-#endif /* QAK */
- /* Compute # of rows needed in child indirect block */
- child_rows_needed = (H5V_log2_of2(min_dblock_size) - H5V_log2_of2(hdr->man_dtable.cparam.start_block_size)) + 2;
- HDassert(child_rows_needed > child_nrows);
- child_entry = (next_row + (child_rows_needed - child_nrows)) * hdr->man_dtable.cparam.width;
- if(child_entry > (iblock->nrows * hdr->man_dtable.cparam.width))
- child_entry = iblock->nrows * hdr->man_dtable.cparam.width;
-#ifdef QAK
-HDfprintf(stderr, "%s: child_rows_needed = %u\n", FUNC, child_rows_needed);
-HDfprintf(stderr, "%s: child_entry = %u\n", FUNC, child_entry);
+HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows - 1] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows - 1]);
+HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[new_nrows] = %Hu\n", FUNC, hdr->man_dtable.row_block_off[new_nrows]);
+HDfprintf(stderr, "%s: acc_dblock_free = %Hu\n", FUNC, acc_dblock_free);
#endif /* QAK */
+ if(H5HF_hdr_adjust_heap(hdr, 2 * hdr->man_dtable.row_block_off[new_nrows - 1], -(hssize_t)acc_dblock_free) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce space to cover root direct block")
- /* Add skipped indirect ranges to heap's free space */
- 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 {
- H5HF_indirect_t *new_iblock; /* Pointer to new indirect block */
- hsize_t new_iblock_off; /* Direct block offset in heap address space */
- haddr_t new_iblock_addr; /* New indirect block's address */
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_iblock_root_halve() */
-#ifdef QAK
-HDfprintf(stderr, "%s: Allocating new child indirect block\n", FUNC);
-#endif /* QAK */
- /* Compute the direct block's offset in the heap's address space */
- new_iblock_off = iblock->block_off;
- new_iblock_off += hdr->man_dtable.row_block_off[next_entry / hdr->man_dtable.cparam.width];
- new_iblock_off += hdr->man_dtable.row_block_size[next_entry / hdr->man_dtable.cparam.width] * (next_entry % hdr->man_dtable.cparam.width);
-
- /* Allocate new indirect block */
- if(H5HF_man_iblock_create(hdr, dxpl_id, new_iblock_off, child_nrows, child_nrows, &new_iblock_addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, NULL, "can't allocate fractal heap indirect block")
-
- /* Lock new indirect block */
- if(NULL == (new_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, new_iblock_addr, child_nrows, iblock, next_entry, H5AC_WRITE)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, NULL, "unable to protect fractal heap indirect block")
-
- /* Set parent information */
- HDassert(new_iblock->parent == NULL);
- new_iblock->parent = iblock;
- new_iblock->par_entry = next_entry;
- if(H5HF_iblock_incr(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
-
- /* Point current indirect block at new indirect block */
- iblock->ents[next_entry].addr = new_iblock_addr;
-
- /* Move iterator down one level */
- if(H5HF_man_iter_down(&hdr->next_block, new_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTNEXT, NULL, "unable to advance current block iterator location")
-
- /* Get information about new iterator location */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, NULL) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
- next_size = hdr->man_dtable.row_block_size[next_row];
-#ifdef QAK
-HDfprintf(stderr, "%s: next_row = %u\n", FUNC, next_row);
-HDfprintf(stderr, "%s: next_entry = %u\n", FUNC, next_entry);
-#endif /* QAK */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iblock_root_revert
+ *
+ * Purpose: Revert root indirect block back to root direct block
+ *
+ * Note: Any sections left pointing to the old root indirect block
+ * will be cleaned up by the free space manager
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_man_iblock_root_revert(H5HF_indirect_t *root_iblock, hid_t dxpl_id)
+{
+ H5HF_hdr_t *hdr; /* Pointer to heap's header */
+ H5HF_direct_t *dblock = NULL; /* Pointer to new root indirect block */
+ haddr_t dblock_addr; /* Direct block's address in the file */
+ size_t dblock_size; /* Direct block's size */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_root_revert)
- /* Check for skipping over rows and add free section for skipped rows */
- if(min_dblock_size > next_size) {
- unsigned new_entry; /* Entry of direct block which is large enough */
+ /*
+ * Check arguments.
+ */
+ HDassert(root_iblock);
- /* Compute entry for direct block size requested */
- new_entry = hdr->man_dtable.cparam.width * min_dblock_row;
#ifdef QAK
-HDfprintf(stderr, "%s: Skipping rows in new child indirect block - new_entry = %u\n", FUNC, new_entry);
+HDfprintf(stderr, "%s: Reverting root indirect block\n", FUNC);
#endif /* QAK */
- /* Add skipped blocks to heap's free space */
- 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 */
-
- /* Mark new indirect block as modified */
- if(H5HF_iblock_dirty(new_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty")
+ /* Set up local convenience variables */
+ hdr = root_iblock->hdr;
+ dblock_addr = root_iblock->ents[0].addr;
+ dblock_size = hdr->man_dtable.cparam.start_block_size;
- /* Mark current indirect block as modified */
- if(H5HF_iblock_dirty(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, NULL, "can't mark indirect block as dirty")
+ /* Get pointer to last direct block */
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, root_iblock, 0, H5AC_WRITE)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap direct block")
- /* Unprotect child indirect block */
- if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, new_iblock->addr, new_iblock, H5AC__DIRTIED_FLAG) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, NULL, "unable to release fractal heap indirect block")
- } /* end else */
+ /* Detach direct block from parent */
+ if(H5HF_man_iblock_detach(dblock->parent, dxpl_id, dblock->par_entry) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't detach direct block from parent indirect block")
+ dblock->parent = NULL;
+ dblock->par_entry = 0;
- /* Get information about new iterator location */
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
+ /* Point root at direct block */
+ hdr->man_dtable.curr_root_rows = 0;
+ hdr->man_dtable.table_addr = dblock_addr;
- /* Indicate that we walked down */
- walked_down = TRUE;
- } /* end if */
- } while(walked_down || walked_up);
- } /* end else */
-
- /* 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 */
-
- if(H5HF_man_iter_curr(&hdr->next_block, &next_row, NULL,
- &next_entry, &iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTGET, NULL, "unable to retrieve current block iterator location")
- HDassert(next_row < iblock->nrows);
- next_size = hdr->man_dtable.row_block_size[next_row];
-
- /* Check for skipping over blocks */
- if(min_dblock_size > next_size) {
-HDfprintf(stderr, "%s: Skipping direct block sizes not supported, min_dblock_size = %Zu, next_size = %Zu\n", FUNC, min_dblock_size, next_size);
-HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, NULL, "skipping direct block sizes not supported yet")
- } /* end if */
-
- /* Set entry for new direct block to use */
- *entry_p = next_entry;
-
- /* Set size of direct block to create */
- *dblock_size = next_size;
-
- /* Set return value */
- ret_value = iblock;
-}
+ /* Reset 'next block' iterator */
+ if(H5HF_hdr_reset_iter(hdr, (hsize_t)dblock_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't reset block iterator")
done:
+ if(dblock && 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")
+
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_man_iblock_place_dblock() */
+} /* end H5HF_man_iblock_root_revert() */
/*-------------------------------------------------------------------------
@@ -1132,12 +712,6 @@ H5HF_man_iblock_alloc_range(H5HF_hdr_t *hdr, hid_t dxpl_id,
/* Compute info about range */
cur_entry = (old_sec_node->u.range.row * hdr->man_dtable.cparam.width) + old_sec_node->u.range.col;
- /* Check for range covering indirect blocks */
- if(old_sec_node->u.range.row >= hdr->man_dtable.max_direct_rows) {
-HDfprintf(stderr, "%s: Can't handle range sections over indirect blocks yet\n", FUNC);
-HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections over indirect blocks not supported yet")
- } /* end if */
-
/* Get a pointer to the indirect block covering the range */
iblock = old_sec_node->u.range.iblock;
HDassert(iblock);
@@ -1146,42 +720,13 @@ HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "'range' free space sections over i
HDfprintf(stderr, "%s: cur_entry = %u\n", FUNC, cur_entry);
HDfprintf(stderr, "%s: old_sec_node->u.range.num_entries = %u\n", FUNC, old_sec_node->u.range.num_entries);
#endif /* QAK */
-#ifdef QAK
-HDfprintf(stderr, "%s: hdr->man_dtable.row_block_size[old_sec_node->u.range.row] = %Hu\n", FUNC, 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_info.addr, &dblock_addr, &dblock_sec_node) < 0)
+ if(H5HF_man_dblock_create(dxpl_id, hdr, iblock, cur_entry, &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 */
- iblock->ents[cur_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")
-
- /* Check for only single block covered in range section */
- if(old_sec_node->u.range.num_entries == 1) {
- /* 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);
- } /* end if */
- else {
- /* Adjust section information */
- 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_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 */
+ /* Reduce (& possibly re-add) 'range' section */
+ if(H5HF_sect_range_reduce(hdr, dxpl_id, old_sec_node) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce indirect section node")
/* Point 'sec_node' at new direct block section node */
*sec_node = dblock_sec_node;
@@ -1217,7 +762,6 @@ H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id,
haddr_t child_iblock_addr; /* Address of child indirect block */
haddr_t dblock_addr; /* New direct block's address */
H5HF_free_section_t *dblock_sec_node = NULL; /* Pointer to direct block's section node */
- H5HF_free_section_t *range_sec_node = NULL; /* Pointer to new range section node */
H5HF_free_section_t *old_sec_node = *sec_node; /* Pointer to old indirect section node */
unsigned curr_entry; /* Current entry in indirect block */
unsigned dblock_entry; /* Entry of direct block in child indirect block */
@@ -1246,8 +790,10 @@ H5HF_man_iblock_alloc_indirect(H5HF_hdr_t *hdr, hid_t dxpl_id,
#ifdef QAK
HDfprintf(stderr, "%s: curr_entry = %u\n", FUNC, curr_entry);
+HDfprintf(stderr, "%s: iblock->addr = %a\n", FUNC, iblock->addr);
+HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off);
+HDfprintf(stderr, "%s: iblock->parent = %p\n", FUNC, iblock->parent);
HDfprintf(stderr, "%s: iblock->ents[curr_entry].addr = %a\n", FUNC, iblock->ents[curr_entry].addr);
-HDfprintf(stderr, "%s: iblock->ents[curr_entry].free_space = %Hu\n", FUNC, iblock->ents[curr_entry].free_space);
HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_nrows = %u\n", FUNC, old_sec_node->u.indirect.indir_nrows);
HDfprintf(stderr, "%s: old_sec_node->u.indirect.num_entries = %u\n", FUNC, old_sec_node->u.indirect.num_entries);
#endif /* QAK */
@@ -1260,42 +806,16 @@ HDfprintf(stderr, "%s: old_sec_node->u.indirect.num_entries = %u\n", FUNC, old_s
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
} /* end if */
else {
- hsize_t new_iblock_off; /* Offset of new indirect block */
-
- /* Compute heap offset of new indirect block */
- new_iblock_off = iblock->block_off +
- hdr->man_dtable.row_block_off[old_sec_node->u.indirect.row] +
- (old_sec_node->u.indirect.col *
- hdr->man_dtable.row_block_size[old_sec_node->u.indirect.row]);
-#ifdef QAK
-HDfprintf(stderr, "%s: iblock->block_off = %Hu\n", FUNC, iblock->block_off);
-HDfprintf(stderr, "%s: new_iblock_off = %Hu\n", FUNC, new_iblock_off);
-#endif /* QAK */
-
/* Create child indirect block */
- if(H5HF_man_iblock_create(hdr, dxpl_id, new_iblock_off, old_sec_node->u.indirect.indir_nrows, old_sec_node->u.indirect.indir_nrows, &child_iblock_addr) < 0)
+ if(H5HF_man_iblock_create(hdr, dxpl_id, iblock, curr_entry, old_sec_node->u.indirect.indir_nrows, old_sec_node->u.indirect.indir_nrows, &child_iblock_addr) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTALLOC, FAIL, "can't allocate fractal heap indirect block")
/* Lock new child indirect block */
if(NULL == (child_iblock = H5HF_man_iblock_protect(hdr, dxpl_id, child_iblock_addr, old_sec_node->u.indirect.indir_nrows, iblock, curr_entry, H5AC_WRITE)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to protect fractal heap indirect block")
-
- /* Set parent information */
- HDassert(child_iblock->parent == NULL);
- child_iblock->parent = iblock;
- child_iblock->par_entry = curr_entry;
- if(H5HF_iblock_incr(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
#ifdef QAK
HDfprintf(stderr, "%s: child_iblock->child_free_space = %Hu\n", FUNC, child_iblock->child_free_space);
#endif /* QAK */
-
- /* Hook child up to parent indirect block */
- iblock->ents[curr_entry].addr = child_iblock_addr;
-
- /* Mark parent indirect block as modified */
- if(H5HF_iblock_dirty(iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
} /* end else */
/* Compute entry for new direct block in child indirect block */
@@ -1308,64 +828,19 @@ HDfprintf(stderr, "%s: old_sec_node->u.indirect.indir_row = %u\n", FUNC, old_sec
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_info.addr, &dblock_addr, &dblock_sec_node) < 0)
+ if(H5HF_man_dblock_create(dxpl_id, hdr, child_iblock, dblock_entry, &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 */
- child_iblock->ents[dblock_entry].addr = dblock_addr;
-
- /* Mark child indirect block as modified */
- if(H5HF_iblock_dirty(child_iblock) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDIRTY, FAIL, "can't mark indirect block as dirty")
-
-
/* Create "range" section for other direct blocks in row of child indirect block */
+ if(H5HF_sect_range_add(hdr, dxpl_id, (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]),
+ old_sec_node->sect_info.size, child_iblock, old_sec_node->u.indirect.indir_row,
+ 1, hdr->man_dtable.cparam.width - 1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create range section for indirect block's free space")
- /* Create free list section node for blocks skipped over */
- if(NULL == (range_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 */
- 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_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")
- range_sec_node->u.range.row = old_sec_node->u.indirect.indir_row;
- range_sec_node->u.range.col = 1;
- 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_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")
-
-
- /* Reduce "indirect" section */
-
- /* Check for only single block covered in range section */
- if(old_sec_node->u.indirect.num_entries == 1) {
- /* 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);
- } /* end if */
- else {
- /* Adjust section information */
- 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_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 */
+ /* Reduce (& possibly re-add) 'indirect' section */
+ if(H5HF_sect_indirect_reduce(hdr, dxpl_id, old_sec_node) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce indirect section node")
/* 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)
@@ -1392,9 +867,9 @@ done:
*
*-------------------------------------------------------------------------
*/
-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)
+herr_t
+H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_indirect_t *par_iblock,
+ unsigned par_entry, unsigned nrows, unsigned max_rows, haddr_t *addr_p)
{
H5HF_indirect_t *iblock = NULL; /* Pointer to indirect block */
size_t u; /* Local index variable */
@@ -1424,16 +899,12 @@ H5HF_man_iblock_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared heap header")
#ifdef QAK
-HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows);
+HDfprintf(stderr, "%s: nrows = %u, max_rows = %u\n", FUNC, nrows, max_rows);
#endif /* QAK */
/* Set info for direct block */
iblock->rc = 0;
- iblock->parent = NULL; /* Temporary, except for root indirect block */
- iblock->par_entry = 0;
- iblock->block_off = block_off;
iblock->nrows = nrows;
iblock->max_rows = max_rows;
- iblock->dirty = TRUE;
/* Compute size of buffer needed for indirect block */
iblock->size = H5HF_MAN_INDIRECT_SIZE(hdr, iblock);
@@ -1451,7 +922,26 @@ HDfprintf(stderr, "%s: nrows = %u, max_nrows = %u\n", FUNC, nrows, max_nrows);
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "file allocation failed for fractal heap indirect block")
iblock->addr = *addr_p;
-/* XXX: Update indirect statistics when they are added */
+ /* Attach to parent indirect block, if there is one */
+ iblock->parent = par_iblock;
+ iblock->par_entry = par_entry;
+ if(iblock->parent) {
+ /* Attach new block to parent */
+ if(H5HF_man_iblock_attach(iblock->parent, par_entry, *addr_p) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTATTACH, FAIL, "can't attach indirect block to parent indirect block")
+
+ /* Compute the indirect block's offset in the heap's address space */
+ /* (based on parent's block offset) */
+ iblock->block_off = par_iblock->block_off;
+ iblock->block_off += hdr->man_dtable.row_block_off[par_entry / hdr->man_dtable.cparam.width];
+ iblock->block_off += hdr->man_dtable.row_block_size[par_entry / hdr->man_dtable.cparam.width] * (par_entry % hdr->man_dtable.cparam.width);
+ } /* end if */
+ else
+ iblock->block_off = 0; /* Must be the root indirect block... */
+
+ /* Update indirect block's statistics */
+ iblock->nchildren = 0;
+ iblock->max_child = 0;
/* Cache the new fractal heap header */
if(H5AC_set(hdr->f, dxpl_id, H5AC_FHEAP_IBLOCK, *addr_p, iblock, H5AC__NO_FLAGS_SET) < 0)
@@ -1517,3 +1007,156 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5HF_man_iblock_protect() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iblock_attach
+ *
+ * Purpose: Attach a block to an indirect block
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry, haddr_t child_addr)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_attach)
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock = %p, entry = %u, child_addr = %a, iblock_nrows = %u\n", FUNC, iblock, entry, child_addr);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(iblock);
+ HDassert(H5F_addr_defined(child_addr));
+
+ /* Increment the reference count on this indirect block */
+ if(H5HF_iblock_incr(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+
+ /* Point at the direct block */
+ iblock->ents[entry].addr = child_addr;
+
+ /* Check for max. entry used */
+ if(entry > iblock->max_child)
+ iblock->max_child = entry;
+
+ /* Increment the # of child blocks */
+ iblock->nchildren++;
+
+ /* 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")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_iblock_attach() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iblock_detach
+ *
+ * Purpose: Detach a block from an indirect block
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry)
+{
+ unsigned start_children; /* # of children of iblock when routine was entered */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iblock_detach)
+#ifdef QAK
+HDfprintf(stderr, "%s: iblock = %p, entry = %u, dblock_addr = %a, iblock_nrows = %u\n", FUNC, iblock, entry, dblock_addr);
+#endif /* QAK */
+
+ /*
+ * Check arguments.
+ */
+ HDassert(iblock);
+ HDassert(iblock->nchildren);
+
+ /* Reset address of entry */
+ iblock->ents[entry].addr = HADDR_UNDEF;
+
+ /* Decrement the # of child blocks */
+ /* (If the number of children drop to 0, the indirect block will be
+ * removed from the heap when it's ref. count drops to zero and the
+ * metadata cache calls the indirect block destructor)
+ */
+ /* (Track the initial # of children before the block gets modified, because
+ * this routine is called recursively)
+ */
+ start_children = iblock->nchildren;
+ iblock->nchildren--;
+
+ /* Reduce the max. entry used, if necessary */
+ if(entry == iblock->max_child) {
+ if(iblock->nchildren > 0)
+ while(!H5F_addr_defined(iblock->ents[iblock->max_child].addr))
+ iblock->max_child--;
+ else
+ iblock->max_child = 0;
+ } /* end if */
+
+ /* If this is the root indirect block handle some special cases */
+ if(iblock->block_off == 0) {
+ /* If the number of children drops to 1, and that child is the first
+ * direct block in the heap, convert the heap back to using a root
+ * direct block
+ */
+ if(iblock->nchildren == 1 && H5F_addr_defined(iblock->ents[0].addr))
+ if(H5HF_man_iblock_root_revert(iblock, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't convert root indirect block back to root direct block")
+
+ /* Check for reducing size of root indirect block */
+ if(iblock->nchildren > 0 && iblock->hdr->man_dtable.cparam.start_root_rows != 0
+ && entry > iblock->max_child) {
+ unsigned max_child_row; /* Row for max. child entry */
+
+ /* Compute information needed for determining whether to reduce size of root indirect block */
+ max_child_row = iblock->max_child / iblock->hdr->man_dtable.cparam.width;
+
+ /* Check if the root indirect block should be reduced */
+ if(iblock->nrows > 1 && max_child_row <= (iblock->nrows / 2))
+ if(H5HF_man_iblock_root_halve(iblock, dxpl_id) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce size of root indirect block")
+ } /* end if */
+ } /* end if */
+
+ /* Free indirect block disk space, if it has no children (i.e. it's been deleted) */
+ if(start_children == 1) {
+ HDassert(iblock->nchildren == 0);
+ if(H5MF_xfree(iblock->hdr->f, H5FD_MEM_FHEAP_IBLOCK, dxpl_id, iblock->addr, (hsize_t)iblock->size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTFREE, FAIL, "unable to free fractal heap indirect block disk 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")
+
+ /* Decrement the reference count on this indirect block */
+ /* (should be last, so that potential 'unpin' on this indirect block
+ * doesn't invalidate the 'iblock' variable)
+ */
+ if(H5HF_iblock_decr(iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't decrement reference count on shared indirect block")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_man_iblock_detach() */
+
diff --git a/src/H5HFint.c b/src/H5HFint.c
index 149eacc..c374098 100644
--- a/src/H5HFint.c
+++ b/src/H5HFint.c
@@ -231,25 +231,17 @@ HDfprintf(stderr, "%s: request = %Zu\n", FUNC, request);
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) {
-#ifdef QAK
-HDfprintf(stderr, "%s: Allocate new direct block\n", FUNC);
-#endif /* QAK */
+ /* If we didn't find a node, go create a direct block big enough to hold the requested block */
+ if(!node_found)
/* Allocate direct block big enough to hold requested size */
- if(H5HF_man_dblock_new(hdr, dxpl_id, request) < 0)
+ if(H5HF_man_dblock_new(hdr, dxpl_id, request, sec_node) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTCREATE, FAIL, "can't create fractal heap direct block")
- /* Request space from the free space */
- /* (Ought to be able to be filled, now) */
- 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
-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)->type = %u\n", FUNC, (unsigned)(*sec_node)->type);
+HDfprintf(stderr, "%s: (*sec_node)->sect_info.addr = %a\n", FUNC, (*sec_node)->sect_info.addr);
+HDfprintf(stderr, "%s: (*sec_node)->sect_info.size = %Hu\n", FUNC, (*sec_node)->sect_info.size);
+HDfprintf(stderr, "%s: (*sec_node)->sect_info.type = %u\n", FUNC, (*sec_node)->sect_info.type);
#endif /* QAK */
done:
@@ -279,6 +271,9 @@ H5HF_man_insert(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sec_node,
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_insert)
+#ifdef QAK
+HDfprintf(stderr, "%s: obj_size = %Zu\n", FUNC, obj_size);
+#endif /* QAK */
/*
* Check arguments.
@@ -289,7 +284,7 @@ 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->sect_info.cls->type == H5FS_SECT_FHEAP_INDIRECT) {
+ if(sec_node->sect_info.type == H5HF_FSPACE_SECT_INDIRECT) {
#ifdef QAK
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);
@@ -308,7 +303,7 @@ 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->sect_info.cls->type == H5FS_SECT_FHEAP_RANGE) {
+ else if(sec_node->sect_info.type == H5HF_FSPACE_SECT_RANGE) {
#ifdef QAK
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);
@@ -323,7 +318,7 @@ 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);
+ HDassert(sec_node->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
/* Check for serialized 'single' section */
if(sec_node->sect_info.state == H5FS_SECT_SERIALIZED) {
@@ -334,8 +329,8 @@ HDfprintf(stderr, "%s: sec_node->u.range.num_entries = %u\n", FUNC, sec_node->u.
/* Lock direct block */
#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 = %Hu\n", FUNC, sec_node->sect_info.size);
HDfprintf(stderr, "%s: sec_node->u.single.parent = %p\n", FUNC, sec_node->u.single.parent);
if(sec_node->u.single.parent)
HDfprintf(stderr, "%s: sec_node->u.single.parent->addr = %a\n", FUNC, sec_node->u.single.parent->addr);
@@ -365,29 +360,11 @@ HDfprintf(stderr, "%s: dblock->block_off = %Hu\n", FUNC, dblock->block_off);
HDassert(sec_node->sect_info.size >= obj_size);
#ifdef QAK
-HDfprintf(stderr, "%s: sec_node->sect_info.size = %Zu\n", FUNC, sec_node->sect_info.size);
+HDfprintf(stderr, "%s: sec_node->sect_info.size = %Hu\n", FUNC, sec_node->sect_info.size);
#endif /* QAK */
- 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 ||
- dblock->parent == sec_node->u.single.parent);
- if(sec_node->u.single.parent)
- 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 space section */
- H5FL_FREE(H5HF_free_section_t, sec_node);
- } /* end if */
- else {
- /* Adjust information for section node */
- sec_node->sect_info.addr += obj_size;
- sec_node->sect_info.size -= obj_size;
-
- /* 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 */
+ /* Reduce (& possibly re-add) single section */
+ if(H5HF_sect_single_reduce(hdr, dxpl_id, sec_node, obj_size) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't reduce single section node")
#ifdef QAK
HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off);
@@ -564,9 +541,9 @@ HDfprintf(stderr, "%s: obj_off = %Hu, obj_len = %Zu\n", FUNC, obj_off, obj_len);
HDassert(obj_len > 0);
/* Check for bad offset or length */
- if(obj_off > hdr->man_alloc_size)
+ if(obj_off > hdr->man_size)
HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object offset too large")
- if(obj_len > hdr->man_dtable.cparam.start_block_size)
+ if(obj_len > hdr->man_dtable.cparam.max_direct_size)
HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object size too large for direct block")
if(obj_len > hdr->standalone_size)
HGOTO_ERROR(H5E_HEAP, H5E_BADRANGE, FAIL, "fractal heap object should be standalone")
@@ -623,22 +600,9 @@ HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off);
#endif /* QAK */
/* 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_info.addr = obj_off;
- sec_node->sect_info.size = obj_len;
- 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)
- 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;
+ if(NULL == (sec_node = H5HF_sect_single_new(obj_off, obj_len,
+ dblock->parent, dblock->par_entry, dblock_addr, dblock_size)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't create section for direct block's free space")
/* Unlock direct block */
if(H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
@@ -647,16 +611,15 @@ HDfprintf(stderr, "%s: blk_off = %Zu\n", FUNC, blk_off);
/* Update statistics about heap */
hdr->nobjs--;
- hdr->total_man_free += obj_len;
+
+ /* Reduce space available in heap */
+ if(H5HF_hdr_adj_free(hdr, (ssize_t)obj_len) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't adjust free space for heap")
/* Return free space to the heap's list of space */
if(H5HF_space_return(hdr, dxpl_id, sec_node) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add direct block free space to global list")
- /* 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_remove() */
diff --git a/src/H5HFiter.c b/src/H5HFiter.c
index abc592a..ef926e8 100644
--- a/src/H5HFiter.c
+++ b/src/H5HFiter.c
@@ -138,6 +138,9 @@ H5HF_man_iter_start_offset(H5HF_hdr_t *hdr, hid_t dxpl_id,
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iter_start_offset)
+#ifdef QAK
+HDfprintf(stderr, "%s: offset = %Hu\n", FUNC, offset);
+#endif /* QAK */
/*
* Check arguments.
@@ -270,7 +273,39 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HF_man_iter_start
+ * Function: H5HF_man_iter_set_entry
+ *
+ * Purpose: Set the current entry for the iterator
+ *
+ * Return: SUCCEED/FAIL
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_man_iter_set_entry(const H5HF_hdr_t *hdr, H5HF_block_iter_t *biter, unsigned entry)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_man_iter_set_entry)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(biter);
+
+ /* Set location context */
+ biter->curr->entry = entry;
+ biter->curr->row = entry / hdr->man_dtable.cparam.width;
+ biter->curr->col = entry % hdr->man_dtable.cparam.width;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_man_iter_set_entry() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_man_iter_start_entry
*
* Purpose: Initialize a block iterator to a particular location within
* an indirect block
@@ -411,32 +446,18 @@ H5HF_man_iter_next(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter, unsigned nentries)
HDassert(biter);
HDassert(biter->curr);
HDassert(biter->curr->context);
-
- /* Advance to next entry in current block */
HDassert(biter->curr->row < biter->curr->context->nrows);
- if(nentries == 1) {
- /* Increment block entry */
- biter->curr->entry++;
- /* Increment column */
- biter->curr->col++;
-
- /* Check for walking off end of column */
- if(biter->curr->col == hdr->man_dtable.cparam.width) {
- /* Reset column */
- biter->curr->col = 0;
-
- /* Increment row & block size */
- biter->curr->row++;
- } /* end if */
- } /* end if */
- /* Advance multiple entries */
- else {
- biter->curr->entry += nentries;
- biter->curr->row = biter->curr->entry / hdr->man_dtable.cparam.width;
- biter->curr->col = biter->curr->entry % hdr->man_dtable.cparam.width;
- } /* end else */
+ /* Advance entry in current block */
+ biter->curr->entry += nentries;
+ biter->curr->row = biter->curr->entry / hdr->man_dtable.cparam.width;
+ biter->curr->col = biter->curr->entry % hdr->man_dtable.cparam.width;
/* HDassert(biter->curr->row <= biter->curr->context->nrows); */
+#ifdef QAK
+HDfprintf(stderr, "%s: biter->curr->entry = %u\n", "H5HF_man_iter_next", biter->curr->entry);
+HDfprintf(stderr, "%s: biter->curr->row = %u\n", "H5HF_man_iter_next", biter->curr->row);
+HDfprintf(stderr, "%s: biter->curr->col = %u\n", "H5HF_man_iter_next", biter->curr->col);
+#endif /* QAK */
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5HF_man_iter_next() */
@@ -543,50 +564,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5HF_man_iter_update_iblock
- *
- * Purpose: Update indirect block for current iterator location
- *
- * Return: SUCCEED/FAIL
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Apr 24 2006
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5HF_man_iter_update_iblock(H5HF_block_iter_t *biter, H5HF_indirect_t *iblock)
-{
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_man_iter_update_iblock)
-
- /*
- * Check arguments.
- */
- HDassert(biter);
- HDassert(biter->ready);
- HDassert(biter->curr);
- HDassert(biter->curr->context);
-
- /* Release hold on current location's indirect block */
- if(H5HF_iblock_decr(biter->curr->context) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
-
- /* Update current location's indirect block */
- biter->curr->context = iblock;
-
- /* Add hold to current location's indirect block */
- if(H5HF_iblock_incr(biter->curr->context) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5HF_man_iter_update_iblock() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5HF_man_iter_curr
*
* Purpose: Retrieve information about the current block iterator location
diff --git a/src/H5HFpkg.h b/src/H5HFpkg.h
index 1927445..f2bcfc4 100644
--- a/src/H5HFpkg.h
+++ b/src/H5HFpkg.h
@@ -80,6 +80,7 @@
+ (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 man. space iterator offset in heap */ \
+ (h)->sizeof_size /* Size of alloacted man. space in heap */ \
+ (h)->sizeof_size /* Size of std. space in heap */ \
+ (h)->sizeof_size /* Number of objects in heap */ \
@@ -125,9 +126,9 @@
/* 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 */
+#define H5HF_FSPACE_SECT_SINGLE 0 /* Section is actual bytes in a direct block */
+#define H5HF_FSPACE_SECT_RANGE 1 /* Section is a range of direct blocks */
+#define H5HF_FSPACE_SECT_INDIRECT 2 /* Section is a range of _indirect_ blocks in an indirect block row */
/****************************/
/* Package Private Typedefs */
@@ -148,8 +149,10 @@ typedef struct H5HF_dtable_t {
*/
/* Computed information (not stored) */
- unsigned max_root_rows; /* Maximum # of rows in root indirect block */
- unsigned max_direct_rows; /* Maximum # of direct rows in any indirect block */
+ unsigned max_root_rows; /* Maximum # of rows in root indirect block */
+ unsigned max_direct_rows; /* Maximum # of direct rows in any indirect block */
+ unsigned start_bits; /* # of bits for starting block size (i.e. log2(start_block_size)) */
+ unsigned max_direct_bits; /* # of bits for max. direct block size (i.e. log2(max_direct_size)) */
unsigned max_dir_blk_off_size; /* Max. size of offsets in direct blocks */
unsigned first_row_bits; /* # of bits in address of first row */
hsize_t num_id_first_row; /* Number of IDs in first row of table */
@@ -199,7 +202,7 @@ typedef struct H5HF_free_section_t {
haddr_t dblock_addr; /* Address of direct block for free section */
size_t dblock_size; /* Size of direct block */
- /* (Needed to retrieve direct block) */
+ /* (Needed to retrieve root direct block) */
} single;
struct {
H5HF_indirect_t *iblock; /* Indirect block for free section */
@@ -235,6 +238,7 @@ typedef struct H5HF_hdr_t {
hsize_t total_size; /* Total amount of space used by heap (managed & standalone) */
hsize_t man_size; /* Total amount of managed space in heap */
hsize_t man_alloc_size; /* Total amount of allocated managed space in heap */
+ hsize_t man_iter_off; /* Offset of iterator in managed heap space */
hsize_t std_size; /* Total amount of standalone space in heap */
hsize_t nobjs; /* Number of objects in heap */
@@ -247,16 +251,12 @@ 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 (in bytes) */
- 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 */
/* Doubling table information */
/* (Partially set by user, partially derived/updated internally) */
H5HF_dtable_t man_dtable; /* Doubling-table info for managed objects */
- H5HF_dtable_t std_dtable; /* Doubling-table info for standalone objects */
/* Information set by user */
H5HF_addrmap_t addrmap; /* Type of address mapping */
@@ -283,13 +283,14 @@ struct H5HF_indirect_t {
/* Internal heap information (not stored) */
size_t rc; /* Reference count of child blocks */
- hbool_t dirty; /* Info is modified */
H5HF_hdr_t *hdr; /* Shared heap header info */
struct H5HF_indirect_t *parent; /* Shared parent indirect block info */
unsigned par_entry; /* Entry in parent's table */
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 */
+ unsigned nchildren; /* Number of child blocks */
+ unsigned max_child; /* Max. offset used in child entries */
size_t size; /* Size of indirect block on disk */
/* Stored values */
@@ -320,15 +321,6 @@ struct H5HF_t {
unsigned fo_count; /* Open object count for file */
};
-/* Fractal heap metadata statistics info */
-typedef struct H5HF_stat_t {
- hsize_t total_size; /* Total size of heap allocated (man & std) */
- hsize_t man_size; /* Total size of managed space in heap */
- hsize_t std_size; /* Total size of standalone space in heap */
- hsize_t man_free_space; /* Free space within heap */
- hsize_t nobjs; /* Number of objects in heap */
-} H5HF_stat_t;
-
/* Fractal heap "parent info" (for loading a block) */
typedef struct H5HF_parent_t {
H5HF_hdr_t *hdr; /* Pointer to heap header info */
@@ -357,13 +349,13 @@ H5_DLLVAR const H5AC_class_t H5AC_FHEAP_DBLOCK[1];
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];
+H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_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];
+H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_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];
+H5_DLLVAR H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1];
/* Declare a free list to manage the H5HF_hdr_t struct */
H5FL_EXTERN(H5HF_hdr_t);
@@ -380,9 +372,6 @@ H5FL_EXTERN(H5HF_indirect_t);
/* Declare a free list to manage the H5HF_indirect_ent_t sequence information */
H5FL_SEQ_EXTERN(H5HF_indirect_ent_t);
-/* Declare a free list to manage the H5HF_free_section_t struct */
-H5FL_EXTERN(H5HF_free_section_t);
-
/******************************/
/* Package Private Prototypes */
@@ -399,37 +388,53 @@ H5_DLL herr_t H5HF_dtable_dest(H5HF_dtable_t *dtable);
H5_DLL herr_t H5HF_dtable_lookup(const H5HF_dtable_t *dtable, hsize_t off,
unsigned *row, unsigned *col);
H5_DLL unsigned H5HF_dtable_size_to_row(H5HF_dtable_t *dtable, size_t block_size);
+H5_DLL unsigned H5HF_dtable_size_to_rows(H5HF_dtable_t *dtable, hsize_t size);
/* Heap header routines */
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);
+H5_DLL herr_t H5HF_hdr_adjust_heap(H5HF_hdr_t *hdr, hsize_t new_size, hssize_t extra_free);
+H5_DLL herr_t H5HF_hdr_inc_alloc(H5HF_hdr_t *hdr, size_t alloc_size);
+H5_DLL herr_t H5HF_hdr_start_iter(H5HF_hdr_t *hdr, H5HF_indirect_t *iblock, hsize_t curr_off, unsigned curr_entry);
+H5_DLL herr_t H5HF_hdr_skip_blocks(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_indirect_t *iblock, unsigned start_entry, unsigned nentries);
+H5_DLL herr_t H5HF_hdr_update_iter(H5HF_hdr_t *hdr, hid_t dxpl_id, size_t min_dblock_size);
+H5_DLL herr_t H5HF_hdr_inc_iter(H5HF_hdr_t *hdr, hsize_t adv_size, unsigned nentries);
+H5_DLL herr_t H5HF_hdr_reverse_iter(H5HF_hdr_t *hdr, hid_t dxpl_id);
+H5_DLL herr_t H5HF_hdr_reset_iter(H5HF_hdr_t *hdr, hsize_t curr_off);
H5_DLL herr_t H5HF_hdr_empty(H5HF_hdr_t *hdr);
/* Indirect block routines */
H5_DLL herr_t H5HF_iblock_incr(H5HF_indirect_t *iblock);
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_root_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ size_t min_dblock_size);
+H5_DLL herr_t H5HF_man_iblock_root_double(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ size_t min_dblock_size);
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_create(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_indirect_t *par_iblock, unsigned par_entry, unsigned nrows,
+ unsigned max_rows, haddr_t *addr_p);
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,
H5AC_protect_t rw);
+H5_DLL herr_t H5HF_man_iblock_attach(H5HF_indirect_t *iblock, unsigned entry,
+ haddr_t dblock_addr);
+H5_DLL herr_t H5HF_man_iblock_detach(H5HF_indirect_t *iblock, hid_t dxpl_id, unsigned entry);
/* 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_new(H5HF_hdr_t *fh, hid_t dxpl_id, size_t request,
+ H5HF_free_section_t **ret_sec_node);
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);
+ H5HF_indirect_t *par_iblock, unsigned par_entry, haddr_t *addr_p,
+ H5HF_free_section_t **ret_sec_node);
H5_DLL herr_t H5HF_man_dblock_destroy(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_direct_t *dblock, haddr_t dblock_addr);
H5_DLL H5HF_direct_t *H5HF_man_dblock_protect(H5HF_hdr_t *hdr, hid_t dxpl_id,
@@ -464,21 +469,19 @@ H5_DLL herr_t H5HF_dblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
H5_DLL herr_t H5HF_iblock_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
FILE *stream, int indent, int fwidth, haddr_t hdr_addr, unsigned nrows);
-/* Statistics routines */
-H5_DLL herr_t H5HF_stat_info(H5HF_t *fh, H5HF_stat_t *stats);
-
/* 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,
H5HF_block_iter_t *biter, hsize_t offset);
H5_DLL herr_t H5HF_man_iter_start_entry(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter,
H5HF_indirect_t *iblock, unsigned start_entry);
+H5_DLL herr_t H5HF_man_iter_set_entry(const H5HF_hdr_t *hdr,
+ H5HF_block_iter_t *biter, unsigned entry);
H5_DLL herr_t H5HF_man_iter_next(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter,
unsigned nentries);
H5_DLL herr_t H5HF_man_iter_up(H5HF_block_iter_t *biter);
H5_DLL herr_t H5HF_man_iter_down(H5HF_block_iter_t *biter, H5HF_indirect_t *iblock);
H5_DLL herr_t H5HF_man_iter_reset(H5HF_block_iter_t *biter);
-H5_DLL herr_t H5HF_man_iter_update_iblock(H5HF_block_iter_t *biter, H5HF_indirect_t *iblock);
H5_DLL herr_t H5HF_man_iter_curr(H5HF_block_iter_t *biter, unsigned *row, unsigned *col,
unsigned *entry, H5HF_indirect_t **block);
H5_DLL herr_t H5HF_man_iter_offset(H5HF_hdr_t *hdr, H5HF_block_iter_t *biter,
@@ -494,19 +497,39 @@ H5_DLL herr_t H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5_DLL herr_t H5HF_space_return(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);
+H5_DLL herr_t H5HF_space_delete(H5HF_hdr_t *hdr, hid_t dxpl_id);
/* Free space section routines */
+H5_DLL H5HF_free_section_t *H5HF_sect_single_new(hsize_t sect_off,
+ size_t sect_size, H5HF_indirect_t *parent, unsigned par_entry,
+ haddr_t dblock_addr, size_t dblock_size);
H5_DLL herr_t H5HF_sect_single_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t *sect);
+H5_DLL herr_t H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect, size_t amt);
+H5_DLL herr_t H5HF_sect_range_add(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t sect_off,
+ hsize_t sect_size, H5HF_indirect_t *iblock,
+ unsigned row, unsigned col, unsigned nentries);
H5_DLL herr_t H5HF_sect_range_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t *sect);
+H5_DLL herr_t H5HF_sect_range_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect);
+H5_DLL herr_t H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ hsize_t sect_off, hsize_t sect_size, H5HF_indirect_t *iblock,
+ unsigned row, unsigned col, unsigned nentries,
+ unsigned indir_row, unsigned indir_nrows);
H5_DLL herr_t H5HF_sect_indirect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
H5HF_free_section_t *sect);
+H5_DLL herr_t H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect);
/* Testing routines */
#ifdef H5HF_TESTING
H5_DLL herr_t H5HF_get_cparam_test(const H5HF_t *fh, H5HF_create_t *cparam);
-H5_DLL size_t H5HF_get_dblock_overhead(const H5HF_t *fh);
+H5_DLL unsigned H5HF_get_max_root_rows(const H5HF_t *fh);
+H5_DLL unsigned H5HF_get_dtable_width_test(const H5HF_t *fh);
+H5_DLL unsigned H5HF_get_dtable_max_drows_test(const H5HF_t *fh);
+H5_DLL unsigned H5HF_get_iblock_max_drows_test(const H5HF_t *fh, unsigned pos);
H5_DLL hsize_t H5HF_get_dblock_size_test(const H5HF_t *fh, unsigned row);
H5_DLL hsize_t H5HF_get_dblock_free_test(const H5HF_t *fh, unsigned row);
H5_DLL herr_t H5HF_get_id_off_test(const H5HF_t *fh, const void *id, hsize_t *obj_off);
diff --git a/src/H5HFprivate.h b/src/H5HFprivate.h
index bb562de..b9ae0f4 100644
--- a/src/H5HFprivate.h
+++ b/src/H5HFprivate.h
@@ -67,6 +67,17 @@ typedef struct H5HF_create_t {
/* (i.e. max. size of object to manage) */
} H5HF_create_t;
+/* Fractal heap metadata statistics info */
+typedef struct H5HF_stat_t {
+ hsize_t total_size; /* Total size of heap allocated (man & std) */
+ hsize_t nobjs; /* Number of objects in heap */
+ hsize_t man_size; /* Total size of managed space in heap */
+ hsize_t man_alloc_size; /* Total size of managed space allocated in heap */
+ hsize_t man_iter_off; /* Offset of "new block" iterator in managed heap space */
+ hsize_t man_free_space; /* Free space within managed heap */
+ hsize_t std_size; /* Total size of standalone space in heap */
+} H5HF_stat_t;
+
/* Fractal heap info (forward decl - defined in H5HFpkg.h) */
typedef struct H5HF_t H5HF_t;
@@ -90,6 +101,9 @@ H5_DLL herr_t H5HF_read(H5HF_t *fh, hid_t dxpl_id, const void *id,
H5_DLL herr_t H5HF_remove(H5HF_t *fh, hid_t dxpl_id, const void *id);
H5_DLL herr_t H5HF_close(H5HF_t *fh, hid_t dxpl_id);
+/* Statistics routines */
+H5_DLL herr_t H5HF_stat_info(const H5HF_t *fh, H5HF_stat_t *stats);
+
/* Debugging routines */
#ifdef H5HF_DEBUGGING
H5_DLL herr_t H5HF_sects_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr,
diff --git a/src/H5HFsection.c b/src/H5HFsection.c
index f164cdb..48e2ddb 100644
--- a/src/H5HFsection.c
+++ b/src/H5HFsection.c
@@ -52,30 +52,41 @@
/********************/
/* Shared routines */
-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);
+static H5HF_free_section_t *H5HF_sect_node_new(unsigned sect_type,
+ haddr_t sect_addr, hsize_t sect_size, H5FS_section_state_t state);
static herr_t H5HF_sect_node_free(H5HF_free_section_t *sect,
H5HF_indirect_t *parent);
+static herr_t H5HF_sect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect);
/* 'single' section callbacks */
-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 htri_t H5HF_sect_single_can_merge(const H5FS_section_info_t *sect1,
- const H5FS_section_info_t *sect2, void *udata);
+static H5FS_section_info_t *H5HF_sect_single_deserialize(const uint8_t *buf,
+ haddr_t sect_addr, hsize_t sect_size);
+static htri_t H5HF_sect_single_can_merge(H5FS_section_info_t *sect1,
+ H5FS_section_info_t *sect2, void *udata);
static herr_t H5HF_sect_single_merge(H5FS_section_info_t *sect1,
H5FS_section_info_t *sect2, void *udata);
-static htri_t H5HF_sect_single_can_shrink(H5FS_section_info_t *sect, void *udata);
-static herr_t H5HF_sect_single_shrink(H5FS_section_info_t **sect, void *udata);
+static htri_t H5HF_sect_single_can_shrink(H5FS_section_info_t *sect,
+ void *udata);
static herr_t H5HF_sect_single_free(H5FS_section_info_t *sect);
+/* 'range' section routines */
+static herr_t H5HF_sect_range_from_single(H5HF_hdr_t *hdr,
+ H5HF_free_section_t *sect, H5HF_direct_t *dblock);
+
/* 'range' section callbacks */
static herr_t H5HF_sect_range_init_cls(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 H5FS_section_info_t *H5HF_sect_range_deserialize(const uint8_t *buf,
+ haddr_t sect_addr, hsize_t sect_size);
+static htri_t H5HF_sect_range_can_merge(H5FS_section_info_t *sect1,
+ H5FS_section_info_t *sect2, void *udata);
+static herr_t H5HF_sect_range_merge(H5FS_section_info_t *sect1,
+ H5FS_section_info_t *sect2, void *udata);
+static htri_t H5HF_sect_range_can_shrink(H5FS_section_info_t *sect,
+ void *udata);
+static herr_t H5HF_sect_range_shrink(H5FS_section_info_t **sect,
+ void *udata);
static herr_t H5HF_sect_range_free(H5FS_section_info_t *sect);
static herr_t H5HF_sect_range_debug(const H5FS_section_info_t *sect,
FILE *stream, int indent, int fwidth);
@@ -83,9 +94,8 @@ static herr_t H5HF_sect_range_debug(const H5FS_section_info_t *sect,
/* 'indirect' section callbacks */
static herr_t H5HF_sect_indirect_init_cls(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 H5FS_section_info_t *H5HF_sect_indirect_deserialize(const uint8_t *buf,
+ haddr_t sect_addr, hsize_t sect_size);
static herr_t H5HF_sect_indirect_free(H5FS_section_info_t *sect);
static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect,
FILE *stream, int indent, int fwidth);
@@ -97,8 +107,8 @@ static herr_t H5HF_sect_indirect_debug(const H5FS_section_info_t *sect,
/* Class info for "single" free space sections */
/* (No callbacks necessary) */
-H5FS_section_class_t H5FS_SECT_CLS_FHEAP_SINGLE[1] = {{
- H5FS_SECT_FHEAP_SINGLE, /* Section type */
+H5FS_section_class_t H5HF_FSPACE_SECT_CLS_SINGLE[1] = {{
+ H5HF_FSPACE_SECT_SINGLE, /* Section type */
0, /* Extra serialized size */
NULL, /* Initialize section class */
NULL, /* Serialize section */
@@ -106,29 +116,29 @@ H5FS_section_class_t H5FS_SECT_CLS_FHEAP_SINGLE[1] = {{
H5HF_sect_single_can_merge, /* Can sections merge? */
H5HF_sect_single_merge, /* Merge sections */
H5HF_sect_single_can_shrink, /* Can section shrink container?*/
- H5HF_sect_single_shrink, /* Shrink container w/section */
+ NULL, /* Shrink container w/section */
H5HF_sect_single_free, /* Free section */
NULL, /* Dump debugging for section */
}};
/* Class info for "range" free space sections */
-H5FS_section_class_t H5FS_SECT_CLS_FHEAP_RANGE[1] = {{
- H5FS_SECT_FHEAP_RANGE, /* Section type */
+H5FS_section_class_t H5HF_FSPACE_SECT_CLS_RANGE[1] = {{
+ H5HF_FSPACE_SECT_RANGE, /* Section type */
0, /* Extra serialized size */
H5HF_sect_range_init_cls, /* Initialize section class */
H5HF_sect_range_serialize, /* Serialize section */
H5HF_sect_range_deserialize, /* Deserialize section */
- NULL, /* Can sections merge? */
- NULL, /* Merge sections */
- NULL, /* Can section shrink container?*/
- NULL, /* Shrink container w/section */
+ H5HF_sect_range_can_merge, /* Can sections merge? */
+ H5HF_sect_range_merge, /* Merge sections */
+ H5HF_sect_range_can_shrink, /* Can section shrink container?*/
+ H5HF_sect_range_shrink, /* Shrink container w/section */
H5HF_sect_range_free, /* Free section */
H5HF_sect_range_debug, /* Dump debugging for section */
}};
/* Class info for "indirect" free space sections */
-H5FS_section_class_t H5FS_SECT_CLS_FHEAP_INDIRECT[1] = {{
- H5FS_SECT_FHEAP_INDIRECT, /* Section type */
+H5FS_section_class_t H5HF_FSPACE_SECT_CLS_INDIRECT[1] = {{
+ H5HF_FSPACE_SECT_INDIRECT, /* Section type */
0, /* Extra serialized size */
H5HF_sect_indirect_init_cls, /* Initialize section class */
H5HF_sect_indirect_serialize, /* Serialize section */
@@ -157,7 +167,7 @@ H5FL_DEFINE(H5HF_free_section_t);
/*-------------------------------------------------------------------------
- * Function: H5HF_sect_node_alloc
+ * Function: H5HF_sect_node_new
*
* Purpose: Allocate a free space section node of a particular type
*
@@ -170,38 +180,37 @@ H5FL_DEFINE(H5HF_free_section_t);
*
*-------------------------------------------------------------------------
*/
-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)
+static H5HF_free_section_t *
+H5HF_sect_node_new(unsigned sect_type, haddr_t sect_addr, hsize_t sect_size,
+ H5FS_section_state_t sect_state)
{
H5HF_free_section_t *new_sect; /* New section */
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_free_section_t *ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_node_alloc)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_node_new)
/* 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")
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for direct block free list section")
/* Set the information passed in */
new_sect->sect_info.addr = sect_addr;
new_sect->sect_info.size = sect_size;
/* Set the section's class & state */
- new_sect->sect_info.cls = &sect_cls[sect_type];
- new_sect->sect_info.state = H5FS_SECT_SERIALIZED;
+ new_sect->sect_info.type = sect_type;
+ new_sect->sect_info.state = sect_state;
- /* Update the return parameter */
- *sect = (H5FS_section_info_t *)new_sect;
+ /* Set return value */
+ ret_value = new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_node_alloc() */
+} /* H5HF_sect_node_new() */
/*-------------------------------------------------------------------------
@@ -241,6 +250,121 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_revive
+ *
+ * Purpose: Revive a section node
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_revive(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *sect)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_revive)
+
+ /* Sanity check */
+ HDassert(hdr);
+ HDassert(sect);
+
+ /* Call appropriate 'revive' routine */
+ switch(sect->sect_info.type) {
+ case H5HF_FSPACE_SECT_INDIRECT:
+ if(H5HF_sect_indirect_revive(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive range free section")
+ break;
+
+ case H5HF_FSPACE_SECT_RANGE:
+ if(H5HF_sect_range_revive(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive range free section")
+ break;
+
+ case H5HF_FSPACE_SECT_SINGLE:
+ if(H5HF_sect_single_revive(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
+ break;
+
+ default:
+ HGOTO_ERROR(H5E_HEAP, H5E_BADVALUE, FAIL, "unknown section type")
+ } /* end switch */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_revive() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_single_new
+ *
+ * Purpose: Create a new 'single' section and return it to the caller
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+H5HF_free_section_t *
+H5HF_sect_single_new(hsize_t sect_off, size_t sect_size,
+ H5HF_indirect_t *parent, unsigned par_entry,
+ haddr_t dblock_addr, size_t dblock_size)
+{
+ H5HF_free_section_t *sect = NULL; /* 'Single' free space section to add */
+ hbool_t par_incr = FALSE; /* Indicate that parent iblock has been incremented */
+ H5HF_free_section_t *ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_new)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(sect_size);
+
+ /* Create free space section node */
+ if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_off, (hsize_t)sect_size, H5FS_SECT_LIVE)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for single section")
+
+ /* Set the 'single' specific fields */
+ sect->u.single.parent = parent;
+ if(sect->u.single.parent) {
+ if(H5HF_iblock_incr(sect->u.single.parent) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, NULL, "can't increment reference count on shared indirect block")
+ par_incr = TRUE;
+ } /* end if */
+ sect->u.single.par_entry = par_entry;
+ sect->u.single.dblock_addr = dblock_addr;
+ sect->u.single.dblock_size = dblock_size;
+
+ /* Set return value */
+ ret_value = sect;
+
+done:
+ if(!ret_value && sect) {
+ /* Check if we should decrement parent ref. count */
+ if(par_incr) {
+ HDassert(sect->u.single.parent);
+ if(H5HF_iblock_decr(sect->u.single.parent) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, NULL, "can't decrement reference count on parent indirect block")
+ } /* end if */
+
+ /* Release the section */
+ H5FL_FREE(H5HF_free_section_t, sect);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_single_new() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_single_revive
*
* Purpose: Update the memory information for a 'single' free section
@@ -313,6 +437,58 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_single_reduce
+ *
+ * Purpose: Reduce the size of a single section (possibly freeing it)
+ * and re-add it back to the free space manager for the heap
+ * (if it hasn't been freed)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_single_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect, size_t amt)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_reduce)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_SINGLE);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+
+ /* Check for eliminating the section */
+ if(sect->sect_info.size == amt) {
+ /* Free single section */
+ if(H5HF_sect_single_free((H5FS_section_info_t *)sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free single section node")
+ } /* end if */
+ else {
+ /* Adjust information for section */
+ sect->sect_info.addr += amt;
+ sect->sect_info.size -= amt;
+
+ /* Re-insert section node into heap's free space */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add single section to free space manager")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_single_reduce() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_single_deserialize
*
* Purpose: Deserialize a buffer into a "live" single section
@@ -326,12 +502,12 @@ done:
*
*-------------------------------------------------------------------------
*/
-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 H5FS_section_info_t *
+H5HF_sect_single_deserialize(const uint8_t *buf, haddr_t sect_addr,
+ hsize_t sect_size)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_free_section_t *new_sect; /* New section */
+ H5FS_section_info_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_deserialize)
@@ -339,11 +515,13 @@ H5HF_sect_single_deserialize(H5FS_section_class_t *sect_cls,
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")
+ if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_SINGLE, sect_addr, sect_size, H5FS_SECT_SERIALIZED)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section")
+
+ /* Set return value */
+ ret_value = (H5FS_section_info_t *)new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -367,32 +545,87 @@ done:
*-------------------------------------------------------------------------
*/
static htri_t
-H5HF_sect_single_can_merge(const H5FS_section_info_t *sect1,
- const H5FS_section_info_t *sect2, void UNUSED *udata)
+H5HF_sect_single_can_merge(H5FS_section_info_t *_sect1,
+ H5FS_section_info_t *_sect2, void *_udata)
{
+ H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
+ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
+ H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
+ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
+ size_t dblock_size; /* Section's direct block's size */
+ size_t dblock_overhead; /* Direct block's overhead */
+ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
htri_t ret_value = FALSE; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_single_can_merge)
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_can_merge)
/* Check arguments. */
HDassert(sect1);
HDassert(sect2);
- HDassert(H5F_addr_lt(sect1->addr, sect2->addr));
+ HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sect_info.addr, sect2->sect_info.size, sect2->sect_info.type, (sect2->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+#endif /* QAK */
+
+ /* Check to see if we should revive either section */
+ if(sect1->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_single_revive(hdr, dxpl_id, sect1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
+ if(sect2->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_revive(hdr, dxpl_id, sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive free section")
+ /* Check for section occupying entire direct block */
+ dblock_size = sect1->u.single.dblock_size;
+ dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
#ifdef QAK
-HDfprintf(stderr, "%s: sect1->size = %Hu, sect1->addr = %a\n", "H5HF_sect_single_can_merge", sect1->size, sect1->addr);
-HDfprintf(stderr, "%s: sect2->size = %Hu, sect2->addr = %a\n", "H5HF_sect_single_can_merge", sect2->size, sect2->addr);
+HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size);
#endif /* QAK */
+ if((dblock_size - dblock_overhead) == sect1->sect_info.size) {
+ H5HF_direct_t *dblock; /* Pointer to direct block for section */
+ haddr_t dblock_addr; /* Section's direct block's address */
+
+ /* Protect the direct block for the section */
+ dblock_addr = sect1->u.single.dblock_addr;
+#ifdef QAK
+HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
+#endif /* QAK */
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect1->u.single.parent, sect1->u.single.par_entry, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
+ HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect1->sect_info.addr));
+
+ /* Convert 'single' section into 'range' section */
+ if(H5HF_sect_range_from_single(hdr, sect1, dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into range section")
+
+ /* Destroy direct block */
+ if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
+ dblock = NULL;
+
+ /* Check if second section is a range section */
+ if(sect2->sect_info.type == H5HF_FSPACE_SECT_RANGE) {
+ htri_t status; /* Status from range 'can merge' call */
+
+ /* Check if two sections can merge now */
+ /* (i.e. assumes responsibility for passing along 'can merge' callback) */
+ if((status = H5HF_sect_range_can_merge((H5FS_section_info_t *)sect1, (H5FS_section_info_t *)sect2, udata)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTMERGE, FAIL, "can't check for merging sections")
+ HGOTO_DONE(status)
+ } /* end if */
+ } /* end if */
/* Single section can only merge with other single sections */
- if(sect1->cls->type != sect2->cls->type)
+ if(sect1->sect_info.type != sect2->sect_info.type)
HGOTO_DONE(FALSE)
/* Check if second section adjoins first section */
/* (This can only occurs within a direct block, due to the direct block
* overhead at the beginning of a block)
*/
- if(H5F_addr_eq(sect1->addr + sect1->size, sect2->addr))
+ if(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr))
HGOTO_DONE(TRUE)
done:
@@ -417,30 +650,40 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5HF_sect_single_merge(H5FS_section_info_t *sect1, H5FS_section_info_t *sect2,
+H5HF_sect_single_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
void UNUSED *udata)
{
+ H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
+ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_merge)
/* Check arguments. */
HDassert(sect1);
+ HDassert(sect1->sect_info.state == H5FS_SECT_LIVE);
HDassert(sect2);
- HDassert(H5F_addr_eq(sect1->addr + sect1->size, sect2->addr));
+ HDassert(sect2->sect_info.state == H5FS_SECT_LIVE);
+ HDassert(H5F_addr_eq(sect1->sect_info.addr + sect1->sect_info.size, sect2->sect_info.addr));
#ifdef QAK
-HDfprintf(stderr, "%s: sect1->size = %Hu, sect1->addr = %a\n", "H5HF_sect_single_merge", sect1->size, sect1->addr);
-HDfprintf(stderr, "%s: sect2->size = %Hu, sect2->addr = %a\n", "H5HF_sect_single_merge", sect2->size, sect2->addr);
+HDfprintf(stderr, "%s: sect1->sect_info.size = %Hu, sect1->sect_info.addr = %a\n", FUNC, sect1->sect_info.size, sect1->sect_info.addr);
+HDfprintf(stderr, "%s: sect2->sect_info.size = %Hu, sect2->sect_info.addr = %a\n", FUNC, sect2->sect_info.size, sect2->sect_info.addr);
#endif /* QAK */
/* Add second section's size to first section */
- sect1->size += sect2->size;
+ sect1->sect_info.size += sect2->sect_info.size;
/* Get rid of second section */
- if(H5HF_sect_single_free(sect2) < 0)
+ if(H5HF_sect_single_free((H5FS_section_info_t *)sect2) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
+ /* Defer checking if 'single' section should be converted into 'range' section
+ * until next pass through the "can merge" callback, to make certain that
+ * removing a direct block in the root indirect block gives neighboring
+ * "range" sections a chance to deserialize. *ick* -QAK
+ */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5HF_sect_single_merge() */
@@ -449,14 +692,18 @@ done:
/*-------------------------------------------------------------------------
* Function: H5HF_sect_single_can_shrink
*
- * Purpose: Can this section shrink the heap?
+ * Purpose: Can this section shrink the container?
+ *
+ * Note: This isn't actually shrinking the heap (since that's already
+ * been done) as much as it's cleaning up _after_ the heap
+ * shrink.
*
* Return: Success: non-negative (TRUE/FALSE)
*
* Failure: negative
*
* Programmer: Quincey Koziol
- * Wednesday, May 17, 2006
+ * Monday, June 5, 2006
*
*-------------------------------------------------------------------------
*/
@@ -465,117 +712,66 @@ H5HF_sect_single_can_shrink(H5FS_section_info_t *_sect, void *_udata)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Fractal heap free section */
H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
- H5HF_hdr_t *hdr; /* Fractal heap header */
- H5HF_direct_t *dblock = NULL; /* Pointer to direct block for section */
- haddr_t dblock_addr; /* Section's direct block's address */
+ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
size_t dblock_size; /* Section's direct block's size */
size_t dblock_overhead; /* Direct block's overhead */
- hid_t dxpl_id; /* DXPL ID for operation */
+ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
htri_t ret_value = FALSE; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_can_shrink)
/* Check arguments. */
HDassert(sect);
- HDassert(udata);
- HDassert(udata->hdr);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
#ifdef QAK
-HDfprintf(stderr, "%s: sect->sect_info.size = %Hu, sect->sect_info.addr = %a\n", FUNC, sect->sect_info.size, sect->sect_info.addr);
+HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
#endif /* QAK */
- /* Initialize some local convenience variables */
- hdr = udata->hdr;
- dxpl_id = udata->dxpl_id;
-
- /* Revive the section, if it's still serialized */
- if(sect->sect_info.state != H5FS_SECT_LIVE) {
+ /* Check to see if we should revive section */
+ if(sect->sect_info.state != H5FS_SECT_LIVE)
if(H5HF_sect_single_revive(hdr, dxpl_id, sect) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
- } /* end if */
- /* Protect the direct block for the section */
- dblock_addr = sect->u.single.dblock_addr;
+ /* Check for section occupying entire direct block */
dblock_size = sect->u.single.dblock_size;
+ dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
#ifdef QAK
-HDfprintf(stderr, "%s: dblock_size = %u, dblock_addr = %a\n", FUNC, dblock_size, dblock_addr);
+HDfprintf(stderr, "%s: dblock_size = %u\n", FUNC, dblock_size);
#endif /* QAK */
- if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC_READ)))
- HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
-
- /* Check for section occupying entire direct block */
- dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr);
- if(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr) &&
- (dblock_size - dblock_overhead) == sect->sect_info.size) {
- /* Stash the direct block pointer away for the 'shrink' callback */
- udata->dblock = dblock;
-
- /* Indicate that the heap can be shrunk */
- HGOTO_DONE(TRUE)
- } /* end if */
-
-done:
- /* Unprotect the direct block, if we aren't going to use it in the 'shrink' callback */
- if(ret_value != TRUE)
- if(dblock && H5AC_unprotect(hdr->f, dxpl_id, H5AC_FHEAP_DBLOCK, dblock_addr, dblock, H5AC__NO_FLAGS_SET) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTUNPROTECT, FAIL, "unable to release fractal heap direct block")
-
- FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_single_can_shrink() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5HF_sect_single_shrink
- *
- * Purpose: Shrink heap w/section
- *
- * Return: Success: non-negative
- *
- * Failure: negative
- *
- * Programmer: Quincey Koziol
- * Wednesday, May 17, 2006
- *
- *-------------------------------------------------------------------------
- */
-static herr_t
-H5HF_sect_single_shrink(H5FS_section_info_t **_sect, void *_udata)
-{
- H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
- H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_single_shrink)
-
- /* Check arguments. */
- HDassert(sect);
- HDassert(*sect);
- HDassert((*sect)->sect_info.state == H5FS_SECT_LIVE);
- HDassert(udata);
- HDassert(udata->hdr);
- HDassert(udata->dblock);
+ if((dblock_size - dblock_overhead) == sect->sect_info.size) {
+ H5HF_direct_t *dblock; /* Pointer to direct block for section */
+ haddr_t dblock_addr; /* Section's direct block's address */
+ htri_t status; /* Status from range 'can shrink' call */
+ /* Protect the direct block for the section */
+ dblock_addr = sect->u.single.dblock_addr;
#ifdef QAK
-HDfprintf(stderr, "%s: (*sect)->sect_info.size = %Hu, (*sect)->sect_info.addr = %a\n", "H5HF_sect_single_shrink", (*sect)->sect_info.size, (*sect)->sect_info.addr);
+HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
#endif /* QAK */
-
- /* Destroy direct block */
- if(H5HF_man_dblock_destroy(udata->hdr, udata->dxpl_id, udata->dblock, (*sect)->u.single.dblock_addr) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
-
- /* Mark section as "dead", since it's direct block is destroyed */
- (*sect)->sect_info.state = H5FS_SECT_SERIALIZED;
-
- /* Release section */
- if(H5HF_sect_single_free((H5FS_section_info_t *)*sect) < 0)
- HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
-
- /* Set section pointer to NULL, to indicate that the section was released */
- *sect = NULL;
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect->u.single.parent, sect->u.single.par_entry, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
+ HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect->sect_info.addr));
+
+ /* Convert 'single' section into 'range' section */
+ if(H5HF_sect_range_from_single(hdr, sect, dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into range section")
+
+ /* Destroy direct block */
+ if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
+ dblock = NULL;
+
+ /* Check if section can shrink container now */
+ /* (i.e. assumes responsibility for passing along 'can shrink' callback) */
+ if((status = H5HF_sect_range_can_shrink((H5FS_section_info_t *)sect, udata)) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTSHRINK, FAIL, "can't check for shrinking container")
+ HGOTO_DONE(status)
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_sect_single_shrink() */
+} /* H5HF_sect_single_can_shrink() */
/*-------------------------------------------------------------------------
@@ -592,7 +788,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5HF_sect_single_free(H5FS_section_info_t *_sect)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
@@ -651,6 +847,72 @@ H5HF_sect_range_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata)
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_add
+ *
+ * Purpose: Add a new 'range' section to the free space manager for this
+ * heap
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_range_add(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t sect_off,
+ hsize_t sect_size, H5HF_indirect_t *iblock,
+ unsigned row, unsigned col, unsigned nentries)
+{
+ H5HF_free_section_t *sect = NULL; /* 'Range' free space section to add */
+ hbool_t iblock_incr = FALSE; /* Indicate that parent iblock has been incremented */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_add)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(iblock);
+ HDassert(sect_size);
+ HDassert(nentries);
+ HDassert(row < hdr->man_dtable.max_direct_rows); /* Can't handle ranges on indirect blocks */
+
+ /* Create free space section node */
+ if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_RANGE, sect_off, sect_size, H5FS_SECT_LIVE)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for range section")
+
+ /* Set the 'range' specific fields */
+ sect->u.range.iblock = iblock;
+ if(H5HF_iblock_incr(sect->u.range.iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ iblock_incr = TRUE;
+ sect->u.range.row = row;
+ sect->u.range.col = col;
+ sect->u.range.num_entries = nentries;
+
+ /* Add new free space to the free space manager for this heap */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add range section to free space manager")
+
+done:
+ if(ret_value < 0 && sect) {
+ /* Check if we should decrement parent ref. count */
+ if(iblock_incr)
+ if(H5HF_iblock_decr(sect->u.range.iblock) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
+
+ /* Release the section */
+ H5FL_FREE(H5HF_free_section_t, sect);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_range_add() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_range_revive
*
* Purpose: Update the memory information for a 'range' free section
@@ -705,6 +967,104 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_reduce
+ *
+ * Purpose: Reduce the size of a range section (possibly freeing it)
+ * and re-add it back to the free space manager for the heap
+ * (if it hasn't been freed)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_range_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_reduce)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+
+ /* Check for eliminating the section */
+ if(sect->u.range.num_entries == 1) {
+ /* Free range section */
+ if(H5HF_sect_range_free((H5FS_section_info_t *)sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free range section node")
+ } /* end if */
+ else {
+ /* Adjust section information */
+ sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.range.row];
+
+ /* Adjust range information */
+ sect->u.range.col++;
+ sect->u.range.num_entries--;
+
+ /* Add section back to free space list */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add range section to free space manager")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_range_reduce() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_from_single
+ *
+ * Purpose: Convert a 'single' section into a 'range' section
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_range_from_single(H5HF_hdr_t *hdr, H5HF_free_section_t *sect,
+ H5HF_direct_t *dblock)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_from_single)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(dblock);
+#ifdef QAK
+HDfprintf(stderr, "%s: sect.sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_range_from_single", sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: dblock->parent = %p\n", "H5HF_sect_range_from_single", dblock->parent);
+HDfprintf(stderr, "%s: hdr->man_dtable.curr_root_rows = %u\n", "H5HF_sect_range_from_single", hdr->man_dtable.curr_root_rows);
+#endif /* QAK */
+
+ /* Update information for range block */
+ sect->sect_info.addr = dblock->block_off;
+ sect->sect_info.type = H5HF_FSPACE_SECT_RANGE;
+ sect->u.range.iblock = dblock->parent;
+ sect->u.range.row = dblock->par_entry / hdr->man_dtable.cparam.width;
+ sect->u.range.col = dblock->par_entry % hdr->man_dtable.cparam.width;
+ sect->u.range.num_entries = 1;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5HF_sect_range_from_single() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_range_serialize
*
* Purpose: Serialize a "live" range section into a buffer
@@ -756,12 +1116,12 @@ 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 H5FS_section_info_t *
+H5HF_sect_range_deserialize(const uint8_t *buf, haddr_t sect_addr,
+ hsize_t sect_size)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_free_section_t *new_sect; /* New section */
+ H5FS_section_info_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_deserialize)
@@ -769,20 +1129,22 @@ H5HF_sect_range_deserialize(H5FS_section_class_t *sect_cls,
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")
+ if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_RANGE, sect_addr, sect_size, H5FS_SECT_SERIALIZED)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section")
/* Range's row */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.row);
+ UINT16DECODE(buf, new_sect->u.range.row);
/* Range's column */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.col);
+ UINT16DECODE(buf, new_sect->u.range.col);
/* Range's # of entries */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.range.num_entries);
+ UINT16DECODE(buf, new_sect->u.range.num_entries);
+
+ /* Set return value */
+ ret_value = (H5FS_section_info_t *)new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -790,6 +1152,289 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_can_merge
+ *
+ * Purpose: Can two sections of this type merge?
+ *
+ * Note: Second section must be "after" first section
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5HF_sect_range_can_merge(H5FS_section_info_t *_sect1,
+ H5FS_section_info_t *_sect2, void *_udata)
+{
+ H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
+ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
+ H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
+ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
+ hid_t dxpl_id = udata->dxpl_id; /* DXPL ID for operation */
+ hsize_t sect2_off; /* Offset of second section in heap */
+ size_t dblock_overhead = H5HF_MAN_ABS_DIRECT_OVERHEAD(hdr); /* Direct block's overhead */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_can_merge)
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert(sect2);
+ HDassert(H5F_addr_lt(sect1->sect_info.addr, sect2->sect_info.addr));
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect2->sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sect_info.addr, sect2->sect_info.size, sect2->sect_info.type, (sect2->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+#endif /* QAK */
+ /* Check to see if we should revive either section */
+ if(sect1->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_range_revive(hdr, dxpl_id, sect1) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive single free section")
+ if(sect2->sect_info.state != H5FS_SECT_LIVE)
+ if(H5HF_sect_revive(hdr, dxpl_id, sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't revive free section")
+
+ /* Check for special case of delayed conversion of 2nd section from
+ * single -> range section
+ */
+ if(sect2->sect_info.type == H5HF_FSPACE_SECT_SINGLE) {
+ size_t dblock_size; /* Section's direct block's size */
+
+ /* Check for section occupying entire direct block */
+ dblock_size = sect2->u.single.dblock_size;
+ if((dblock_size - dblock_overhead) == sect2->sect_info.size) {
+ H5HF_direct_t *dblock; /* Pointer to direct block for section */
+ haddr_t dblock_addr; /* Section's direct block's address */
+
+ /* Protect the direct block for the section */
+ dblock_addr = sect2->u.single.dblock_addr;
+#ifdef QAK
+HDfprintf(stderr, "%s: dblock_addr = %a\n", FUNC, dblock_addr);
+#endif /* QAK */
+ if(NULL == (dblock = H5HF_man_dblock_protect(hdr, dxpl_id, dblock_addr, dblock_size, sect2->u.single.parent, sect2->u.single.par_entry, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTPROTECT, FAIL, "unable to load fractal heap direct block")
+ HDassert(H5F_addr_eq(dblock->block_off + dblock_overhead, sect2->sect_info.addr));
+
+ /* Convert 'single' section into 'range' section */
+ if(H5HF_sect_range_from_single(hdr, sect2, dblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCONVERT, FAIL, "can't convert single section into range section")
+
+ /* Destroy direct block */
+ if(H5HF_man_dblock_destroy(hdr, dxpl_id, dblock, dblock_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't release direct block")
+ dblock = NULL;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off);
+#endif /* QAK */
+ } /* end if */
+ } /* end if */
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1.u.range = {%p, %u, %u, %u}\n", FUNC, sect1->u.range.iblock, sect1->u.range.row, sect1->u.range.col, sect1->u.range.num_entries);
+#endif /* QAK */
+
+ /* Range section can only merge with other range sections */
+ if(sect1->sect_info.type != sect2->sect_info.type)
+ HGOTO_DONE(FALSE)
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect2.u.range = {%p, %u, %u, %u}\n", FUNC, sect2->u.range.iblock, sect2->u.range.row, sect2->u.range.col, sect2->u.range.num_entries);
+HDfprintf(stderr, "%s: sect2.u.range.iblock->nchildren = %u\n", FUNC, sect2->u.range.iblock->nchildren);
+#endif /* QAK */
+
+ /* Check if second section is in indirect block that's being deleted */
+ if(sect2->u.range.iblock->nchildren == 0)
+ HGOTO_DONE(TRUE)
+
+ /* Check if second section is past end of "next block" iterator */
+ sect2_off = sect2->u.range.iblock->block_off;
+ sect2_off += hdr->man_dtable.row_block_off[sect2->u.range.row];
+ sect2_off += hdr->man_dtable.row_block_size[sect2->u.range.row] * sect2->u.range.col;
+#ifdef QAK
+HDfprintf(stderr, "%s: hdr->man_iter_off = %Hu\n", FUNC, hdr->man_iter_off);
+HDfprintf(stderr, "%s: sect2.u.range.iblock->block_off = %Hu\n", FUNC, sect2->u.range.iblock->block_off);
+HDfprintf(stderr, "%s: hdr->man_dtable.row_block_off[%u] = %Hu\n", FUNC, sect2->u.range.row, hdr->man_dtable.row_block_off[sect2->u.range.row]);
+HDfprintf(stderr, "%s: sect2_off = %Hu\n", FUNC, sect2_off);
+#endif /* QAK */
+ if(sect2_off > hdr->man_iter_off)
+ HGOTO_DONE(TRUE)
+
+ /* Check if second section adjoins first section & is in the same row */
+ if(H5F_addr_eq(sect1->sect_info.addr + (sect1->u.range.num_entries * (sect1->sect_info.size + dblock_overhead)), sect2->sect_info.addr) &&
+ sect1->u.range.row == sect2->u.range.row)
+ HGOTO_DONE(TRUE)
+
+done:
+#ifdef QAK
+HDfprintf(stderr, "%s: ret_value = %t\n", FUNC, ret_value);
+#endif /* QAK */
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_range_can_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_merge
+ *
+ * Purpose: Merge two sections of this type
+ *
+ * Note: Second section always merges into first node
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_range_merge(H5FS_section_info_t *_sect1, H5FS_section_info_t *_sect2,
+ void *_udata)
+{
+ H5HF_free_section_t *sect1 = (H5HF_free_section_t *)_sect1; /* Fractal heap free section */
+ H5HF_free_section_t *sect2 = (H5HF_free_section_t *)_sect2; /* Fractal heap free section */
+ H5HF_add_ud1_t *udata = (H5HF_add_ud1_t *)_udata; /* User callback data */
+ H5HF_hdr_t *hdr = udata->hdr; /* Fractal heap header */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_merge)
+
+ /* Check arguments. */
+ HDassert(sect1);
+ HDassert(sect1->sect_info.state == H5FS_SECT_LIVE);
+ HDassert(sect1->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+ HDassert(sect2);
+ HDassert(sect2->sect_info.state == H5FS_SECT_LIVE);
+ HDassert(sect2->sect_info.type == H5HF_FSPACE_SECT_RANGE);
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect1.sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect1->sect_info.addr, sect1->sect_info.size, sect1->sect_info.type, (sect1->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect1.u.range = {%p, %u, %u, %u}\n", FUNC, sect1->u.range.iblock, sect1->u.range.row, sect1->u.range.col, sect1->u.range.num_entries);
+HDfprintf(stderr, "%s: sect2.sect_info = {%a, %Hu, %u, %s}\n", FUNC, sect2->sect_info.addr, sect2->sect_info.size, sect2->sect_info.type, (sect2->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect2.u.range = {%p, %u, %u, %u}\n", FUNC, sect2->u.range.iblock, sect2->u.range.row, sect2->u.range.col, sect2->u.range.num_entries);
+#endif /* QAK */
+
+ /* Add second section's size to first section, if it's in the same row */
+ if(sect1->u.range.row == sect2->u.range.row)
+ sect1->u.range.num_entries += sect2->u.range.num_entries;
+
+ /* Get rid of second section */
+ if(H5HF_sect_range_free((H5FS_section_info_t *)sect2) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
+
+ /* Check if 'range' section should be converted into 'indirect' section (?) */
+ if(sect1->u.range.num_entries == hdr->man_dtable.cparam.width &&
+ sect1->u.range.row >= hdr->man_dtable.max_direct_rows) {
+HDfprintf(stderr, "%s: converting range section to indirect section not supported yet!\n", FUNC);
+HGOTO_ERROR(H5E_HEAP, H5E_UNSUPPORTED, FAIL, "converting range section to indirect section not supported yet")
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_range_merge() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_can_shrink
+ *
+ * Purpose: Can this section shrink the container?
+ *
+ * Note: This isn't actually shrinking the heap (since that's already
+ * been done) as much as it's cleaning up _after_ the heap
+ * shrink.
+ *
+ * Return: Success: non-negative (TRUE/FALSE)
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static htri_t
+H5HF_sect_range_can_shrink(H5FS_section_info_t *_sect, void UNUSED *_udata)
+{
+ const H5HF_free_section_t *sect = (const H5HF_free_section_t *)_sect; /* Fractal heap free section */
+ htri_t ret_value = FALSE; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_sect_range_can_shrink)
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+
+#ifdef QAK
+HDfprintf(stderr, "%s: sect->sect_info = {%a, %Hu, %u, %s}\n", "H5HF_sect_range_can_shrink", sect->sect_info.addr, sect->sect_info.size, sect->sect_info.type, (sect->sect_info.state == H5FS_SECT_LIVE ? "H5FS_SECT_LIVE" : "H5FS_SECT_SERIALIZED"));
+HDfprintf(stderr, "%s: sect->u.range = {%p, %u, %u, %u}\n", "H5HF_sect_range_can_shrink", sect->u.range.iblock, sect->u.range.row, sect->u.range.col, sect->u.range.num_entries);
+if(sect->u.range.iblock != NULL)
+ HDfprintf(stderr, "%s: sect->u.range.iblock->nchildren = %u\n", "H5HF_sect_range_can_shrink", sect->u.range.iblock->nchildren);
+#endif /* QAK */
+
+ /* If section has no parent, it should go away */
+ if(sect->u.range.iblock == NULL)
+ HGOTO_DONE(TRUE)
+
+ /* If section is in an indirect block with no children, it should go away */
+ if(sect->u.range.iblock->nchildren == 0)
+ HGOTO_DONE(TRUE)
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_range_can_shrink() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_range_shrink
+ *
+ * Purpose: Shrink container with section
+ *
+ * Return: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 5, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5HF_sect_range_shrink(H5FS_section_info_t **_sect, void UNUSED *_udata)
+{
+ H5HF_free_section_t **sect = (H5HF_free_section_t **)_sect; /* Fractal heap free section */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_range_shrink)
+
+ /* Check arguments. */
+ HDassert(sect);
+ HDassert(*sect);
+ HDassert((*sect)->sect_info.state == H5FS_SECT_LIVE);
+
+#ifdef QAK
+HDfprintf(stderr, "%s: (*sect).sect_info = {%a, %Hu, %u}\n", FUNC, (*sect)->sect_info.addr, (*sect)->sect_info.size, (*sect)->sect_info.type);
+HDfprintf(stderr, "%s: (*sect).u.range = {%p, %u, %u, %u}\n", FUNC, (*sect)->u.range.iblock, (*sect)->u.range.row, (*sect)->u.range.col, (*sect)->u.range.num_entries);
+#endif /* QAK */
+
+ /* Get rid of section */
+ if(H5HF_sect_range_free((H5FS_section_info_t *)*sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free section node")
+
+ /* Indicate that the section has been released */
+ *sect = NULL;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_sect_range_shrink() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_range_free
*
* Purpose: Free a 'range' section node
@@ -803,7 +1448,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5HF_sect_range_free(H5FS_section_info_t *_sect)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
@@ -904,6 +1549,74 @@ H5HF_sect_indirect_init_cls(H5FS_section_class_t *cls, const void UNUSED *udata)
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_add
+ *
+ * Purpose: Add a new 'indirect' section to the free space manager for this
+ * heap
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 30 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_indirect_add(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ hsize_t sect_off, hsize_t sect_size, H5HF_indirect_t *iblock,
+ unsigned row, unsigned col, unsigned nentries,
+ unsigned indir_row, unsigned indir_nrows)
+{
+ H5HF_free_section_t *sect = NULL; /* 'Indirect' free space section to add */
+ hbool_t iblock_incr = FALSE; /* Indicate that parent iblock has been incremented */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_add)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(iblock);
+ HDassert(sect_size);
+ HDassert(nentries);
+
+ /* Create free space section node */
+ if(NULL == (sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_off, sect_size, H5FS_SECT_LIVE)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for indirect section")
+
+ /* Set the 'indirect' specific fields */
+ sect->u.indirect.iblock = iblock;
+ if(H5HF_iblock_incr(sect->u.indirect.iblock) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINC, FAIL, "can't increment reference count on shared indirect block")
+ iblock_incr = TRUE;
+ sect->u.indirect.row = row;
+ sect->u.indirect.col = col;
+ sect->u.indirect.num_entries = nentries;
+ sect->u.indirect.indir_row = indir_row;
+ sect->u.indirect.indir_nrows = indir_nrows;
+
+ /* Add new free space to the free space manager for the heap */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't add indirect section to free space")
+
+done:
+ if(ret_value < 0 && sect) {
+ /* Check if we should decrement parent ref. count */
+ if(iblock_incr)
+ if(H5HF_iblock_decr(sect->u.indirect.iblock) < 0)
+ HDONE_ERROR(H5E_HEAP, H5E_CANTDEC, FAIL, "can't decrement reference count on shared indirect block")
+
+ /* Release the section */
+ H5FL_FREE(H5HF_free_section_t, sect);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_add() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_indirect_revive
*
* Purpose: Update the memory information for a 'indirect' free section
@@ -958,6 +1671,61 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5HF_sect_indirect_reduce
+ *
+ * Purpose: Reduce the size of a indirect section (possibly freeing it)
+ * and re-add it back to the free space manager for the heap
+ * (if it hasn't been freed)
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * May 31 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5HF_sect_indirect_reduce(H5HF_hdr_t *hdr, hid_t dxpl_id,
+ H5HF_free_section_t *sect)
+{
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_reduce)
+
+ /*
+ * Check arguments.
+ */
+ HDassert(hdr);
+ HDassert(sect);
+ HDassert(sect->sect_info.type == H5HF_FSPACE_SECT_INDIRECT);
+ HDassert(sect->sect_info.state == H5FS_SECT_LIVE);
+
+ /* Check for eliminating the section */
+ if(sect->u.indirect.num_entries == 1) {
+ /* Free indirect section */
+ if(H5HF_sect_indirect_free((H5FS_section_info_t *)sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTRELEASE, FAIL, "can't free indirect section node")
+ } /* end if */
+ else {
+ /* Adjust section information */
+ sect->sect_info.addr += hdr->man_dtable.row_block_size[sect->u.indirect.row];
+
+ /* Adjust range information */
+ sect->u.indirect.col++;
+ sect->u.indirect.num_entries--;
+
+ /* Add 'indirect' section back to free space list */
+ if(H5HF_space_add(hdr, dxpl_id, sect) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't re-add indirect section to free space manager")
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5HF_sect_indirect_reduce() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5HF_sect_indirect_serialize
*
* Purpose: Serialize a "live" indirect section into a buffer
@@ -1015,12 +1783,12 @@ 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 H5FS_section_info_t *
+H5HF_sect_indirect_deserialize(const uint8_t *buf, haddr_t sect_addr,
+ hsize_t sect_size)
{
- herr_t ret_value = SUCCEED; /* Return value */
+ H5HF_free_section_t *new_sect; /* New section */
+ H5FS_section_info_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_sect_indirect_deserialize)
@@ -1028,26 +1796,28 @@ H5HF_sect_indirect_deserialize(H5FS_section_class_t *sect_cls,
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")
+ if(NULL == (new_sect = H5HF_sect_node_new(H5HF_FSPACE_SECT_INDIRECT, sect_addr, sect_size, H5FS_SECT_SERIALIZED)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "allocation failed for direct block free list section")
/* Range's row */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.row);
+ UINT16DECODE(buf, new_sect->u.indirect.row);
/* Range's column */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.col);
+ UINT16DECODE(buf, new_sect->u.indirect.col);
/* Range's # of entries */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.num_entries);
+ UINT16DECODE(buf, new_sect->u.indirect.num_entries);
/* Range's indirect row */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.indir_row);
+ UINT16DECODE(buf, new_sect->u.indirect.indir_row);
/* Range's indirect # of rows */
- UINT16DECODE(buf, ((H5HF_free_section_t *)*sect)->u.indirect.indir_nrows);
+ UINT16DECODE(buf, new_sect->u.indirect.indir_nrows);
+
+ /* Set return value */
+ ret_value = (H5FS_section_info_t *)new_sect;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1068,7 +1838,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5HF_sect_indirect_free(H5FS_section_info_t *_sect)
{
H5HF_free_section_t *sect = (H5HF_free_section_t *)_sect; /* Pointer to section to free */
diff --git a/src/H5HFspace.c b/src/H5HFspace.c
index 91cc742..3519e91 100644
--- a/src/H5HFspace.c
+++ b/src/H5HFspace.c
@@ -96,10 +96,9 @@ 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 */
+ H5HF_FSPACE_SECT_CLS_SINGLE,
+ H5HF_FSPACE_SECT_CLS_RANGE,
+ H5HF_FSPACE_SECT_CLS_INDIRECT};
herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5HF_space_start)
@@ -109,25 +108,11 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id)
*/
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,
- hdr->nsect_classes, hdr->sect_cls, hdr)))
+ NELMTS(classes), classes, hdr)))
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize free space info")
} /* end if */
else {
@@ -142,13 +127,10 @@ H5HF_space_start(H5HF_hdr_t *hdr, hid_t dxpl_id)
/* Create the free space structure for the heap */
if(NULL == (hdr->fspace = H5FS_create(hdr->f, dxpl_id, &hdr->fs_addr,
- &fs_create, hdr->nsect_classes, hdr->sect_cls, hdr)))
+ &fs_create, NELMTS(classes), classes, 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() */
@@ -185,7 +167,7 @@ H5HF_space_find(H5HF_hdr_t *hdr, hid_t dxpl_id, hsize_t request, H5HF_free_secti
HDassert(node);
/* Check if the free space for the heap has been initialized */
- if(!hdr->fspace_open)
+ if(!hdr->fspace)
if(H5HF_space_start(hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
@@ -228,7 +210,6 @@ H5HF_space_add(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node)
*/
HDassert(hdr);
HDassert(node);
- HDassert(hdr->fspace_open);
HDassert(hdr->fspace);
/* Add to the free space for the heap */
@@ -270,7 +251,7 @@ H5HF_space_return(H5HF_hdr_t *hdr, hid_t dxpl_id, H5HF_free_section_t *node)
HDassert(node);
/* Check if the free space for the heap has been initialized */
- if(!hdr->fspace_open)
+ if(!hdr->fspace)
if(H5HF_space_start(hdr, dxpl_id) < 0)
HGOTO_ERROR(H5E_HEAP, H5E_CANTINIT, FAIL, "can't initialize heap free space")
@@ -316,20 +297,27 @@ H5HF_space_close(H5HF_hdr_t *hdr, hid_t dxpl_id)
HDassert(hdr);
/* Check if the free space was ever opened */
- if(hdr->fspace_open) {
- /* Sanity check */
- HDassert(hdr->fspace);
+ if(hdr->fspace) {
+ hsize_t nsects; /* Number of sections for this heap */
+
+ /* Retrieve the number of sections for this heap */
+ if(H5FS_get_sect_count(hdr->fspace, &nsects) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTCOUNT, FAIL, "can't query free space section count")
+#ifdef QAK
+HDfprintf(stderr, "%s: nsects = %Hu\n", FUNC, nsects);
+#endif /* QAK */
/* 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;
+ /* Check if we can delete the free space manager for this heap */
+ if(!nsects) {
+ if(H5FS_delete(hdr->f, dxpl_id, hdr->fs_addr) < 0)
+ HGOTO_ERROR(H5E_HEAP, H5E_CANTDELETE, FAIL, "can't delete free space info")
+ hdr->fs_addr = HADDR_UNDEF;
+ } /* end if */
} /* end if */
done:
diff --git a/src/H5HFstat.c b/src/H5HFstat.c
index 693a6fa..e0e762f 100644
--- a/src/H5HFstat.c
+++ b/src/H5HFstat.c
@@ -83,7 +83,7 @@
*-------------------------------------------------------------------------
*/
herr_t
-H5HF_stat_info(H5HF_t *fh, H5HF_stat_t *stats)
+H5HF_stat_info(const H5HF_t *fh, H5HF_stat_t *stats)
{
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_stat_info)
@@ -94,6 +94,8 @@ H5HF_stat_info(H5HF_t *fh, H5HF_stat_t *stats)
/* Report statistics for fractal heap */
stats->total_size = fh->hdr->total_size;
stats->man_size = fh->hdr->man_size;
+ stats->man_alloc_size = fh->hdr->man_alloc_size;
+ stats->man_iter_off = fh->hdr->man_iter_off;
stats->std_size = fh->hdr->std_size;
stats->man_free_space = fh->hdr->total_man_free;
stats->nobjs = fh->hdr->nobjs;
diff --git a/src/H5HFtest.c b/src/H5HFtest.c
index a171acd..5e57af3 100644
--- a/src/H5HFtest.c
+++ b/src/H5HFtest.c
@@ -102,34 +102,133 @@ H5HF_get_cparam_test(const H5HF_t *fh, H5HF_create_t *cparam)
/*-------------------------------------------------------------------------
- * Function: H5HF_get_dblock_overhead
+ * Function: H5HF_get_max_root_rows
*
- * Purpose: Retrieve the size of direct block overhead
+ * Purpose: Retrieve the max. # of rows in the root indirect block
*
- * Return: Success: Size of direct block overhead
+ * Return: Success: Max. # of rows in root indirect block
*
* Failure: 0
*
* Programmer: Quincey Koziol
- * Tuesday, May 9, 2006
+ * Monday, May 22, 2006
*
*-------------------------------------------------------------------------
*/
-size_t
-H5HF_get_dblock_overhead(const H5HF_t *fh)
+unsigned
+H5HF_get_max_root_rows(const H5HF_t *fh)
{
- size_t ret_value; /* Return value */
+ unsigned ret_value; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_dblock_overhead)
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_max_root_rows)
/* Check arguments. */
HDassert(fh);
- /* Return direct block overhead */
- ret_value = H5HF_MAN_ABS_DIRECT_OVERHEAD(fh->hdr);
+ /* Return max. # of rows in root indirect block */
+ ret_value = fh->hdr->man_dtable.max_root_rows;
FUNC_LEAVE_NOAPI(ret_value)
-} /* H5HF_get_dblock_overhead() */
+} /* H5HF_get_max_root_rows() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_get_dtable_width_test
+ *
+ * Purpose: Retrieve the width of the doubling table for a heap
+ *
+ * Return: Success: Width of the doubling table
+ *
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Monday, May 22, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5HF_get_dtable_width_test(const H5HF_t *fh)
+{
+ unsigned ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_dtable_width_test)
+
+ /* Check arguments. */
+ HDassert(fh);
+
+ /* Return width of doubling table */
+ ret_value = fh->hdr->man_dtable.cparam.width;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_get_dtable_width_test() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_get_dtable_max_drows_test
+ *
+ * Purpose: Retrieve the max. # of direct block rows in any indirect block
+ *
+ * Return: Success: Max. # of direct block rows
+ *
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Monday, May 22, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5HF_get_dtable_max_drows_test(const H5HF_t *fh)
+{
+ unsigned ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_dtable_max_drows_test)
+
+ /* Check arguments. */
+ HDassert(fh);
+
+ /* Return max. # of direct blocks in any indirect block */
+ ret_value = fh->hdr->man_dtable.max_direct_rows;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_get_dtable_max_drows_test() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5HF_get_iblock_max_drows_test
+ *
+ * Purpose: Retrieve the max. # of direct block rows in an indirect block
+ *
+ * Note: POS is indexed from 1 and is only really working for the
+ * 2nd-level indirect blocks (i.e. indirect blocks with
+ * only direct block children)
+ *
+ * Return: Success: Max. # of direct block rows
+ *
+ * Failure: 0
+ *
+ * Programmer: Quincey Koziol
+ * Monday, May 22, 2006
+ *
+ *-------------------------------------------------------------------------
+ */
+unsigned
+H5HF_get_iblock_max_drows_test(const H5HF_t *fh, unsigned pos)
+{
+ unsigned ret_value; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5HF_get_iblock_max_drows_test)
+
+ /* Check arguments. */
+ HDassert(fh);
+ HDassert(pos);
+
+ /* Return max. # of direct blocks in this indirect block row */
+ ret_value = pos + (fh->hdr->man_dtable.max_direct_bits -
+ fh->hdr->man_dtable.first_row_bits) + 1;
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* H5HF_get_iblock_max_drows_test() */
/*-------------------------------------------------------------------------
diff --git a/src/H5err.txt b/src/H5err.txt
index ca8f515..51807f8 100644
--- a/src/H5err.txt
+++ b/src/H5err.txt
@@ -218,6 +218,8 @@ MINOR, MPI, H5E_CANTRECV, Can't receive data
MINOR, HEAP, H5E_CANTRESTORE, Can't restore condition
MINOR, HEAP, H5E_CANTCOMPUTE, Can't compute value
MINOR, HEAP, H5E_CANTEXTEND, Can't extend heap's space
+MINOR, HEAP, H5E_CANTATTACH, Can't attach object
+MINOR, HEAP, H5E_CANTUPDATE, Can't update object
# Free space manager errors
MINOR, FSPACE, H5E_CANTMERGE, Can't merge objects