From 4d86e9e8b87f5abd5d1c6fcfbcef738d36db387f Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Thu, 10 Mar 2005 21:30:53 -0500 Subject: [svn-r10186] Purpose: New feature Description: Add basic code to insert blocks into block tracker. Platforms tested: FreeBSD 4.11 (sleipnir) Solaris 2.9 (shanti) --- src/H5BT.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5BTprivate.h | 2 + test/blocktrack.c | 74 +++++++++++++++++++++++++++++++++-- 3 files changed, 187 insertions(+), 3 deletions(-) diff --git a/src/H5BT.c b/src/H5BT.c index c24ce06..fa59af0 100644 --- a/src/H5BT.c +++ b/src/H5BT.c @@ -108,3 +108,117 @@ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5BT_create() */ + +/*------------------------------------------------------------------------- + * Function: H5BT_insert_neighbor_cb + * + * Purpose: v2 B-tree neighbor callback for H5BT_insert() + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Thursday, March 10, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +H5BT_insert_neighbor_cb(const void *_record, void *_op_data) +{ + const H5BT_blk_info_t *record = (const H5BT_blk_info_t *)_record; + H5BT_blk_info_t *search = (H5BT_blk_info_t *)_op_data; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5BT_insert_neighbor_cb) + + *search = *record; + + FUNC_LEAVE_NOAPI(0) +} /* end H5BT_insert_neighbor_cb() */ + + +/*------------------------------------------------------------------------- + * Function: H5BT_insert + * + * Purpose: Insert new block (offset/length) into a block tracker. + * Duplicate and overlapping blocks are rejected. + * + * Return: Non-negative on success, negative on failure + * + * Programmer: Quincey Koziol + * koziol@ncsa.uiuc.edu + * Mar 10 2005 + * + *------------------------------------------------------------------------- + */ +herr_t +H5BT_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, haddr_t offset, hsize_t length) +{ + H5BT_t *bt = NULL; /* The new B-tree header information */ + H5BT_blk_info_t lower, upper; /* Info for blocks less than & greater than new block */ + hbool_t lower_valid = FALSE, upper_valid = FALSE; /* Lower & upper blocks valid? */ + H5BT_blk_info_t new_block; /* Info for new block */ + herr_t ret_value=SUCCEED; + + FUNC_ENTER_NOAPI(H5BT_insert, FAIL) + + /* + * Check arguments. + */ + HDassert(f); + HDassert(H5F_addr_defined(addr)); + + /* Look up the block tracker header */ + if (NULL == (bt = H5AC_protect(f, dxpl_id, H5AC_BLTR, addr, NULL, NULL, H5AC_WRITE))) + HGOTO_ERROR(H5E_BLKTRK, H5E_CANTPROTECT, FAIL, "unable to load block tracker info") + + /* Check for block at this address already */ + if (H5B2_find(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, &offset, NULL, NULL) >= 0) + HGOTO_ERROR(H5E_BLKTRK, H5E_EXISTS, FAIL, "block at address already exists") + /* Clear any errors from H5B2_find() */ + H5E_clear_stack(NULL); + + /* Find next block lower than the new block */ + if ( H5B2_neighbor(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, H5B2_COMPARE_LESS, &offset, H5BT_insert_neighbor_cb, &lower) >= 0) { + if ( H5F_addr_overlap(lower.addr, lower.len, offset, length) ) + HGOTO_ERROR(H5E_BLKTRK, H5E_OVERLAPS, FAIL, "new block overlaps existing block") + + /* Set flag to indicate lower bound found */ + lower_valid = TRUE; + } /* end if */ + /* Clear any errors from H5B2_neighbor() */ + H5E_clear_stack(NULL); + + /* Find next block higher than the new block */ + if ( H5B2_neighbor(f, dxpl_id, H5B2_BLKTRK, bt->bt2_addr, H5B2_COMPARE_GREATER, &offset, H5BT_insert_neighbor_cb, &upper) >= 0) { + if ( H5F_addr_overlap(upper.addr, upper.len, offset, length) ) + HGOTO_ERROR(H5E_BLKTRK, H5E_OVERLAPS, FAIL, "new block overlaps existing block") + + /* Set flag to indicate upper bound found */ + upper_valid = TRUE; + } /* end if */ + /* Clear any errors from H5B2_neighbor() */ + H5E_clear_stack(NULL); + + /* 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 */ + + /* 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") + +done: + /* Release the block tracker info */ + if (bt && H5AC_unprotect(f, dxpl_id, H5AC_BLTR, addr, bt, H5AC__NO_FLAGS_SET) < 0) + HDONE_ERROR(H5E_BLKTRK, H5E_CANTUNPROTECT, FAIL, "unable to release block tracker info") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5BT_insert() */ + diff --git a/src/H5BTprivate.h b/src/H5BTprivate.h index e506051..2c01e51 100644 --- a/src/H5BTprivate.h +++ b/src/H5BTprivate.h @@ -46,6 +46,8 @@ /* Library-private Function Prototypes */ /***************************************/ H5_DLL herr_t H5BT_create(H5F_t *f, hid_t dxpl_id, haddr_t *addr_p); +H5_DLL herr_t H5BT_insert(H5F_t *f, hid_t dxpl_id, haddr_t addr, haddr_t offset, + hsize_t length); #endif /* _H5BTprivate_H */ diff --git a/test/blocktrack.c b/test/blocktrack.c index 992e54d..2b271a2 100644 --- a/test/blocktrack.c +++ b/test/blocktrack.c @@ -65,17 +65,17 @@ test_create(hid_t fapl) if (NULL==(f=H5I_object(file))) { H5Eprint_stack(H5E_DEFAULT, stdout); TEST_ERROR; - } + } /* end if */ /* * Test block tracker creation */ - TESTING("Block tracker creation"); + TESTING("block tracker creation"); if (H5BT_create(f, H5P_DATASET_XFER_DEFAULT, &bt_addr/*out*/)<0) { H5_FAILED(); H5Eprint_stack(H5E_DEFAULT, stdout); goto error; - } + } /* end if */ PASSED(); if (H5Fclose(file)<0) TEST_ERROR; @@ -91,6 +91,71 @@ error: /*------------------------------------------------------------------------- + * Function: test_insert_one + * + * Purpose: Basic tests for the block tracker code + * + * Return: Success: 0 + * + * Failure: 1 + * + * Programmer: Quincey Koziol + * Thursday, March 10, 2005 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static int +test_insert_one(hid_t fapl) +{ + hid_t file=-1; + char filename[1024]; + H5F_t *f=NULL; + haddr_t bt_addr; /* Address of block tracker created */ + + h5_fixname(FILENAME[0], fapl, filename, sizeof filename); + + /* Create the file to work on */ + if ((file=H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl))<0) TEST_ERROR; + + /* Get a pointer to the internal file object */ + if (NULL==(f=H5I_object(file))) { + H5Eprint_stack(H5E_DEFAULT, stdout); + TEST_ERROR; + } /* end if */ + + /* + * Test inserting one block + */ + TESTING("insert 1 block"); + if (H5BT_create(f, H5P_DATASET_XFER_DEFAULT, &bt_addr/*out*/)<0) { + H5_FAILED(); + H5Eprint_stack(H5E_DEFAULT, stdout); + goto error; + } /* end if */ + + if (H5BT_insert(f, H5P_DATASET_XFER_DEFAULT, bt_addr, (haddr_t)10, (hsize_t)20)<0) { + H5_FAILED(); + H5Eprint_stack(H5E_DEFAULT, stdout); + goto error; + } /* end if */ + + PASSED(); + + if (H5Fclose(file)<0) TEST_ERROR; + + return 0; + +error: + H5E_BEGIN_TRY { + H5Fclose(file); + } H5E_END_TRY; + return 1; +} /* test_insert_one() */ + + +/*------------------------------------------------------------------------- * Function: main * * Purpose: Test the block tracker code @@ -119,6 +184,9 @@ main(void) /* Test block tracker creation */ nerrors += test_create(fapl); + /* Test block tracker insertion */ + nerrors += test_insert_one(fapl); + if (nerrors) goto error; puts("All block tracker tests passed."); #ifndef QAK -- cgit v0.12