summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/H5.c14
-rw-r--r--src/H5AC.c4
-rw-r--r--src/H5B.c2
-rw-r--r--src/H5B2cache.c3
-rw-r--r--src/H5B2test.c2
-rw-r--r--src/H5Bprivate.h2
-rw-r--r--src/H5C.c3
-rw-r--r--src/H5Dchunk.c5
-rw-r--r--src/H5Dscatgath.c11
-rw-r--r--src/H5F.c16
-rw-r--r--src/H5FL.c591
-rw-r--r--src/H5FLprivate.h24
-rw-r--r--src/H5FO.c4
-rw-r--r--src/H5FSsection.c11
-rw-r--r--src/H5Fpkg.h6
-rw-r--r--src/H5Fsuper.c20
-rw-r--r--src/H5Ftest.c40
-rw-r--r--src/H5G.c167
-rw-r--r--src/H5Gobj.c109
-rw-r--r--src/H5Gpkg.h7
-rw-r--r--src/H5Gprivate.h8
-rw-r--r--src/H5Groot.c368
-rw-r--r--src/H5Gstab.c3
-rw-r--r--src/H5Gtest.c56
-rw-r--r--src/H5I.c40
-rw-r--r--src/H5L.c18
-rw-r--r--src/H5O.c2
-rw-r--r--src/H5Ocopy.c2
-rw-r--r--src/H5Opline.c4
-rw-r--r--src/H5Pdapl.c2
-rw-r--r--src/H5Pdcpl.c2
-rw-r--r--src/H5Pint.c20
-rw-r--r--src/H5SL.c859
-rw-r--r--src/H5SLprivate.h4
-rw-r--r--src/H5Tconv.c54
-rw-r--r--src/H5Z.c74
-rw-r--r--src/H5Zdeflate.c2
-rw-r--r--src/H5Zfletcher32.c2
-rw-r--r--src/H5Znbit.c2
-rw-r--r--src/H5Zpkg.h14
-rw-r--r--src/H5Zprivate.h5
-rw-r--r--src/H5Zpublic.h26
-rw-r--r--src/H5Zscaleoffset.c2
-rw-r--r--src/H5Zshuffle.c2
-rw-r--r--src/H5Zszip.c2
-rw-r--r--src/H5config.h.in3
-rw-r--r--src/H5detect.c64
-rw-r--r--src/H5private.h1
-rw-r--r--src/H5public.h4
-rw-r--r--src/H5trace.c2
-rw-r--r--src/H5vers.txt1
-rw-r--r--src/H5version.h16
-rwxr-xr-xsrc/Makefile.am2
-rw-r--r--src/Makefile.in19
54 files changed, 1828 insertions, 898 deletions
diff --git a/src/H5.c b/src/H5.c
index bbd14ce..b49db8d 100644
--- a/src/H5.c
+++ b/src/H5.c
@@ -28,6 +28,7 @@
#include "H5Lprivate.h" /* Links */
#include "H5Pprivate.h" /* Property lists */
#include "H5Tprivate.h" /* Datatypes */
+#include "H5SLprivate.h" /* Skip lists */
/****************/
@@ -270,6 +271,9 @@ H5_term_library(void)
/* Don't shut down the ID code until other APIs which use them are shut down */
if(pending == 0)
pending += DOWN(I);
+ /* Don't shut down the skip list code until everything that uses it is down */
+ if(pending == 0)
+ pending += DOWN(SL);
/* Don't shut down the free list code until _everything_ else is down */
if(pending == 0)
pending += DOWN(FL);
@@ -405,6 +409,9 @@ done:
* global lists, up to 3 MB of total storage might be allocated (1MB on
* each of regular, array and block type lists).
*
+ * The settings for block free lists are duplicated to factory free lists.
+ * Factory free list limits cannot be set independently currently.
+ *
* Parameters:
* int reg_global_lim; IN: The limit on all "regular" free list memory used
* int reg_list_lim; IN: The limit on memory used in each "regular" free list
@@ -420,7 +427,9 @@ done:
* Programmer: Quincey Koziol
* Wednesday, August 2, 2000
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Wednesday, April 8, 2009
+ * Added support for factory free lists
*
*-------------------------------------------------------------------------
*/
@@ -435,7 +444,8 @@ H5set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_lim,
arr_list_lim, blk_global_lim, blk_list_lim);
/* Call the free list function to actually set the limits */
- if(H5FL_set_free_list_limits(reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim, blk_global_lim, blk_list_lim)<0)
+ if(H5FL_set_free_list_limits(reg_global_lim, reg_list_lim, arr_global_lim, arr_list_lim,
+ blk_global_lim, blk_list_lim, blk_global_lim, blk_list_lim)<0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTSET, FAIL, "can't set garbage collection limits")
done:
diff --git a/src/H5AC.c b/src/H5AC.c
index a496952..145daa5 100644
--- a/src/H5AC.c
+++ b/src/H5AC.c
@@ -589,7 +589,7 @@ H5AC_create(const H5F_t *f,
if ( mpi_rank == 0 ) {
aux_ptr->d_slist_ptr =
- H5SL_create(H5SL_TYPE_HADDR,0.5,(size_t)16);
+ H5SL_create(H5SL_TYPE_HADDR);
if ( aux_ptr->d_slist_ptr == NULL ) {
@@ -598,7 +598,7 @@ H5AC_create(const H5F_t *f,
}
aux_ptr->c_slist_ptr =
- H5SL_create(H5SL_TYPE_HADDR,0.5,(size_t)16);
+ H5SL_create(H5SL_TYPE_HADDR);
if ( aux_ptr->c_slist_ptr == NULL ) {
diff --git a/src/H5B.c b/src/H5B.c
index c504507..aba62b0 100644
--- a/src/H5B.c
+++ b/src/H5B.c
@@ -2057,7 +2057,6 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B_get_info() */
-#ifndef H5_STRICT_FORMAT_CHECKS
/*-------------------------------------------------------------------------
* Function: H5B_valid
@@ -2099,5 +2098,4 @@ H5B_valid(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type, haddr_t addr)
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5B_valid() */
-#endif /* H5_STRICT_FORMAT_CHECKS */
diff --git a/src/H5B2cache.c b/src/H5B2cache.c
index c44820a..5ca7ed8 100644
--- a/src/H5B2cache.c
+++ b/src/H5B2cache.c
@@ -275,7 +275,8 @@ done:
*-------------------------------------------------------------------------
*/
static herr_t
-H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr, H5B2_t *bt2, unsigned UNUSED * flags_ptr)
+H5B2_cache_hdr_flush(H5F_t *f, hid_t dxpl_id, hbool_t destroy, haddr_t addr,
+ H5B2_t *bt2, unsigned UNUSED * flags_ptr)
{
H5WB_t *wb = NULL; /* Wrapped buffer for header data */
uint8_t hdr_buf[H5B2_HDR_BUF_SIZE]; /* Buffer for header */
diff --git a/src/H5B2test.c b/src/H5B2test.c
index f2cf79d..46cd510 100644
--- a/src/H5B2test.c
+++ b/src/H5B2test.c
@@ -456,7 +456,7 @@ H5B2_get_node_depth_test(H5F_t *f, hid_t dxpl_id, const H5B2_class_t *type, hadd
HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "error looking up node info")
/* Set return value */
- ret_value = ninfo.depth;
+ ret_value = (int)ninfo.depth;
done:
FUNC_LEAVE_NOAPI(ret_value)
diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h
index 2ec2c22..716b608 100644
--- a/src/H5Bprivate.h
+++ b/src/H5Bprivate.h
@@ -168,9 +168,7 @@ H5_DLL H5B_shared_t *H5B_shared_new(const H5F_t *f, const H5B_class_t *type,
H5_DLL herr_t H5B_shared_free(void *_shared);
H5_DLL herr_t H5B_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE * stream,
int indent, int fwidth, const H5B_class_t *type, void *udata);
-#ifndef H5_STRICT_FORMAT_CHECKS
H5_DLL htri_t H5B_valid(H5F_t *f, hid_t dxpl_id, const H5B_class_t *type,
haddr_t addr);
-#endif /* H5_STRICT_FORMAT_CHECKS */
#endif /* _H5Bprivate_H */
diff --git a/src/H5C.c b/src/H5C.c
index 1d6e421..16b6d22 100644
--- a/src/H5C.c
+++ b/src/H5C.c
@@ -3046,8 +3046,7 @@ H5C_create(size_t max_cache_size,
"memory allocation failed")
}
- if ( (cache_ptr->slist_ptr = H5SL_create(H5SL_TYPE_HADDR,0.5,(size_t)16))
- == NULL ) {
+ if ( (cache_ptr->slist_ptr = H5SL_create(H5SL_TYPE_HADDR)) == NULL ) {
HGOTO_ERROR(H5E_CACHE, H5E_CANTCREATE, NULL, "can't create skip list.")
}
diff --git a/src/H5Dchunk.c b/src/H5Dchunk.c
index a88df43..ae90627 100644
--- a/src/H5Dchunk.c
+++ b/src/H5Dchunk.c
@@ -63,9 +63,6 @@
/* Local Macros */
/****************/
-/* Default skip list height for storing list of chunks */
-#define H5D_CHUNK_DEFAULT_SKIPLIST_HEIGHT 8
-
/* Macros for iterating over chunks to operate on */
#define H5D_CHUNK_GET_FIRST_NODE(map) (map->use_single ? (H5SL_node_t *)(1) : H5SL_first(map->sel_chunks))
#define H5D_CHUNK_GET_NODE_INFO(map, node) (map->use_single ? map->single_chunk_info : (H5D_chunk_info_t *)H5SL_item(node))
@@ -534,7 +531,7 @@ H5D_chunk_io_init(const H5D_io_info_t *io_info, const H5D_type_info_t *type_info
else {
/* Initialize skip list for chunk selections */
if(NULL == dataset->shared->cache.chunk.sel_chunks) {
- if(NULL == (dataset->shared->cache.chunk.sel_chunks = H5SL_create(H5SL_TYPE_HSIZE, 0.5, (size_t)H5D_CHUNK_DEFAULT_SKIPLIST_HEIGHT)))
+ if(NULL == (dataset->shared->cache.chunk.sel_chunks = H5SL_create(H5SL_TYPE_HSIZE)))
HGOTO_ERROR(H5E_DATASET, H5E_CANTCREATE, FAIL, "can't create skip list for chunk selections")
} /* end if */
fm->sel_chunks = dataset->shared->cache.chunk.sel_chunks;
diff --git a/src/H5Dscatgath.c b/src/H5Dscatgath.c
index bb9f46b..ed73f3c 100644
--- a/src/H5Dscatgath.c
+++ b/src/H5Dscatgath.c
@@ -662,6 +662,12 @@ H5D_scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file gather failed")
} /* end if */
+ /* Do the data transform before the type conversion (since
+ * transforms must be done in the memory type). */
+ if(!type_info->is_xform_noop)
+ if(H5Z_xform_eval(dxpl_cache->data_xform_prop, type_info->tconv_buf, smine_nelmts, type_info->mem_type) < 0)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
+
/*
* Perform datatype conversion.
*/
@@ -669,11 +675,6 @@ H5D_scatgath_write(const H5D_io_info_t *io_info, const H5D_type_info_t *type_inf
smine_nelmts, (size_t)0, (size_t)0, type_info->tconv_buf,
type_info->bkg_buf, io_info->dxpl_id) < 0)
HGOTO_ERROR(H5E_DATASET, H5E_CANTCONVERT, FAIL, "datatype conversion failed")
-
- /* Do the data transform after the type conversion (since we're using dataset->shared->type). */
- if(!type_info->is_xform_noop)
- if(H5Z_xform_eval(dxpl_cache->data_xform_prop, type_info->tconv_buf, smine_nelmts, type_info->dset_type) < 0)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Error performing data transform")
} /* end else */
/*
diff --git a/src/H5F.c b/src/H5F.c
index 921fe27..fc85688 100644
--- a/src/H5F.c
+++ b/src/H5F.c
@@ -893,6 +893,7 @@ H5F_new(H5F_file_t *shared, hid_t fcpl_id, hid_t fapl_id, H5FD_t *lf)
f->shared->driver_addr = HADDR_UNDEF;
f->shared->accum.loc = HADDR_UNDEF;
f->shared->lf = lf;
+ f->shared->root_addr = HADDR_UNDEF;
/*
* Copy the file creation and file access property lists into the
@@ -1369,7 +1370,7 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
/* (This must be after the space for the superblock is allocated in
* the file, since the superblock must be at offset 0)
*/
- if(H5G_mkroot(file, dxpl_id, NULL) < 0)
+ if(H5G_mkroot(file, dxpl_id, TRUE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to create/open root group")
/* Write the superblock to the file */
@@ -1379,21 +1380,12 @@ H5F_open(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id, hid_t d
if(H5F_super_write(file, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, "unable to write file superblock")
} else if (1 == shared->nrefs) {
- H5G_loc_t root_loc; /*root location */
- H5O_loc_t root_oloc; /*root object location */
- H5G_name_t root_path; /*root group hier. path */
-
- /* Set up root location to fill in */
- root_loc.oloc = &root_oloc;
- root_loc.path = &root_path;
- H5G_loc_reset(&root_loc);
-
/* Read the superblock if it hasn't been read before. */
- if(H5F_super_read(file, dxpl_id, &root_loc) < 0)
+ if(H5F_super_read(file, dxpl_id) < 0)
HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "unable to read superblock")
/* Open the root group */
- if(H5G_mkroot(file, dxpl_id, &root_loc) < 0)
+ if(H5G_mkroot(file, dxpl_id, FALSE) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to read root group")
} /* end if */
diff --git a/src/H5FL.c b/src/H5FL.c
index 1045658..dca300c 100644
--- a/src/H5FL.c
+++ b/src/H5FL.c
@@ -52,6 +52,8 @@ static size_t H5FL_arr_glb_mem_lim=4*1024*1024; /* Default to 4MB limit on all a
static size_t H5FL_arr_lst_mem_lim=4*65536; /* Default to 256KB limit on each array free list */
static size_t H5FL_blk_glb_mem_lim=16*1024*1024; /* Default to 16MB limit on all block free lists */
static size_t H5FL_blk_lst_mem_lim=1024*1024; /* Default to 1024KB (1MB) limit on each block free list */
+static size_t H5FL_fac_glb_mem_lim=16*1024*1024; /* Default to 16MB limit on all factory free lists */
+static size_t H5FL_fac_lst_mem_lim=1024*1024; /* Default to 1024KB (1MB) limit on each factory free list */
/* A garbage collection node for regular free lists */
typedef struct H5FL_reg_gc_node_t {
@@ -98,6 +100,36 @@ typedef struct H5FL_blk_gc_list_t {
/* The head of the list of PQs to garbage collect */
static H5FL_blk_gc_list_t H5FL_blk_gc_head={0,NULL};
+/* A garbage collection node for factory free lists */
+typedef struct H5FL_fac_gc_node_t {
+ H5FL_fac_head_t *list; /* Pointer to the head of the list to garbage collect */
+ struct H5FL_fac_gc_node_t *next; /* Pointer to the next node in the list of things to garbage collect */
+} H5FL_fac_gc_node_t;
+
+/* The garbage collection head for factory free lists */
+typedef struct H5FL_fac_gc_list_t {
+ size_t mem_freed; /* Amount of free memory on list */
+ struct H5FL_fac_gc_node_t *first; /* Pointer to the first node in the list of things to garbage collect */
+} H5FL_fac_gc_list_t;
+
+/* Data structure to store each block in factory free list */
+typedef struct H5FL_fac_node_t {
+ struct H5FL_fac_node_t *next; /* Pointer to next block in free list */
+} H5FL_fac_node_t;
+
+/* Data structure for free list block factory */
+struct H5FL_fac_head_t {
+ unsigned init; /* Whether the free list has been initialized */
+ unsigned allocated; /* Number of blocks allocated */
+ unsigned onlist; /* Number of blocks on free list */
+ size_t size; /* Size of the blocks in the list */
+ H5FL_fac_node_t *list; /* List of free blocks */
+ H5FL_fac_gc_node_t *prev_gc; /* Previous garbage collection node in list */
+};
+
+/* The head of the list of factory things to garbage collect */
+static H5FL_fac_gc_list_t H5FL_fac_gc_head={0,NULL};
+
#ifdef H5FL_TRACK
/* Extra headers needed */
@@ -114,14 +146,18 @@ static herr_t H5FL_arr_gc(void);
static herr_t H5FL_arr_gc_list(H5FL_arr_head_t *head);
static herr_t H5FL_blk_gc(void);
static herr_t H5FL_blk_gc_list(H5FL_blk_head_t *head);
-static herr_t H5FL_blk_unlink(H5FL_blk_head_t *pq);
-
-/* Declare a free list to manage the H5FL_fac_head_t struct */
-H5FL_DEFINE(H5FL_fac_head_t);
+static herr_t H5FL_fac_gc(void);
+static herr_t H5FL_fac_gc_list(H5FL_fac_head_t *head);
/* Declare a free list to manage the H5FL_blk_node_t struct */
H5FL_DEFINE(H5FL_blk_node_t);
+/* Declare a free list to manage the H5FL_fac_gc_node_t struct */
+H5FL_DEFINE(H5FL_fac_gc_node_t);
+
+/* Declare a free list to manage the H5FL_fac_head_t struct */
+H5FL_DEFINE(H5FL_fac_head_t);
+
/*--------------------------------------------------------------------------
NAME
@@ -225,15 +261,15 @@ H5FL_reg_init(H5FL_reg_head_t *head)
/* Indicate that the free list is initialized */
head->init=1;
+ /* Make certain that the space allocated is large enough to store a free list pointer (eventually) */
+ if(head->size<sizeof(H5FL_reg_node_t))
+ head->size=sizeof(H5FL_reg_node_t);
+
/* Make certain there's room for tracking information, if any */
#ifdef H5FL_TRACK
head->size += sizeof(H5FL_track_t);
#endif /* H5FL_TRACK */
- /* Make certain that the space allocated is large enough to store a free list pointer (eventually) */
- if(head->size<sizeof(void *))
- head->size=sizeof(void *);
-
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FL_reg_init() */
@@ -259,11 +295,13 @@ H5FL_reg_free(H5FL_reg_head_t *head, void *obj)
{
void *ret_value=NULL; /* Return value */
- FUNC_ENTER_NOAPI(H5FL_reg_free, NULL)
+ /* NOINIT OK here because this must be called after H5FL_reg_malloc/calloc
+ * -NAF */
+ FUNC_ENTER_NOAPI_NOINIT(H5FL_reg_free)
/* Double check parameters */
- assert(head);
- assert(obj);
+ HDassert(head);
+ HDassert(obj);
#ifdef H5FL_TRACK
{
@@ -294,7 +332,7 @@ H5FL_reg_free(H5FL_reg_head_t *head, void *obj)
#endif /* H5FL_DEBUG */
/* Make certain that the free list is initialized */
- assert(head->init);
+ HDassert(head->init);
/* Link into the free list */
((H5FL_reg_node_t *)obj)->next=head->list;
@@ -302,16 +340,15 @@ H5FL_reg_free(H5FL_reg_head_t *head, void *obj)
/* Point free list at the node freed */
head->list=(H5FL_reg_node_t *)obj;
- /* Increment the number of blocks & memory on free list */
+ /* Increment the number of blocks on free list */
head->onlist++;
- head->list_mem+=head->size;
/* Increment the amount of "regular" freed memory globally */
H5FL_reg_gc_head.mem_freed+=head->size;
/* Check for exceeding free list memory use limits */
/* First check this particular list */
- if(head->list_mem>H5FL_reg_lst_mem_lim)
+ if(head->onlist * head->size > H5FL_reg_lst_mem_lim)
if(H5FL_reg_gc_list(head)<0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, NULL, "garbage collection failed during free")
@@ -348,7 +385,7 @@ H5FL_reg_malloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS)
FUNC_ENTER_NOAPI(H5FL_reg_malloc, NULL)
/* Double check parameters */
- assert(head);
+ HDassert(head);
/* Make certain the list is initialized first */
if(!head->init)
@@ -365,7 +402,6 @@ H5FL_reg_malloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS)
/* Decrement the number of blocks & memory on free list */
head->onlist--;
- head->list_mem-=head->size;
/* Decrement the amount of global "regular" free list memory in use */
H5FL_reg_gc_head.mem_freed-=(head->size);
@@ -426,7 +462,7 @@ H5FL_reg_calloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS)
FUNC_ENTER_NOAPI(H5FL_reg_calloc, NULL)
/* Double check parameters */
- assert(head);
+ HDassert(head);
/* Allocate the block */
if (NULL==(ret_value = H5FL_reg_malloc(head H5FL_TRACK_INFO_INT)))
@@ -476,17 +512,11 @@ H5FL_reg_gc_list(H5FL_reg_head_t *head)
/* Decrement the count of nodes allocated and free the node */
head->allocated--;
- /* Decrement count of free memory on this list */
- head->list_mem-=head->size;
-
- H5MM_xfree(free_list);
+ H5MM_free(free_list);
free_list = (H5FL_reg_node_t *)tmp;
} /* end while */
- /* Double check that all the memory on this list is recycled */
- HDassert(0 == head->list_mem);
-
/* Indicate no free nodes on the free list */
head->list=NULL;
head->onlist=0;
@@ -535,7 +565,7 @@ H5FL_reg_gc(void)
} /* end while */
/* Double check that all the memory on the free lists is recycled */
- assert(H5FL_reg_gc_head.mem_freed==0);
+ HDassert(H5FL_reg_gc_head.mem_freed==0);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -797,7 +827,7 @@ H5FL_blk_free_block_avail(H5FL_blk_head_t *head, size_t size)
FUNC_ENTER_NOAPI(H5FL_blk_free_block_avail, FAIL)
/* Double check parameters */
- assert(head);
+ HDassert(head);
/* check if there is a free list for blocks of this size */
/* and if there are any blocks available on the list */
@@ -838,8 +868,8 @@ H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS)
FUNC_ENTER_NOAPI(H5FL_blk_malloc, NULL)
/* Double check parameters */
- assert(head);
- assert(size);
+ HDassert(head);
+ HDassert(size);
/* Make certain the list is initialized first */
if(!head->init)
@@ -928,8 +958,8 @@ H5FL_blk_calloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS)
FUNC_ENTER_NOAPI(H5FL_blk_calloc, NULL)
/* Double check parameters */
- assert(head);
- assert(size);
+ HDassert(head);
+ HDassert(size);
/* Allocate the block */
if (NULL==(ret_value = H5FL_blk_malloc(head,size H5FL_TRACK_INFO_INT)))
@@ -969,11 +999,13 @@ H5FL_blk_free(H5FL_blk_head_t *head, void *block)
size_t free_size; /* Size of the block freed */
void *ret_value=NULL; /* Return value */
- FUNC_ENTER_NOAPI(H5FL_blk_free, NULL)
+ /* NOINIT OK here because this must be called after H5FL_blk_malloc/calloc
+ * -NAF */
+ FUNC_ENTER_NOAPI_NOINIT(H5FL_blk_free)
/* Double check parameters */
- assert(head);
- assert(block);
+ HDassert(head);
+ HDassert(block);
#ifdef H5FL_TRACK
{
@@ -1070,8 +1102,8 @@ H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size H5FL_TRACK_
FUNC_ENTER_NOAPI(H5FL_blk_realloc, NULL)
/* Double check parameters */
- assert(head);
- assert(new_size);
+ HDassert(head);
+ HDassert(new_size);
/* Check if we are actually re-allocating a block */
if(block!=NULL) {
@@ -1119,67 +1151,6 @@ done:
} /* end H5FL_blk_realloc() */
-/*--------------------------------------------------------------------------
- NAME
- H5FL_blk_unlink
- PURPOSE
- Remove a block free list from the global list of initialized block free
- lists.
- USAGE
- void H5FL_blk_unlink(H5FL_blk_head_t *pq)
- H5FL_blk_head_t *pq; IN: Block free list to remove from global list
- RETURNS
- Success: Non-negative
- Failure: Negative
- DESCRIPTION
- Search through the global list of initialized block free lists and remove
- a particular free list.
- GLOBAL VARIABLES
- COMMENTS, BUGS, ASSUMPTIONS
- EXAMPLES
- REVISION LOG
---------------------------------------------------------------------------*/
-static herr_t
-H5FL_blk_unlink(H5FL_blk_head_t *pq)
-{
- H5FL_blk_gc_node_t *last; /* Pointer to the last garbage collection node examined */
- H5FL_blk_gc_node_t *tmp; /* Temporary pointer to a garbage collection node */
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI_NOINIT(H5FL_blk_unlink)
-
- /* Find the node to remove from the global list */
- last=NULL;
- tmp=H5FL_blk_gc_head.first;
- while(tmp!=NULL) {
- /* Check if the list has allocations outstanding */
- if(tmp->pq==pq) {
- /* Unlink node from linked list */
- if(last==NULL)
- H5FL_blk_gc_head.first=H5FL_blk_gc_head.first->next;
- else
- last->next=tmp->next;
-
- /* Free the block node */
- H5MM_xfree(tmp);
-
- /* Leave now */
- break;
- } /* end if */
-
- /* Advance to next node in list */
- last=tmp;
- tmp=tmp->next;
- } /* end while */
-
- if(tmp==NULL)
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL, "can't release block free list")
-
-done:
- FUNC_LEAVE_NOAPI(ret_value);
-} /* end H5FL_blk_unlink() */
-
-
/*-------------------------------------------------------------------------
* Function: H5FL_blk_gc_list
*
@@ -1221,7 +1192,7 @@ H5FL_blk_gc_list(H5FL_blk_head_t *head)
H5FL_blk_gc_head.mem_freed-=head->head->size;
/* Free the block */
- H5MM_xfree(list);
+ H5MM_free(list);
list = (H5FL_blk_list_t *)next;
} /* end while */
@@ -1279,7 +1250,7 @@ H5FL_blk_gc(void)
} /* end while */
/* Double check that all the memory on the free lists are recycled */
- assert(H5FL_blk_gc_head.mem_freed==0);
+ HDassert(H5FL_blk_gc_head.mem_freed==0);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1334,7 +1305,7 @@ printf("H5FL_blk_term: head->name=%s, head->allocated=%d\n", H5FL_blk_gc_head.fi
H5FL_blk_gc_head.first->pq->init=0;
/* Free the node from the garbage collection list */
- H5MM_xfree(H5FL_blk_gc_head.first);
+ H5MM_free(H5FL_blk_gc_head.first);
} /* end else */
H5FL_blk_gc_head.first=tmp;
@@ -1422,17 +1393,19 @@ H5FL_arr_free(H5FL_arr_head_t *head, void *obj)
size_t free_nelem; /* Number of elements in node being free'd */
void *ret_value=NULL; /* Return value */
- FUNC_ENTER_NOAPI(H5FL_arr_free, NULL)
+ /* NOINIT OK here because this must be called after H5FL_arr_malloc/calloc
+ * -NAF */
+ FUNC_ENTER_NOAPI_NOINIT(H5FL_arr_free)
/* The H5MM_xfree code allows obj to null */
if (!obj)
HGOTO_DONE (NULL)
/* Double check parameters */
- assert(head);
+ HDassert(head);
/* Make certain that the free list is initialized */
- assert(head->init);
+ HDassert(head->init);
/* Get the pointer to the info header in front of the block to free */
temp=(H5FL_arr_list_t *)((unsigned char *)obj-sizeof(H5FL_arr_list_t)); /*lint !e826 Pointer-to-pointer cast is appropriate here */
@@ -1441,7 +1414,7 @@ H5FL_arr_free(H5FL_arr_head_t *head, void *obj)
free_nelem=temp->nelem;
/* Double-check that there is enough room for arrays of this size */
- assert((int)free_nelem<=head->maxelem);
+ HDassert((int)free_nelem<=head->maxelem);
/* Link into the free list */
temp->next=head->list_arr[free_nelem].list;
@@ -1500,8 +1473,8 @@ H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem)
FUNC_ENTER_NOAPI(H5FL_arr_malloc, NULL)
/* Double check parameters */
- assert(head);
- assert(elem);
+ HDassert(head);
+ HDassert(elem);
/* Make certain the list is initialized first */
if(!head->init)
@@ -1509,7 +1482,7 @@ H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem)
HGOTO_ERROR (H5E_RESOURCE, H5E_CANTINIT, NULL, "can't initialize 'array' blocks")
/* Sanity check that the number of elements is supported */
- assert(elem<=(unsigned) head->maxelem);
+ HDassert(elem<=(unsigned) head->maxelem);
/* Get the set of the memory block */
mem_size=head->list_arr[elem].size;
@@ -1573,8 +1546,8 @@ H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem)
FUNC_ENTER_NOAPI(H5FL_arr_calloc, NULL)
/* Double check parameters */
- assert(head);
- assert(elem);
+ HDassert(head);
+ HDassert(elem);
/* Allocate the array */
if (NULL==(ret_value = H5FL_arr_malloc(head,elem)))
@@ -1611,8 +1584,8 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void * obj, size_t new_elem)
FUNC_ENTER_NOAPI(H5FL_arr_realloc, NULL)
/* Double check parameters */
- assert(head);
- assert(new_elem);
+ HDassert(head);
+ HDassert(new_elem);
/* Check if we are really allocating the object */
if(obj==NULL)
@@ -1621,7 +1594,7 @@ H5FL_arr_realloc(H5FL_arr_head_t *head, void * obj, size_t new_elem)
H5FL_arr_list_t *temp; /* Temp. ptr to the new free list node allocated */
/* Sanity check that the number of elements is supported */
- assert((int)new_elem<=head->maxelem);
+ HDassert((int)new_elem<=head->maxelem);
/* Get the pointer to the info header in front of the block to free */
temp=(H5FL_arr_list_t *)((unsigned char *)obj-sizeof(H5FL_arr_list_t)); /*lint !e826 Pointer-to-pointer cast is appropriate here */
@@ -1687,7 +1660,7 @@ H5FL_arr_gc_list(H5FL_arr_head_t *head)
/* Decrement the count of nodes allocated and free the node */
head->allocated--;
- H5MM_xfree(arr_free_list);
+ H5MM_free(arr_free_list);
arr_free_list = (H5FL_arr_list_t *)tmp;
} /* end while */
@@ -1705,7 +1678,7 @@ H5FL_arr_gc_list(H5FL_arr_head_t *head)
} /* end for */
/* Double check that all the memory on this list is recycled */
- assert(head->list_mem==0);
+ HDassert(head->list_mem==0);
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5FL_arr_gc_list() */
@@ -1746,7 +1719,7 @@ H5FL_arr_gc(void)
} /* end while */
/* Double check that all the memory on the free lists are recycled */
- assert(H5FL_arr_gc_head.mem_freed==0);
+ HDassert(H5FL_arr_gc_head.mem_freed==0);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1803,7 +1776,7 @@ printf("H5FL_arr_term: head->name=%s, head->allocated=%d\n", H5FL_arr_gc_head.fi
H5FL_arr_gc_head.first->list->init=0;
/* Free the node from the garbage collection list */
- H5MM_xfree(H5FL_arr_gc_head.first);
+ H5MM_free(H5FL_arr_gc_head.first);
} /* end else */
H5FL_arr_gc_head.first=tmp;
@@ -1834,14 +1807,16 @@ printf("H5FL_arr_term: head->name=%s, head->allocated=%d\n", H5FL_arr_gc_head.fi
void *
H5FL_seq_free(H5FL_seq_head_t *head, void *obj)
{
+ /* NOINIT OK here because this must be called after H5FL_seq_malloc/calloc
+ * -NAF */
FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FL_seq_free)
/* Double check parameters */
- assert(head);
- assert(obj);
+ HDassert(head);
+ HDassert(obj);
/* Make certain that the free list is initialized */
- assert(head->queue.init);
+ HDassert(head->queue.init);
/* Use block routine */
H5FL_blk_free(&(head->queue),obj);
@@ -1873,8 +1848,8 @@ H5FL_seq_malloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS)
FUNC_ENTER_NOAPI(H5FL_seq_malloc, NULL)
/* Double check parameters */
- assert(head);
- assert(elem);
+ HDassert(head);
+ HDassert(elem);
/* Use block routine */
ret_value=H5FL_blk_malloc(&(head->queue),head->size*elem H5FL_TRACK_INFO_INT);
@@ -1907,8 +1882,8 @@ H5FL_seq_calloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS)
FUNC_ENTER_NOAPI(H5FL_seq_calloc, NULL)
/* Double check parameters */
- assert(head);
- assert(elem);
+ HDassert(head);
+ HDassert(elem);
/* Use block routine */
ret_value=H5FL_blk_calloc(&(head->queue),head->size*elem H5FL_TRACK_INFO_INT);
@@ -1941,8 +1916,8 @@ H5FL_seq_realloc(H5FL_seq_head_t *head, void * obj, size_t new_elem H5FL_TRACK_P
FUNC_ENTER_NOAPI(H5FL_seq_realloc, NULL)
/* Double check parameters */
- assert(head);
- assert(new_elem);
+ HDassert(head);
+ HDassert(new_elem);
/* Use block routine */
ret_value=H5FL_blk_realloc(&(head->queue),obj,head->size*new_elem H5FL_TRACK_INFO_INT);
@@ -1964,14 +1939,18 @@ done:
* Wednesday, February 2, 2005
*
* Modifications:
+ * Neil Fortner
+ * Friday, December 19, 2008
+ * Totally rewritten to support new factory implementation
*
*-------------------------------------------------------------------------
*/
H5FL_fac_head_t *
H5FL_fac_init(size_t size)
{
- H5FL_fac_head_t *factory; /* Pointer to new block factory */
- H5FL_fac_head_t *ret_value; /* Return value */
+ H5FL_fac_gc_node_t *new_node; /* Pointer to the node for the new list to garbage collect */
+ H5FL_fac_head_t *factory; /* Pointer to new block factory */
+ H5FL_fac_head_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI(H5FL_fac_init, NULL)
@@ -1979,15 +1958,38 @@ H5FL_fac_init(size_t size)
HDassert(size>0);
/* Allocate room for the new factory */
- if(NULL==(factory=H5FL_MALLOC(H5FL_fac_head_t)))
+ if(NULL == (factory = (H5FL_fac_head_t *)H5FL_CALLOC(H5FL_fac_head_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for factory object")
- /* Initialize block header information */
- HDmemset(&(factory->queue),0,sizeof(H5FL_blk_head_t));
-
/* Set size of blocks for factory */
factory->size=size;
+ /* Allocate a new garbage collection node */
+ if(NULL == (new_node = (H5FL_fac_gc_node_t *)H5FL_MALLOC(H5FL_fac_gc_node_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Initialize the new garbage collection node */
+ new_node->list = factory;
+
+ /* Link in to the garbage collection list */
+ new_node->next=H5FL_fac_gc_head.first;
+ H5FL_fac_gc_head.first=new_node;
+ if(new_node->next)
+ new_node->next->list->prev_gc=new_node;
+ /* The new factory's prev_gc field will be set to NULL */
+
+ /* Make certain that the space allocated is large enough to store a free list pointer (eventually) */
+ if(factory->size<sizeof(H5FL_fac_node_t))
+ factory->size=sizeof(H5FL_fac_node_t);
+
+ /* Make certain there's room for tracking information, if any */
+#ifdef H5FL_TRACK
+ factory->size += sizeof(H5FL_track_t);
+#endif /* H5FL_TRACK */
+
+ /* Indicate that the free list is initialized */
+ factory->init=1;
+
/* Set return value */
ret_value=factory;
@@ -2001,32 +2003,86 @@ done:
*
* Purpose: Release a block back to a factory & put on free list
*
- * Return: Success: Non-negative
- * Failure: Negative
+ * Return: NULL
*
* Programmer: Quincey Koziol
* Wednesday, February 2, 2005
*
* Modifications:
+ * Neil Fortner
+ * Friday, December 19, 2008
+ * Totally rewritten to support new factory implementation
*
*-------------------------------------------------------------------------
*/
void *
H5FL_fac_free(H5FL_fac_head_t *head, void *obj)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FL_fac_free)
+ void *ret_value=NULL; /* Return value */
+
+ /* NOINIT OK here because this must be called after H5FL_fac_init -NAF */
+ FUNC_ENTER_NOAPI_NOINIT(H5FL_fac_free)
/* Double check parameters */
- assert(head);
- assert(obj);
+ HDassert(head);
+ HDassert(obj);
+
+#ifdef H5FL_TRACK
+ {
+ H5FL_track_t *trk = obj = ((unsigned char *)obj) - sizeof(H5FL_track_t);
+
+ /* Free tracking information about the allocation location */
+ H5CS_close_stack(trk->stack);
+ trk->stack = H5MM_xfree(trk->stack);
+ trk->file = H5MM_xfree(trk->file);
+ trk->func = H5MM_xfree(trk->func);
+
+ /* Remove from "outstanding allocations" list */
+ if(trk == H5FL_out_head_g) {
+ H5FL_out_head_g = H5FL_out_head_g->next;
+ if(H5FL_out_head_g)
+ H5FL_out_head_g->prev = NULL;
+ } /* end if */
+ else {
+ trk->prev->next = trk->next;
+ if(trk->next)
+ trk->next->prev = trk->prev;
+ } /* end else */
+ }
+#endif /* H5FL_TRACK */
+
+#ifdef H5FL_DEBUG
+ HDmemset(obj,255,head->size);
+#endif /* H5FL_DEBUG */
/* Make certain that the free list is initialized */
- assert(head->queue.init);
+ HDassert(head->init);
- /* Use block routine */
- H5FL_blk_free(&(head->queue),obj);
+ /* Link into the free list */
+ ((H5FL_fac_node_t *)obj)->next=head->list;
- FUNC_LEAVE_NOAPI(NULL)
+ /* Point free list at the node freed */
+ head->list=(H5FL_fac_node_t *)obj;
+
+ /* Increment the number of blocks on free list */
+ head->onlist++;
+
+ /* Increment the amount of "factory" freed memory globally */
+ H5FL_fac_gc_head.mem_freed+=head->size;
+
+ /* Check for exceeding free list memory use limits */
+ /* First check this particular list */
+ if(head->onlist * head->size > H5FL_fac_lst_mem_lim)
+ if(H5FL_fac_gc_list(head)<0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, NULL, "garbage collection failed during free")
+
+ /* Then check the global amount memory on factory free lists */
+ if(H5FL_fac_gc_head.mem_freed > H5FL_fac_glb_mem_lim)
+ if(H5FL_fac_gc()<0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, NULL, "garbage collection failed during free")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FL_fac_free() */
@@ -2042,6 +2098,9 @@ H5FL_fac_free(H5FL_fac_head_t *head, void *obj)
* Wednesday, February 2, 2005
*
* Modifications:
+ * Neil Fortner
+ * Friday, December 19, 2008
+ * Totally rewritten to support new factory implementation
*
*-------------------------------------------------------------------------
*/
@@ -2050,13 +2109,54 @@ H5FL_fac_malloc(H5FL_fac_head_t *head H5FL_TRACK_PARAMS)
{
void *ret_value; /* Pointer to object to return */
- FUNC_ENTER_NOAPI(H5FL_fac_malloc, NULL)
+ /* NOINIT OK here because this must be called after H5FL_fac_init -NAF */
+ FUNC_ENTER_NOAPI_NOINIT(H5FL_fac_malloc)
/* Double check parameters */
- assert(head);
+ HDassert(head);
+ HDassert(head->init);
- /* Use block routine */
- ret_value=H5FL_blk_malloc(&(head->queue),head->size H5FL_TRACK_INFO_INT);
+ /* Check for nodes available on the free list first */
+ if(head->list!=NULL) {
+ /* Get a pointer to the block on the free list */
+ ret_value=(void *)(head->list);
+
+ /* Remove node from free list */
+ head->list=head->list->next;
+
+ /* Decrement the number of blocks & memory on free list */
+ head->onlist--;
+
+ /* Decrement the amount of global "factory" free list memory in use */
+ H5FL_fac_gc_head.mem_freed-=(head->size);
+ } /* end if */
+ /* Otherwise allocate a node */
+ else {
+ if (NULL==(ret_value = H5FL_malloc(head->size)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Increment the number of blocks allocated in list */
+ head->allocated++;
+ } /* end else */
+
+#ifdef H5FL_TRACK
+ /* Copy allocation location information */
+ ((H5FL_track_t *)ret_value)->stack = H5MM_calloc(sizeof(H5CS_t));
+ H5CS_copy_stack(((H5FL_track_t *)ret_value)->stack);
+ ((H5FL_track_t *)ret_value)->file = H5MM_strdup(call_file);
+ ((H5FL_track_t *)ret_value)->func = H5MM_strdup(call_func);
+ ((H5FL_track_t *)ret_value)->line = call_line;
+
+ /* Add to "outstanding allocations" list */
+ ((H5FL_track_t *)ret_value)->prev = NULL;
+ ((H5FL_track_t *)ret_value)->next = H5FL_out_head_g;
+ if(H5FL_out_head_g)
+ H5FL_out_head_g->prev = (H5FL_track_t *)ret_value;
+ H5FL_out_head_g = (H5FL_track_t *)ret_value;
+
+ /* Adjust for allocation tracking information */
+ ret_value = ((unsigned char *)ret_value) + sizeof(H5FL_track_t);
+#endif /* H5FL_TRACK */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2075,6 +2175,9 @@ done:
* Wednesday, February 2, 2005
*
* Modifications:
+ * Neil Fortner
+ * Friday, December 19, 2008
+ * Totally rewritten to support new factory implementation
*
*-------------------------------------------------------------------------
*/
@@ -2083,17 +2186,115 @@ H5FL_fac_calloc(H5FL_fac_head_t *head H5FL_TRACK_PARAMS)
{
void *ret_value; /* Pointer to object to return */
- FUNC_ENTER_NOAPI(H5FL_fac_calloc, NULL)
+ /* NOINIT OK here because this must be called after H5FL_fac_init -NAF */
+ FUNC_ENTER_NOAPI_NOINIT(H5FL_fac_calloc)
/* Double check parameters */
- assert(head);
+ HDassert(head);
- /* Use block routine */
- ret_value=H5FL_blk_calloc(&(head->queue),head->size H5FL_TRACK_INFO_INT);
+ /* Allocate the block */
+ if (NULL==(ret_value = H5FL_fac_malloc(head H5FL_TRACK_INFO_INT)))
+ HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ /* Clear to zeros */
+ /* (Accomodate tracking information, if present) */
+ HDmemset(ret_value,0,head->size - H5FL_TRACK_SIZE);
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FL_fac_calloc() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5FL_fac_gc_list
+ *
+ * Purpose: Garbage collect on a particular factory free list
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Neil Fortner
+ * Friday, December 19, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FL_fac_gc_list(H5FL_fac_head_t *head)
+{
+ H5FL_fac_node_t *free_list; /* Pointer to nodes in free list being garbage collected */
+ void *tmp; /* Temporary node pointer */
+ size_t total_mem; /* Total memory used on list */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FL_fac_gc_list)
+
+ /* Calculate the total memory used on this list */
+ total_mem=head->onlist*head->size;
+
+ /* For each free list being garbage collected, walk through the nodes and free them */
+ free_list=head->list;
+ while(free_list!=NULL) {
+ tmp=free_list->next;
+
+ /* Decrement the count of nodes allocated and free the node */
+ head->allocated--;
+
+ H5MM_free(free_list);
+
+ free_list = (H5FL_fac_node_t *)tmp;
+ } /* end while */
+
+ /* Indicate no free nodes on the free list */
+ head->list=NULL;
+ head->onlist=0;
+
+ /* Decrement global count of free memory on "factory" lists */
+ H5FL_fac_gc_head.mem_freed-=total_mem;
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5FL_fac_gc_list() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5FL_fac_gc
+ *
+ * Purpose: Garbage collect on all the factory free lists
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Neil Fortner
+ * Friday, December 19, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5FL_fac_gc(void)
+{
+ H5FL_fac_gc_node_t *gc_node; /* Pointer into the list of things to garbage collect */
+ herr_t ret_value=SUCCEED; /* return value*/
+
+ FUNC_ENTER_NOAPI_NOINIT(H5FL_fac_gc)
+
+ /* Walk through all the free lists, free()'ing the nodes */
+ gc_node=H5FL_fac_gc_head.first;
+ while(gc_node!=NULL) {
+ /* Release the free nodes on the list */
+ if(H5FL_fac_gc_list(gc_node->list)<0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL, "garbage collection of list failed")
+
+ /* Go on to the next free list to garbage collect */
+ gc_node=gc_node->next;
+ } /* end while */
+
+ /* Double check that all the memory on the free lists is recycled */
+ HDassert(H5FL_fac_gc_head.mem_freed==0);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5FL_fac_gc() */
/*-------------------------------------------------------------------------
@@ -2108,29 +2309,50 @@ done:
* Wednesday, February 2, 2005
*
* Modifications:
+ * Neil Fortner
+ * Friday, December 19, 2008
+ * Totally rewritten to support new factory implementation
*
*-------------------------------------------------------------------------
*/
herr_t
H5FL_fac_term(H5FL_fac_head_t *factory)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ H5FL_fac_gc_node_t *tmp; /* Temporary pointer to a garbage collection node */
+ herr_t ret_value = SUCCEED; /* Return value */
+ /* NOINIT OK here because this must be called after H5FL_fac_init -NAF */
FUNC_ENTER_NOAPI_NOINIT(H5FL_fac_term)
/* Sanity check */
HDassert(factory);
/* Garbage collect all the blocks in the factory's free list */
- if(H5FL_blk_gc_list(&(factory->queue))<0)
+ if(H5FL_fac_gc_list(factory)<0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL, "garbage collection of factory failed")
/* Verify that all the blocks have been freed */
- if(factory->queue.allocated>0)
+ if(factory->allocated>0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTRELEASE, FAIL, "factory still has objects allocated")
/* Unlink block free list for factory from global free list */
- H5FL_blk_unlink(&(factory->queue));
+ if(factory->prev_gc) {
+ H5FL_fac_gc_node_t *last = factory->prev_gc; /* Garbage collection node before the one being removed */
+
+ HDassert(last->next->list == factory);
+ tmp = last->next->next;
+ (void)H5FL_FREE(H5FL_fac_gc_node_t, last->next);
+ last->next = tmp;
+ if(tmp)
+ tmp->list->prev_gc = last;
+ } else {
+ HDassert(H5FL_fac_gc_head.first->list == factory);
+ tmp = H5FL_fac_gc_head.first->next;
+ (void)H5FL_FREE(H5FL_fac_gc_node_t, H5FL_fac_gc_head.first);
+ H5FL_fac_gc_head.first = tmp;
+ if(tmp)
+ tmp->list->prev_gc = NULL;
+ } /* end else */
/* Free factory info */
(void)H5FL_FREE(H5FL_fac_head_t, factory);
@@ -2141,6 +2363,52 @@ done:
/*-------------------------------------------------------------------------
+ * Function: H5FL_fac_term_all
+ *
+ * Purpose: Terminate all block factories
+ *
+ * Return: 0. There should never be any outstanding allocations
+ * when this is called.
+ *
+ * Programmer: Neil Fortner
+ * Friday, December 19, 2008
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+H5FL_fac_term_all(void)
+{
+ H5FL_fac_gc_node_t *tmp; /* Temporary pointer to a garbage collection node */
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5FL_fac_term_all)
+
+ /* Free the nodes on the garbage collection list */
+ while(H5FL_fac_gc_head.first != NULL) {
+ tmp=H5FL_fac_gc_head.first->next;
+
+#ifdef H5FL_DEBUG
+printf("H5FL_fac_term: head->size=%d, head->allocated=%d\n", (int)H5FL_fac_gc_head.first->list->size,(int)H5FL_fac_gc_head.first->list->allocated);
+#endif /* H5FL_DEBUG */
+
+ /* The list cannot have any allocations outstanding */
+ HDassert(H5FL_fac_gc_head.first->list->allocated == 0);
+
+ /* Reset the "initialized" flag, in case we restart this list somehow (I don't know how..) */
+ H5FL_fac_gc_head.first->list->init = 0;
+
+ /* Free the node from the garbage collection list */
+ (void)H5FL_FREE(H5FL_fac_gc_node_t, H5FL_fac_gc_head.first);
+
+ H5FL_fac_gc_head.first = tmp;
+ } /* end while */
+
+ FUNC_LEAVE_NOAPI(0)
+} /* end H5FL_fac_term_all() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5FL_garbage_coll
*
* Purpose: Garbage collect on all the free lists
@@ -2160,7 +2428,7 @@ H5FL_garbage_coll(void)
{
herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT(H5FL_garbage_coll)
+ FUNC_ENTER_NOAPI(H5FL_garbage_coll, FAIL)
/* Garbage collect the free lists for array objects */
if(H5FL_arr_gc()<0)
@@ -2174,6 +2442,10 @@ H5FL_garbage_coll(void)
if(H5FL_reg_gc()<0)
HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL, "can't garbage collect regular objects")
+ /* Garbage collect the free lists for factory objects */
+ if(H5FL_fac_gc()<0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTGC, FAIL, "can't garbage collect regular objects")
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5FL_garbage_coll() */
@@ -2204,13 +2476,16 @@ done:
* Programmer: Quincey Koziol
* Wednesday, August 2, 2000
*
- * Modifications:
+ * Modifications: Neil Fortner
+ * Wednesday, April 8, 2009
+ * Added support for factory free lists
*
*-------------------------------------------------------------------------
*/
herr_t
H5FL_set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_lim,
- int arr_list_lim, int blk_global_lim, int blk_list_lim)
+ int arr_list_lim, int blk_global_lim, int blk_list_lim, int fac_global_lim,
+ int fac_list_lim)
{
herr_t ret_value = SUCCEED;
@@ -2229,6 +2504,10 @@ H5FL_set_free_list_limits(int reg_global_lim, int reg_list_lim, int arr_global_l
H5FL_blk_glb_mem_lim=(blk_global_lim==-1 ? UINT_MAX : (size_t)blk_global_lim);
/* limit on each block free list */
H5FL_blk_lst_mem_lim=(blk_list_lim==-1 ? UINT_MAX : (size_t)blk_list_lim);
+ /* limit on all factory free lists */
+ H5FL_fac_glb_mem_lim=(fac_global_lim==-1 ? UINT_MAX : (size_t)fac_global_lim);
+ /* limit on each factory free list */
+ H5FL_fac_lst_mem_lim=(fac_list_lim==-1 ? UINT_MAX : (size_t)fac_list_lim);
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2264,7 +2543,7 @@ H5FL_term_interface(void)
/* Garbage collect any nodes on the free lists */
(void)H5FL_garbage_coll();
- ret_value=H5FL_reg_term()+H5FL_arr_term()+H5FL_blk_term();
+ ret_value=H5FL_reg_term()+H5FL_fac_term_all()+H5FL_arr_term()+H5FL_blk_term();
#ifdef H5FL_TRACK
/* If we haven't freed all the allocated memory, dump out the list now */
diff --git a/src/H5FLprivate.h b/src/H5FLprivate.h
index a799dc4..c1a865a 100644
--- a/src/H5FLprivate.h
+++ b/src/H5FLprivate.h
@@ -100,7 +100,6 @@ typedef struct H5FL_reg_head_t {
unsigned init; /* Whether the free list has been initialized */
unsigned allocated; /* Number of blocks allocated */
unsigned onlist; /* Number of blocks on free list */
- size_t list_mem; /* Amount of memory on free list */
const char *name; /* Name of the type */
size_t size; /* Size of the blocks in the list */
H5FL_reg_node_t *list; /* List of free blocks */
@@ -112,7 +111,7 @@ typedef struct H5FL_reg_head_t {
#define H5FL_REG_NAME(t) H5_##t##_reg_free_list
#ifndef H5_NO_REG_FREE_LISTS
/* Common macros for H5FL_DEFINE & H5FL_DEFINE_STATIC */
-#define H5FL_DEFINE_COMMON(t) H5FL_reg_head_t H5FL_REG_NAME(t)={0,0,0,0,#t,sizeof(t),NULL}
+#define H5FL_DEFINE_COMMON(t) H5FL_reg_head_t H5FL_REG_NAME(t)={0,0,0,#t,sizeof(t),NULL}
/* Declare a free list to manage objects of type 't' */
#define H5FL_DEFINE(t) H5_DLL H5FL_DEFINE_COMMON(t)
@@ -349,11 +348,8 @@ typedef struct H5FL_seq_head_t {
#define H5FL_SEQ_REALLOC(t,obj,new_elem) (t *)H5MM_realloc(obj,(new_elem)*sizeof(t))
#endif /* H5_NO_SEQ_FREE_LISTS */
-/* Data structure for free list block factory */
-typedef struct H5FL_fac_head_t {
- H5FL_blk_head_t queue; /* Priority queue of blocks */
- size_t size; /* Size of the blocks managed */
-} H5FL_fac_head_t;
+/* Forward declaration of the data structure for free list block factory */
+typedef struct H5FL_fac_head_t H5FL_fac_head_t;
/*
* Macros for defining & using free list factories
@@ -381,30 +377,42 @@ typedef struct H5FL_fac_head_t {
/*
* Library prototypes.
*/
+ /* Block free lists */
H5_DLL void * H5FL_blk_malloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS);
H5_DLL void * H5FL_blk_calloc(H5FL_blk_head_t *head, size_t size H5FL_TRACK_PARAMS);
H5_DLL void * H5FL_blk_free(H5FL_blk_head_t *head, void *block);
H5_DLL void * H5FL_blk_realloc(H5FL_blk_head_t *head, void *block, size_t new_size H5FL_TRACK_PARAMS);
H5_DLL htri_t H5FL_blk_free_block_avail(H5FL_blk_head_t *head, size_t size);
+
+/* Regular free lists */
H5_DLL void * H5FL_reg_malloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS);
H5_DLL void * H5FL_reg_calloc(H5FL_reg_head_t *head H5FL_TRACK_PARAMS);
H5_DLL void * H5FL_reg_free(H5FL_reg_head_t *head, void *obj);
+
+/* Array free lists */
H5_DLL void * H5FL_arr_malloc(H5FL_arr_head_t *head, size_t elem);
H5_DLL void * H5FL_arr_calloc(H5FL_arr_head_t *head, size_t elem);
H5_DLL void * H5FL_arr_free(H5FL_arr_head_t *head, void *obj);
H5_DLL void * H5FL_arr_realloc(H5FL_arr_head_t *head, void *obj, size_t new_elem);
+
+/* Sequence free lists */
H5_DLL void * H5FL_seq_malloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS);
H5_DLL void * H5FL_seq_calloc(H5FL_seq_head_t *head, size_t elem H5FL_TRACK_PARAMS);
H5_DLL void * H5FL_seq_free(H5FL_seq_head_t *head, void *obj);
H5_DLL void * H5FL_seq_realloc(H5FL_seq_head_t *head, void *obj, size_t new_elem H5FL_TRACK_PARAMS);
+
+/* Factory free lists */
H5_DLL H5FL_fac_head_t *H5FL_fac_init(size_t size);
H5_DLL void * H5FL_fac_malloc(H5FL_fac_head_t *head H5FL_TRACK_PARAMS);
H5_DLL void * H5FL_fac_calloc(H5FL_fac_head_t *head H5FL_TRACK_PARAMS);
H5_DLL void * H5FL_fac_free(H5FL_fac_head_t *head, void *obj);
H5_DLL herr_t H5FL_fac_term(H5FL_fac_head_t *head);
+
+/* General free list routines */
H5_DLL herr_t H5FL_garbage_coll(void);
H5_DLL herr_t H5FL_set_free_list_limits(int reg_global_lim, int reg_list_lim,
- int arr_global_lim, int arr_list_lim, int blk_global_lim, int blk_list_lim);
+ int arr_global_lim, int arr_list_lim, int blk_global_lim, int blk_list_lim,
+ int fac_global_lim, int fac_list_lim);
H5_DLL int H5FL_term_interface(void);
#endif
diff --git a/src/H5FO.c b/src/H5FO.c
index fe3eaa9..33241f0 100644
--- a/src/H5FO.c
+++ b/src/H5FO.c
@@ -82,7 +82,7 @@ H5FO_create(const H5F_t *f)
assert(f->shared);
/* Create container used to store open object info */
- if((f->shared->open_objs = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16)) == NULL)
+ if((f->shared->open_objs = H5SL_create(H5SL_TYPE_HADDR)) == NULL)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object container")
done:
@@ -400,7 +400,7 @@ H5FO_top_create(H5F_t *f)
HDassert(f);
/* Create container used to store open object info */
- if((f->obj_count = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16)) == NULL)
+ if((f->obj_count = H5SL_create(H5SL_TYPE_HADDR)) == NULL)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to create open object container")
done:
diff --git a/src/H5FSsection.c b/src/H5FSsection.c
index 42c0f86..77e6d1a 100644
--- a/src/H5FSsection.c
+++ b/src/H5FSsection.c
@@ -45,9 +45,6 @@
/* Default starting size of section buffer */
#define H5FS_SINFO_SIZE_DEFAULT 64
-/* Max. height of the skip list holding free list nodes */
-#define H5FS_DEFAULT_SKIPLIST_HEIGHT 16
-
/******************/
/* Local Typedefs */
@@ -962,7 +959,7 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a\n", FUNC, sect->size, s
bin = H5V_log2_gen(sect->size);
HDassert(bin < sinfo->nbins);
if(sinfo->bins[bin].bin_list == NULL) {
- if(NULL == (sinfo->bins[bin].bin_list = H5SL_create(H5SL_TYPE_HSIZE, 0.5, (size_t)H5FS_DEFAULT_SKIPLIST_HEIGHT)))
+ if(NULL == (sinfo->bins[bin].bin_list = H5SL_create(H5SL_TYPE_HSIZE)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for free space nodes")
} /* end if */
else {
@@ -979,7 +976,7 @@ HDfprintf(stderr, "%s: sect->size = %Hu, sect->addr = %a\n", FUNC, sect->size, s
/* Initialize the free list size node */
fspace_node->sect_size = sect->size;
fspace_node->serial_count = fspace_node->ghost_count = 0;
- if(NULL == (fspace_node->sect_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)H5FS_DEFAULT_SKIPLIST_HEIGHT)))
+ if(NULL == (fspace_node->sect_list = H5SL_create(H5SL_TYPE_HADDR)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for free space nodes")
/* Insert new free space size node into bin's list */
@@ -1058,7 +1055,7 @@ H5FS_sect_link_rest(H5FS_t *fspace, const H5FS_section_class_t *cls,
HDfprintf(stderr, "%s: inserting object into merge list, sect->type = %u\n", FUNC, (unsigned)sect->type);
#endif /* QAK */
if(fspace->sinfo->merge_list == NULL)
- if(NULL == (fspace->sinfo->merge_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)H5FS_DEFAULT_SKIPLIST_HEIGHT)))
+ if(NULL == (fspace->sinfo->merge_list = H5SL_create(H5SL_TYPE_HADDR)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for merging free space sections")
if(H5SL_insert(fspace->sinfo->merge_list, sect, &sect->addr) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into merging skip list")
@@ -2101,7 +2098,7 @@ HDfprintf(stderr, "%s: to_mergable = %u\n", FUNC, to_mergable);
HDfprintf(stderr, "%s: inserting object into merge list, sect->type = %u\n", FUNC, (unsigned)sect->type);
#endif /* QAK */
if(fspace->sinfo->merge_list == NULL)
- if(NULL == (fspace->sinfo->merge_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)H5FS_DEFAULT_SKIPLIST_HEIGHT)))
+ if(NULL == (fspace->sinfo->merge_list = H5SL_create(H5SL_TYPE_HADDR)))
HGOTO_ERROR(H5E_FSPACE, H5E_CANTCREATE, FAIL, "can't create skip list for merging free space sections")
if(H5SL_insert(fspace->sinfo->merge_list, sect, &sect->addr) < 0)
HGOTO_ERROR(H5E_FSPACE, H5E_CANTINSERT, FAIL, "can't insert free space node into merging skip list")
diff --git a/src/H5Fpkg.h b/src/H5Fpkg.h
index 4080705..49af73e 100644
--- a/src/H5Fpkg.h
+++ b/src/H5Fpkg.h
@@ -158,7 +158,8 @@ typedef struct H5F_file_t {
int ncwfs; /* Num entries on cwfs list */
struct H5HG_heap_t **cwfs; /* Global heap cache */
struct H5G_t *root_grp; /* Open root group */
- H5G_entry_t *root_ent; /* Root group symbol table entry */
+ H5G_entry_t *root_ent; /* Root group symbol table entry */
+ haddr_t root_addr; /* Root group address */
H5FO_t *open_objs; /* Open objects in file */
H5RC_t *grp_btree_shared; /* Ref-counted group B-tree node info */
@@ -225,7 +226,7 @@ H5_DLL herr_t H5F_mount_count_ids(H5F_t *f, unsigned *nopen_files, unsigned *nop
/* Superblock related routines */
H5_DLL herr_t H5F_super_init(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5F_super_write(H5F_t *f, hid_t dxpl_id);
-H5_DLL herr_t H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc);
+H5_DLL herr_t H5F_super_read(H5F_t *f, hid_t dxpl_id);
H5_DLL herr_t H5F_super_ext_size(H5F_t *f, hid_t dxpl_id, hsize_t *super_ext_info);
/* Metadata accumulator routines */
@@ -247,6 +248,7 @@ H5_DLL herr_t H5F_sfile_remove(H5F_file_t *shared);
#ifdef H5F_TESTING
H5_DLL herr_t H5F_get_sohm_mesg_count_test(hid_t fid, unsigned type_id,
size_t *mesg_count);
+H5_DLL herr_t H5F_check_cached_stab_test(hid_t file_id);
#endif /* H5F_TESTING */
#endif /* _H5Fpkg_H */
diff --git a/src/H5Fsuper.c b/src/H5Fsuper.c
index 8040554..32541ae 100644
--- a/src/H5Fsuper.c
+++ b/src/H5Fsuper.c
@@ -32,6 +32,7 @@
#include "H5FDprivate.h" /* File drivers */
#include "H5Iprivate.h" /* IDs */
#include "H5MFprivate.h" /* File memory management */
+#include "H5MMprivate.h" /* Memory management */
#include "H5Pprivate.h" /* Property lists */
#include "H5SMprivate.h" /* Shared Object Header Messages */
@@ -230,7 +231,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
+H5F_super_read(H5F_t *f, hid_t dxpl_id)
{
uint8_t sbuf[H5F_MAX_SUPERBLOCK_SIZE]; /* Buffer for superblock */
H5P_genplist_t *c_plist; /* File creation property list */
@@ -383,8 +384,9 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
H5F_addr_decode(f, (const uint8_t **)&p, &shared->extension_addr/*out*/);
H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/);
H5F_addr_decode(f, (const uint8_t **)&p, &shared->driver_addr/*out*/);
- if(H5G_obj_ent_decode(f, (const uint8_t **)&p, root_loc->oloc/*out*/,
- &shared->root_ent/*out*/) < 0)
+
+ /* Decode the symbol table entry */
+ if(H5G_root_ent_decode(f, (const uint8_t **)&p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to read root symbol entry")
/*
@@ -468,7 +470,6 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
} /* end if */
} /* end if */
else {
- haddr_t root_addr; /* Address of root group */
uint32_t computed_chksum; /* Computed checksum */
uint32_t read_chksum; /* Checksum read from file */
@@ -499,7 +500,7 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
H5F_addr_decode(f, (const uint8_t **)&p, &shared->base_addr/*out*/);
H5F_addr_decode(f, (const uint8_t **)&p, &shared->extension_addr/*out*/);
H5F_addr_decode(f, (const uint8_t **)&p, &stored_eoa/*out*/);
- H5F_addr_decode(f, (const uint8_t **)&p, &root_addr/*out*/);
+ H5F_addr_decode(f, (const uint8_t **)&p, &shared->root_addr/*out*/);
/* Compute checksum for superblock */
computed_chksum = H5_checksum_metadata(sbuf, (size_t)(p - sbuf), 0);
@@ -511,11 +512,6 @@ H5F_super_read(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc)
if(read_chksum != computed_chksum)
HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "bad checksum on driver information block")
- /* Create root group object location */
- H5O_loc_reset(root_loc->oloc);
- root_loc->oloc->file = f;
- root_loc->oloc->addr = root_addr;
-
/*
* Check if superblock address is different from base address and
* adjust base address and "end of address" address if so.
@@ -930,7 +926,9 @@ H5F_super_write(H5F_t *f, hid_t dxpl_id)
rel_eoa = H5FD_get_eoa(f->shared->lf, H5FD_MEM_SUPER);
H5F_addr_encode(f, &p, (rel_eoa + f->shared->base_addr));
H5F_addr_encode(f, &p, f->shared->driver_addr);
- if(H5G_obj_ent_encode(f, &p, H5G_oloc(f->shared->root_grp)) < 0)
+
+ /* Encode the root group object entry, including the cached stab info */
+ if(H5G_root_ent_encode(f, &p) < 0)
HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to encode root group information")
/* Encode the driver information block. */
diff --git a/src/H5Ftest.c b/src/H5Ftest.c
index 1d7e514..8cbc133 100644
--- a/src/H5Ftest.c
+++ b/src/H5Ftest.c
@@ -32,6 +32,8 @@
#define H5F_TESTING /*suppress warning about H5F testing funcs*/
#define H5SM_PACKAGE /*suppress error about including H5SMpkg */
#define H5SM_TESTING /*suppress warning about H5SM testing funcs*/
+#define H5G_PACKAGE /*suppress error about including H5Gpkg */
+#define H5G_TESTING /*suppress warning about H5G testing funcs*/
/***********/
@@ -40,6 +42,7 @@
#include "H5private.h" /* Generic Functions */
#include "H5Eprivate.h" /* Error handling */
#include "H5Fpkg.h" /* File access */
+#include "H5Gpkg.h" /* Groups */
#include "H5Iprivate.h" /* IDs */
#include "H5SMpkg.h" /* Shared object header messages */
@@ -113,3 +116,40 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5F_get_sohm_mesg_count_test() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5F_check_cached_stab_test
+ *
+ * Purpose: Check that a file's superblock contains a cached symbol
+ * table entry, that the entry matches that in the root
+ * group's object header, and check that the addresses are
+ * valid.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Neil Fortner
+ * Mar 31, 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5F_check_cached_stab_test(hid_t file_id)
+{
+ H5F_t *file; /* File info */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5F_check_cached_stab_test)
+
+ /* Check arguments */
+ if(NULL == (file = (H5F_t *)H5I_object_verify(file_id, H5I_FILE)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file")
+
+ /* Verify the cached stab info */
+ if(H5G_verify_cached_stab_test(H5G_oloc(file->shared->root_grp), file->shared->root_ent) < 0)
+ HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to verify cached symbol table info")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5F_check_cached_stab_test() */
+
diff --git a/src/H5G.c b/src/H5G.c
index 042ce90..2afd837 100644
--- a/src/H5G.c
+++ b/src/H5G.c
@@ -817,141 +817,6 @@ H5G_term_interface(void)
/*-------------------------------------------------------------------------
- * Function: H5G_mkroot
- *
- * Purpose: Creates a root group in an empty file and opens it. If a
- * root group is already open then this function immediately
- * returns. If ENT is non-null then it's the symbol table
- * entry for an existing group which will be opened as the root
- * group. Otherwise a new root group is created and then
- * opened.
- *
- * Return: Non-negative on success/Negative on failure
- *
- * Programmer: Robb Matzke
- * matzke@llnl.gov
- * Aug 11 1997
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_loc_t *loc)
-{
- H5O_loc_t new_root_oloc; /* New root object location */
- H5G_name_t new_root_path; /* New root path */
- H5G_loc_t new_root_loc; /* New root location information */
- H5G_loc_t root_loc; /* Root location information */
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5G_mkroot, FAIL)
-
- /* check args */
- HDassert(f);
-
- /* Check if the root group is already initialized */
- if(f->shared->root_grp)
- HGOTO_DONE(SUCCEED)
-
- /* Create information needed for group nodes */
- if(H5G_node_init(f) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group node info")
-
- /*
- * If there is no root object then create one. The root group always starts
- * with a hard link count of one since it's pointed to by the superblock.
- */
- if(loc == NULL) {
- H5P_genplist_t *fc_plist; /* File creation property list */
- H5O_ginfo_t ginfo; /* Group info parameters */
- H5O_linfo_t linfo; /* Link info parameters */
-
- /* Get the file creation property list */
- /* (Which is a sub-class of the group creation property class) */
- if(NULL == (fc_plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
-
- /* Get the group info property */
- if(H5P_get(fc_plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get group info")
-
- /* Get the link info property */
- if(H5P_get(fc_plist, H5G_CRT_LINK_INFO_NAME, &linfo) < 0)
- HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get link info")
-
- /* Set up group location for root group */
- new_root_loc.oloc = &new_root_oloc;
- new_root_loc.path = &new_root_path;
- H5G_loc_reset(&new_root_loc);
- loc = &new_root_loc;
-
- /* Create root group */
- if(H5G_obj_create(f, dxpl_id, &ginfo, &linfo, f->shared->fcpl_id, loc->oloc/*out*/) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group entry")
- if(1 != H5O_link(loc->oloc, 1, dxpl_id))
- HGOTO_ERROR(H5E_SYM, H5E_LINKCOUNT, FAIL, "internal error (wrong link count)")
- } /* end if */
- else {
- /*
- * Open the root object as a group.
- */
- if(H5O_open(loc->oloc) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open root group")
-
-#ifndef H5_STRICT_FORMAT_CHECKS
- /* If symbol table information is cached, check if we should replace the
- * symbol table message with the cached symbol table information */
- if((H5F_INTENT(f) & H5F_ACC_RDWR) && f->shared->root_ent
- && (f->shared->root_ent->type == H5G_CACHED_STAB)) {
- H5O_stab_t cached_stab;
-
- /* Retrieve the cached symbol table information */
- cached_stab.btree_addr = f->shared->root_ent->cache.stab.btree_addr;
- cached_stab.heap_addr = f->shared->root_ent->cache.stab.heap_addr;
-
- /* Check if the symbol table message is valid, and replace with the
- * cached symbol table if necessary */
- if(H5G_stab_valid(loc->oloc, dxpl_id, &cached_stab) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to verify symbol table")
- } /* end if */
-#endif /* H5_STRICT_FORMAT_CHECKS */
- } /* end else */
-
- /* Create the path names for the root group's entry */
- H5G_name_init(loc->path, "/");
-
- /*
- * Create the group pointer. Also decrement the open object count so we
- * don't count the root group as an open object. The root group will
- * never be closed.
- */
- if(NULL == (f->shared->root_grp = H5FL_CALLOC(H5G_t)))
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- if(NULL == (f->shared->root_grp->shared = H5FL_CALLOC(H5G_shared_t))) {
- (void)H5FL_FREE(H5G_t, f->shared->root_grp);
- HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
- } /* end if */
-
- /* Shallow copy (take ownership) of the group object info */
- root_loc.oloc = &(f->shared->root_grp->oloc);
- root_loc.path = &(f->shared->root_grp->path);
- if(H5G_loc_copy(&root_loc, loc, H5_COPY_SHALLOW) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTCOPY, FAIL, "can't copy group object location")
-
- f->shared->root_grp->shared->fo_count = 1;
- /* The only other open object should be the superblock extension, if it
- * exists. Don't count either the superblock extension or the root group
- * in the number of open objects in the file.
- */
- HDassert((1 == f->nopen_objs) ||
- (2 == f->nopen_objs && HADDR_UNDEF != f->shared->extension_addr));
- f->nopen_objs--;
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_mkroot() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5G_create
*
* Purpose: Creates a new empty group with the specified name. The name
@@ -1351,36 +1216,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5G_rootof
- *
- * Purpose: Return a pointer to the root group of the file. If the file
- * is part of a virtual file then the root group of the virtual
- * file is returned.
- *
- * Return: Success: Ptr to the root group of the file. Do not
- * free the pointer -- it points directly into
- * the file struct.
- *
- * Failure: NULL
- *
- * Programmer: Robb Matzke
- * Tuesday, October 13, 1998
- *
- *-------------------------------------------------------------------------
- */
-H5G_t *
-H5G_rootof(H5F_t *f)
-{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_rootof)
-
- while(f->parent)
- f = f->parent;
-
- FUNC_LEAVE_NOAPI(f->shared->root_grp)
-} /* end H5G_rootof() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5G_oloc
*
* Purpose: Returns a pointer to the object location for a group.
@@ -1975,7 +1810,7 @@ H5G_visit(hid_t loc_id, const char *group_name, H5_index_t idx_type,
udata.curr_path_len = 0;
/* Create skip list to store visited object information */
- if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, 0.5, (size_t)16)) == NULL)
+ if((udata.visited = H5SL_create(H5SL_TYPE_OBJ)) == NULL)
HGOTO_ERROR(H5E_SYM, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects")
/* Get the group's reference count and type */
diff --git a/src/H5Gobj.c b/src/H5Gobj.c
index 2eb1924..08a9268 100644
--- a/src/H5Gobj.c
+++ b/src/H5Gobj.c
@@ -221,115 +221,6 @@ done:
/*-------------------------------------------------------------------------
- * Function: H5G_obj_ent_decode
- *
- * Purpose: Decodes a symbol table entry into a object location
- *
- * Return: Success: Non-negative with *pp pointing to the first byte
- * following the symbol table entry.
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Sep 26 2005
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp, H5O_loc_t *oloc, H5G_entry_t **entp)
-{
- const uint8_t *p_ret = *pp;
- herr_t ret_value = SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5G_obj_ent_decode, FAIL)
-
- /* check arguments */
- HDassert(f);
- HDassert(pp);
- HDassert(oloc);
-
- if(entp) {
- /* If entp is not NULL we allocate space for the symbol table entry and
- * decode the entire entry. */
- if(!(*entp)) /* Only allocate space if *entp is NULL */
- if(NULL == (*entp = (H5G_entry_t *) H5MM_calloc(sizeof(H5G_entry_t))))
- HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate space for symbol table entry")
- if(H5G_ent_decode_vec(f, pp, *entp, 1) < 0)
- HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode symbol table entry")
-
- /* Set oloc to the correct values */
- oloc->file = (*entp)->file;
- oloc->addr = (*entp)->header;
- } else {
- /* Set file pointer for root object location */
- oloc->file = f;
-
- /* decode header */
- *pp += H5F_SIZEOF_SIZE(f); /* Skip over local heap address */
- H5F_addr_decode(f, pp, &(oloc->addr));
- *pp += 4; /* Skip over "cache type" */
- *pp += 4; /* Reserved */
- }
-
- /* Common oloc settings */
- oloc->holding_file = FALSE;
-
- /* Set decode pointer */
- *pp = p_ret + H5G_SIZEOF_ENTRY(f);
-
-done:
- FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5G_obj_ent_decode() */
-
-
-/*-------------------------------------------------------------------------
- * Function: H5G_obj_ent_encode
- *
- * Purpose: Encodes the specified object location into a symbol table
- * entry in the buffer pointed to by *pp.
- *
- * Return: Success: Non-negative, with *pp pointing to the first byte
- * after the symbol table entry.
- *
- * Failure: Negative
- *
- * Programmer: Quincey Koziol
- * koziol@ncsa.uiuc.edu
- * Sep 26 2005
- *
- *-------------------------------------------------------------------------
- */
-herr_t
-H5G_obj_ent_encode(const H5F_t *f, uint8_t **pp, const H5O_loc_t *oloc)
-{
- uint8_t *p_ret = *pp + H5G_SIZEOF_ENTRY(f);
-
- FUNC_ENTER_NOAPI_NOFUNC(H5G_obj_ent_encode)
-
- /* check arguments */
- HDassert(f);
- HDassert(pp);
-
- /* encode header */
- H5F_ENCODE_LENGTH(f, *pp, 0); /* No name for root group */
- if(oloc)
- H5F_addr_encode(f, pp, oloc->addr);
- else
- H5F_addr_encode(f, pp, HADDR_UNDEF);
- UINT32ENCODE(*pp, H5G_NOTHING_CACHED);
- UINT32ENCODE(*pp, 0); /*reserved*/
-
- /* fill with zero */
- while(*pp < p_ret)
- *(*pp)++ = 0;
- *pp = p_ret;
-
- FUNC_LEAVE_NOAPI(SUCCEED)
-} /* end H5G_obj_ent_encode() */
-
-
-/*-------------------------------------------------------------------------
* Function: H5G_obj_get_linfo
*
* Purpose: Retrieves the "link info" message for an object. Also
diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h
index 38c7628..0840ee7 100644
--- a/src/H5Gpkg.h
+++ b/src/H5Gpkg.h
@@ -340,6 +340,12 @@ H5_DLLVAR const H5B2_class_t H5G_BT2_NAME[1];
/* The v2 B-tree class for indexing 'creation order' field on links */
H5_DLLVAR const H5B2_class_t H5G_BT2_CORDER[1];
+/* Free list for managing H5G_t structs */
+H5FL_EXTERN(H5G_t);
+
+/* Free list for managing H5G_shared_t structs */
+H5FL_EXTERN(H5G_shared_t);
+
/******************************/
/* Package Private Prototypes */
/******************************/
@@ -565,6 +571,7 @@ H5_DLL htri_t H5G_is_new_dense_test(hid_t gid);
H5_DLL herr_t H5G_new_dense_info_test(hid_t gid, hsize_t *name_count, hsize_t *corder_count);
H5_DLL herr_t H5G_lheap_size_test(hid_t gid, size_t *lheap_size);
H5_DLL herr_t H5G_user_path_test(hid_t obj_id, char *user_path, size_t *user_path_len, unsigned *user_path_hidden);
+H5_DLL herr_t H5G_verify_cached_stab_test(H5O_loc_t *grp_oloc, H5G_entry_t *ent);
#endif /* H5G_TESTING */
#endif /* _H5Gpkg_H */
diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h
index b1db96f..7f001e0 100644
--- a/src/H5Gprivate.h
+++ b/src/H5Gprivate.h
@@ -151,7 +151,7 @@ typedef struct H5G_entry_t H5G_entry_t;
* Library prototypes... These are the ones that other packages routinely
* call.
*/
-H5_DLL herr_t H5G_mkroot(H5F_t *f, hid_t dxpl_id, H5G_loc_t *root_loc);
+H5_DLL herr_t H5G_mkroot(H5F_t *f, hid_t dxpl_id, hbool_t create_root);
H5_DLL struct H5O_loc_t *H5G_oloc(H5G_t *grp);
H5_DLL H5G_t *H5G_rootof(H5F_t *f);
H5_DLL H5G_name_t * H5G_nameof(H5G_t *grp);
@@ -181,10 +181,8 @@ H5_DLL herr_t H5G_node_debug(H5F_t *f, hid_t dxpl_id, haddr_t addr, FILE *stream
/*
* These functions operate on group object locations.
*/
-H5_DLL herr_t H5G_obj_ent_decode(H5F_t *f, const uint8_t **pp,
- struct H5O_loc_t *oloc, H5G_entry_t **entp);
-H5_DLL herr_t H5G_obj_ent_encode(const H5F_t *f, uint8_t **pp,
- const struct H5O_loc_t *oloc);
+H5_DLL herr_t H5G_root_ent_decode(H5F_t *f, const uint8_t **pp);
+H5_DLL herr_t H5G_root_ent_encode(H5F_t *f, uint8_t **pp);
/*
* These functions operate on group hierarchy names.
diff --git a/src/H5Groot.c b/src/H5Groot.c
new file mode 100644
index 0000000..b8a1468
--- /dev/null
+++ b/src/H5Groot.c
@@ -0,0 +1,368 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * 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://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+ /*-------------------------------------------------------------------------
+ *
+ * Created: H5Gobj.c
+ * Apr 8 2009
+ * Neil Fortner <nfortne2@hdfgroup.org>
+ *
+ * Purpose: Functions for operating on the root group.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/****************/
+/* Module Setup */
+/****************/
+
+#define H5F_PACKAGE /*suppress error about including H5Fpkg */
+#define H5G_PACKAGE /*suppress error about including H5Gpkg */
+
+
+/***********/
+/* Headers */
+/***********/
+#include "H5private.h" /* Generic Functions */
+#include "H5Eprivate.h" /* Error handling */
+#include "H5Fpkg.h" /* File access */
+#include "H5Gpkg.h" /* Groups */
+#include "H5Iprivate.h" /* IDs */
+#include "H5MMprivate.h" /* Memory management */
+#include "H5Pprivate.h" /* Property Lists */
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_rootof
+ *
+ * Purpose: Return a pointer to the root group of the file. If the file
+ * is part of a virtual file then the root group of the virtual
+ * file is returned.
+ *
+ * Return: Success: Ptr to the root group of the file. Do not
+ * free the pointer -- it points directly into
+ * the file struct.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, October 13, 1998
+ *
+ *-------------------------------------------------------------------------
+ */
+H5G_t *
+H5G_rootof(H5F_t *f)
+{
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5G_rootof)
+
+ while(f->parent)
+ f = f->parent;
+
+ FUNC_LEAVE_NOAPI(f->shared->root_grp)
+} /* end H5G_rootof() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_root_ent_decode
+ *
+ * Purpose: Decodes the root group symbol table entry into the file
+ * structure, and updates the root group address in the file
+ * structure.
+ *
+ * Return: Success: Non-negative with *pp pointing to the first byte
+ * following the symbol table entry.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Sep 26 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_root_ent_decode(H5F_t *f, const uint8_t **pp)
+{
+ const uint8_t *p_ret = *pp + H5G_SIZEOF_ENTRY(f);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_root_ent_decode, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(pp);
+
+ /* Allocate space for the root group symbol table entry */
+ HDassert(!f->shared->root_ent);
+ if(NULL == (f->shared->root_ent = (H5G_entry_t *) H5MM_calloc(sizeof(H5G_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate space for symbol table entry")
+
+ /* decode the root group symbol table entry */
+ if(H5G_ent_decode_vec(f, pp, f->shared->root_ent, 1) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTDECODE, FAIL, "can't decode symbol table entry")
+
+ /* Set the root group address to the correct value */
+ f->shared->root_addr = f->shared->root_ent->header;
+
+ /* Set decode pointer */
+ *pp = p_ret;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_root_ent_decode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_root_ent_encode
+ *
+ * Purpose: Encodes the root group symbol table entry into the buffer
+ * pointed to by *pp.
+ *
+ * Return: Success: Non-negative, with *pp pointing to the first byte
+ * after the symbol table entry.
+ *
+ * Failure: Negative
+ *
+ * Programmer: Quincey Koziol
+ * koziol@ncsa.uiuc.edu
+ * Sep 26 2005
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_root_ent_encode(H5F_t *f, uint8_t **pp)
+{
+ uint8_t *p_ret = *pp + H5G_SIZEOF_ENTRY(f);
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_root_ent_encode, FAIL)
+
+ /* check arguments */
+ HDassert(f);
+ HDassert(f->shared);
+ HDassert(f->shared->root_ent);
+ HDassert(pp);
+
+ /* Encode entry */
+ if(H5G_ent_encode_vec(f, pp, f->shared->root_ent, 1) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTENCODE, FAIL, "can't encode symbol table entry")
+
+ /* Set encode pointer */
+ *pp = p_ret;
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_root_ent_encode() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_mkroot
+ *
+ * Purpose: Creates a root group in an empty file and opens it. If a
+ * root group is already open then this function immediately
+ * returns. If ENT is non-null then it's the symbol table
+ * entry for an existing group which will be opened as the root
+ * group. Otherwise a new root group is created and then
+ * opened.
+ *
+ * Return: Non-negative on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * matzke@llnl.gov
+ * Aug 11 1997
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_mkroot(H5F_t *f, hid_t dxpl_id, hbool_t create_root)
+{
+ H5G_loc_t root_loc; /* Root location information */
+ htri_t stab_exists = -1; /* Whether the symbol table exists */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5G_mkroot, FAIL)
+
+ /* check args */
+ HDassert(f);
+
+ /* Check if the root group is already initialized */
+ if(f->shared->root_grp)
+ HGOTO_DONE(SUCCEED)
+
+ /* Create information needed for group nodes */
+ if(H5G_node_init(f) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group node info")
+
+ /*
+ * Create the group pointer
+ */
+ if(NULL == (f->shared->root_grp = H5FL_CALLOC(H5G_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ if(NULL == (f->shared->root_grp->shared = H5FL_CALLOC(H5G_shared_t))) {
+ (void)H5FL_FREE(H5G_t, f->shared->root_grp);
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } /* end if */
+
+ /* Initialize the root_loc structure to point to fields in the newly created
+ * f->shared->root_grp structure */
+ root_loc.oloc = &(f->shared->root_grp->oloc);
+ root_loc.path = &(f->shared->root_grp->path);
+ H5G_loc_reset(&root_loc);
+
+ /*
+ * If there is no root object then create one. The root group always starts
+ * with a hard link count of one since it's pointed to by the superblock.
+ */
+ if(create_root) {
+ H5P_genplist_t *fc_plist; /* File creation property list */
+ H5O_ginfo_t ginfo; /* Group info parameters */
+ H5O_linfo_t linfo; /* Link info parameters */
+ unsigned super_vers; /* Superblock version */
+
+ /* Get the file creation property list */
+ /* (Which is a sub-class of the group creation property class) */
+ if(NULL == (fc_plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
+ HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
+
+ /* Get the group info property */
+ if(H5P_get(fc_plist, H5G_CRT_GROUP_INFO_NAME, &ginfo) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get group info")
+
+ /* Get the link info property */
+ if(H5P_get(fc_plist, H5G_CRT_LINK_INFO_NAME, &linfo) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get link info")
+
+ /* Get the superblock version */
+ if(H5P_get(fc_plist, H5F_CRT_SUPER_VERS_NAME, &super_vers) < 0)
+ HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get superblock version")
+
+ /* Create root group */
+ if(H5G_obj_create(f, dxpl_id, &ginfo, &linfo, f->shared->fcpl_id, root_loc.oloc/*out*/) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTINIT, FAIL, "unable to create group entry")
+ if(1 != H5O_link(root_loc.oloc, 1, dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_LINKCOUNT, FAIL, "internal error (wrong link count)")
+
+ /* Create the root group symbol table entry */
+ HDassert(!f->shared->root_ent);
+ if(super_vers < HDF5_SUPERBLOCK_VERSION_2) {
+ /* Allocate space for the root group symbol table entry */
+ if(NULL == (f->shared->root_ent = (H5G_entry_t *) H5MM_calloc(sizeof(H5G_entry_t))))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate space for symbol table entry")
+
+ /* Initialize the root group symbol table entry */
+ f->shared->root_ent->dirty = TRUE;
+ f->shared->root_ent->type = H5G_NOTHING_CACHED; /* We will cache the stab later */
+ f->shared->root_ent->name_off = 0; /* No name (yet) */
+ f->shared->root_ent->header = root_loc.oloc->addr;
+ f->shared->root_ent->file = root_loc.oloc->file;
+ } /* end if */
+ } /* end if */
+ else {
+ /* Create root group object location from f */
+ root_loc.oloc->addr = f->shared->root_addr;
+ root_loc.oloc->file = f;
+
+ /*
+ * Open the root object as a group.
+ */
+ if(H5O_open(root_loc.oloc) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTOPENOBJ, FAIL, "unable to open root group")
+
+ /* Actions to take if the symbol table information is cached */
+ if(f->shared->root_ent && f->shared->root_ent->type == H5G_CACHED_STAB) {
+ /* Check for the situation where the symbol table is cached but does
+ * not exist. This can happen if, for example, an external link is
+ * added to the root group. */
+ if((stab_exists = H5O_msg_exists(root_loc.oloc, H5O_STAB_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check if symbol table message exists")
+
+ /* Remove the cache if the stab does not exist */
+ if(!stab_exists)
+ f->shared->root_ent->type = H5G_NOTHING_CACHED;
+#ifndef H5_STRICT_FORMAT_CHECKS
+ /* If symbol table information is cached, check if we should replace the
+ * symbol table message with the cached symbol table information */
+ else if(H5F_INTENT(f) & H5F_ACC_RDWR) {
+ H5O_stab_t cached_stab;
+
+ /* Retrieve the cached symbol table information */
+ cached_stab.btree_addr = f->shared->root_ent->cache.stab.btree_addr;
+ cached_stab.heap_addr = f->shared->root_ent->cache.stab.heap_addr;
+
+ /* Check if the symbol table message is valid, and replace with the
+ * cached symbol table if necessary */
+ if(H5G_stab_valid(root_loc.oloc, dxpl_id, &cached_stab) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to verify symbol table")
+ } /* end if */
+#endif /* H5_STRICT_FORMAT_CHECKS */
+ } /* end if */
+ } /* end else */
+
+ /* Cache the root group's symbol table information in the root group symbol
+ * table entry. It will have been allocated by now if it needs to be
+ * present, so we don't need to check the superblock version. We do this if
+ * we have write access, the root entry has been allocated (i.e.
+ * super_vers < 2) and the stab info is not already cached. */
+ if((H5F_INTENT(f) & H5F_ACC_RDWR) && stab_exists != FALSE && f->shared->root_ent
+ && f->shared->root_ent->type != H5G_CACHED_STAB) {
+ H5O_stab_t stab; /* Symbol table */
+
+ /* Check if the stab message exists. It's possible for the root group
+ * to use the latest version while the superblock is an old version.
+ * If stab_exists is not -1 then we have already checked. */
+ if(stab_exists == -1 && (stab_exists = H5O_msg_exists(root_loc.oloc, H5O_STAB_ID, dxpl_id)) < 0)
+ HGOTO_ERROR(H5E_SYM, H5E_CANTGET, FAIL, "can't check if symbol table message exists")
+
+ if(stab_exists) {
+ /* Read the root group's symbol table message */
+ if(NULL == H5O_msg_read(root_loc.oloc, H5O_STAB_ID, &stab, dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "unable to read symbol table message")
+
+ /* Update the root group symbol table entry */
+ f->shared->root_ent->type = H5G_CACHED_STAB;
+ f->shared->root_ent->cache.stab.btree_addr = stab.btree_addr;
+ f->shared->root_ent->cache.stab.heap_addr = stab.heap_addr;
+ } /* end if */
+ } /* end if */
+
+ /* Create the path names for the root group's entry */
+ H5G_name_init(root_loc.path, "/");
+
+ f->shared->root_grp->shared->fo_count = 1;
+ /* The only other open object should be the superblock extension, if it
+ * exists. Don't count either the superblock extension or the root group
+ * in the number of open objects in the file.
+ */
+ HDassert((1 == f->nopen_objs) ||
+ (2 == f->nopen_objs && HADDR_UNDEF != f->shared->extension_addr));
+ f->nopen_objs--;
+
+done:
+ /* In case of error, free various memory locations that may have been
+ * allocated */
+ if(ret_value < 0) {
+ if(f->shared->root_grp) {
+ if(f->shared->root_grp->shared)
+ f->shared->root_grp->shared = H5FL_FREE(H5G_shared_t, f->shared->root_grp->shared);
+ f->shared->root_grp = H5FL_FREE(H5G_t, f->shared->root_grp);
+ } /* end if */
+ f->shared->root_ent = (H5G_entry_t *) H5MM_xfree(f->shared->root_ent);
+ H5G_name_free(root_loc.path);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_mkroot() */
+
diff --git a/src/H5Gstab.c b/src/H5Gstab.c
index c2df8e7..52c9d07 100644
--- a/src/H5Gstab.c
+++ b/src/H5Gstab.c
@@ -1011,7 +1011,8 @@ H5G_stab_valid(H5O_loc_t *grp_oloc, hid_t dxpl_id, H5O_stab_t *alt_stab)
FUNC_ENTER_NOAPI(H5G_stab_valid, FAIL)
/* Read the symbol table message */
- H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id);
+ if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "unable to read symbol table message");
/* Check if the symbol table message's b-tree address is valid */
if(H5B_valid(grp_oloc->file, dxpl_id, H5B_SNODE, stab.btree_addr) < 0) {
diff --git a/src/H5Gtest.c b/src/H5Gtest.c
index 1f09048..f3508eb 100644
--- a/src/H5Gtest.c
+++ b/src/H5Gtest.c
@@ -550,3 +550,59 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5G_user_path_test() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5G_verify_cached_stab_test
+ *
+ * Purpose: Check that a that the provided group entry contains a
+ * cached symbol table entry, that the entry matches that in
+ * the provided group's object header, and check that the
+ * addresses are valid.
+ *
+ * Return: Success: Non-negative
+ * Failure: Negative
+ *
+ * Programmer: Neil Fortner
+ * Mar 31, 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5G_verify_cached_stab_test(H5O_loc_t *grp_oloc, H5G_entry_t *ent)
+{
+ H5O_stab_t stab; /* Symbol table */
+ H5HL_t *heap = NULL; /* Pointer to local heap */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT(H5G_verify_cached_stab_test)
+
+ /* Verify that stab info is cached in ent */
+ if(ent->type != H5G_CACHED_STAB)
+ HGOTO_ERROR(H5E_SYM, H5E_BADTYPE, FAIL, "symbol table information is not cached")
+
+ /* Read the symbol table message from the group */
+ if(NULL == H5O_msg_read(grp_oloc, H5O_STAB_ID, &stab, H5AC_ind_dxpl_id))
+ HGOTO_ERROR(H5E_SYM, H5E_BADMESG, FAIL, "unable to read symbol table message")
+
+ /* Verify that the cached symbol table info matches the symbol table message
+ * in the object header */
+ if((ent->cache.stab.btree_addr != stab.btree_addr)
+ || (ent->cache.stab.heap_addr != stab.heap_addr))
+ HGOTO_ERROR(H5E_SYM, H5E_BADVALUE, FAIL, "cached stab info does not match object header")
+
+ /* Verify that the btree address is valid */
+ if(H5B_valid(grp_oloc->file, H5AC_ind_dxpl_id, H5B_SNODE, stab.btree_addr) < 0)
+ HGOTO_ERROR(H5E_BTREE, H5E_NOTFOUND, FAIL, "b-tree address is invalid")
+
+ /* Verify that the heap address is valid */
+ if(NULL == (heap = H5HL_protect(grp_oloc->file, H5AC_ind_dxpl_id, stab.heap_addr, H5AC_READ)))
+ HGOTO_ERROR(H5E_HEAP, H5E_NOTFOUND, FAIL, "heap address is invalid")
+
+done:
+ /* Release resources */
+ if(heap && H5HL_unprotect(grp_oloc->file, H5AC_ind_dxpl_id, heap, stab.heap_addr) < 0)
+ HDONE_ERROR(H5E_SYM, H5E_PROTECT, FAIL, "unable to unprotect symbol table heap")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5G_verify_cached_stab_test() */
+
diff --git a/src/H5I.c b/src/H5I.c
index c6fcb17..841b491 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -1847,40 +1847,35 @@ done:
/*-------------------------------------------------------------------------
* Function: H5Iis_valid
*
- * Purpose: Check if the given id is valid. And id is valid if it is in
- * use and has an application reference count of at least 1.
+ * Purpose: Check if the given id is valid. An id is valid if it is in
+ * use and has an application reference count of at least 1.
*
- * Return: Success: TRUE if the id is valid, FALSE otherwise.
+ * Return: Success: TRUE if the id is valid, FALSE otherwise.
*
- * Failure: Negative (never fails currently)
+ * Failure: Negative (never fails currently)
*
* Programmer: Neil Fortner
* Friday, October 31, 2008 (boo)
*
+ * Modifications:
+ * Raymond Lu
+ * 1 April 2009 (Believe it or not!)
+ * Moved the argument check down to H5I_find_id because other
+ * caller functions may pass in some invalid IDs to H5I_find_id.
+ * It used to do assertion check.
*-------------------------------------------------------------------------
*/
htri_t
H5Iis_valid(hid_t id)
{
- H5I_id_type_t *type_ptr; /* ptr to ID's type */
H5I_id_info_t *id_ptr; /* ptr to the ID */
- H5I_type_t type; /* ID's type */
htri_t ret_value = TRUE; /* Return value */
FUNC_ENTER_API(H5Iis_valid, FAIL)
H5TRACE1("t", "i", id);
- type = H5I_TYPE(id);
- /* Check for conditions that would cause H5I_find_id to throw an assertion */
- if (type <= H5I_BADID || type >= H5I_next_type)
- HGOTO_DONE(FALSE);
-
- type_ptr = H5I_id_type_list_g[type];
- if (!type_ptr || type_ptr->count <= 0)
- ret_value = FALSE;
-
/* Find the ID */
- else if (NULL == (id_ptr = H5I_find_id(id)))
+ if (NULL == (id_ptr = H5I_find_id(id)))
ret_value = FALSE;
/* Check if the found id is an internal id */
@@ -2012,7 +2007,9 @@ done:
* Programmer:
*
* Modifications:
- *
+ * Raymond Lu
+ * 1 April 2009 (Believe it or not!)
+ * Added argument check, took away assertion check.
*-------------------------------------------------------------------------
*/
static H5I_id_info_t *
@@ -2029,10 +2026,12 @@ H5I_find_id(hid_t id)
/* Check arguments */
type = H5I_TYPE(id);
- HDassert(type > H5I_BADID && type < H5I_next_type);
- type_ptr = H5I_id_type_list_g[type];
+ if (type <= H5I_BADID || type >= H5I_next_type)
+ HGOTO_DONE(NULL);
- HDassert(type_ptr && type_ptr->count > 0);
+ type_ptr = H5I_id_type_list_g[type];
+ if (!type_ptr || type_ptr->count <= 0)
+ HGOTO_DONE(NULL);
/* Get the bucket in which the ID is located */
hash_loc = (unsigned)H5I_LOC(id, type_ptr->hash_size);
@@ -2057,6 +2056,7 @@ H5I_find_id(hid_t id)
/* Set the return value */
ret_value = id_ptr;
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_find_id() */
diff --git a/src/H5L.c b/src/H5L.c
index 368272b..0de2e10 100644
--- a/src/H5L.c
+++ b/src/H5L.c
@@ -82,6 +82,7 @@ typedef struct {
const char *dst_name; /* Destination name for moving object */
H5T_cset_t cset; /* Char set for new name */
H5G_loc_t *dst_loc; /* Destination location for moving object */
+ unsigned dst_target_flags; /* Target flags for destination object */
hbool_t copy; /* TRUE if this is a copy operation */
hid_t lapl_id; /* LAPL to use in callback */
hid_t dxpl_id; /* DXPL to use in callback */
@@ -285,6 +286,9 @@ H5L_term_interface(void)
H5L_table_g = (H5L_class_t *)H5MM_xfree(H5L_table_g);
H5L_table_used_g = H5L_table_alloc_g = 0;
+ /* Mark the interface as uninitialized */
+ H5_interface_initialize_g = 0;
+
FUNC_LEAVE_NOAPI(n)
} /* H5L_term_interface() */
@@ -557,6 +561,8 @@ H5Lcreate_ud(hid_t link_loc_id, const char *link_name, H5L_type_t link_type,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
if(!link_name || !*link_name)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no link name specified")
+ if(link_type < H5L_TYPE_UD_MIN || link_type > H5L_TYPE_MAX)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid link class")
/* Create external link */
if(H5L_create_ud(&link_loc, link_name, udata, udata_size, link_type, lcpl_id, lapl_id, H5AC_dxpl_id) < 0)
@@ -2528,7 +2534,8 @@ H5L_move_cb(H5G_loc_t *grp_loc/*in*/, const char *name, const H5O_link_t *lnk,
orig_name = H5MM_xstrdup(name);
/* Insert the link into its new location */
- if(H5G_traverse(udata->dst_loc, udata->dst_name, H5G_TARGET_NORMAL, H5L_move_dest_cb, &udata_out, udata->lapl_id, udata->dxpl_id) < 0)
+ if(H5G_traverse(udata->dst_loc, udata->dst_name, udata->dst_target_flags,
+ H5L_move_dest_cb, &udata_out, udata->lapl_id, udata->dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to follow symbolic link")
/* If this is a move and not a copy operation, change the object's name and remove the old link */
@@ -2614,7 +2621,7 @@ H5L_move(H5G_loc_t *src_loc, const char *src_name, H5G_loc_t *dst_loc,
const char *dst_name, hbool_t copy_flag, hid_t lcpl_id, hid_t lapl_id,
hid_t dxpl_id)
{
- unsigned target_flags = H5G_TARGET_MOUNT|H5G_TARGET_SLINK|H5G_TARGET_UDLINK;
+ unsigned dst_target_flags = H5G_TARGET_NORMAL;
H5T_cset_t char_encoding = H5F_DEFAULT_CSET; /* Character encoding for link */
H5P_genplist_t* lc_plist; /* Link creation property list */
H5P_genplist_t* la_plist; /* Link access property list */
@@ -2641,8 +2648,9 @@ H5L_move(H5G_loc_t *src_loc, const char *src_name, H5G_loc_t *dst_loc,
if(H5P_get(lc_plist, H5L_CRT_INTERMEDIATE_GROUP_NAME, &crt_intmd_group) < 0)
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get property value for creating missing groups")
+ /* Set target flags for source and destination */
if(crt_intmd_group > 0)
- target_flags |= H5G_CRT_INTMD_GROUP;
+ dst_target_flags |= H5G_CRT_INTMD_GROUP;
/* Get character encoding property */
if(H5P_get(lc_plist, H5P_STRCRT_CHAR_ENCODING_NAME, &char_encoding) < 0)
@@ -2664,13 +2672,15 @@ H5L_move(H5G_loc_t *src_loc, const char *src_name, H5G_loc_t *dst_loc,
/* Set up user data */
udata.dst_loc = dst_loc;
udata.dst_name= dst_name;
+ udata.dst_target_flags = dst_target_flags;
udata.cset = char_encoding;
udata.copy = copy_flag;
udata.lapl_id = lapl_copy;
udata.dxpl_id = dxpl_id;
/* Do the move */
- if(H5G_traverse(src_loc, src_name, target_flags, H5L_move_cb, &udata, lapl_id, dxpl_id) < 0)
+ if(H5G_traverse(src_loc, src_name, H5G_TARGET_MOUNT | H5G_TARGET_SLINK | H5G_TARGET_UDLINK,
+ H5L_move_cb, &udata, lapl_id, dxpl_id) < 0)
HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, FAIL, "unable to find link")
done:
diff --git a/src/H5O.c b/src/H5O.c
index 9b9d0ef..85fda74 100644
--- a/src/H5O.c
+++ b/src/H5O.c
@@ -2879,7 +2879,7 @@ H5O_visit(hid_t loc_id, const char *obj_name, H5_index_t idx_type,
udata.op_data = op_data;
/* Create skip list to store visited object information */
- if((udata.visited = H5SL_create(H5SL_TYPE_OBJ, 0.5, (size_t)16)) == NULL)
+ if((udata.visited = H5SL_create(H5SL_TYPE_OBJ)) == NULL)
HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create skip list for visited objects")
/* If its ref count is > 1, we add it to the list of visited objects */
diff --git a/src/H5Ocopy.c b/src/H5Ocopy.c
index 7b76f3d..2926c6b 100644
--- a/src/H5Ocopy.c
+++ b/src/H5Ocopy.c
@@ -913,7 +913,7 @@ H5O_copy_header(const H5O_loc_t *oloc_src, H5O_loc_t *oloc_dst /*out */,
cpy_info.preserve_null = TRUE;
/* Create a skip list to keep track of which objects are copied */
- if((cpy_info.map_list = H5SL_create(H5SL_TYPE_HADDR, 0.5, (size_t)16)) == NULL)
+ if((cpy_info.map_list = H5SL_create(H5SL_TYPE_HADDR)) == NULL)
HGOTO_ERROR(H5E_SLIST, H5E_CANTCREATE, FAIL, "cannot make skip list")
/* copy the object from the source file to the destination file */
diff --git a/src/H5Opline.c b/src/H5Opline.c
index 20a9d26..070ab87 100644
--- a/src/H5Opline.c
+++ b/src/H5Opline.c
@@ -273,7 +273,7 @@ H5O_pline_encode(H5F_t UNUSED *f, uint8_t *p/*out*/, const void *mesg)
name = NULL;
} /* end if */
else {
- H5Z_class_t *cls; /* Filter class */
+ H5Z_class2_t *cls; /* Filter class */
/*
* Get the filter name. If the pipeline message has a name in it then
@@ -453,7 +453,7 @@ H5O_pline_size(const H5F_t UNUSED *f, const void *mesg)
if(pline->version > H5O_PLINE_VERSION_1 && pline->filter[i].id < H5Z_FILTER_RESERVED)
name_len = 0;
else {
- H5Z_class_t *cls; /* Filter class */
+ H5Z_class2_t *cls; /* Filter class */
/* Get the name of the filter, same as done with H5O_pline_encode() */
if(NULL == (name = pline->filter[i].name) && (cls = H5Z_find(pline->filter[i].id)))
diff --git a/src/H5Pdapl.c b/src/H5Pdapl.c
index a4d036d..db66366 100644
--- a/src/H5Pdapl.c
+++ b/src/H5Pdapl.c
@@ -154,7 +154,7 @@ done:
* property list. Each of thhese values can be individually unset
* (or not set at all) by passing the macros:
* H5D_CHUNK_CACHE_NCHUNKS_DEFAULT,
- * H5D_CHUNK_CACHE_NBYTES_DEFAULT, and/or
+ * H5D_CHUNK_CACHE_NSLOTS_DEFAULT, and/or
* H5D_CHUNK_CACHE_W0_DEFAULT
* as appropriate.
*
diff --git a/src/H5Pdcpl.c b/src/H5Pdcpl.c
index b2bd71d..853e45d 100644
--- a/src/H5Pdcpl.c
+++ b/src/H5Pdcpl.c
@@ -1574,7 +1574,7 @@ H5P_get_filter(const H5Z_filter_info_t *filter, unsigned int *flags/*out*/,
/* If there's no name on the filter, use the class's filter name */
if(!s) {
- H5Z_class_t *cls = H5Z_find(filter->id);
+ H5Z_class2_t *cls = H5Z_find(filter->id);
if(cls)
s = cls->name;
diff --git a/src/H5Pint.c b/src/H5Pint.c
index 799535f..56f1929 100644
--- a/src/H5Pint.c
+++ b/src/H5Pint.c
@@ -42,8 +42,6 @@
/* Local Macros */
/****************/
-#define H5P_DEFAULT_SKIPLIST_HEIGHT 8
-
/******************/
/* Local Typedefs */
@@ -652,11 +650,11 @@ H5P_copy_plist(H5P_genplist_t *old_plist, hbool_t app_ref)
new_plist->class_init = 0; /* Initially, wait until the class callback finishes to set */
/* Initialize the skip list to hold the changed properties */
- if((new_plist->props = H5SL_create(H5SL_TYPE_STR, 0.5, (size_t)H5P_DEFAULT_SKIPLIST_HEIGHT)) == NULL)
+ if((new_plist->props = H5SL_create(H5SL_TYPE_STR)) == NULL)
HGOTO_ERROR(H5E_PLIST,H5E_CANTCREATE,FAIL,"can't create skip list for changed properties");
/* Create the skip list for deleted properties */
- if((new_plist->del = H5SL_create(H5SL_TYPE_STR, 0.5, (size_t)H5P_DEFAULT_SKIPLIST_HEIGHT)) == NULL)
+ if((new_plist->del = H5SL_create(H5SL_TYPE_STR)) == NULL)
HGOTO_ERROR(H5E_PLIST,H5E_CANTCREATE,FAIL,"can't create skip list for deleted properties");
/* Create the skip list to hold names of properties already seen
@@ -664,7 +662,7 @@ H5P_copy_plist(H5P_genplist_t *old_plist, hbool_t app_ref)
* 'create' callback called, if a property in the class hierarchy has
* already been seen)
*/
- if((seen = H5SL_create(H5SL_TYPE_STR, 0.5, (size_t)H5P_DEFAULT_SKIPLIST_HEIGHT))== NULL)
+ if((seen = H5SL_create(H5SL_TYPE_STR))== NULL)
HGOTO_ERROR(H5E_PLIST,H5E_CANTCREATE,FAIL,"can't create skip list for seen properties");
nseen = 0;
@@ -1462,7 +1460,7 @@ H5P_create_class(H5P_genclass_t *par_class, const char *name, unsigned internal,
pclass->revision = H5P_GET_NEXT_REV; /* Get a revision number for the class */
/* Create the skip list for properties */
- if((pclass->props = H5SL_create(H5SL_TYPE_STR, 0.5, (size_t)H5P_DEFAULT_SKIPLIST_HEIGHT)) == NULL)
+ if((pclass->props = H5SL_create(H5SL_TYPE_STR)) == NULL)
HGOTO_ERROR(H5E_PLIST,H5E_CANTCREATE,NULL,"can't create skip list for properties");
/* Set callback functions and pass-along data */
@@ -1544,11 +1542,11 @@ H5P_create(H5P_genclass_t *pclass)
plist->class_init = 0; /* Initially, wait until the class callback finishes to set */
/* Create the skip list for changed properties */
- if((plist->props = H5SL_create(H5SL_TYPE_STR, 0.5, (size_t)H5P_DEFAULT_SKIPLIST_HEIGHT)) == NULL)
+ if((plist->props = H5SL_create(H5SL_TYPE_STR)) == NULL)
HGOTO_ERROR(H5E_PLIST,H5E_CANTCREATE,NULL,"can't create skip list for changed properties");
/* Create the skip list for deleted properties */
- if((plist->del = H5SL_create(H5SL_TYPE_STR, 0.5, (size_t)H5P_DEFAULT_SKIPLIST_HEIGHT)) == NULL)
+ if((plist->del = H5SL_create(H5SL_TYPE_STR)) == NULL)
HGOTO_ERROR(H5E_PLIST,H5E_CANTCREATE,NULL,"can't create skip list for deleted properties");
/* Create the skip list to hold names of properties already seen
@@ -1556,7 +1554,7 @@ H5P_create(H5P_genclass_t *pclass)
* 'create' callback called, if a property in the class hierarchy has
* already been seen)
*/
- if((seen = H5SL_create(H5SL_TYPE_STR, 0.5, (size_t)H5P_DEFAULT_SKIPLIST_HEIGHT)) == NULL)
+ if((seen = H5SL_create(H5SL_TYPE_STR)) == NULL)
HGOTO_ERROR(H5E_PLIST,H5E_CANTCREATE,NULL,"can't create skip list for seen properties");
/*
@@ -3147,7 +3145,7 @@ H5P_iterate_plist(hid_t plist_id, int *idx, H5P_iterate_t iter_func, void *iter_
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list");
/* Create the skip list to hold names of properties already seen */
- if((seen = H5SL_create(H5SL_TYPE_STR, 0.5, (size_t)H5P_DEFAULT_SKIPLIST_HEIGHT)) == NULL)
+ if((seen = H5SL_create(H5SL_TYPE_STR)) == NULL)
HGOTO_ERROR(H5E_PLIST,H5E_CANTCREATE,FAIL,"can't create skip list for seen properties");
/* Walk through the changed properties in the list */
@@ -4071,7 +4069,7 @@ H5P_close(void *_plist)
* 'close' callback called, if a property in the class hierarchy has
* already been seen)
*/
- if((seen = H5SL_create(H5SL_TYPE_STR, 0.5, (size_t)H5P_DEFAULT_SKIPLIST_HEIGHT)) == NULL)
+ if((seen = H5SL_create(H5SL_TYPE_STR)) == NULL)
HGOTO_ERROR(H5E_PLIST,H5E_CANTCREATE,FAIL,"can't create skip list for seen properties");
nseen = 0;
diff --git a/src/H5SL.c b/src/H5SL.c
index fe810d1..31e81c2 100644
--- a/src/H5SL.c
+++ b/src/H5SL.c
@@ -16,17 +16,34 @@
/*
* Purpose: Provides a skip list abstract data type.
*
+ * (See "Deterministic Skip Lists" by Munro, Papadakis & Sedgewick)
+ *
+ * (Implementation changed to a deterministic skip list from a
+ * probabilistic one. This implementation uses a 1-2-3 skip list
+ * using arrays, as described by Munro, Papadakis & Sedgewick.
+ *
+ * Arrays are allocated using a free list factory for each size
+ * that is a power of two. Factories are created as soon as they
+ * are needed, and are never destroyed until the package is shut
+ * down. There is no longer a maximum level or "p" value.
+ * -NAF 2008/11/05)
+ *
* (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)
+ * Cookbook" by William Pugh
+ * -Removed as our implementation of this was useless for a 1-2-3
+ * skip list. The implementation in that document hurts
+ * performance, at least for integer keys. -NAF)
*
* (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)
+ * containing the forward pointer -QAK
+ * -No longer uses update vector, as insertions/deletions are now
+ * always at level 0. -NAF)
*
* (Note: This implementation does not have the information for
* implementing the "Linear List Operations" (like insert/delete/
@@ -36,9 +53,6 @@
* (This implementation has an additional backward pointer, which
* allows the list to be iterated in reverse)
*
- * (We should also look into "Deterministic Skip Lists" (see
- * paper by Munro, Papadakis & Sedgewick))
- *
* (There's also an article on "Alternating Skip Lists", which
* are similar to deterministic skip lists, in the August 2000
* issue of Dr. Dobb's Journal)
@@ -54,61 +68,28 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5SLprivate.h" /* Skip list routines */
+#include "H5MMprivate.h" /* Memory management */
/* Local Macros */
-/* Define the code template for insertions for the "OP" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_INSERT_FOUND(SLIST, X, UPDATE, I) \
- HGOTO_ERROR(H5E_SLIST, H5E_CANTINSERT, NULL, "can't insert duplicate key")
-
-/* Define the code template for removals for the "OP" in the H5SL_LOCATE macro */
-/* (NOTE: the code in H5SL_remove_first() is largely the same, fix bugs in both places) */
-#define H5SL_LOCATE_REMOVE_FOUND(SLIST,X,UPDATE,I) \
- void *tmp; \
- \
- for(I=0; I<=(int)SLIST->curr_level; I++) { \
- if(*UPDATE[I]!=X) \
- break; \
- *UPDATE[I]=X->forward[I]; \
- } /* end for */ \
- if(SLIST->last==X) \
- SLIST->last=X->backward; \
- else \
- X->forward[0]->backward=X->backward; \
- tmp=X->item; \
- H5FL_ARR_FREE(H5SL_node_ptr_t,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_LOCATE macro */
-#define H5SL_LOCATE_SEARCH_FOUND(SLIST, X, UPDATE, I) \
+#define H5SL_LOCATE_SEARCH_FOUND(SLIST, X, I) \
HGOTO_DONE(X->item);
/* Define the code template for finds for the "OP" in the H5SL_LOCATE macro */
-#define H5SL_LOCATE_FIND_FOUND(SLIST, X, UPDATE, I) \
+#define H5SL_LOCATE_FIND_FOUND(SLIST, X, I) \
HGOTO_DONE(X);
-/* Define a code template for "OP"s that update the "update" vector for the H5SL_LOCATE macro */
-#define H5SL_LOCATE_INSERT_UPDATE(X, UPDATE, I) \
- UPDATE[I] = &X->forward[I];
-#define H5SL_LOCATE_REMOVE_UPDATE(X, UPDATE, I) \
- UPDATE[I] = &X->forward[I];
-
-/* Define a code template for "OP"s that _DON'T_ update the "update" vector for the H5SL_LOCATE macro */
-#define H5SL_LOCATE_SEARCH_UPDATE(X, UPDATE, I)
-#define H5SL_LOCATE_FIND_UPDATE(X, UPDATE, I)
-
-
/* Define a code template for comparing scalar keys for the "CMP" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_SCALAR_CMP(TYPE, PNODE, PKEY, HASHVAL) \
(*(TYPE *)((PNODE)->key) < *(TYPE *)PKEY)
/* Define a code template for comparing string keys for the "CMP" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_STRING_CMP(TYPE, PNODE, PKEY, HASHVAL) \
- (((PNODE)->hashval == HASHVAL) ? (HDstrcmp((PNODE)->key, PKEY) < 0) : ((PNODE)->hashval < HASHVAL))
+ (((PNODE)->hashval == HASHVAL) ? \
+ (HDstrcmp((const char *)(PNODE)->key, (const char *)PKEY) < 0) : \
+ ((PNODE)->hashval < HASHVAL))
/* Define a code template for comparing H5_obj_t keys for the "CMP" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_OBJ_CMP(TYPE, PNODE, PKEY, HASHVAL) \
@@ -121,7 +102,7 @@
/* Define a code template for comparing string keys for the "EQ" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_STRING_EQ(TYPE, PNODE, PKEY, HASHVAL) \
- (((PNODE)->hashval == HASHVAL) && (HDstrcmp(((PNODE)->key), PKEY) == 0))
+ (((PNODE)->hashval == HASHVAL) && (HDstrcmp((const char *)(PNODE)->key, (const char *)PKEY) == 0))
/* Define a code template for comparing H5_obj_t keys for the "EQ" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_OBJ_EQ(TYPE, PNODE, PKEY, HASHVAL) \
@@ -133,50 +114,358 @@
/* Define a code template for initializing the hash value for string keys for the "HASHINIT" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_STRING_HASHINIT(KEY, HASHVAL) \
- HASHVAL = H5_hash_string(KEY);
+ HASHVAL = H5_hash_string((const char *)KEY);
/* Define a code template for initializing the hash value for H5_obj_t keys for the "HASHINIT" in the H5SL_LOCATE macro */
#define H5SL_LOCATE_OBJ_HASHINIT(KEY, HASHVAL)
/* Macro used to find node for operation */
-#define H5SL_LOCATE(OP, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
+#define H5SL_LOCATE(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \
{ \
- H5SL_node_t *_checked; /* Pointer to last node checked */ \
int _i; /* Local index variable */ \
+ unsigned _count; /* Num nodes searched at this height */ \
\
- _checked = NULL; \
H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \
for(_i = (int)SLIST->curr_level; _i >= 0; _i--) { \
- if(X->forward[_i] != _checked) { \
- while(X->forward[_i] && H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, X->forward[_i], KEY, HASHVAL) ) \
- X = X->forward[_i]; \
- _checked = X->forward[_i]; \
- } /* end if */ \
- H5_GLUE3(H5SL_LOCATE_,OP,_UPDATE)(X, UPDATE, _i) \
+ _count = 0; \
+ while(_count < 3 && X->forward[_i] && \
+ H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, X->forward[_i], KEY, HASHVAL) ) { \
+ X = X->forward[_i]; \
+ _count++; \
+ } /* end while */ \
} /* end for */ \
X = X->forward[0]; \
if(X != NULL && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(TYPE, X, KEY, HASHVAL) ) { \
/* What to do when a node is found */ \
- H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST, X, UPDATE, _i) \
+ H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST, X, _i) \
} /* end if */ \
}
-/* Macro used to insert node */
-#define H5SL_INSERT(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
- H5SL_LOCATE(INSERT, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL)
+
+/* Macro used to grow a node by 1. Does not update pointers. LVL is the current
+ * level of X. Does not update LVL but does update X->lvl. */
+#define H5SL_GROW(X, LVL) \
+{ \
+ /* Check if we need to increase allocation of forward pointers */ \
+ if(LVL + 1 >= 1u << X->log_nalloc) { \
+ H5SL_node_t **_tmp; \
+ HDassert(LVL + 1 == 1u << X->log_nalloc); \
+ /* Double the amount of allocated space */ \
+ X->log_nalloc++; \
+ \
+ /* Check if we need to create a new factory */ \
+ if(X->log_nalloc >= H5SL_fac_nused_g) { \
+ HDassert(X->log_nalloc == H5SL_fac_nused_g); \
+ \
+ /* Check if we need to allocate space for the factory pointer*/ \
+ if(H5SL_fac_nused_g >= H5SL_fac_nalloc_g) { \
+ HDassert(H5SL_fac_nused_g == H5SL_fac_nalloc_g); \
+ /* Double the size of the array of factory pointers */ \
+ H5SL_fac_nalloc_g *= 2; \
+ H5SL_fac_g = (H5FL_fac_head_t **)H5MM_realloc((void *)H5SL_fac_g, \
+ H5SL_fac_nalloc_g * sizeof(H5FL_fac_head_t *)); \
+ } /* end if */ \
+ \
+ /* Create the new factory */ \
+ H5SL_fac_g[H5SL_fac_nused_g] = H5FL_fac_init((1u << H5SL_fac_nused_g) * sizeof(H5SL_node_t *)); \
+ H5SL_fac_nused_g++; \
+ } /* end if */ \
+ \
+ /* Allocate space for new forward pointers */ \
+ if(NULL == (_tmp = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[X->log_nalloc]))) \
+ HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed") \
+ HDmemcpy((void *)_tmp, (const void *)X->forward, (LVL + 1) * sizeof(H5SL_node_t *)); \
+ (void)H5FL_FAC_FREE(H5SL_fac_g[X->log_nalloc-1], (void *)X->forward); \
+ X->forward = _tmp; \
+ } /* end if */ \
+ \
+ X->level++; \
+}
+
+
+/* Macro used to shrink a node by 1. Does not update pointers. LVL is the
+ * current level of X. Does not update LVL but does update X->level. */
+#define H5SL_SHRINK(X, LVL) \
+{ \
+ /* Check if we can reduce the allocation of forward pointers */ \
+ if(LVL <= 1u << (X->log_nalloc - 1)) { \
+ H5SL_node_t **_tmp; \
+ HDassert(LVL == 1u << (X->log_nalloc - 1)); \
+ X->log_nalloc--; \
+ \
+ /* Allocate space for new forward pointers */ \
+ if(NULL == (_tmp = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[X->log_nalloc]))) \
+ HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed") \
+ HDmemcpy((void *)_tmp, (const void *)X->forward, (LVL) * sizeof(H5SL_node_t *)); \
+ (void)H5FL_FAC_FREE(H5SL_fac_g[X->log_nalloc+1], (void *)X->forward); \
+ X->forward = _tmp; \
+ } /* end if */ \
+ \
+ X->level--; \
+}
+
+
+/* Macro used to grow the level of a node by 1, with appropriate changes to the
+ * head node if necessary. PREV is the previous node of the height that X is to
+ * grow to. */
+#define H5SL_PROMOTE(SLIST, X, PREV) \
+{ \
+ size_t _lvl = X->level; \
+ \
+ H5SL_GROW(X, _lvl); \
+ \
+ if(_lvl == (size_t) SLIST->curr_level) { \
+ HDassert(PREV == SLIST->header); \
+ /* Grow the head */ \
+ H5SL_GROW(PREV, _lvl); \
+ SLIST->curr_level++; \
+ X->forward[_lvl+1] = NULL; \
+ } else { \
+ HDassert(_lvl < (size_t) SLIST->curr_level); \
+ X->forward[_lvl+1] = PREV->forward[_lvl+1]; \
+ } /* end else */ \
+ PREV->forward[_lvl+1] = X; \
+}
+
+
+/* Macro used to reduce the level of a node by 1. Does not update the head node
+ * "current level". PREV is the previous node of the currrent height of X. */
+#define H5SL_DEMOTE(X, PREV) \
+{ \
+ size_t _lvl = X->level; \
+ \
+ HDassert(PREV->forward[_lvl] == X); \
+ PREV->forward[_lvl] = X->forward[_lvl]; \
+ H5SL_SHRINK(X, _lvl); \
+}
+
+
+/* Macro used to insert node. Does not actually insert the node. After running
+ * this macro, X will contain the node before where the new node should be
+ * inserted (at level 0). */
+#define H5SL_INSERT(CMP, SLIST, X, TYPE, KEY, HASHVAL) \
+{ \
+ H5SL_node_t *_last = X; /* Lowest node in the current gap */ \
+ H5SL_node_t *_next = NULL; /* Highest node in the currect gap */ \
+ H5SL_node_t *_drop; /* Low node of the gap to drop into */ \
+ int _count; /* Number of nodes in the current gap */ \
+ int _i; \
+ \
+ H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \
+ for(_i = (int)SLIST->curr_level; _i >= 0; _i--) { \
+ /* Search for the node to drop into, also count the number of nodes */ \
+ /* of height _i in this gap */ \
+ _drop = NULL; \
+ for(_count = 0; ; _count++) { \
+ /* Terminate if this is the last node in the gap */ \
+ if(X->forward[_i] == _next) { \
+ if(!_drop) \
+ _drop = X; \
+ break; \
+ } /* end if */ \
+ \
+ /* Check if this node is the start of the next gap */ \
+ if(!_drop && !H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, X->forward[_i], KEY, HASHVAL)) \
+ _drop = X; \
+ \
+ /* No need to check the last node in the gap if there are 3, as */ \
+ /* there cannot be a fourth */ \
+ if(_count == 2) { \
+ if(!_drop) \
+ _drop = X->forward[_i]; \
+ _count = 3; \
+ break; \
+ } \
+ X = X->forward[_i]; \
+ } /* end for */ \
+ HDassert(!_drop->forward[_i] || \
+ !H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, _drop->forward[_i], KEY, HASHVAL)); \
+ \
+ /* Promote the middle node if necessary */ \
+ if(_count == 3) { \
+ HDassert(X == _last->forward[_i]->forward[_i]); \
+ H5SL_PROMOTE(SLIST, X, _last) \
+ } \
+ \
+ /* Prepare to drop down */ \
+ X = _last = _drop; \
+ _next = _drop->forward[_i]; \
+ } /* end for */ \
+ \
+ if(_next && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(TYPE, _next, KEY, HASHVAL)) \
+ HGOTO_ERROR(H5E_SLIST, H5E_CANTINSERT, NULL, "can't insert duplicate key") \
+}
+
/* Macro used to remove node */
-#define H5SL_REMOVE(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
- H5SL_LOCATE(REMOVE, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL)
+#define H5SL_REMOVE(CMP, SLIST, X, TYPE, KEY, HASHVAL) \
+{ \
+ H5SL_node_t *_last = X; /* Lowest node in the current gap */ \
+ H5SL_node_t *_llast = X; /* Lowest node in the previous gap */ \
+ H5SL_node_t *_next = NULL; /* Highest node in the currect gap */ \
+ H5SL_node_t *_drop = NULL; /* Low node of the gap to drop into */ \
+ H5SL_node_t *_ldrop = NULL; /* Low node of gap before the one to drop into */ \
+ H5SL_node_t *_head = SLIST->header; /* Head of the skip list */ \
+ int _count; /* Number of nodes in the current gap */ \
+ int _i = (int)SLIST->curr_level; \
+ \
+ if(_i < 0) \
+ HGOTO_DONE(NULL); \
+ \
+ H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \
+ \
+ /* Find the gap to drop in to at the highest level */ \
+ while(X && (!X->key || H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, X, KEY, HASHVAL))) { \
+ _llast = _last; \
+ _last = X; \
+ X = X->forward[_i]; \
+ } \
+ _next = X; \
+ \
+ /* Main loop */ \
+ for(_i--; _i >= 0; _i--) { \
+ /* Search for the node to drop into, also count the number of nodes */ \
+ /* of height _i in this gap and keep track of of the node before */ \
+ /* the one to drop into (_ldrop will become _llast, _drop will */ \
+ /* become _last). */ \
+ X = _ldrop = _last; \
+ _drop = NULL; \
+ for(_count = 0; ; _count++) { \
+ /* Terminate if this is the last node in the gap */ \
+ if(X->forward[_i] == _next) { \
+ if(!_drop) \
+ _drop = X; \
+ break; \
+ } /* end if */ \
+ \
+ /* If we have already found the node to drop into and there is */ \
+ /* more than one node in this gap, we can stop searching */ \
+ if(_drop) { \
+ HDassert(_count >= 1); \
+ _count = 2; \
+ break; \
+ } else { /* !_drop */ \
+ /* Check if this node is the start of the next gap */ \
+ if (!H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, X->forward[_i], KEY, HASHVAL)) { \
+ _drop = X; \
+ /* Again check if we can stop searching */ \
+ if(_count) { \
+ _count = 2; \
+ break; \
+ } /* end if */ \
+ } /* end if */ \
+ else \
+ _ldrop = X; \
+ } /* end else */ \
+ \
+ /* No need to check the last node in the gap if there are 3, as */ \
+ /* there cannot be a fourth */ \
+ if(_count == 2) { \
+ if(!_drop) \
+ _drop = X->forward[_i]; \
+ break; \
+ } /* end if */ \
+ X = X->forward[_i]; \
+ } /* end for */ \
+ HDassert(_count >= 1 && _count <= 3); \
+ HDassert(!_drop->forward[_i] || \
+ !H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(TYPE, _drop->forward[_i], KEY, HASHVAL)); \
+ \
+ /* Check if we need to adjust node heights */ \
+ if(_count == 1) { \
+ /* Check if we are in the first gap */ \
+ if(_llast == _last) { \
+ /* We are in the first gap, count the number of nodes of */ \
+ /* height _i in the next gap. We need only check one node */ \
+ /* to see if we should promote the first node in the next */ \
+ /* gap */ \
+ _llast = _next->forward[_i+1]; \
+ \
+ /* Demote the separator node */ \
+ H5SL_DEMOTE(_next, _last) \
+ \
+ /* If there are 2 or more nodes, promote the first */ \
+ if(_next->forward[_i]->forward[_i] != _llast) { \
+ X = _next->forward[_i]; \
+ H5SL_PROMOTE(SLIST, X, _last) \
+ } else if(!_head->forward[_i+1]) { \
+ /* shrink the header */ \
+ HDassert(_i == SLIST->curr_level - 1); \
+ HDassert((size_t) SLIST->curr_level == _head->level); \
+ \
+ H5SL_SHRINK(_head, (size_t) (_i+1)) \
+ SLIST->curr_level--; \
+ } /* end else */ \
+ } else { \
+ /* We are not in the first gap, count the number of nodes */ \
+ /* of height _i in the previous gap. Note we "look ahead" */ \
+ /* in this loop so X has the value of the last node in the */ \
+ /* previous gap. */ \
+ X = _llast->forward[_i]; \
+ for(_count = 1; _count < 3 && X->forward[_i] != _last; _count++) \
+ X = X->forward[_i]; \
+ HDassert(X->forward[_i] == _last); \
+ \
+ /* Demote the separator node */ \
+ H5SL_DEMOTE(_last, _llast) \
+ \
+ /* If there are 2 or more nodes, promote the last */ \
+ if(_count >= 2) \
+ H5SL_PROMOTE(SLIST, X, _llast) \
+ else if(!_head->forward[_i+1]) { \
+ /* shrink the header */ \
+ HDassert(_i == SLIST->curr_level - 1); \
+ HDassert((size_t) SLIST->curr_level == _head->level); \
+ \
+ H5SL_SHRINK(_head, (size_t) (_i+1)) \
+ SLIST->curr_level--; \
+ } /* end else */ \
+ } /* end else */ \
+ } /* end if */ \
+ \
+ /* Prepare to drop down */ \
+ _llast = _ldrop; \
+ _last = _drop; \
+ _next = _drop->forward[_i]; \
+ } /* end for */ \
+ \
+ /* Check if we've found the node */ \
+ if(_next && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(TYPE, _next, KEY, HASHVAL)) { \
+ void *tmp = _next->item; \
+ X = _next; \
+ \
+ /* If the node has a height > 0, swap it with its (lower) neighbor */ \
+ if(X->level) { \
+ X = X->backward; \
+ _next->key = X->key; \
+ _next->item = X->item; \
+ _next->hashval = X->hashval; \
+ } /* end if */ \
+ HDassert(!X->level); \
+ \
+ /* Remove the node */ \
+ X->backward->forward[0] = X->forward[0]; \
+ if(SLIST->last == X) \
+ SLIST->last = X->backward; \
+ else \
+ X->forward[0]->backward = X->backward; \
+ SLIST->nobjs--; \
+ (void)H5FL_FAC_FREE(H5SL_fac_g[0], X->forward); \
+ (void)H5FL_FREE(H5SL_node_t, X); \
+ \
+ HGOTO_DONE(tmp); \
+ } /* end if */ \
+}
+
/* Macro used to search for node */
-#define H5SL_SEARCH(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
- H5SL_LOCATE(SEARCH, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL)
+#define H5SL_SEARCH(CMP, SLIST, X, TYPE, KEY, HASHVAL) \
+ H5SL_LOCATE(SEARCH, CMP, SLIST, X, TYPE, KEY, HASHVAL)
/* Macro used to find a node */
-#define H5SL_FIND(CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL) \
- H5SL_LOCATE(FIND, CMP, SLIST, X, UPDATE, TYPE, KEY, HASHVAL)
+#define H5SL_FIND(CMP, SLIST, X, TYPE, KEY, HASHVAL) \
+ H5SL_LOCATE(FIND, CMP, SLIST, X, TYPE, KEY, HASHVAL)
/* Private typedefs & structs */
@@ -186,6 +475,7 @@ struct H5SL_node_t {
const void *key; /* Pointer to node's key */
void *item; /* Pointer to node's item */
size_t level; /* The level of this node */
+ size_t log_nalloc; /* log2(Number of slots allocated in forward) */
uint32_t hashval; /* Hash value for key (only for strings, currently) */
struct H5SL_node_t **forward; /* Array of forward pointers from this node */
struct H5SL_node_t *backward; /* Backward pointer from this node */
@@ -195,9 +485,6 @@ struct H5SL_node_t {
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) */
- int p1; /* Probability converted into appropriate value for random # generator on this machine */
- size_t max_level; /* Maximum number of levels */
/* Dynamic values for each list */
int curr_level; /* Current top level used in list */
@@ -207,8 +494,7 @@ struct H5SL_t {
};
/* Static functions */
-static size_t H5SL_random_level(int p1, size_t max_level);
-static H5SL_node_t * H5SL_new_node(size_t lvl, void *item, const void *key, uint32_t hashval);
+static H5SL_node_t * H5SL_new_node(void *item, const void *key, uint32_t hashval);
static H5SL_node_t *H5SL_insert_common(H5SL_t *slist, void *item, const void *key);
static herr_t H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data);
static herr_t H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data);
@@ -216,9 +502,13 @@ static herr_t H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data
/* Declare a free list to manage the H5SL_t struct */
H5FL_DEFINE_STATIC(H5SL_t);
-/* Declare a "base + array" list to manage the H5SL_node_t struct */
-typedef H5SL_node_t *H5SL_node_ptr_t;
-H5FL_BARR_DEFINE_STATIC(H5SL_node_t,H5SL_node_ptr_t,H5SL_LEVEL_MAX);
+/* Declare a free list to manage the H5SL_node_t struct */
+H5FL_DEFINE_STATIC(H5SL_node_t);
+
+/* Global variables */
+static H5FL_fac_head_t **H5SL_fac_g;
+static size_t H5SL_fac_nused_g;
+static size_t H5SL_fac_nalloc_g;
/*--------------------------------------------------------------------------
@@ -241,13 +531,15 @@ H5FL_BARR_DEFINE_STATIC(H5SL_node_t,H5SL_node_ptr_t,H5SL_LEVEL_MAX);
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);
- HDsrand((unsigned)curr_time);
+ /* Allocate space for array of factories */
+ H5SL_fac_g = (H5FL_fac_head_t **)H5MM_malloc(sizeof(H5FL_fac_head_t *));
+ H5SL_fac_nalloc_g = 1;
+
+ /* Initialize first factory */
+ H5SL_fac_g[0] = H5FL_fac_init(sizeof(H5SL_node_t *));
+ H5SL_fac_nused_g = 1;
FUNC_LEAVE_NOAPI(SUCCEED)
} /* end H5SL_init_interface() */
@@ -255,87 +547,45 @@ H5SL_init_interface(void)
/*--------------------------------------------------------------------------
NAME
- H5SL_random_level
- PURPOSE
- Generate a random level
- USAGE
- size_t H5SL_random_level(p,max_level)
- int p1; 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(int p1, size_t max_level)
-{
- size_t lvl; /* Level generated */
-
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_random_level);
-
- /* Account for starting at zero offset */
- max_level--;
-
- lvl=0;
- while(HDrand()<p1 && lvl < max_level)
- lvl++;
-
- FUNC_LEAVE_NOAPI(lvl);
-} /* end H5SL_random_level() */
-
-
-/*--------------------------------------------------------------------------
- NAME
H5SL_new_node
PURPOSE
- Create a new skip list node
+ Create a new skip list node of level 0
USAGE
- H5SL_node_t *H5SL_new_node(lvl,item,key)
- size_t lvl; IN: Level for node height
+ H5SL_node_t *H5SL_new_node(item,key,hasval)
void *item; IN: Pointer to item info for node
void *key; IN: Pointer to key info for node
+ uint32_t hashval; IN: Hash value 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
+ Create a new skip list node of the height 0, 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, const void *key, uint32_t hashval)
+H5SL_new_node(void *item, const void *key, uint32_t hashval)
{
H5SL_node_t *ret_value; /* New skip list node */
FUNC_ENTER_NOAPI_NOINIT(H5SL_new_node)
/* Allocate the node */
- if(NULL == (ret_value = (H5SL_node_t *)H5FL_ARR_MALLOC(H5SL_node_ptr_t, (lvl + 1))))
+ if(NULL == (ret_value = (H5SL_node_t *)H5FL_MALLOC(H5SL_node_t)))
HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed")
/* Initialize node */
ret_value->key = key;
ret_value->item = item;
- ret_value->level = lvl;
+ ret_value->level = 0;
ret_value->hashval = hashval;
- ret_value->forward = (H5SL_node_t **)((unsigned char *)ret_value + sizeof(H5SL_node_t));
+ if(NULL == (ret_value->forward = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[0])))
+ HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed")
+ ret_value->log_nalloc = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -366,18 +616,16 @@ done:
static H5SL_node_t *
H5SL_insert_common(H5SL_t *slist, void *item, const void *key)
{
- H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */
H5SL_node_t *x; /* Current node to examine */
+ H5SL_node_t *prev; /* Node before the new node */
uint32_t hashval = 0; /* Hash value for key */
- size_t lvl; /* Level of new node */
- int i; /* Local index value */
H5SL_node_t *ret_value; /* Return value */
FUNC_ENTER_NOAPI_NOINIT(H5SL_insert_common);
/* Check args */
- assert(slist);
- assert(key);
+ HDassert(slist);
+ HDassert(key);
/* Check internal consistency */
/* (Pre-condition) */
@@ -387,75 +635,60 @@ H5SL_insert_common(H5SL_t *slist, void *item, const void *key)
/* Work through the forward pointers for a node, finding the node at each
* level that is before the location to insert
*/
- x=slist->header;
+ prev=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_INSERT(SCALAR, slist, x, update, const int, key, -)
+ H5SL_INSERT(SCALAR, slist, prev, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_INSERT(SCALAR, slist, x, update, const haddr_t, key, -)
+ H5SL_INSERT(SCALAR, slist, prev, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_INSERT(STRING, slist, x, update, char *, key, hashval)
+ H5SL_INSERT(STRING, slist, prev, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_INSERT(SCALAR, slist, x, update, const hsize_t, key, -)
+ H5SL_INSERT(SCALAR, slist, prev, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_INSERT(SCALAR, slist, x, update, const unsigned, key, -)
+ H5SL_INSERT(SCALAR, slist, prev, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_INSERT(SCALAR, slist, x, update, const size_t, key, -)
+ H5SL_INSERT(SCALAR, slist, prev, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
- H5SL_INSERT(OBJ, slist, x, update, const H5_obj_t, key, -)
+ H5SL_INSERT(OBJ, slist, prev, const H5_obj_t, key, -)
break;
default:
HDassert(0 && "Unknown skiplist type!");
} /* 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->p1,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];
+ /* 'key' must not have been found in existing list, if we get here */
- /* Increase the maximum level of the list */
- slist->curr_level=(int)lvl;
- } /* end if */
+ if(slist->curr_level < 0)
+ slist->curr_level = 0;
- /* Create new node of proper level */
- if(NULL == (x = H5SL_new_node(lvl, item, key, hashval)))
+ /* Create new node of level 0 */
+ if(NULL == (x = H5SL_new_node(item, key, hashval)))
HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node")
- /* Update the backward links */
- if(*update[0]!=NULL) {
- x->backward=(*update[0])->backward;
- (*update[0])->backward=x;
- } /* end if */
+ /* Update the links */
+ x->backward = prev;
+ x->forward[0] = prev->forward[0];
+ prev->forward[0] = x;
+ if(x->forward[0])
+ x->forward[0]->backward = x;
else {
HDassert(slist->last);
- x->backward=slist->last;
- slist->last=x;
- } /* end else */
-
- /* Link the new node into the existing forward pointers */
- for(i=0; i<=(int)lvl; i++) {
- x->forward[i]=*update[i];
- *update[i]=x;
- } /* end for */
+ slist->last = x;
+ }
/* Increment the number of nodes in the skip list */
slist->nobjs++;
@@ -474,7 +707,7 @@ done:
PURPOSE
Release all nodes from a skip list, optionally calling a 'free' operator
USAGE
- herr_t H5SL_release_common(slist)
+ herr_t H5SL_release_common(slist,op,opdata)
H5SL_t *slist; IN/OUT: Pointer to skip list to release nodes
H5SL_operator_t op; IN: Callback function to free item & key
void *op_data; IN/OUT: Pointer to application data for callback
@@ -496,9 +729,9 @@ herr_t
H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
{
H5SL_node_t *node, *next_node; /* Pointers to skip list nodes */
- size_t u; /* Local index variable */
+ herr_t ret_value = SUCCEED;
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_release_common);
+ FUNC_ENTER_NOAPI_NOINIT(H5SL_release_common);
/* Check args */
assert(slist);
@@ -516,13 +749,18 @@ H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
/* Casting away const OK -QAK */
(void)(op)(node->item,(void *)node->key,op_data);
- H5FL_ARR_FREE(H5SL_node_ptr_t,node);
+ (void)H5FL_FAC_FREE(H5SL_fac_g[node->log_nalloc], node->forward);
+ (void)H5FL_FREE(H5SL_node_t, node);
node=next_node;
} /* end while */
/* Reset the header pointers */
- for(u=0; u<slist->max_level; u++)
- slist->header->forward[u]=NULL;
+ (void)H5FL_FAC_FREE(H5SL_fac_g[slist->header->log_nalloc], slist->header->forward);
+ if(NULL == (slist->header->forward = (H5SL_node_t **) H5FL_FAC_MALLOC(H5SL_fac_g[0])))
+ HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, FAIL, "memory allocation failed")
+ slist->header->forward[0] = NULL;
+ slist->header->log_nalloc = 0;
+ slist->header->level = 0;
/* Reset the last pointer */
slist->last=slist->header;
@@ -531,7 +769,8 @@ H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
slist->curr_level=-1;
slist->nobjs=0;
- FUNC_LEAVE_NOAPI(SUCCEED);
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
} /* end H5SL_release_common() */
@@ -561,7 +800,9 @@ H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
herr_t
H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
{
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_close_common)
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI_NOINIT(H5SL_close_common)
/* Check args */
HDassert(slist);
@@ -570,15 +811,18 @@ H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
/* (Pre-condition) */
/* Free skip list nodes */
- (void)H5SL_release_common(slist, op, op_data); /* always succeeds */
+ if(H5SL_release_common(slist, op, op_data) < 0)
+ HGOTO_ERROR(H5E_SLIST, H5E_CANTFREE, FAIL, "can't release skip list nodes")
/* Release header node */
- H5FL_ARR_FREE(H5SL_node_ptr_t, slist->header);
+ (void)H5FL_FAC_FREE(H5SL_fac_g[slist->header->log_nalloc], slist->header->forward);
+ (void)H5FL_FREE(H5SL_node_t, slist->header);
/* Free skip list object */
(void)H5FL_FREE(H5SL_t, slist);
- FUNC_LEAVE_NOAPI(SUCCEED)
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SL_close_common() */
@@ -588,7 +832,7 @@ H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
PURPOSE
Create a skip list
USAGE
- H5SL_t *H5SL_create(void)
+ H5SL_t *H5SL_create(H5SL_type_t type)
RETURNS
Returns a pointer to a skip list on success, NULL on failure.
@@ -600,18 +844,15 @@ H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
REVISION LOG
--------------------------------------------------------------------------*/
H5SL_t *
-H5SL_create(H5SL_type_t type, double p, size_t max_level)
+H5SL_create(H5SL_type_t type)
{
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_OBJ);
/* Allocate skip list structure */
@@ -620,21 +861,17 @@ H5SL_create(H5SL_type_t type, double p, size_t max_level)
/* Set the static internal fields */
new_slist->type = type;
- new_slist->p = p;
- new_slist->p1 = (int)(p*RAND_MAX);
- 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(NULL == (header = H5SL_new_node((max_level - 1), NULL, NULL, ULONG_MAX)))
+ if(NULL == (header = H5SL_new_node(NULL, NULL, ULONG_MAX)))
HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node")
- /* Initialize header node's forward pointers */
- for(u = 0; u < max_level; u++)
- header->forward[u] = NULL;
+ /* Initialize header node's forward pointer */
+ header->forward[0] = NULL;
/* Initialize header node's backward pointer */
header->backward = NULL;
@@ -803,12 +1040,11 @@ done:
void *
H5SL_remove(H5SL_t *slist, const void *key)
{
- H5SL_node_t **update[H5SL_LEVEL_MAX]; /* 'update' vector */
H5SL_node_t *x; /* Current node to examine */
uint32_t hashval = 0; /* Hash value for key */
void *ret_value = NULL; /* Return value */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_remove)
+ FUNC_ENTER_NOAPI_NOINIT(H5SL_remove)
/* Check args */
HDassert(slist);
@@ -825,31 +1061,31 @@ H5SL_remove(H5SL_t *slist, const void *key)
x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_REMOVE(SCALAR, slist, x, update, const int, key, -)
+ H5SL_REMOVE(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_REMOVE(SCALAR, slist, x, update, const haddr_t, key, -)
+ H5SL_REMOVE(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_REMOVE(STRING, slist, x, update, char *, key, hashval)
+ H5SL_REMOVE(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_REMOVE(SCALAR, slist, x, update, const hsize_t, key, -)
+ H5SL_REMOVE(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_REMOVE(SCALAR, slist, x, update, const unsigned, key, -)
+ H5SL_REMOVE(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_REMOVE(SCALAR, slist, x, update, const size_t, key, -)
+ H5SL_REMOVE(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
- H5SL_REMOVE(OBJ, slist, x, update, const H5_obj_t, key, -)
+ H5SL_REMOVE(OBJ, slist, x, const H5_obj_t, key, -)
break;
default:
@@ -876,8 +1112,6 @@ done:
Remove first element from a skip list.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
- This algorithm is basically the same as the one in the
- H5SL_LOCATE_REMOVE_FOUND macro, fix bugs in both places
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
@@ -885,8 +1119,13 @@ void *
H5SL_remove_first(H5SL_t *slist)
{
void *ret_value = NULL; /* Return value */
+ H5SL_node_t *head = slist->header; /* Skip list header */
+ H5SL_node_t *tmp = slist->header->forward[0]; /* Temporary node pointer */
+ H5SL_node_t *next; /* Next node to search for */
+ size_t level = slist->curr_level; /* Skip list level */
+ size_t i; /* Index */
- FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_remove_first)
+ FUNC_ENTER_NOAPI_NOINIT(H5SL_remove_first)
/* Check args */
HDassert(slist);
@@ -898,39 +1137,62 @@ H5SL_remove_first(H5SL_t *slist)
/* Check for empty list */
if(slist->last != slist->header) {
- H5SL_node_t *x; /* Current node to examine */
- int i; /* Local index value */
- /* Get pointer to first node on the list */
- x = slist->header->forward[0];
-
- /* Patch forward pointers in list header around node to remove */
- for(i = 0; i <= (int)slist->curr_level; i++) {
- if(slist->header->forward[i] != x)
- break;
- slist->header->forward[i] = x->forward[i];
- } /* end for */
+ /* Assign return value */
+ ret_value = tmp->item;
+ HDassert(level == head->level);
+ HDassert(0 == tmp->level);
- /* Update tail/backward pointer */
- if(slist->last == x)
- slist->last = x->backward;
+ /* Remove the first node */
+ head->forward[0] = tmp->forward[0];
+ if(slist->last == tmp)
+ slist->last = head;
else
- x->forward[0]->backward = x->backward;
-
- /* Get the item to return */
- ret_value = x->item;
-
- /* Free the skip list node */
- H5FL_ARR_FREE(H5SL_node_ptr_t, x);
-
- /* Lower the level of the list, if we removed the tallest node */
- while(slist->curr_level > 0 && slist->header->forward[slist->curr_level] == NULL)
- slist->curr_level--;
-
- /* Decrement the # of objects in the list */
+ tmp->forward[0]->backward = head;
slist->nobjs--;
+ /* Free memory */
+ (void)H5FL_FAC_FREE(H5SL_fac_g[0], tmp->forward);
+ (void)H5FL_FREE(H5SL_node_t, tmp);
+
+ /* Reshape the skip list as necessary to maintain 1-2-3 condition */
+ for(i=0; i < level; i++) {
+ next = head->forward[i+1];
+ HDassert(next);
+
+ /* Check if head->forward[i] == head->forward[i+1] (illegal) */
+ if(head->forward[i] == next) {
+ tmp = next;
+ next = next->forward[i+1];
+
+ HDassert(tmp->level == i+1);
+
+ /* Demote head->forward[i] */
+ H5SL_DEMOTE(tmp, head)
+
+ /* Check if we need to promote the following node to maintain
+ * 1-2-3 condition */
+ if(tmp->forward[i]->forward[i] != next) {
+ HDassert(tmp->forward[i]->forward[i]->forward[i] == next ||
+ tmp->forward[i]->forward[i]->forward[i]->forward[i] == next);
+ tmp = tmp->forward[i];
+ H5SL_PROMOTE(slist, tmp, head);
+ /* In this case, since there is a node of height = i+1 here
+ * now (tmp), we know the skip list must be valid and can
+ * break */
+ break;
+ } else if(!head->forward[i+1]) {
+ /* We just shrunk the largest node, shrink the header */
+ HDassert(i == level - 1);
+
+ H5SL_SHRINK(head, level)
+ slist->curr_level--;
+ } /* end else */
+ } else
+ break;
+ } /* end for */
} /* end if */
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5SL_remove_first() */
@@ -978,31 +1240,31 @@ H5SL_search(H5SL_t *slist, const void *key)
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval)
+ H5SL_SEARCH(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
- H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -)
+ H5SL_SEARCH(OBJ, slist, x, const H5_obj_t, key, -)
break;
default:
@@ -1063,31 +1325,31 @@ H5SL_less(H5SL_t *slist, const void *key)
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval)
+ H5SL_SEARCH(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
- H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -)
+ H5SL_SEARCH(OBJ, slist, x, const H5_obj_t, key, -)
break;
default:
@@ -1161,31 +1423,31 @@ H5SL_greater(H5SL_t *slist, const void *key)
x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_SEARCH(SCALAR, slist, x, -, const int, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_SEARCH(SCALAR, slist, x, -, const haddr_t, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_SEARCH(STRING, slist, x, -, char *, key, hashval)
+ H5SL_SEARCH(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, const hsize_t, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_SEARCH(SCALAR, slist, x, -, const unsigned, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_SEARCH(SCALAR, slist, x, -, const size_t, key, -)
+ H5SL_SEARCH(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
- H5SL_SEARCH(OBJ, slist, x, -, const H5_obj_t, key, -)
+ H5SL_SEARCH(OBJ, slist, x, const H5_obj_t, key, -)
break;
default:
@@ -1249,31 +1511,31 @@ H5SL_find(H5SL_t *slist, const void *key)
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_FIND(SCALAR, slist, x, -, const int, key, -)
+ H5SL_FIND(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -)
+ H5SL_FIND(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_FIND(STRING, slist, x, -, char *, key, hashval)
+ H5SL_FIND(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -)
+ H5SL_FIND(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -)
+ H5SL_FIND(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -)
+ H5SL_FIND(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
- H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -)
+ H5SL_FIND(OBJ, slist, x, const H5_obj_t, key, -)
break;
default:
@@ -1334,31 +1596,31 @@ H5SL_below(H5SL_t *slist, const void *key)
x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_FIND(SCALAR, slist, x, -, const int, key, -)
+ H5SL_FIND(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -)
+ H5SL_FIND(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_FIND(STRING, slist, x, -, char *, key, hashval)
+ H5SL_FIND(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -)
+ H5SL_FIND(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -)
+ H5SL_FIND(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -)
+ H5SL_FIND(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
- H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -)
+ H5SL_FIND(OBJ, slist, x, const H5_obj_t, key, -)
break;
} /* end switch */
@@ -1429,31 +1691,31 @@ H5SL_above(H5SL_t *slist, const void *key)
x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
- H5SL_FIND(SCALAR, slist, x, -, const int, key, -)
+ H5SL_FIND(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
- H5SL_FIND(SCALAR, slist, x, -, const haddr_t, key, -)
+ H5SL_FIND(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
- H5SL_FIND(STRING, slist, x, -, char *, key, hashval)
+ H5SL_FIND(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
- H5SL_FIND(SCALAR, slist, x, -, const hsize_t, key, -)
+ H5SL_FIND(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
- H5SL_FIND(SCALAR, slist, x, -, const unsigned, key, -)
+ H5SL_FIND(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
- H5SL_FIND(SCALAR, slist, x, -, const size_t, key, -)
+ H5SL_FIND(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
- H5SL_FIND(OBJ, slist, x, -, const H5_obj_t, key, -)
+ H5SL_FIND(OBJ, slist, x, const H5_obj_t, key, -)
break;
} /* end switch */
@@ -1868,3 +2130,50 @@ H5SL_close(H5SL_t *slist)
FUNC_LEAVE_NOAPI(SUCCEED);
} /* end H5SL_close() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5SL_term_interface
+ PURPOSE
+ Terminate all the H5FL factories used in this package, and clear memory
+ USAGE
+ int H5SL_term_interface()
+ RETURNS
+ Success: Positive if any action might have caused a change in some
+ other interface; zero otherwise.
+ Failure: Negative
+ DESCRIPTION
+ Release any resources allocated.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Can't report errors...
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+int H5SL_term_interface(void)
+{
+ size_t i;
+ herr_t ret;
+ int n = H5_interface_initialize_g ? 1 : 0;
+
+ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5SL_term_interface)
+
+ if(n) {
+ /* Terminate all the factories */
+ for(i=0; i<H5SL_fac_nused_g; i++) {
+ ret = H5FL_fac_term(H5SL_fac_g[i]);
+ HDassert(ret >= 0);
+ }
+ H5SL_fac_nused_g = 0;
+
+ /* Free the list of factories */
+ H5SL_fac_g = (H5FL_reg_head_t **)H5MM_xfree((void *)H5SL_fac_g);
+ H5SL_fac_nalloc_g = 0;
+
+ /* Mark the interface as uninitialized */
+ H5_interface_initialize_g = 0;
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(n);
+} /* H5SL_term_interface() */
+
diff --git a/src/H5SLprivate.h b/src/H5SLprivate.h
index 27bb4d1..40fbfa9 100644
--- a/src/H5SLprivate.h
+++ b/src/H5SLprivate.h
@@ -53,7 +53,6 @@ typedef enum {
/**********/
/* Macros */
/**********/
-#define H5SL_LEVEL_MAX 32 /* (for now) */
/* Typedef for iteration operations */
typedef herr_t (*H5SL_operator_t)(void *item, void *key,
@@ -62,7 +61,7 @@ typedef herr_t (*H5SL_operator_t)(void *item, void *key,
/********************/
/* Private routines */
/********************/
-H5_DLL H5SL_t *H5SL_create(H5SL_type_t type, double p, size_t max_level);
+H5_DLL H5SL_t *H5SL_create(H5SL_type_t type);
H5_DLL size_t H5SL_count(H5SL_t *slist);
H5_DLL herr_t H5SL_insert(H5SL_t *slist, void *item, const void *key);
H5_DLL H5SL_node_t *H5SL_add(H5SL_t *slist, void *item, const void *key);
@@ -84,6 +83,7 @@ H5_DLL herr_t H5SL_release(H5SL_t *slist);
H5_DLL herr_t H5SL_free(H5SL_t *slist, H5SL_operator_t op, void *op_data);
H5_DLL herr_t H5SL_close(H5SL_t *slist);
H5_DLL herr_t H5SL_destroy(H5SL_t *slist, H5SL_operator_t op, void *op_data);
+H5_DLL int H5SL_term_interface(void);
#endif /* _H5SLprivate_H */
diff --git a/src/H5Tconv.c b/src/H5Tconv.c
index 90b7a21..c621bf4 100644
--- a/src/H5Tconv.c
+++ b/src/H5Tconv.c
@@ -194,7 +194,7 @@
src_id, dst_id, S, D, cb_struct.user_data); \
if(except_ret == H5T_CONV_UNHANDLED) \
/* Let compiler convert if case is ignored by user handler*/ \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
else if(except_ret == H5T_CONV_ABORT) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
/* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
@@ -203,7 +203,7 @@
src_id, dst_id, S, D, cb_struct.user_data); \
if(except_ret == H5T_CONV_UNHANDLED) \
/* Let compiler convert if case is ignored by user handler*/ \
- *((DT*)D) = (D_MIN); \
+ *((DT*)D) = (DT)(D_MIN); \
else if(except_ret == H5T_CONV_ABORT) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
/* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
@@ -212,9 +212,9 @@
}
#define H5T_CONV_Xx_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX) { \
if (*((ST*)S) > (DT)(D_MAX)) { \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
} else if (*((ST*)S) < (DT)(D_MIN)) { \
- *((DT*)D) = (D_MIN); \
+ *((DT*)D) = (DT)(D_MIN); \
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
@@ -225,7 +225,7 @@
src_id, dst_id, S, D, cb_struct.user_data); \
if(except_ret == H5T_CONV_UNHANDLED) \
/* Let compiler convert if case is ignored by user handler*/ \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
else if(except_ret == H5T_CONV_ABORT) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
/* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
@@ -234,7 +234,7 @@
}
#define H5T_CONV_Ux_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX) { \
if (*((ST*)S) > (DT)(D_MAX)) { \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
@@ -270,12 +270,12 @@
}
#define H5T_CONV_uS_CORE(S,D,ST,DT,D_MIN,D_MAX) { \
- if (sizeof(ST)==sizeof(DT) && *((ST*)S) > (D_MAX)) { \
+ if (sizeof(ST)==sizeof(DT) && *((ST*)S) > (DT)(D_MAX)) { \
H5T_conv_ret_t except_ret = (cb_struct.func)(H5T_CONV_EXCEPT_RANGE_HI, \
src_id, dst_id, S, D, cb_struct.user_data); \
if(except_ret == H5T_CONV_UNHANDLED) \
/* Let compiler convert if case is ignored by user handler*/ \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
else if(except_ret == H5T_CONV_ABORT) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
/* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
@@ -319,7 +319,7 @@
src_id, dst_id, S, D, cb_struct.user_data); \
if(except_ret == H5T_CONV_UNHANDLED) \
/* Let compiler convert if case is ignored by user handler*/ \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
else if(except_ret == H5T_CONV_ABORT) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
/* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
@@ -330,7 +330,7 @@
if (*((ST*)S) < 0) { \
*((DT*)D) = 0; \
} else if (sizeof(ST)>sizeof(DT) && *((ST*)S) > (DT)(D_MAX)) { \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
@@ -384,7 +384,7 @@
src_id, dst_id, S, D, cb_struct.user_data); \
if(except_ret == H5T_CONV_UNHANDLED) \
/* Let compiler convert if case is ignored by user handler*/ \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
else if(except_ret == H5T_CONV_ABORT) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
/* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
@@ -394,7 +394,7 @@
#define H5T_CONV_us_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX) { \
/* Assumes memory format of unsigned & signed integers is same */ \
if (*((ST*)S) > (DT)(D_MAX)) { \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
} else \
*((DT*)D) = (DT)(*((ST*)S)); \
}
@@ -553,7 +553,7 @@
src_id, dst_id, S, D, cb_struct.user_data); \
if(except_ret == H5T_CONV_UNHANDLED) \
/* Let compiler convert if case is ignored by user handler*/ \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
else if(except_ret == H5T_CONV_ABORT) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
/* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
@@ -562,7 +562,7 @@
src_id, dst_id, S, D, cb_struct.user_data); \
if(except_ret == H5T_CONV_UNHANDLED) \
/* Let compiler convert if case is ignored by user handler*/ \
- *((DT*)D) = (D_MIN); \
+ *((DT*)D) = (DT)(D_MIN); \
else if(except_ret == H5T_CONV_ABORT) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception") \
/* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \
@@ -581,9 +581,9 @@
}
#define H5T_CONV_Fx_NOEX_CORE(S,D,ST,DT,D_MIN,D_MAX) { \
if (*((ST*)S) > (DT)(D_MAX)) { \
- *((DT*)D) = (D_MAX); \
+ *((DT*)D) = (DT)(D_MAX); \
} else if (*((ST*)S) < (DT)(D_MIN)) { \
- *((DT*)D) = (D_MIN); \
+ *((DT*)D) = (DT)(D_MIN); \
} \
else \
*((DT*)D) = (DT)(*((ST*)S)); \
@@ -621,7 +621,7 @@
case H5T_CONV_INIT: \
/* Sanity check and initialize statistics */ \
cdata->need_bkg = H5T_BKG_NO; \
- if (NULL==(st=H5I_object(src_id)) || NULL==(dt=H5I_object(dst_id))) \
+ if (NULL==(st=(H5T_t*)H5I_object(src_id)) || NULL==(dt=(H5T_t*)H5I_object(dst_id))) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, \
"unable to dereference datatype object ID") \
if (st->shared->size!=sizeof(ST) || dt->shared->size!=sizeof(DT)) \
@@ -669,7 +669,7 @@
HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "unable to get conversion exception callback"); \
\
/* Get source and destination datatypes */ \
- if (NULL==(st=H5I_object(src_id)) || NULL==(dt=H5I_object(dst_id))) \
+ if (NULL==(st=(H5T_t*)H5I_object(src_id)) || NULL==(dt=(H5T_t*)H5I_object(dst_id))) \
HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, \
"unable to dereference datatype object ID") \
\
@@ -714,7 +714,7 @@
} /* end if */ \
else { \
/* Single forward pass over all data */ \
- src = dst = buf; \
+ src = dst = (uint8_t*)buf; \
safe=nelmts; \
} /* end else */ \
\
@@ -9755,8 +9755,8 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
switch (cdata->command) {
case H5T_CONV_INIT:
- if (NULL==(src_p=H5I_object(src_id)) ||
- NULL==(dst_p=H5I_object(dst_id)))
+ if (NULL==(src_p=(H5T_t*)H5I_object(src_id)) ||
+ NULL==(dst_p=(H5T_t*)H5I_object(dst_id)))
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
@@ -9774,8 +9774,8 @@ H5T_conv_f_i (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
case H5T_CONV_CONV:
/* Get the datatypes */
- if (NULL==(src_p=H5I_object(src_id)) ||
- NULL==(dst_p=H5I_object(dst_id)))
+ if (NULL==(src_p=(H5T_t*)H5I_object(src_id)) ||
+ NULL==(dst_p=(H5T_t*)H5I_object(dst_id)))
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
@@ -10345,8 +10345,8 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
switch (cdata->command) {
case H5T_CONV_INIT:
- if (NULL==(src_p=H5I_object(src_id)) ||
- NULL==(dst_p=H5I_object(dst_id)))
+ if (NULL==(src_p=(H5T_t*)H5I_object(src_id)) ||
+ NULL==(dst_p=(H5T_t*)H5I_object(dst_id)))
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
@@ -10364,8 +10364,8 @@ H5T_conv_i_f (hid_t src_id, hid_t dst_id, H5T_cdata_t *cdata, size_t nelmts,
case H5T_CONV_CONV:
/* Get the datatypes */
- if (NULL==(src_p=H5I_object(src_id)) ||
- NULL==(dst_p=H5I_object(dst_id)))
+ if (NULL==(src_p=(H5T_t*)H5I_object(src_id)) ||
+ NULL==(dst_p=(H5T_t*)H5I_object(dst_id)))
HGOTO_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype");
src = src_p->shared->u.atomic;
dst = dst_p->shared->u.atomic;
diff --git a/src/H5Z.c b/src/H5Z.c
index 4df6abd..417ae77 100644
--- a/src/H5Z.c
+++ b/src/H5Z.c
@@ -53,7 +53,7 @@ typedef enum {
/* Local variables */
static size_t H5Z_table_alloc_g = 0;
static size_t H5Z_table_used_g = 0;
-static H5Z_class_t *H5Z_table_g = NULL;
+static H5Z_class2_t *H5Z_table_g = NULL;
#ifdef H5Z_DEBUG
static H5Z_stats_t *H5Z_stat_table_g = NULL;
#endif /* H5Z_DEBUG */
@@ -191,7 +191,7 @@ H5Z_term_interface(void)
}
#endif /* H5Z_DEBUG */
/* Free the table of filters */
- H5Z_table_g = (H5Z_class_t *)H5MM_xfree(H5Z_table_g);
+ H5Z_table_g = (H5Z_class2_t *)H5MM_xfree(H5Z_table_g);
#ifdef H5Z_DEBUG
H5Z_stat_table_g = (H5Z_stats_t *)H5MM_xfree(H5Z_stat_table_g);
#endif /* H5Z_DEBUG */
@@ -220,32 +220,62 @@ H5Z_term_interface(void)
*-------------------------------------------------------------------------
*/
herr_t
-H5Zregister(const H5Z_class_t *cls)
+H5Zregister(const void *cls)
{
- herr_t ret_value=SUCCEED; /* Return value */
+ const H5Z_class2_t *cls_real = (const H5Z_class2_t *) cls; /* "Real" class pointer */
+ H5Z_class2_t cls_new; /* Translated class struct */
+ herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_API(H5Zregister, FAIL)
- H5TRACE1("e", "*Zc", cls);
+ H5TRACE1("e", "*x", cls);
/* Check args */
- if (cls==NULL)
+ if (cls_real==NULL)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter class")
/* Check H5Z_class_t version number; this is where a function to convert
* from an outdated version should be called.
+ *
+ * If the version number is invalid, we assume that the target of cls is the
+ * old style "H5Z_class1_t" structure, which did not contain a version
+ * field. In this structure, the first field is the id. Since both version
+ * and id are integers they will have the same value, and since id must be
+ * at least 256, there should be no overlap and the version of the struct
+ * can be determined by the value of the first field.
*/
- if(cls->version != H5Z_CLASS_T_VERS)
- HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid H5Z_class_t version number");
+ if(cls_real->version != H5Z_CLASS_T_VERS) {
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+ /* Assume it is an old "H5Z_class1_t" instead */
+ const H5Z_class1_t *cls_old = (const H5Z_class1_t *) cls;
+
+ /* Translate to new H5Z_class2_t */
+ cls_new.version = H5Z_CLASS_T_VERS;
+ cls_new.id = cls_old->id;
+ cls_new.encoder_present = 1;
+ cls_new.decoder_present = 1;
+ cls_new.name = cls_old->name;
+ cls_new.can_apply = cls_old->can_apply;
+ cls_new.set_local = cls_old->set_local;
+ cls_new.filter = cls_old->filter;
+
+ /* Set cls_real to point to the translated structure */
+ cls_real = &cls_new;
+
+#else /* H5_NO_DEPRECATED_SYMBOLS */
+ /* Deprecated symbols not allowed, throw an error */
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid H5Z_class_t version number");
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+ } /* end if */
- if (cls->id<0 || cls->id>H5Z_FILTER_MAX)
+ if (cls_real->id<0 || cls_real->id>H5Z_FILTER_MAX)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid filter identification number")
- if (cls->id<H5Z_FILTER_RESERVED)
+ if (cls_real->id<H5Z_FILTER_RESERVED)
HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "unable to modify predefined filters")
- if (cls->filter==NULL)
+ if (cls_real->filter==NULL)
HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no filter function specified")
/* Do it */
- if (H5Z_register (cls)<0)
+ if (H5Z_register (cls_real)<0)
HGOTO_ERROR (H5E_PLINE, H5E_CANTINIT, FAIL, "unable to register filter")
done:
@@ -269,7 +299,7 @@ done:
*-------------------------------------------------------------------------
*/
herr_t
-H5Z_register (const H5Z_class_t *cls)
+H5Z_register (const H5Z_class2_t *cls)
{
size_t i;
herr_t ret_value = SUCCEED; /* Return value */
@@ -288,7 +318,7 @@ H5Z_register (const H5Z_class_t *cls)
if(i >= H5Z_table_used_g) {
if(H5Z_table_used_g >= H5Z_table_alloc_g) {
size_t n = MAX(H5Z_MAX_NFILTERS, 2*H5Z_table_alloc_g);
- H5Z_class_t *table = (H5Z_class_t *)H5MM_realloc(H5Z_table_g, n * sizeof(H5Z_class_t));
+ H5Z_class2_t *table = (H5Z_class2_t *)H5MM_realloc(H5Z_table_g, n * sizeof(H5Z_class2_t));
#ifdef H5Z_DEBUG
H5Z_stats_t *stat_table = (H5Z_stats_t *)H5MM_realloc(H5Z_stat_table_g, n * sizeof(H5Z_stats_t));
#endif /* H5Z_DEBUG */
@@ -305,7 +335,7 @@ H5Z_register (const H5Z_class_t *cls)
/* Initialize */
i = H5Z_table_used_g++;
- HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class_t));
+ HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class2_t));
#ifdef H5Z_DEBUG
HDmemset(H5Z_stat_table_g+i, 0, sizeof(H5Z_stats_t));
#endif /* H5Z_DEBUG */
@@ -313,7 +343,7 @@ H5Z_register (const H5Z_class_t *cls)
/* Filter already registered */
else {
/* Replace old contents */
- HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class_t));
+ HDmemcpy(H5Z_table_g+i, cls, sizeof(H5Z_class2_t));
} /* end else */
done:
@@ -394,7 +424,7 @@ H5Z_unregister (H5Z_filter_t id)
/* Remove filter from table */
/* Don't worry about shrinking table size (for now) */
- HDmemmove(&H5Z_table_g[i],&H5Z_table_g[i+1],sizeof(H5Z_class_t)*((H5Z_table_used_g-1)-i));
+ HDmemmove(&H5Z_table_g[i],&H5Z_table_g[i+1],sizeof(H5Z_class2_t)*((H5Z_table_used_g-1)-i));
#ifdef H5Z_DEBUG
HDmemmove(&H5Z_stat_table_g[i],&H5Z_stat_table_g[i+1],sizeof(H5Z_stats_t)*((H5Z_table_used_g-1)-i));
#endif /* H5Z_DEBUG */
@@ -516,7 +546,7 @@ H5Z_prelude_callback(hid_t dcpl_id, hid_t type_id, H5Z_prelude_type_t prelude_ty
/* Iterate over filters */
for(u = 0; u < dcpl_pline.nused; u++) {
- H5Z_class_t *fclass; /* Individual filter information */
+ H5Z_class2_t *fclass; /* Individual filter information */
/* Get filter information */
if(NULL == (fclass = H5Z_find(dcpl_pline.filter[u].id))) {
@@ -890,11 +920,11 @@ done:
*
*-------------------------------------------------------------------------
*/
-H5Z_class_t *
+H5Z_class2_t *
H5Z_find(H5Z_filter_t id)
{
int idx; /* Filter index in global table */
- H5Z_class_t *ret_value=NULL; /* Return value */
+ H5Z_class2_t *ret_value=NULL; /* Return value */
FUNC_ENTER_NOAPI(H5Z_find, NULL)
@@ -946,7 +976,7 @@ H5Z_pipeline(const H5O_pline_t *pline, unsigned flags,
{
size_t i, idx, new_nbytes;
int fclass_idx; /* Index of filter class in global table */
- H5Z_class_t *fclass=NULL; /* Filter class pointer */
+ H5Z_class2_t *fclass=NULL; /* Filter class pointer */
#ifdef H5Z_DEBUG
H5Z_stats_t *fstats=NULL; /* Filter stats pointer */
H5_timer_t timer;
@@ -1242,7 +1272,7 @@ done:
herr_t
H5Zget_filter_info(H5Z_filter_t filter, unsigned int *filter_config_flags)
{
- H5Z_class_t *fclass;
+ H5Z_class2_t *fclass;
herr_t ret_value = SUCCEED;
FUNC_ENTER_API(H5Zget_filter_info, FAIL)
diff --git a/src/H5Zdeflate.c b/src/H5Zdeflate.c
index 56b910b..7cda2c8 100644
--- a/src/H5Zdeflate.c
+++ b/src/H5Zdeflate.c
@@ -37,7 +37,7 @@ static size_t H5Z_filter_deflate (unsigned flags, size_t cd_nelmts,
const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf);
/* This message derives from H5Z */
-const H5Z_class_t H5Z_DEFLATE[1] = {{
+const H5Z_class2_t H5Z_DEFLATE[1] = {{
H5Z_CLASS_T_VERS, /* H5Z_class_t version */
H5Z_FILTER_DEFLATE, /* Filter id number */
1, /* encoder_present flag (set to true) */
diff --git a/src/H5Zfletcher32.c b/src/H5Zfletcher32.c
index aa3a173..e3a77bd 100644
--- a/src/H5Zfletcher32.c
+++ b/src/H5Zfletcher32.c
@@ -34,7 +34,7 @@ static size_t H5Z_filter_fletcher32 (unsigned flags, size_t cd_nelmts,
const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf);
/* This message derives from H5Z */
-const H5Z_class_t H5Z_FLETCHER32[1] = {{
+const H5Z_class2_t H5Z_FLETCHER32[1] = {{
H5Z_CLASS_T_VERS, /* H5Z_class_t version */
H5Z_FILTER_FLETCHER32, /* Filter id number */
1, /* encoder_present flag (set to true) */
diff --git a/src/H5Znbit.c b/src/H5Znbit.c
index 97a00f0..6f090c3 100644
--- a/src/H5Znbit.c
+++ b/src/H5Znbit.c
@@ -80,7 +80,7 @@ static void H5Z_nbit_compress(unsigned char *data, unsigned d_nelmts, unsigned c
size_t *buffer_size, const unsigned parms[]);
/* This message derives from H5Z */
-H5Z_class_t H5Z_NBIT[1] = {{
+H5Z_class2_t H5Z_NBIT[1] = {{
H5Z_CLASS_T_VERS, /* H5Z_class_t version */
H5Z_FILTER_NBIT, /* Filter id number */
1, /* Assume encoder present: check before registering */
diff --git a/src/H5Zpkg.h b/src/H5Zpkg.h
index 9cd126e..ae33def 100644
--- a/src/H5Zpkg.h
+++ b/src/H5Zpkg.h
@@ -42,46 +42,46 @@
/*
* Deflate filter
*/
-H5_DLLVAR const H5Z_class_t H5Z_DEFLATE[1];
+H5_DLLVAR const H5Z_class2_t H5Z_DEFLATE[1];
#endif /* H5_HAVE_FILTER_DEFLATE */
#ifdef H5_HAVE_FILTER_SHUFFLE
/*
* Shuffle filter
*/
-H5_DLLVAR const H5Z_class_t H5Z_SHUFFLE[1];
+H5_DLLVAR const H5Z_class2_t H5Z_SHUFFLE[1];
#endif /* H5_HAVE_FILTER_SHUFFLE */
#ifdef H5_HAVE_FILTER_FLETCHER32
/*
* Fletcher32 filter
*/
-H5_DLLVAR const H5Z_class_t H5Z_FLETCHER32[1];
+H5_DLLVAR const H5Z_class2_t H5Z_FLETCHER32[1];
#endif /* H5_HAVE_FILTER_FLETCHER32 */
#ifdef H5_HAVE_FILTER_SZIP
/*
* szip filter
*/
-H5_DLLVAR H5Z_class_t H5Z_SZIP[1];
+H5_DLLVAR H5Z_class2_t H5Z_SZIP[1];
#endif /* H5_HAVE_FILTER_SZIP */
#ifdef H5_HAVE_FILTER_NBIT
/*
* nbit filter
*/
-H5_DLLVAR H5Z_class_t H5Z_NBIT[1];
+H5_DLLVAR H5Z_class2_t H5Z_NBIT[1];
#endif /* H5_HAVE_FILTER_NBIT */
#ifdef H5_HAVE_FILTER_SCALEOFFSET
/*
* scaleoffset filter
*/
-H5_DLLVAR H5Z_class_t H5Z_SCALEOFFSET[1];
+H5_DLLVAR H5Z_class2_t H5Z_SCALEOFFSET[1];
#endif /* H5_HAVE_FILTER_SCALEOFFSET */
/* Package-local function prototypes */
-H5_DLL void H5Z_update_class_vers(H5Z_class_t * old_vers, H5Z_class_t * curr_vers);
+H5_DLL void H5Z_update_class_vers(H5Z_class2_t * old_vers, H5Z_class2_t * curr_vers);
#endif /* _H5Zpkg_H */
diff --git a/src/H5Zprivate.h b/src/H5Zprivate.h
index 15b7289..3ce0a0c 100644
--- a/src/H5Zprivate.h
+++ b/src/H5Zprivate.h
@@ -72,7 +72,8 @@ typedef struct {
struct H5O_pline_t; /*forward decl*/
/* Internal API routines */
-H5_DLL herr_t H5Z_register(const H5Z_class_t *cls);
+H5_DLL herr_t H5Z_init(void);
+H5_DLL herr_t H5Z_register(const H5Z_class2_t *cls);
H5_DLL herr_t H5Z_unregister(H5Z_filter_t id);
H5_DLL herr_t H5Z_append(struct H5O_pline_t *pline, H5Z_filter_t filter,
unsigned flags, size_t cd_nelmts, const unsigned int cd_values[]);
@@ -83,7 +84,7 @@ H5_DLL herr_t H5Z_pipeline(const struct H5O_pline_t *pline,
H5Z_EDC_t edc_read, H5Z_cb_t cb_struct,
size_t *nbytes/*in,out*/, size_t *buf_size/*in,out*/,
void **buf/*in,out*/);
-H5_DLL H5Z_class_t *H5Z_find(H5Z_filter_t id);
+H5_DLL H5Z_class2_t *H5Z_find(H5Z_filter_t id);
H5_DLL herr_t H5Z_can_apply(hid_t dcpl_id, hid_t type_id);
H5_DLL herr_t H5Z_set_local(hid_t dcpl_id, hid_t type_id);
H5_DLL H5Z_filter_info_t *H5Z_filter_info(const struct H5O_pline_t *pline,
diff --git a/src/H5Zpublic.h b/src/H5Zpublic.h
index ce60650..44d2bbb 100644
--- a/src/H5Zpublic.h
+++ b/src/H5Zpublic.h
@@ -206,7 +206,7 @@ typedef size_t (*H5Z_func_t)(unsigned int flags, size_t cd_nelmts,
* The filter table maps filter identification numbers to structs that
* contain a pointers to the filter function and timing statistics.
*/
-typedef struct H5Z_class_t {
+typedef struct H5Z_class2_t {
int version; /* Version number of the H5Z_class_t struct */
H5Z_filter_t id; /* Filter ID number */
unsigned encoder_present; /* Does this filter have an encoder? */
@@ -215,13 +215,33 @@ typedef struct H5Z_class_t {
H5Z_can_apply_func_t can_apply; /* The "can apply" callback for a filter */
H5Z_set_local_func_t set_local; /* The "set local" callback for a filter */
H5Z_func_t filter; /* The actual filter function */
-} H5Z_class_t;
+} H5Z_class2_t;
-H5_DLL herr_t H5Zregister(const H5Z_class_t *cls);
+H5_DLL herr_t H5Zregister(const void *cls);
H5_DLL herr_t H5Zunregister(H5Z_filter_t id);
H5_DLL htri_t H5Zfilter_avail(H5Z_filter_t id);
H5_DLL herr_t H5Zget_filter_info(H5Z_filter_t filter, unsigned int *filter_config_flags);
+/* Symbols defined for compatibility with previous versions of the HDF5 API.
+ *
+ * Use of these symbols is deprecated.
+ */
+#ifndef H5_NO_DEPRECATED_SYMBOLS
+
+/*
+ * The filter table maps filter identification numbers to structs that
+ * contain a pointers to the filter function and timing statistics.
+ */
+typedef struct H5Z_class1_t {
+ H5Z_filter_t id; /* Filter ID number */
+ const char *name; /* Comment for debugging */
+ H5Z_can_apply_func_t can_apply; /* The "can apply" callback for a filter */
+ H5Z_set_local_func_t set_local; /* The "set local" callback for a filter */
+ H5Z_func_t filter; /* The actual filter function */
+} H5Z_class1_t;
+
+#endif /* H5_NO_DEPRECATED_SYMBOLS */
+
#ifdef __cplusplus
}
#endif
diff --git a/src/H5Zscaleoffset.c b/src/H5Zscaleoffset.c
index 10618c3..d59499c 100644
--- a/src/H5Zscaleoffset.c
+++ b/src/H5Zscaleoffset.c
@@ -80,7 +80,7 @@ static void H5Z_scaleoffset_compress(unsigned char *data, unsigned d_nelmts, uns
size_t buffer_size, parms_atomic p);
/* This message derives from H5Z */
-H5Z_class_t H5Z_SCALEOFFSET[1] = {{
+H5Z_class2_t H5Z_SCALEOFFSET[1] = {{
H5Z_CLASS_T_VERS, /* H5Z_class_t version */
H5Z_FILTER_SCALEOFFSET, /* Filter id number */
1, /* Assume encoder present: check before registering */
diff --git a/src/H5Zshuffle.c b/src/H5Zshuffle.c
index 3f40707..2e4f1fa 100644
--- a/src/H5Zshuffle.c
+++ b/src/H5Zshuffle.c
@@ -32,7 +32,7 @@ static size_t H5Z_filter_shuffle(unsigned flags, size_t cd_nelmts,
const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf);
/* This message derives from H5Z */
-const H5Z_class_t H5Z_SHUFFLE[1] = {{
+const H5Z_class2_t H5Z_SHUFFLE[1] = {{
H5Z_CLASS_T_VERS, /* H5Z_class_t version */
H5Z_FILTER_SHUFFLE, /* Filter id number */
1, /* encoder_present flag (set to true) */
diff --git a/src/H5Zszip.c b/src/H5Zszip.c
index b40c028..5da92ac 100644
--- a/src/H5Zszip.c
+++ b/src/H5Zszip.c
@@ -40,7 +40,7 @@ static size_t H5Z_filter_szip (unsigned flags, size_t cd_nelmts,
const unsigned cd_values[], size_t nbytes, size_t *buf_size, void **buf);
/* This message derives from H5Z */
-H5Z_class_t H5Z_SZIP[1] = {{
+H5Z_class2_t H5Z_SZIP[1] = {{
H5Z_CLASS_T_VERS, /* H5Z_class_t version */
H5Z_FILTER_SZIP, /* Filter id number */
1, /* Assume encoder present: check before registering */
diff --git a/src/H5config.h.in b/src/H5config.h.in
index 1c70790..a3e879b 100644
--- a/src/H5config.h.in
+++ b/src/H5config.h.in
@@ -84,6 +84,9 @@
/* Define to 1 if you have the <dmalloc.h> header file. */
#undef HAVE_DMALLOC_H
+/* Define if library information should be embedded in the executables */
+#undef HAVE_EMBEDDED_LIBINFO
+
/* Define to 1 if you have the <features.h> header file. */
#undef HAVE_FEATURES_H
diff --git a/src/H5detect.c b/src/H5detect.c
index b67c2b0..146750c 100644
--- a/src/H5detect.c
+++ b/src/H5detect.c
@@ -108,6 +108,7 @@ static void detect_C99_integers16(void);
static void detect_C99_integers32(void);
static void detect_C99_integers64(void);
static void detect_alignments(void);
+static void insert_libhdf5_settings(void);
static size_t align_g[] = {1, 2, 4, 8, 16};
static jmp_buf jbuf_g;
@@ -502,6 +503,64 @@ sigbus_handler(int UNUSED signo)
/*-------------------------------------------------------------------------
+ * Function: insert_libhdf5_settings
+ *
+ * Purpose: Insert contents of libhdf5.settings so that it is included
+ * in all hdf5 executables.
+ *
+ * Return: void
+ *
+ * Programmer: Albert Cheng
+ * Apr 20, 2009
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+#define LIBSETTINGSFNAME "libhdf5.settings"
+static void
+insert_libhdf5_settings(void)
+{
+ FILE *fsettings;
+ char inchar;
+ int bol=0; /* indicates the beginning of a new line */
+
+ if (NULL==(fsettings=HDfopen(LIBSETTINGSFNAME, "r"))){
+ perror(LIBSETTINGSFNAME);
+ exit(1);
+ }
+ /* print variable definition */
+ printf("extern char H5libhdf5_settings[]=\n");
+ bol++;
+ while (EOF != (inchar = getc(fsettings))){
+ if (bol){
+ /* Start a new line */
+ printf("\t\"");
+ bol = 0;
+ }
+ if (inchar == '\n'){
+ /* end of a line */
+ printf("\\n\"\n");
+ bol++;
+ }else{
+ putchar(inchar);
+ }
+ }
+ if (feof(fsettings)){
+ /* wrap up */
+ if (!bol){
+ /* EOF found without a new line */
+ printf("\\n\"\n");
+ };
+ printf(";\n\n");
+ }else{
+ fprintf(stderr, "Read errors encountered with %s\n", LIBSETTINGSFNAME);
+ exit(1);
+ }
+}
+
+
+/*-------------------------------------------------------------------------
* Function: print_results
*
* Purpose: Prints information about the detected data types.
@@ -580,6 +639,11 @@ print_results(int nd, detected_t *d, int na, malign_t *misc_align)
/*******************/\n\
\n");
+#ifdef H5_HAVE_EMBEDDED_LIBINFO
+ /* Insert content of libhdf5.settings */
+ insert_libhdf5_settings();
+#endif
+
/* The interface initialization function */
printf("\n\
\n\
diff --git a/src/H5private.h b/src/H5private.h
index 695b015..d392548 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -144,6 +144,7 @@
#define VC_EXTRALEAN /*Exclude rarely-used stuff from Windows headers */
#include <windows.h>
+#include <direct.h> /* For _getcwd() */
#endif /*_WIN32*/
diff --git a/src/H5public.h b/src/H5public.h
index 367e601..371847d 100644
--- a/src/H5public.h
+++ b/src/H5public.h
@@ -71,10 +71,10 @@ extern "C" {
/* Version numbers */
#define H5_VERS_MAJOR 1 /* For major interface/format changes */
#define H5_VERS_MINOR 9 /* For minor interface/format changes */
-#define H5_VERS_RELEASE 36 /* For tweaks, bug-fixes, or development */
+#define H5_VERS_RELEASE 39 /* For tweaks, bug-fixes, or development */
#define H5_VERS_SUBRELEASE "FA_a1" /* For pre-releases like snap0 */
/* Empty string for real releases. */
-#define H5_VERS_INFO "HDF5 library version: 1.9.36-FA_a1" /* Full version string */
+#define H5_VERS_INFO "HDF5 library version: 1.9.39-FA_a1" /* Full version string */
#define H5check() H5check_version(H5_VERS_MAJOR,H5_VERS_MINOR, \
H5_VERS_RELEASE)
diff --git a/src/H5trace.c b/src/H5trace.c
index 4a42f0b..6e2578b 100644
--- a/src/H5trace.c
+++ b/src/H5trace.c
@@ -1978,7 +1978,7 @@ H5_trace (const double *returning, const char *func, const char *type, ...)
fprintf(out, "NULL");
}
} else {
- H5Z_class_t *filter = va_arg (ap, H5Z_class_t*); /*lint !e64 Type mismatch not really occuring */
+ H5Z_class2_t *filter = va_arg (ap, H5Z_class2_t*); /*lint !e64 Type mismatch not really occuring */
fprintf (out, "0x%lx", (unsigned long)filter);
}
break;
diff --git a/src/H5vers.txt b/src/H5vers.txt
index 00ab84b..18a88d9 100644
--- a/src/H5vers.txt
+++ b/src/H5vers.txt
@@ -71,4 +71,5 @@ FUNCTION: H5Topen; ; v10, v18
# (although not required, it's easier to compare this file with the headers
# generated if the list below is in alphanumeric sort order - QAK)
TYPEDEF: H5E_auto; v10, v18
+TYPEDEF: H5Z_class; v16, v18
diff --git a/src/H5version.h b/src/H5version.h
index fd9e780..58de2ab 100644
--- a/src/H5version.h
+++ b/src/H5version.h
@@ -134,6 +134,10 @@
#define H5E_auto_t_vers 1
#endif /* !defined(H5E_auto_t_vers) */
+#if !defined(H5Z_class_t_vers)
+#define H5Z_class_t_vers 1
+#endif /* !defined(H5Z_class_t_vers) */
+
#endif /* H5_USE_16_API */
@@ -399,5 +403,17 @@
#error "H5E_auto_t_vers set to invalid value"
#endif /* H5E_auto_t_vers */
+
+#if !defined(H5Z_class_t_vers) || H5Z_class_t_vers == 2
+#ifndef H5Z_class_t_vers
+#define H5Z_class_t_vers 2
+#endif /* H5Z_class_t_vers */
+#define H5Z_class_t H5Z_class2_t
+#elif H5Z_class_t_vers == 1
+#define H5Z_class_t H5Z_class1_t
+#else /* H5Z_class_t_vers */
+#error "H5Z_class_t_vers set to invalid value"
+#endif /* H5Z_class_t_vers */
+
#endif /* H5version_H */
diff --git a/src/Makefile.am b/src/Makefile.am
index b2b0a98..f6d92dd 100755
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,7 +61,7 @@ libhdf5_la_SOURCES= H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5G.c H5Gbtree2.c H5Gcache.c \
H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
H5Gint.c H5Glink.c \
- H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Gstab.c H5Gtest.c \
+ H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Groot.c H5Gstab.c H5Gtest.c \
H5Gtraverse.c \
H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \
H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \
diff --git a/src/Makefile.in b/src/Makefile.in
index a437a3e..57a4cc8 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.10.1 from Makefile.am.
+# Makefile.in generated by automake 1.10.2 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
@@ -97,9 +97,9 @@ am_libhdf5_la_OBJECTS = H5.lo H5checksum.lo H5dbg.lo H5system.lo \
H5FScache.lo H5FSdbg.lo H5FSsection.lo H5FSstat.lo H5FStest.lo \
H5G.lo H5Gbtree2.lo H5Gcache.lo H5Gcompact.lo H5Gdense.lo \
H5Gdeprec.lo H5Gent.lo H5Gint.lo H5Glink.lo H5Gloc.lo \
- H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Gstab.lo H5Gtest.lo \
- H5Gtraverse.lo H5HF.lo H5HFbtree2.lo H5HFcache.lo H5HFdbg.lo \
- H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo \
+ H5Gname.lo H5Gnode.lo H5Gobj.lo H5Goh.lo H5Groot.lo H5Gstab.lo \
+ H5Gtest.lo H5Gtraverse.lo H5HF.lo H5HFbtree2.lo H5HFcache.lo \
+ H5HFdbg.lo H5HFdblock.lo H5HFdtable.lo H5HFhdr.lo H5HFhuge.lo \
H5HFiblock.lo H5HFiter.lo H5HFman.lo H5HFsection.lo \
H5HFspace.lo H5HFstat.lo H5HFtest.lo H5HFtiny.lo H5HG.lo \
H5HGcache.lo H5HGdbg.lo H5HL.lo H5HLcache.lo H5HLdbg.lo \
@@ -409,7 +409,7 @@ CHECK_CLEANFILES = *.chkexe *.chklog *.clog
# Add libtool shared library version numbers to the HDF5 library
# See libtool versioning documentation online.
LT_VERS_INTERFACE = 6
-LT_VERS_REVISION = 26
+LT_VERS_REVISION = 29
LT_VERS_AGE = 0
H5detect_CFLAGS = -g
@@ -445,7 +445,7 @@ libhdf5_la_SOURCES = H5.c H5checksum.c H5dbg.c H5system.c H5timer.c H5trace.c \
H5G.c H5Gbtree2.c H5Gcache.c \
H5Gcompact.c H5Gdense.c H5Gdeprec.c H5Gent.c \
H5Gint.c H5Glink.c \
- H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Gstab.c H5Gtest.c \
+ H5Gloc.c H5Gname.c H5Gnode.c H5Gobj.c H5Goh.c H5Groot.c H5Gstab.c H5Gtest.c \
H5Gtraverse.c \
H5HF.c H5HFbtree2.c H5HFcache.c H5HFdbg.c H5HFdblock.c H5HFdtable.c \
H5HFhdr.c H5HFhuge.c H5HFiblock.c H5HFiter.c H5HFman.c H5HFsection.c \
@@ -525,8 +525,8 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
- && exit 0; \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
@@ -711,6 +711,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gnode.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gobj.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Goh.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Groot.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gstab.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gtest.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/H5Gtraverse.Plo@am__quote@
@@ -936,7 +937,7 @@ ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
- $(AWK) '{ files[$$0] = 1; nonemtpy = 1; } \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS