diff options
-rw-r--r-- | MANIFEST | 3 | ||||
-rw-r--r-- | src/H5Edefin.h | 8 | ||||
-rw-r--r-- | src/H5Einit.h | 24 | ||||
-rw-r--r-- | src/H5Epubgen.h | 12 | ||||
-rw-r--r-- | src/H5Eterm.h | 8 | ||||
-rw-r--r-- | src/H5HP.c | 16 | ||||
-rw-r--r-- | src/H5SL.c | 715 | ||||
-rw-r--r-- | src/H5SLprivate.h | 66 | ||||
-rw-r--r-- | src/H5err.txt | 10 | ||||
-rw-r--r-- | src/Makefile.in | 6 | ||||
-rw-r--r-- | test/Makefile.in | 13 | ||||
-rw-r--r-- | test/testhdf5.c | 1 | ||||
-rw-r--r-- | test/testhdf5.h | 1 | ||||
-rw-r--r-- | test/tskiplist.c | 497 |
14 files changed, 1353 insertions, 27 deletions
@@ -918,6 +918,8 @@ ./src/H5Spublic.h ./src/H5Sselect.c ./src/H5Stest.c +./src/H5SL.c +./src/H5SLprivate.h ./src/H5ST.c ./src/H5STprivate.h ./src/H5T.c @@ -1045,6 +1047,7 @@ ./test/trefer.c ./test/trefstr.c ./test/tselect.c +./test/tskiplist.c ./test/ttbbt.c ./test/ttst.c ./test/ttsafe.c diff --git a/src/H5Edefin.h b/src/H5Edefin.h index fc629bb..983a615 100644 --- a/src/H5Edefin.h +++ b/src/H5Edefin.h @@ -41,6 +41,7 @@ hid_t H5E_TBBT_g = FAIL; /* Threaded, Balanced, Binary Trees */ hid_t H5E_ATOM_g = FAIL; /* Object atom */ hid_t H5E_ATTR_g = FAIL; /* Attribute */ hid_t H5E_IO_g = FAIL; /* Low-level I/O */ +hid_t H5E_SLIST_g = FAIL; /* Skip Lists */ hid_t H5E_EFL_g = FAIL; /* External file list */ hid_t H5E_TST_g = FAIL; /* Ternary Search Trees */ hid_t H5E_ARGS_g = FAIL; /* Invalid arguments to routine */ @@ -50,6 +51,9 @@ hid_t H5E_CACHE_g = FAIL; /* Object cache */ /* Minor error IDs */ +/* Threaded, balanced binary tree errors */ +hid_t H5E_CANTMAKETREE_g = FAIL; /* Can't create a binary tree node */ + /* Generic low-level file I/O errors */ hid_t H5E_SEEKERROR_g = FAIL; /* Seek failed */ hid_t H5E_READERROR_g = FAIL; /* Read failed */ @@ -68,6 +72,9 @@ hid_t H5E_CANTUNLOCK_g = FAIL; /* Unable to unlock object */ hid_t H5E_CANTGC_g = FAIL; /* Unable to garbage collect */ hid_t H5E_CANTGETSIZE_g = FAIL; /* Unable to compute size */ +/* Heap errors */ +hid_t H5E_CANTRESTORE_g = FAIL; /* Can't restore condition */ + /* Function entry/exit interface errors */ hid_t H5E_CANTINIT_g = FAIL; /* Unable to initialize object */ hid_t H5E_ALREADYINIT_g = FAIL; /* Object already initialized */ @@ -86,7 +93,6 @@ hid_t H5E_BADMESG_g = FAIL; /* Unrecognized message */ hid_t H5E_CANTDELETE_g = FAIL; /* Can't delete message */ /* FPHDF5 errors */ -hid_t H5E_CANTMAKETREE_g = FAIL; /* Can't create a binary tree node */ hid_t H5E_CANTRECV_g = FAIL; /* Can't receive messages from processes */ hid_t H5E_CANTSENDMDATA_g = FAIL; /* Can't send metadata message */ hid_t H5E_CANTCHANGE_g = FAIL; /* Can't register change with server */ diff --git a/src/H5Einit.h b/src/H5Einit.h index 0e43071..065a4d1 100644 --- a/src/H5Einit.h +++ b/src/H5Einit.h @@ -128,6 +128,11 @@ if((msg = H5E_create_msg(cls, H5E_MAJOR, "Low-level I/O"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") if((H5E_IO_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +assert(H5E_SLIST_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MAJOR, "Skip Lists"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_SLIST_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") assert(H5E_EFL_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MAJOR, "External file list"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") @@ -164,6 +169,13 @@ if((H5E_CACHE_g = H5I_register(H5I_ERROR_MSG, msg))<0) /*********************/ +/* Threaded, balanced binary tree errors */ +assert(H5E_CANTMAKETREE_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't create a binary tree node"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_CANTMAKETREE_g = H5I_register(H5I_ERROR_MSG, msg))<0) + HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") + /* Generic low-level file I/O errors */ assert(H5E_SEEKERROR_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MINOR, "Seek failed"))==NULL) @@ -238,6 +250,13 @@ if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to compute size"))==NULL) if((H5E_CANTGETSIZE_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") +/* Heap errors */ +assert(H5E_CANTRESTORE_g==(-1)); +if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't restore condition"))==NULL) + HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") +if((H5E_CANTRESTORE_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)); if((msg = H5E_create_msg(cls, H5E_MINOR, "Unable to initialize object"))==NULL) @@ -300,11 +319,6 @@ if((H5E_CANTDELETE_g = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") /* FPHDF5 errors */ -assert(H5E_CANTMAKETREE_g==(-1)); -if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't create a binary tree node"))==NULL) - HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") -if((H5E_CANTMAKETREE_g = H5I_register(H5I_ERROR_MSG, msg))<0) - HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") assert(H5E_CANTRECV_g==(-1)); if((msg = H5E_create_msg(cls, H5E_MINOR, "Can't receive messages from processes"))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "error message initialization failed") diff --git a/src/H5Epubgen.h b/src/H5Epubgen.h index e59e53b..f2a4a42 100644 --- a/src/H5Epubgen.h +++ b/src/H5Epubgen.h @@ -44,6 +44,7 @@ #define H5E_ATOM (H5OPEN H5E_ATOM_g) #define H5E_ATTR (H5OPEN H5E_ATTR_g) #define H5E_IO (H5OPEN H5E_IO_g) +#define H5E_SLIST (H5OPEN H5E_SLIST_g) #define H5E_EFL (H5OPEN H5E_EFL_g) #define H5E_TST (H5OPEN H5E_TST_g) #define H5E_ARGS (H5OPEN H5E_ARGS_g) @@ -71,6 +72,7 @@ H5_DLLVAR hid_t H5E_TBBT_g; /* Threaded, Balanced, Binary Trees */ H5_DLLVAR hid_t H5E_ATOM_g; /* Object atom */ H5_DLLVAR hid_t H5E_ATTR_g; /* Attribute */ H5_DLLVAR hid_t H5E_IO_g; /* Low-level I/O */ +H5_DLLVAR hid_t H5E_SLIST_g; /* Skip Lists */ H5_DLLVAR hid_t H5E_EFL_g; /* External file list */ H5_DLLVAR hid_t H5E_TST_g; /* Ternary Search Trees */ H5_DLLVAR hid_t H5E_ARGS_g; /* Invalid arguments to routine */ @@ -82,6 +84,10 @@ H5_DLLVAR hid_t H5E_CACHE_g; /* Object cache */ /* Minor error codes */ /*********************/ +/* Threaded, balanced binary tree errors */ +#define H5E_CANTMAKETREE (H5OPEN H5E_CANTMAKETREE_g) +H5_DLLVAR hid_t H5E_CANTMAKETREE_g; /* Can't create a binary tree node */ + /* Generic low-level file I/O errors */ #define H5E_SEEKERROR (H5OPEN H5E_SEEKERROR_g) #define H5E_READERROR (H5OPEN H5E_READERROR_g) @@ -114,6 +120,10 @@ H5_DLLVAR hid_t H5E_CANTUNLOCK_g; /* Unable to unlock object */ H5_DLLVAR hid_t H5E_CANTGC_g; /* Unable to garbage collect */ H5_DLLVAR hid_t H5E_CANTGETSIZE_g; /* Unable to compute size */ +/* Heap errors */ +#define H5E_CANTRESTORE (H5OPEN H5E_CANTRESTORE_g) +H5_DLLVAR hid_t H5E_CANTRESTORE_g; /* Can't restore condition */ + /* Function entry/exit interface errors */ #define H5E_CANTINIT (H5OPEN H5E_CANTINIT_g) #define H5E_ALREADYINIT (H5OPEN H5E_ALREADYINIT_g) @@ -143,12 +153,10 @@ H5_DLLVAR hid_t H5E_BADMESG_g; /* Unrecognized message */ H5_DLLVAR hid_t H5E_CANTDELETE_g; /* Can't delete message */ /* FPHDF5 errors */ -#define H5E_CANTMAKETREE (H5OPEN H5E_CANTMAKETREE_g) #define H5E_CANTRECV (H5OPEN H5E_CANTRECV_g) #define H5E_CANTSENDMDATA (H5OPEN H5E_CANTSENDMDATA_g) #define H5E_CANTCHANGE (H5OPEN H5E_CANTCHANGE_g) #define H5E_CANTALLOC (H5OPEN H5E_CANTALLOC_g) -H5_DLLVAR hid_t H5E_CANTMAKETREE_g; /* Can't create a binary tree node */ H5_DLLVAR hid_t H5E_CANTRECV_g; /* Can't receive messages from processes */ H5_DLLVAR hid_t H5E_CANTSENDMDATA_g;/* Can't send metadata message */ H5_DLLVAR hid_t H5E_CANTCHANGE_g; /* Can't register change with server */ diff --git a/src/H5Eterm.h b/src/H5Eterm.h index 4f5bda9..49db49d 100644 --- a/src/H5Eterm.h +++ b/src/H5Eterm.h @@ -42,6 +42,7 @@ H5E_TBBT_g= H5E_ATOM_g= H5E_ATTR_g= H5E_IO_g= +H5E_SLIST_g= H5E_EFL_g= H5E_TST_g= H5E_ARGS_g= @@ -52,6 +53,9 @@ H5E_CACHE_g= (-1); /* Reset minor error IDs */ +/* Threaded, balanced binary tree errors */ +H5E_CANTMAKETREE_g= + /* Generic low-level file I/O errors */ H5E_SEEKERROR_g= H5E_READERROR_g= @@ -70,6 +74,9 @@ H5E_CANTUNLOCK_g= H5E_CANTGC_g= H5E_CANTGETSIZE_g= +/* Heap errors */ +H5E_CANTRESTORE_g= + /* Function entry/exit interface errors */ H5E_CANTINIT_g= H5E_ALREADYINIT_g= @@ -88,7 +95,6 @@ H5E_BADMESG_g= H5E_CANTDELETE_g= /* FPHDF5 errors */ -H5E_CANTMAKETREE_g= H5E_CANTRECV_g= H5E_CANTSENDMDATA_g= H5E_CANTCHANGE_g= @@ -700,21 +700,21 @@ H5HP_change(H5HP_t *heap, int val, void *_obj) if(val<old_val) { if(heap->type==H5HP_MAX_HEAP) { if(H5HP_sink_max(heap,obj_loc)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCHANGE, FAIL, "unable to restore heap condition"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); } /* end if */ else { if(H5HP_swim_min(heap,obj_loc)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCHANGE, FAIL, "unable to restore heap condition"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); } /* end else */ } /* end if */ else { if(heap->type==H5HP_MAX_HEAP) { if(H5HP_swim_max(heap,obj_loc)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCHANGE, FAIL, "unable to restore heap condition"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); } /* end if */ else { if(H5HP_sink_min(heap,obj_loc)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCHANGE, FAIL, "unable to restore heap condition"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); } /* end else */ } /* end else */ @@ -783,11 +783,11 @@ H5HP_incr(H5HP_t *heap, unsigned amt, void *_obj) /* Restore heap condition */ if(heap->type==H5HP_MAX_HEAP) { if(H5HP_swim_max(heap,obj_loc)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCHANGE, FAIL, "unable to restore heap condition"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); } /* end if */ else { if(H5HP_sink_min(heap,obj_loc)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCHANGE, FAIL, "unable to restore heap condition"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); } /* end else */ done: @@ -855,11 +855,11 @@ H5HP_decr(H5HP_t *heap, unsigned amt, void *_obj) /* Restore heap condition */ if(heap->type==H5HP_MAX_HEAP) { if(H5HP_sink_max(heap,obj_loc)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCHANGE, FAIL, "unable to restore heap condition"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); } /* end if */ else { if(H5HP_swim_min(heap,obj_loc)<0) - HGOTO_ERROR(H5E_HEAP, H5E_CANTCHANGE, FAIL, "unable to restore heap condition"); + HGOTO_ERROR(H5E_HEAP, H5E_CANTRESTORE, FAIL, "unable to restore heap condition"); } /* end else */ done: diff --git a/src/H5SL.c b/src/H5SL.c new file mode 100644 index 0000000..4e2e646 --- /dev/null +++ b/src/H5SL.c @@ -0,0 +1,715 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Provides a skip list abstract data type. + * + * (See "Skip Lists: A Probabilistic Alternative to Balanced Trees" + * by William Pugh for additional information) + * + * (This implementation has the optimization for reducing key + * key comparisons mentioned in section 3.5 of "A Skip List + * Cookbook" by William Pugh) + * + * (Also, this implementation has a couple of home-grown + * optimizations, including setting the "update" vector to the + * actual 'forward' pointer to update, instead of the node + * containing the forward pointer -QAK) + * + */ + +/* Interface initialization */ +#define H5_INTERFACE_INIT_FUNC H5SL_init_interface + +/* Pablo information */ +/* (Put before include files to avoid problems with inline functions) */ +#define PABLO_MASK H5SL_mask + +/* Private headers needed */ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5FLprivate.h" /* Free Lists */ +#include "H5MMprivate.h" /* Memory management */ +#include "H5SLprivate.h" /* Skip list routines */ + +/* Local Macros */ + +/* Define the code template for insertions for the "OP" in the H5SL_FIND macro */ +#define H5SL_FIND_INSERT_FOUND(SLIST,X,UPDATE,I,ITEM) \ + X->item=ITEM; \ + HGOTO_DONE(SUCCEED); + +/* Define the code template for removals for the "OP" in the H5SL_FIND macro */ +#define H5SL_FIND_REMOVE_FOUND(SLIST,X,UPDATE,I,ITEM) \ + void *tmp; \ + \ + for(I=0; I<=(int)SLIST->curr_level; I++) { \ + if(*UPDATE[I]!=X) \ + break; \ + *UPDATE[I]=X->forward[I]; \ + } /* end for */ \ + tmp=X->item; \ + H5MM_xfree(X); \ + while(SLIST->curr_level>0 && SLIST->header->forward[SLIST->curr_level]==NULL) \ + SLIST->curr_level--; \ + SLIST->nobjs--; \ + HGOTO_DONE(tmp); + +/* Define the code template for searches for the "OP" in the H5SL_FIND macro */ +#define H5SL_FIND_SEARCH_FOUND(SLIST,X,UPDATE,I,ITEM) \ + HGOTO_DONE(X->item); + +/* Define a code template for updating the "update" vector for the "DOUPDATE" in the H5SL_FIND macro */ +#define H5SL_FIND_YES_UPDATE(X,UPDATE,I) \ + UPDATE[I]=&X->forward[I]; + +/* Define a code template for _NOT_ updating the "update" vector for the "DOUPDATE" in the H5SL_FIND macro */ +#define H5SL_FIND_NO_UPDATE(X,UPDATE,I) + +/* Macro used to find node for operation */ +#define H5SL_FIND(OP,DOUPDATE,SLIST,X,UPDATE,I,TYPE,ITEM,KEY,CHECKED) \ + CHECKED=NULL; \ + for(I=(int)SLIST->curr_level; I>=0; I--) { \ + if(X->forward[I]!=CHECKED) { \ + while(X->forward[I] && *(TYPE *)X->forward[I]->key<*(TYPE *)KEY) \ + X=X->forward[I]; \ + CHECKED=X->forward[I]; \ + } /* end if */ \ + H5_GLUE3(H5SL_FIND_,DOUPDATE,_UPDATE)(X,UPDATE,I) \ + } /* end for */ \ + X=X->forward[0]; \ + if(X!=NULL && *(TYPE *)X->key==*(TYPE *)key) { \ + /* What to do when a node is found */ \ + H5_GLUE3(H5SL_FIND_,OP,_FOUND)(SLIST,X,UPDATE,I,ITEM) \ + } /* end if */ + +/* Macro used to insert node */ +#define H5SL_INSERT(SLIST,X,UPDATE,I,TYPE,ITEM,KEY,CHECKED) \ + H5SL_FIND(INSERT,YES,SLIST,X,UPDATE,I,TYPE,ITEM,KEY,CHECKED) + +/* Macro used to remove node */ +#define H5SL_REMOVE(SLIST,X,UPDATE,I,TYPE,ITEM,KEY,CHECKED) \ + H5SL_FIND(REMOVE,YES,SLIST,X,UPDATE,I,TYPE,ITEM,KEY,CHECKED) + +/* Macro used to search for node */ +#define H5SL_SEARCH(SLIST,X,UPDATE,I,TYPE,ITEM,KEY,CHECKED) \ + H5SL_FIND(SEARCH,NO,SLIST,X,UPDATE,I,TYPE,ITEM,KEY,CHECKED) + + +/* Private typedefs & structs */ + +/* Skip list node data structure */ +struct H5SL_node_t { + void *key; /* Pointer to node's key */ + void *item; /* Pointer to node's item */ + size_t level; /* The level of this node */ + struct H5SL_node_t *forward[1]; /* Array of forward pointers from this node */ +}; + +/* Main skip list data structure */ +struct H5SL_t { + /* Static values for each list */ + H5SL_type_t type; /* Type of skip list */ + double p; /* Probability of using a higher level [0..1) */ + size_t max_level; /* Maximum number of levels */ + + /* Dynamic values for each list */ + int curr_level; /* Current top level used in list */ + size_t nobjs; /* Number of active objects in skip list */ + H5SL_node_t *header; /* Header for nodes in skip list */ +}; + +/* Static functions */ +static size_t H5SL_random_level(double p, size_t max_level); +static H5SL_node_t * H5SL_new_node(size_t lvl, void *item, void *key); + +/* Declare a free list to manage the H5SL_t struct */ +H5FL_DEFINE_STATIC(H5SL_t); + + +/*-------------------------------------------------------------------------- + NAME + H5SL_init_interface + PURPOSE + Initialize interface-specific information + USAGE + herr_t H5SL_init_interface() + + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Initializes any interface-specific data or routines. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5SL_init_interface(void) +{ + time_t curr_time; /* Current time, for seeding random number generator */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_init_interface) + + /* Create randomized set of numbers */ + curr_time=HDtime(NULL); + HDsrandom((unsigned long)curr_time); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5SL_init_interface() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_random_level + PURPOSE + Generate a random level + USAGE + size_t H5SL_random_level(p,max_level) + double p; IN: probability distribution + size_t max_level; IN: Maximum level for node height + + RETURNS + Returns non-negative level value + DESCRIPTION + Count elements in a skip list. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Do we really need a 'random' value, or is a series of nodes with the + correct heights "good enough". We could track the state of the nodes + allocated for this list and issue node heights appropriately (i.e. 1,2, + 1,4,1,2,1,8,...) (or would that be 1,1,2,1,1,2,4,... ?) + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static size_t +H5SL_random_level(double p, size_t max_level) +{ + size_t lvl; /* Level generated */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_random_level); + + lvl=0; + while((((double)HDrandom())/((double)LONG_MAX))<p && lvl < max_level) + lvl++; + + FUNC_LEAVE_NOAPI(lvl); +} /* end H5SL_random_level() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_new_node + PURPOSE + Create a new skip list node + USAGE + H5SL_node_t *H5SL_new_node(lvl,item,key) + size_t lvl; IN: Level for node height + void *item; IN: Pointer to item info for node + void *key; IN: Pointer to key info for node + + RETURNS + Returns a pointer to a skip list node on success, NULL on failure. + DESCRIPTION + Create a new skip list node of the specified height, setting the item + and key values internally. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + This routine does _not_ initialize the 'forward' pointers + + We should set up a custom free-list for allocating & freeing these sort + of nodes. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static H5SL_node_t * +H5SL_new_node(size_t lvl, void *item, void *key) +{ + H5SL_node_t *ret_value; /* New skip list node */ + + FUNC_ENTER_NOAPI_NOINIT(H5SL_new_node); + + /* Allocate the node */ + if((ret_value=H5MM_malloc(sizeof(H5SL_node_t)+(sizeof(H5SL_node_t *)*lvl)))==NULL) + HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed"); + + /* Initialize node */ + ret_value->key=key; + ret_value->item=item; + ret_value->level=lvl; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5SL_new_node() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_create + PURPOSE + Create a skip list + USAGE + H5SL_t *H5SL_create(void) + + RETURNS + Returns a pointer to a skip list on success, NULL on failure. + DESCRIPTION + Create a skip list. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5SL_t * +H5SL_create(H5SL_type_t type, double p, size_t max_level) +{ + H5SL_t *new_slist=NULL; /* Pointer to new skip list object created */ + H5SL_node_t *header; /* Pointer to skip list header node */ + size_t u; /* Local index variable */ + H5SL_t *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5SL_create,NULL); + + /* Check args */ + HDassert(p>0.0 && p<1.0); + HDassert(max_level>0 && max_level<=H5SL_LEVEL_MAX); + HDassert(type>=H5SL_TYPE_INT && type<=H5SL_TYPE_HADDR); + + /* Allocate skip list structure */ + if((new_slist=H5FL_MALLOC(H5SL_t))==NULL) + HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed"); + + /* Set the static internal fields */ + new_slist->type=type; + new_slist->p=p; + new_slist->max_level=max_level; + + /* Set the dynamic internal fields */ + new_slist->curr_level=-1; + new_slist->nobjs=0; + + /* Allocate the header node */ + if((header=H5SL_new_node(max_level-1,NULL,NULL))==NULL) + HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"memory allocation failed"); + + /* Initialize header node's forward pointers */ + for(u=0; u<max_level; u++) + header->forward[u]=NULL; + + /* Attach the header */ + new_slist->header=header; + + /* Set the return value */ + ret_value=new_slist; + +done: + /* Error cleanup */ + if(ret_value==NULL) { + if(new_slist!=NULL) { + H5FL_FREE(H5SL_t,new_slist); + } /* end if */ + } /* end if */ + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5SL_create() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_count + PURPOSE + Count the number of objects in a skip list + USAGE + ssize_t H5SL_count(slist) + H5SL_t *slist; IN: Pointer to skip list to count + + RETURNS + Returns non-negative on success, negative on failure. + DESCRIPTION + Count elements in a skip list. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +ssize_t +H5SL_count(H5SL_t *slist) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_count); + + /* Check args */ + assert(slist); + + /* Check internal consistency */ + /* (Pre-condition) */ + + FUNC_LEAVE_NOAPI(slist->nobjs); +} /* end H5SL_count() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_insert + PURPOSE + Insert an objects into a skip list + USAGE + herr_t H5SL_insert(slist,item,key) + H5SL_t *slist; IN/OUT: Pointer to skip list + void *item; IN: Item to insert + void *key; IN: Key for item to insert + + RETURNS + Returns non-negative on success, negative on failure. + DESCRIPTION + Insert element into a skip list. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Inserting an item with the same key as an existing object replaces + the existing object's item pointer with the new item pointer. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5SL_insert(H5SL_t *slist, void *item, void *key) +{ + H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */ + H5SL_node_t *checked; /* Pointer to last node checked */ + H5SL_node_t *x; /* Current node to examine */ + size_t lvl; /* Level of new node */ + int i; /* Local index value */ + herr_t ret_value=SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT(H5SL_insert); + + /* Check args */ + assert(slist); + assert(key); + + /* Check internal consistency */ + /* (Pre-condition) */ + + /* Insert item into skip list */ + + /* Work through the forward pointers for a node, finding the node at each + * level that is before the location to insert + */ + x=slist->header; + switch(slist->type) { + case H5SL_TYPE_INT: + H5SL_INSERT(slist,x,update,i,int,item,key,checked) + break; + + case H5SL_TYPE_HADDR: + H5SL_INSERT(slist,x,update,i,haddr_t,item,key,checked) + break; + } /* end switch */ + + /* 'key' must not have been found in existing list, if we get here */ + + /* Generate level for new node */ + lvl=H5SL_random_level(slist->p,slist->max_level); + if((int)lvl>slist->curr_level) { + /* Cap the increase in the current level to just one greater */ + lvl=slist->curr_level+1; + + /* Set the update pointer correctly */ + update[lvl]=&slist->header->forward[lvl]; + + /* Increase the maximum level of the list */ + slist->curr_level=lvl; + } /* end if */ + + /* Create new node of proper level */ + if((x=H5SL_new_node(lvl,item,key))==NULL) + HGOTO_ERROR(H5E_SLIST,H5E_NOSPACE,NULL,"can't create new skip list node"); + + /* Link the new node into the existing list */ + for(i=0; i<=(int)lvl; i++) { + x->forward[i]=*update[i]; + *update[i]=x; + } /* end for */ + + /* Increment the number of nodes in the skip list */ + slist->nobjs++; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5SL_insert() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_search + PURPOSE + Search for objects into a skip list + USAGE + void *H5SL_search(slist,key) + H5SL_t *slist; IN/OUT: Pointer to skip list + void *key; IN: Key for item to search for + + RETURNS + Returns pointer to item on success, NULL on failure + DESCRIPTION + Search for an object in a skip list, according to it's key + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +void * +H5SL_search(H5SL_t *slist, void *key) +{ + H5SL_node_t *checked; /* Pointer to last node checked */ + H5SL_node_t *x; /* Current node to examine */ + int i; /* Local index value */ + void *ret_value; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_search); + + /* Check args */ + assert(slist); + assert(key); + + /* Check internal consistency */ + /* (Pre-condition) */ + + /* Insert item into skip list */ + + /* Work through the forward pointers for a node, finding the node at each + * level that is before the location to insert + */ + x=slist->header; + switch(slist->type) { + case H5SL_TYPE_INT: + H5SL_SEARCH(slist,x,-,i,int,-,key,checked) + break; + + case H5SL_TYPE_HADDR: + H5SL_SEARCH(slist,x,-,i,haddr_t,-,key,checked) + break; + } /* end switch */ + + /* 'key' must not have been found in existing list, if we get here */ + ret_value=NULL; + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5SL_search() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_remove + PURPOSE + Removes an object from a skip list + USAGE + void *H5SL_remove(slist,key) + H5SL_t *slist; IN/OUT: Pointer to skip list + void *key; IN: Key for item to remove + + RETURNS + Returns pointer to item removed on success, NULL on failure. + DESCRIPTION + Remove element from a skip list. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +void * +H5SL_remove(H5SL_t *slist, void *key) +{ + H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */ + H5SL_node_t *checked; /* Pointer to last node checked */ + H5SL_node_t *x; /* Current node to examine */ + int i; /* Local index value */ + void *ret_value=NULL; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_remove); + + /* Check args */ + assert(slist); + assert(key); + + /* Check internal consistency */ + /* (Pre-condition) */ + + /* Remove item from skip list */ + + /* Work through the forward pointers for a node, finding the node at each + * level that is before the location to remove + */ + x=slist->header; + switch(slist->type) { + case H5SL_TYPE_INT: + H5SL_REMOVE(slist,x,update,i,int,-,key,checked) + break; + + case H5SL_TYPE_HADDR: + H5SL_REMOVE(slist,x,update,i,haddr_t,-,key,checked) + break; + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5SL_remove() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_first + PURPOSE + Gets a pointer to the first node in a skip list + USAGE + H5SL_node_t *H5SL_first(slist) + H5SL_t *slist; IN: Pointer to skip list + + RETURNS + Returns pointer to first node in skip list on success, NULL on failure. + DESCRIPTION + Retrieves a pointer to the first node in a skip list, for iterating over + the list. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5SL_node_t * +H5SL_first(H5SL_t *slist) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_first); + + /* Check args */ + assert(slist); + + /* Check internal consistency */ + /* (Pre-condition) */ + + FUNC_LEAVE_NOAPI(slist->header->forward[0]); +} /* end H5SL_first() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_next + PURPOSE + Gets a pointer to the next node in a skip list + USAGE + H5SL_node_t *H5SL_next(slist_node) + H5SL_node_t *slist_node; IN: Pointer to skip list node + + RETURNS + Returns pointer to node after slist_node in skip list on success, NULL on failure. + DESCRIPTION + Retrieves a pointer to the next node in a skip list, for iterating over + the list. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +H5SL_node_t * +H5SL_next(H5SL_node_t *slist_node) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_next); + + /* Check args */ + assert(slist_node); + + /* Check internal consistency */ + /* (Pre-condition) */ + + FUNC_LEAVE_NOAPI(slist_node->forward[0]); +} /* end H5SL_next() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_item + PURPOSE + Gets pointer to the 'item' for a skip list node + USAGE + void *H5SL_item(slist_node) + H5SL_node_t *slist_node; IN: Pointer to skip list node + + RETURNS + Returns pointer to node 'item' on success, NULL on failure. + DESCRIPTION + Retrieves a node's 'item' + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +void * +H5SL_item(H5SL_node_t *slist_node) +{ + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_item); + + /* Check args */ + assert(slist_node); + + /* Check internal consistency */ + /* (Pre-condition) */ + + FUNC_LEAVE_NOAPI(slist_node->item); +} /* end H5SL_item() */ + + +/*-------------------------------------------------------------------------- + NAME + H5SL_close + PURPOSE + Close a skip list, deallocating it. + USAGE + herr_t H5SL_close(slist) + H5SL_t *slist; IN/OUT: Pointer to skip list to close + + RETURNS + Returns non-negative on success, negative on failure. + DESCRIPTION + Close a skip list, freeing all internal information. Any objects left in + the skip list are not deallocated. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t +H5SL_close(H5SL_t *slist) +{ + H5SL_node_t *node, *next_node; /* Pointers to skip list nodes */ + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_close); + + /* Check args */ + assert(slist); + + /* Check internal consistency */ + /* (Pre-condition) */ + + /* Free skip list nodes */ + node=slist->header; + while(node!=NULL) { + next_node=node->forward[0]; + H5MM_xfree(node); + node=next_node; + } /* end while */ + + /* Free skip list object */ + H5FL_FREE(H5SL_t,slist); + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* end H5SL_close() */ + diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h new file mode 100644 index 0000000..94e2b4d --- /dev/null +++ b/src/H5SLprivate.h @@ -0,0 +1,66 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * This file contains private information about the H5SL module + */ +#ifndef _H5SLprivate_H +#define _H5SLprivate_H + +/**************************************/ +/* Public headers needed by this file */ +/**************************************/ +#ifdef LATER +#include "H5SLpublic.h" +#endif /* LATER */ + +/***************************************/ +/* Private headers needed by this file */ +/***************************************/ +#include "H5private.h" + +/************/ +/* Typedefs */ +/************/ + +/* Typedefs for skip list struct (defined in H5SL.c) */ +typedef struct H5SL_t H5SL_t; +typedef struct H5SL_node_t H5SL_node_t; + +/* Typedef for kinds of skip lists supported */ +typedef enum { + H5SL_TYPE_INT, /* Skip list keys are 'int's */ + H5SL_TYPE_HADDR /* Skip list keys are 'haddr_t's */ +} H5SL_type_t; + +/**********/ +/* Macros */ +/**********/ +#define H5SL_LEVEL_MAX 32 /* (for now) */ + +/********************/ +/* Private routines */ +/********************/ +H5_DLL H5SL_t *H5SL_create(H5SL_type_t type, double p, size_t max_level); +H5_DLL ssize_t H5SL_count(H5SL_t *slist); +H5_DLL herr_t H5SL_insert(H5SL_t *slist, void *item, void *key); +H5_DLL void *H5SL_remove(H5SL_t *slist, void *key); +H5_DLL void *H5SL_search(H5SL_t *slist, void *key); +H5_DLL H5SL_node_t *H5SL_first(H5SL_t *slist); +H5_DLL H5SL_node_t *H5SL_next(H5SL_node_t *slist_node); +H5_DLL void *H5SL_item(H5SL_node_t *slist_node); +H5_DLL herr_t H5SL_close(H5SL_t *slist); + +#endif /* _H5HPprivate_H */ + diff --git a/src/H5err.txt b/src/H5err.txt index 8b42b3c..82bd041 100644 --- a/src/H5err.txt +++ b/src/H5err.txt @@ -71,6 +71,7 @@ MAJOR, H5E_FPHDF5, Flexible Parallel HDF5 MAJOR, H5E_TST, Ternary Search Trees MAJOR, H5E_RS, Reference Counted Strings MAJOR, H5E_ERROR, Error API +MAJOR, H5E_SLIST, Skip Lists # Sections (for grouping minor errors) SECTION, ARGS, Argument errors @@ -87,6 +88,8 @@ SECTION, TYPECONV, Datatype conversion errors SECTION, DSPACE, Dataspace errors SECTION, PLIST, Property list errors SECTION, MPI, Parallel MPI errors +SECTION, HEAP, Heap errors +SECTION, TBBT, Threaded, balanced binary tree errors SECTION, FPH5, FPHDF5 errors SECTION, PIPELINE, I/O pipeline errors @@ -198,8 +201,13 @@ MINOR, PLIST, H5E_DUPCLASS, Duplicate class name in parent class MINOR, MPI, H5E_MPI, Some MPI function failed MINOR, MPI, H5E_MPIERRSTR, MPI Error String +# Heap errors +MINOR, HEAP, H5E_CANTRESTORE, Can't restore condition + +# TBBT errors +MINOR, TBBT, H5E_CANTMAKETREE, Can't create a binary tree node + # FPHDF5 errors -MINOR, FPH5, H5E_CANTMAKETREE, Can't create a binary tree node MINOR, FPH5, H5E_CANTRECV, Can't receive messages from processes MINOR, FPH5, H5E_CANTSENDMDATA, Can't send metadata message MINOR, FPH5, H5E_CANTCHANGE, Can't register change with server diff --git a/src/Makefile.in b/src/Makefile.in index c980764..685c916 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -42,7 +42,8 @@ LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5C.c H5D.c H5Dcontig.c H5Dcompact.c H5Defl.c \ H5Omtime.c H5Oname.c H5Onull.c H5Opline.c H5Osdspace.c H5Oshared.c \ H5Ostab.c H5P.c H5Pdcpl.c H5Pdxpl.c H5Pfapl.c H5Pfcpl.c H5Ptest.c \ H5R.c H5RC.c H5RS.c H5S.c H5Sall.c H5Shyper.c H5Smpio.c H5Snone.c \ - H5Spoint.c H5Sselect.c H5Stest.c H5ST.c H5T.c H5Tarray.c H5Tbit.c \ + H5Spoint.c H5Sselect.c H5Stest.c H5SL.c H5ST.c H5T.c H5Tarray.c \ + H5Tbit.c \ H5Tcommit.c H5Tcompound.c H5Tconv.c H5Tcset.c H5Tenum.c H5Tfields.c \ H5Tfixed.c H5Tfloat.c H5Tinit.c H5Tnative.c H5Toffset.c H5Topaque.c \ H5Torder.c H5Tpad.c H5Tprecis.c H5Tstrpad.c H5Tvlen.c H5TB.c H5TS.c \ @@ -71,7 +72,8 @@ PRIVATE_HDR=H5private.h H5Aprivate.h H5Apkg.h H5ACprivate.h H5Bprivate.h \ H5FSprivate.h H5Gprivate.h H5Gpkg.h H5HGprivate.h H5HGpkg.h \ H5HLprivate.h H5HLpkg.h H5HPprivate.h H5Iprivate.h H5MFprivate.h \ H5MMprivate.h H5Oprivate.h H5Opkg.h H5Pprivate.h H5Ppkg.h \ - H5Rprivate.h H5RCprivate.h H5RSprivate.h H5Sprivate.h H5STprivate.h \ + H5Rprivate.h H5RCprivate.h H5RSprivate.h H5Sprivate.h H5SLprivate.h \ + H5STprivate.h \ H5Tprivate.h H5TBprivate.h H5Tpkg.h H5TSprivate.h H5Vprivate.h \ H5Zprivate.h H5Zpkg.h H5config.h diff --git a/test/Makefile.in b/test/Makefile.in index 56ea6fb..bf3a3d4 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -83,9 +83,9 @@ TEST_SRC=big.c bittests.c cache.c cmpd_dset.c dsets.c dtypes.c extend.c \ external.c fillval.c flush1.c flush2.c gheap.c h5test.c hyperslab.c \ istore.c lheap.c links.c mount.c mtime.c ohdr.c stab.c tarray.c \ tattr.c tconfig.c testhdf5.c testmeta.c tfile.c \ - tgenprop.c th5s.c theap.c titerate.c tmeta.c trefer.c trefstr.c \ - tselect.c ttime.c ttbbt.c ttst.c tvltypes.c tvlstr.c tmisc.c tid.c \ - unlink.c enum.c ttsafe.c ttsafe_dcreate.c ttsafe_error.c \ + tgenprop.c th5s.c theap.c tid.c titerate.c tmeta.c tmisc.c trefer.c \ + trefstr.c tselect.c tskiplist.c ttime.c ttbbt.c ttst.c tvltypes.c \ + tvlstr.c unlink.c enum.c ttsafe.c ttsafe_dcreate.c ttsafe_error.c \ ttsafe_cancel.c ttsafe_acreate.c gass_write.c gass_read.c \ gass_append.c srb_read.c srb_write.c srb_append.c stream_test.c \ set_extent.c getname.c file_handle.c ntypes.c dangle.c error_test.c \ @@ -115,10 +115,9 @@ check test _test: $(PROGS) ## How to build the tests... They all depend on the test and hdf5 libraries. $(PROGS): $(LIB) $(LIBHDF5) -TESTHDF5_OBJ=testhdf5.lo tarray.lo tattr.lo tconfig.lo tfile.lo \ - tgenprop.lo th5s.lo theap.lo titerate.lo tmeta.lo ttime.lo trefer.lo \ - trefstr.lo tselect.lo ttbbt.lo ttst.lo tvltypes.lo tvlstr.lo tmisc.lo \ - tid.lo +TESTHDF5_OBJ=testhdf5.lo tarray.lo tattr.lo tconfig.lo tfile.lo tgenprop.lo \ + th5s.lo theap.lo tid.lo titerate.lo tmeta.lo tmisc.lo trefer.lo trefstr.lo \ + tselect.lo tskiplist.lo ttbbt.lo ttime.lo ttst.lo tvltypes.lo tvlstr.lo TTS_OBJ=ttsafe.lo ttsafe_dcreate.lo ttsafe_error.lo \ ttsafe_cancel.lo ttsafe_acreate.lo diff --git a/test/testhdf5.c b/test/testhdf5.c index 6234d01..9d86032 100644 --- a/test/testhdf5.c +++ b/test/testhdf5.c @@ -48,6 +48,7 @@ main(int argc, char *argv[]) AddTest("tbbt", test_tbbt, NULL, "Threaded, Balanced, Binary Trees", NULL); AddTest("tst", test_tst, NULL, "Ternary Search Trees", NULL); AddTest("heap", test_heap, NULL, "Memory Heaps", NULL); + AddTest("skiplist", test_skiplist, NULL, "Skip Lists", NULL); AddTest("refstr", test_refstr, NULL, "Reference Counted Strings", NULL); AddTest("file", test_file, cleanup_file, "Low-Level File I/O", NULL); AddTest("h5s", test_h5s, cleanup_h5s, "Dataspaces", NULL); diff --git a/test/testhdf5.h b/test/testhdf5.h index e00f56d..61674a8 100644 --- a/test/testhdf5.h +++ b/test/testhdf5.h @@ -130,6 +130,7 @@ void test_genprop(void); void test_configure(void); void test_misc(void); void test_ids(void); +void test_skiplist(void); /* Prototypes for the cleanup routines */ void cleanup_metadata(void); diff --git a/test/tskiplist.c b/test/tskiplist.c new file mode 100644 index 0000000..20bde76 --- /dev/null +++ b/test/tskiplist.c @@ -0,0 +1,497 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by the Board of Trustees of the University of Illinois. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the files COPYING and Copyright.html. COPYING can be found at the root * + * of the source code distribution tree; Copyright.html can be found at the * + * root level of an installed copy of the electronic HDF5 document set and * + * is linked from the top-level documents page. It can also be found at * + * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * + * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + Test HDF Skip List routines. + + REMARKS + + DESIGN + + BUGS/LIMITATIONS + + EXPORTED ROUTINES + + AUTHOR + Quincey Koziol + + MODIFICATION HISTORY + 11/15/04 - Started coding + */ + +#include <time.h> +#include <stdlib.h> + +#include "testhdf5.h" +#include "H5SLprivate.h" + +/* The number of elements in testing arrays */ +#define NUM_ELEMS 1000 + +/* Random numbers */ +static int rand_num[NUM_ELEMS]; +static int sort_rand_num[NUM_ELEMS]; +static int rev_sort_rand_num[NUM_ELEMS]; + +static int tst_sort(const void *i1, const void *i2) +{ + return(*(const int *)i1-*(const int *)i2); +} + +static int tst_rev_sort(const void *i1, const void *i2) +{ + return(*(const int *)i2-*(const int *)i1); +} + +/**************************************************************** +** +** test_skiplist_init(): Test H5SL (skiplist) code. +** Initialize data for skip list testing +** +****************************************************************/ +static void +test_skiplist_init(void) +{ + time_t curr_time; /* Current time, for seeding random number generator */ + int new_val; /* New value to insert */ + unsigned found; /* Flag to indicate value was inserted already */ + size_t u,v; /* Local index variables */ + + /* Initialize random number seed */ + curr_time=time(NULL); + HDsrandom((unsigned long)curr_time); + + /* Create randomized set of numbers */ + for(u=0; u<NUM_ELEMS; u++) { + do { + /* Reset flag */ + found=0; + + /* Generate random numbers from -5000 to 5000 */ + new_val=(int)(HDrandom()%10001)-5001; + + /* Check if the value is already in the array */ + for(v=0; v<u; v++) + if(rand_num[v]==new_val) + found=1; + } while(found); + + /* Set unique value in array */ + rand_num[u]=new_val; + } /* end for */ + + /* Copy random values to sorted array */ + HDmemcpy(sort_rand_num,rand_num,sizeof(int)*NUM_ELEMS); + + /* Sort random numbers */ + HDqsort(sort_rand_num,NUM_ELEMS,sizeof(int),tst_sort); + + /* Copy random values to reverse sorted array */ + HDmemcpy(rev_sort_rand_num,rand_num,sizeof(int)*NUM_ELEMS); + + /* Sort random numbers */ + HDqsort(rev_sort_rand_num,NUM_ELEMS,sizeof(int),tst_rev_sort); +} /* end test_tst_init() */ + +/**************************************************************** +** +** test_skiplist_create(): Test basic H5SL (skiplist) code. +** Tests creating and closing skip lists. +** +****************************************************************/ +static void +test_skiplist_create(void) +{ + H5SL_t *slist; /* Skip list created */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(6, ("Testing Creating & Closing Skip Lists\n")); + + /* Try creating a skip list */ + slist=H5SL_create(H5SL_TYPE_INT, 0.5,16); + CHECK(slist, NULL, "H5SL_create"); + + /* Try closing the skip list */ + ret=H5SL_close(slist); + CHECK(ret, FAIL, "H5SL_close"); + +} /* end test_skiplist_create() */ + +/**************************************************************** +** +** test_skiplist_insert(): Test H5SL (skip list) code. +** Tests inserting single object into skip list. +** +****************************************************************/ +static void +test_skiplist_insert(void) +{ + H5SL_t *slist; /* Skip list created */ + int key, /* Key of item to insert */ + item; /* Item to insert */ + int search_key; /* Key of item to search for in skip list */ + int *found_item; /* Item found in skip list */ + ssize_t num; /* Number of elements in skip list */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(7, ("Testing Insertion Into Skip List\n")); + + /* Create a Heap */ + slist=H5SL_create(H5SL_TYPE_INT, 0.5, 16); + CHECK(slist, NULL, "H5SL_create"); + + /* Check that the skip list has no elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + + /* Try searching for item in empty skip list */ + key=37; + found_item=H5SL_search(slist,&key); + VERIFY(found_item, NULL, "H5SL_search"); + + /* Insert an object into the skip list */ + key=2; item=10; + ret=H5SL_insert(slist,&item,&key); + CHECK(ret, FAIL, "H5SL_insert"); + + /* Check that the skip list has one element */ + num=H5SL_count(slist); + VERIFY(num, 1, "H5SL_count"); + + /* Search for the item just inserted */ + found_item=H5SL_search(slist,&key); + CHECK(found_item, NULL, "H5SL_search"); + VERIFY(*found_item,item,"H5SL_search"); + + /* Search for an item not in list */ + search_key=37; + found_item=H5SL_search(slist,&search_key); + VERIFY(found_item, NULL, "H5SL_search"); + + /* Close the skip list */ + ret=H5SL_close(slist); + CHECK(ret, FAIL, "H5SL_close"); + +} /* end test_skiplist_insert() */ + +/**************************************************************** +** +** test_skiplist_insert_many(): Test H5SL (skip list) code. +** Tests inserting many objects into skip list. +** +****************************************************************/ +static void +test_skiplist_insert_many(void) +{ + H5SL_t *slist; /* Skip list created */ + ssize_t num; /* Number of elements in skip list */ + size_t u; /* Local index variable */ + int *found_item; /* Item found in skip list */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(7, ("Testing Insertion of Many Items Into Skip List\n")); + + /* Create a Heap */ + slist=H5SL_create(H5SL_TYPE_INT, 0.5, 16); + CHECK(slist, NULL, "H5SL_create"); + + /* Check that the skip list has no elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + + /* Insert many objects into the skip list */ + for(u=0; u<NUM_ELEMS; u++) { + ret=H5SL_insert(slist,&rand_num[u],&rand_num[u]); + CHECK(ret, FAIL, "H5SL_insert"); + } /* end for */ + + /* Check that the skip list has correct # of elements */ + num=H5SL_count(slist); + VERIFY(num, NUM_ELEMS, "H5SL_count"); + + /* Search for all objects in the skip list */ + for(u=0; u<NUM_ELEMS; u++) { + found_item=H5SL_search(slist,&rand_num[u]); + CHECK(found_item, NULL, "H5SL_search"); + VERIFY(*found_item,rand_num[u],"H5SL_search"); + } /* end for */ + + /* Close the skip list */ + ret=H5SL_close(slist); + CHECK(ret, FAIL, "H5SL_close"); + +} /* end test_skiplist_insert_many() */ + +/**************************************************************** +** +** test_skiplist_remove(): Test H5SL (skip list) code. +** Tests basic object removal from skip list. +** +****************************************************************/ +static void +test_skiplist_remove(void) +{ + H5SL_t *slist; /* Skip list created */ + int key1, /* Key of 1st item to insert */ + key2, /* Key of 2nd item to insert */ + key3; /* Key of 3rd item to insert */ + int search_key; /* Key of item to search for in skip list */ + int *found_item; /* Item found in skip list */ + ssize_t num; /* Number of elements in skip list */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(7, ("Testing Removal From Skip List\n")); + + /* Create a Heap */ + slist=H5SL_create(H5SL_TYPE_INT, 0.5, 16); + CHECK(slist, NULL, "H5SL_create"); + + /* Check that the skip list has no elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + + /* Try removing an item in empty skip list */ + search_key=37; + found_item=H5SL_remove(slist,&search_key); + VERIFY(found_item, NULL, "H5SL_remove"); + + /* Insert three objects into the skip list */ + key1=15; + ret=H5SL_insert(slist,&key1,&key1); + CHECK(ret, FAIL, "H5SL_insert"); + + key2=10; + ret=H5SL_insert(slist,&key2,&key2); + CHECK(ret, FAIL, "H5SL_insert"); + + key3=20; + ret=H5SL_insert(slist,&key3,&key3); + CHECK(ret, FAIL, "H5SL_insert"); + + /* Check that the skip list has three elements */ + num=H5SL_count(slist); + VERIFY(num, 3, "H5SL_count"); + + /* Try removing items from skip list */ + search_key=key1; + found_item=H5SL_remove(slist,&search_key); + CHECK(found_item, NULL, "H5SL_remove"); + VERIFY(found_item, &key1, "H5SL_remove"); + + search_key=key2; + found_item=H5SL_remove(slist,&search_key); + CHECK(found_item, NULL, "H5SL_remove"); + VERIFY(found_item, &key2, "H5SL_remove"); + + search_key=key3; + found_item=H5SL_remove(slist,&search_key); + CHECK(found_item, NULL, "H5SL_remove"); + VERIFY(found_item, &key3, "H5SL_remove"); + + /* Check that the skip list has no elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + + /* Try removing items from empty skip list (after its been worked on) */ + search_key=key1; + found_item=H5SL_remove(slist,&search_key); + VERIFY(found_item, NULL, "H5SL_remove"); + + /* Close the skip list */ + ret=H5SL_close(slist); + CHECK(ret, FAIL, "H5SL_close"); + +} /* end test_skiplist_remove() */ + +/**************************************************************** +** +** test_skiplist_remove_many(): Test H5SL (skip list) code. +** Tests removing many objects from skip list. +** +****************************************************************/ +static void +test_skiplist_remove_many(void) +{ + H5SL_t *slist; /* Skip list created */ + ssize_t num; /* Number of elements in skip list */ + size_t u; /* Local index variable */ + int *found_item; /* Item found in skip list */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(7, ("Testing Removal of Many Items From Skip List\n")); + + /* Create a Heap */ + slist=H5SL_create(H5SL_TYPE_INT, 0.5, 16); + CHECK(slist, NULL, "H5SL_create"); + + /* Check that the skip list has no elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + + /* Insert many objects into the skip list */ + for(u=0; u<NUM_ELEMS; u++) { + ret=H5SL_insert(slist,&rand_num[u],&rand_num[u]); + CHECK(ret, FAIL, "H5SL_insert"); + } /* end for */ + + /* Check that the skip list has correct # of elements */ + num=H5SL_count(slist); + VERIFY(num, NUM_ELEMS, "H5SL_count"); + + /* Remove all objects from the skip list (in random order) */ + for(u=0; u<NUM_ELEMS; u++) { + found_item=H5SL_remove(slist,&rand_num[u]); + CHECK(found_item, NULL, "H5SL_remove"); + VERIFY(*found_item,rand_num[u],"H5SL_remove"); + } /* end for */ + + /* Check that the skip list has correct # of elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + +/* Insert & remove again (in sorted order), to check that completely empty heaps can be added again */ + + /* Insert many objects into the skip list */ + for(u=0; u<NUM_ELEMS; u++) { + ret=H5SL_insert(slist,&rand_num[u],&rand_num[u]); + CHECK(ret, FAIL, "H5SL_insert"); + } /* end for */ + + /* Check that the skip list has correct # of elements */ + num=H5SL_count(slist); + VERIFY(num, NUM_ELEMS, "H5SL_count"); + + /* Remove all objects from the skip list */ + for(u=0; u<NUM_ELEMS; u++) { + found_item=H5SL_remove(slist,&sort_rand_num[u]); + CHECK(found_item, NULL, "H5SL_remove"); + VERIFY(*found_item,sort_rand_num[u],"H5SL_remove"); + } /* end for */ + + /* Check that the skip list has correct # of elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + +/* Insert & remove again (in reverse sorted order), to check that completely empty heaps can be added again */ + + /* Insert many objects into the skip list */ + for(u=0; u<NUM_ELEMS; u++) { + ret=H5SL_insert(slist,&rand_num[u],&rand_num[u]); + CHECK(ret, FAIL, "H5SL_insert"); + } /* end for */ + + /* Check that the skip list has correct # of elements */ + num=H5SL_count(slist); + VERIFY(num, NUM_ELEMS, "H5SL_count"); + + /* Remove all objects from the skip list */ + for(u=0; u<NUM_ELEMS; u++) { + found_item=H5SL_remove(slist,&rev_sort_rand_num[u]); + CHECK(found_item, NULL, "H5SL_remove"); + VERIFY(*found_item,rev_sort_rand_num[u],"H5SL_remove"); + } /* end for */ + + /* Check that the skip list has correct # of elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + + /* Close the skip list */ + ret=H5SL_close(slist); + CHECK(ret, FAIL, "H5SL_close"); + +} /* end test_skiplist_remove_many() */ + +/**************************************************************** +** +** test_skiplist_iterate(): Test H5SL (skip list) code. +** Tests iterating over nodes in skip list. +** +****************************************************************/ +static void +test_skiplist_iterate(void) +{ + H5SL_t *slist; /* Skip list created */ + H5SL_node_t *node; /* Skip list node */ + ssize_t num; /* Number of elements in skip list */ + size_t u; /* Local index variable */ + int *found_item; /* Item found in skip list */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(7, ("Testing Iterating Over Skip List\n")); + + /* Create a Heap */ + slist=H5SL_create(H5SL_TYPE_INT, 0.5, 16); + CHECK(slist, NULL, "H5SL_create"); + + /* Check that the skip list has no elements */ + num=H5SL_count(slist); + VERIFY(num, 0, "H5SL_count"); + + /* Insert many objects into the skip list */ + for(u=0; u<NUM_ELEMS; u++) { + ret=H5SL_insert(slist,&rand_num[u],&rand_num[u]); + CHECK(ret, FAIL, "H5SL_insert"); + } /* end for */ + + /* Check that the skip list has correct # of elements */ + num=H5SL_count(slist); + VERIFY(num, NUM_ELEMS, "H5SL_count"); + + /* Iterate over all the nodes in the skip list */ + node=H5SL_first(slist); + u=0; + while(node!=NULL) { + found_item=H5SL_item(node); + VERIFY(*found_item,sort_rand_num[u],"H5SL_next"); + u++; + node=H5SL_next(node); + } /* end while */ + + /* Close the skip list */ + ret=H5SL_close(slist); + CHECK(ret, FAIL, "H5SL_close"); + +} /* end test_skiplist_iterate() */ + +/**************************************************************** +** +** test_skiplist(): Main H5SL testing routine. +** +****************************************************************/ +void +test_skiplist(void) +{ + /* Output message about test being performed */ + MESSAGE(5, ("Testing Skip Lists\n")); + + /* Initialize skip list testing data */ + test_skiplist_init(); + + /* Actual skip list tests */ + test_skiplist_create(); /* Test skip list creation */ + test_skiplist_insert(); /* Test basic skip list insertion */ + test_skiplist_insert_many(); /* Test insertion of many items into skip list */ + test_skiplist_remove(); /* Test basic skip list removal */ + test_skiplist_remove_many(); /* Test removal of many items from skip list */ + test_skiplist_iterate(); /* Test iteration over skip list nodes */ + +} /* end test_skiplist() */ + + |