summaryrefslogtreecommitdiffstats
path: root/src/H5BT.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2005-03-11 19:21:04 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2005-03-11 19:21:04 (GMT)
commitdf886c57fca24425956766c6c2b094557ba9797a (patch)
tree5245a484e7278b9602d6b08a272ac7755d7f1d25 /src/H5BT.c
parent46b9fb5081bdb8e8980e71e3c13e48cd14992da6 (diff)
downloadhdf5-df886c57fca24425956766c6c2b094557ba9797a.zip
hdf5-df886c57fca24425956766c6c2b094557ba9797a.tar.gz
hdf5-df886c57fca24425956766c6c2b094557ba9797a.tar.bz2
[svn-r10198] Purpose:
New feature Description: Handle merging new blocks with existing blocks Platforms tested: FreeBSD 4.11 (sleipnir) Solaris 2.9 (shanti)
Diffstat (limited to 'src/H5BT.c')
-rw-r--r--src/H5BT.c216
1 files changed, 179 insertions, 37 deletions
diff --git a/src/H5BT.c b/src/H5BT.c
index 88377cc..4e76278 100644
--- a/src/H5BT.c
+++ b/src/H5BT.c
@@ -142,6 +142,37 @@ H5BT_insert_neighbor_cb(const void *_record, void *_op_data)
/*-------------------------------------------------------------------------
+ * Function: H5BT_insert_modify_cb
+ *
+ * Purpose: v2 B-tree modify callback for H5BT_insert()
+ *
+ * Return: Success: 0
+ *
+ * Failure: 1
+ *
+ * Programmer: Quincey Koziol
+ * Friday, March 11, 2005
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5BT_insert_modify_cb(void *_record, void *_op_data, hbool_t *changed)
+{
+ H5BT_blk_info_t *record = (H5BT_blk_info_t *)_record;
+ H5BT_blk_info_t *modify = (H5BT_blk_info_t *)_op_data;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5BT_insert_modify_cb)
+
+ *record = *modify;
+ *changed = TRUE;
+
+ FUNC_LEAVE_NOAPI(0)
+} /* end H5BT_insert_modify_cb() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5BT_insert
*
* Purpose: Insert new block (offset/length) into a block tracker.
@@ -163,6 +194,7 @@ H5BT_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, haddr_t offset, hsize_t lengt
hbool_t lower_valid = FALSE, upper_valid = FALSE; /* Lower & upper blocks valid? */
H5BT_blk_info_t new_block; /* Info for new block */
hsize_t nblks; /* Number of blocks tracked */
+ unsigned merged = 0; /* How many blocks were merged with */
herr_t ret_value=SUCCEED;
FUNC_ENTER_NOAPI(H5BT_insert, FAIL)
@@ -205,51 +237,161 @@ H5BT_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, haddr_t offset, hsize_t lengt
/* Clear any errors from H5B2_neighbor() */
H5E_clear_stack(NULL);
-#ifdef QAK
/* Check for merged blocks */
if(lower_valid || upper_valid) {
-HDfprintf(stderr,"%s: Lower & upper block merging not supported yet!\n",FUNC);
-HGOTO_ERROR(H5E_BLKTRK, H5E_UNSUPPORTED, FAIL, "lower or upper block found!")
- } /* end if */
-#endif /* QAK */
-
- /* Insert new block into B-tree */
- new_block.addr = offset;
- new_block.len = length;
- if(H5B2_insert(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, &new_block) < 0)
- HDONE_ERROR(H5E_BLKTRK, H5E_CANTINSERT, FAIL, "unable to insert block")
-
-/* Update block tracker metadata */
-
- /* Determine the number of blocks being tracked */
- if(H5B2_get_nrec(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, &nblks) < 0)
- HDONE_ERROR(H5E_BLKTRK, H5E_CANTINSERT, FAIL, "unable to determine # of blocks")
-
- /* This is the only block tracked so far */
- if(nblks == 1) {
- bt->max_block_size = length;
- bt->max_block_cnt = 1;
- bt->status |= H5BT_STATUS_MAX_VALID;
- bt->min_block_size = length;
- bt->min_block_cnt = 1;
- bt->status |= H5BT_STATUS_MIN_VALID;
+ H5BT_blk_info_t *old_block=NULL; /* Pointer to info for block merged with */
+
+ /* Check if the new block should merge with both the lower & upper blocks */
+ if((lower_valid && (lower.addr+lower.len) == offset)
+ && (upper_valid && (offset+length) == upper.addr)) {
+ /* Delete upper block */
+ if(H5B2_remove(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, &upper)<0)
+ HGOTO_ERROR(H5E_BLKTRK, H5E_CANTDELETE, FAIL, "can't remove block")
+
+ /* Update existing lower block */
+ new_block.addr = lower.addr;
+ new_block.len = lower.len + length + upper.len;
+ if(H5B2_modify(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, &lower, H5BT_insert_modify_cb, &new_block) < 0)
+ HGOTO_ERROR(H5E_BLKTRK, H5E_CANTMODIFY, FAIL, "can't change block size")
+
+ /* Merged with 2 blocks */
+ merged = 2;
+ } /* end if */
+ /* Check if the new block should merge with just the lower block */
+ else if(lower_valid && (lower.addr+lower.len) == offset) {
+ /* Update existing lower block */
+ new_block.addr = lower.addr;
+ new_block.len = lower.len + length;
+ if(H5B2_modify(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, &lower, H5BT_insert_modify_cb, &new_block) < 0)
+ HGOTO_ERROR(H5E_BLKTRK, H5E_CANTMODIFY, FAIL, "can't change block size")
+
+ /* Indicate which block we merged with */
+ old_block = &lower;
+
+ /* Merged with 1 block */
+ merged = 1;
+ } /* end else */
+ /* Check if the new block should merge with just the upper block */
+ else if(upper_valid && (offset+length) == upper.addr) {
+ /* Update existing upper block */
+ new_block.addr = offset;
+ new_block.len = length + upper.len;
+ if(H5B2_modify(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, &upper, H5BT_insert_modify_cb, &new_block) < 0)
+ HGOTO_ERROR(H5E_BLKTRK, H5E_CANTMODIFY, FAIL, "can't change block size")
+
+ /* Indicate which block we merged with */
+ old_block = &upper;
+
+ /* Merged with 1 block */
+ merged = 1;
+ } /* end else */
+
+ /* Check for adjusting the block tracking metadata */
+ if(merged == 1) {
+ /* Check for adjusting the max. block size tracked */
+ if(new_block.len > bt->max_block_size) {
+ bt->max_block_size = new_block.len;
+ bt->max_block_cnt = 1;
+ } /* end if */
+ else if(new_block.len == bt->max_block_size)
+ bt->max_block_cnt++;
+
+ /* Check for adjusting the min. block size tracked */
+ if(old_block->len < bt->min_block_size) {
+ /* This should only happen if we don't have full knowledge of all the blocks' sizes */
+ HDassert((bt->status & H5BT_STATUS_MIN_VALID) == 0);
+
+ if(new_block.len < bt->min_block_size) {
+ bt->min_block_size = new_block.len;
+ bt->min_block_cnt = 1;
+ } /* end if */
+ } /* end if */
+ else if(old_block->len == bt->min_block_size) {
+ /* If this was the minimum block, indicate that the min. size
+ * is no longer guaranteed valid over the whole set of blocks
+ * tracked and use the new block size as the minimum value */
+ if(bt->min_block_cnt == 1) {
+ bt->min_block_size = new_block.len;
+ bt->status &= ~H5BT_STATUS_MIN_VALID;
+ } /* end if */
+ else
+ /* Decrement the ref. count for the min. block size */
+ bt->min_block_cnt--;
+ } /* end if */
+ } /* end if */
+ else if(merged == 2) {
+ /* Check for adjusting the max. block size tracked */
+ if(new_block.len > bt->max_block_size) {
+ bt->max_block_size = new_block.len;
+ bt->max_block_cnt = 1;
+ } /* end if */
+ else if(new_block.len == bt->max_block_size)
+ bt->max_block_cnt++;
+
+ /* Check for adjusting the min. block size tracked */
+ if(upper.len < bt->min_block_size || lower.len < bt->min_block_size) {
+ /* This should only happen if we don't have full knowledge of all the blocks' sizes */
+ HDassert((bt->status & H5BT_STATUS_MIN_VALID) == 0);
+
+ if(new_block.len < bt->min_block_size) {
+ bt->min_block_size = new_block.len;
+ bt->min_block_cnt = 1;
+ } /* end if */
+ } /* end if */
+ else if(upper.len == bt->min_block_size || lower.len == bt->min_block_size) {
+ /* If this was the minimum block, indicate that the min. size
+ * is no longer guaranteed valid over the whole set of blocks
+ * tracked and use the new block size as the minimum value */
+ if(bt->min_block_cnt == 1) {
+ bt->min_block_size = new_block.len;
+ bt->status &= ~H5BT_STATUS_MIN_VALID;
+ } /* end if */
+ else
+ /* Decrement the ref. count for the min. block size */
+ bt->min_block_cnt--;
+ } /* end if */
+ } /* end if */
} /* end if */
- else {
- /* Update maximum block size */
- if (length > bt->max_block_size) {
+
+ /* Insert new block into B-tree, if it wasn't marged already*/
+ if(!merged) {
+ new_block.addr = offset;
+ new_block.len = length;
+ if(H5B2_insert(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, &new_block) < 0)
+ HGOTO_ERROR(H5E_BLKTRK, H5E_CANTINSERT, FAIL, "unable to insert block")
+
+ /* Update block tracker metadata */
+
+ /* Determine the number of blocks being tracked */
+ if(H5B2_get_nrec(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, &nblks) < 0)
+ HGOTO_ERROR(H5E_BLKTRK, H5E_CANTINSERT, FAIL, "unable to determine # of blocks")
+
+ /* This is the only block tracked so far */
+ if(nblks == 1) {
bt->max_block_size = length;
bt->max_block_cnt = 1;
- } /* end if */
- else if (length == bt->max_block_size)
- bt->max_block_cnt++;
-
- /* Update minimum block size */
- if (length < bt->min_block_size) {
+ bt->status |= H5BT_STATUS_MAX_VALID;
bt->min_block_size = length;
bt->min_block_cnt = 1;
+ bt->status |= H5BT_STATUS_MIN_VALID;
+ } /* end if */
+ else {
+ /* Update maximum block size */
+ if (length > bt->max_block_size) {
+ bt->max_block_size = length;
+ bt->max_block_cnt = 1;
+ } /* end if */
+ else if (length == bt->max_block_size)
+ bt->max_block_cnt++;
+
+ /* Update minimum block size */
+ if (length < bt->min_block_size) {
+ bt->min_block_size = length;
+ bt->min_block_cnt = 1;
+ } /* end if */
+ else if (length == bt->min_block_size)
+ bt->min_block_cnt++;
} /* end if */
- else if (length == bt->min_block_size)
- bt->min_block_cnt++;
} /* end if */
/* Increment total number of bytes tracked in all blocks */