summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2004-11-27 16:07:11 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2004-11-27 16:07:11 (GMT)
commitb52107a42a19c26894d18f88cab801749c32c34f (patch)
treeedde8937cc8aa2b2e12ca11a7592f71eca9ed000
parenta27b3f81f007b5f60cccd0f861c2d17911b3389a (diff)
downloadhdf5-b52107a42a19c26894d18f88cab801749c32c34f.zip
hdf5-b52107a42a19c26894d18f88cab801749c32c34f.tar.gz
hdf5-b52107a42a19c26894d18f88cab801749c32c34f.tar.bz2
[svn-r9580] Purpose:
Add new internal data structure Description: Add an implementation of skip lists to the library (see comment in src/H5SL.c for references to the papers describing them) as a potential replacement for our current threaded, balanced binary tree container. Skip lists are much simpler to implement and should be faster to use. Also, added new error codes to release branch, so bump the minor version number to indicate that the library is no longer perfectly compatible with the 1.6.3 release. Platforms tested: FreeBSD 4.10 (sleipnir) w/parallel Solaris 2.7 (arabica) Too minor to require further testing (the skip lists aren't actually used by any library code yet)
-rw-r--r--MANIFEST3
-rw-r--r--src/H5Edefin.h8
-rw-r--r--src/H5Einit.h24
-rw-r--r--src/H5Epubgen.h12
-rw-r--r--src/H5Eterm.h8
-rw-r--r--src/H5HP.c16
-rw-r--r--src/H5SL.c715
-rw-r--r--src/H5SLprivate.h66
-rw-r--r--src/H5err.txt10
-rw-r--r--src/Makefile.in6
-rw-r--r--test/Makefile.in13
-rw-r--r--test/testhdf5.c1
-rw-r--r--test/testhdf5.h1
-rw-r--r--test/tskiplist.c497
14 files changed, 1353 insertions, 27 deletions
diff --git a/MANIFEST b/MANIFEST
index 3f07edc..dc5dee0 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -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=
diff --git a/src/H5HP.c b/src/H5HP.c
index b377593..5b35924 100644
--- a/src/H5HP.c
+++ b/src/H5HP.c
@@ -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() */
+
+