1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-05-07 15:22:34 +02:00
audacity/lib-src/redland/librdf/rdf_hash_memory.c
2010-01-24 09:19:39 +00:00

1065 lines
26 KiB
C

/* -*- Mode: c; c-basic-offset: 2 -*-
*
* rdf_hash_memory.c - RDF Hash In Memory Implementation
*
* Copyright (C) 2000-2008, David Beckett http://www.dajobe.org/
* Copyright (C) 2000-2004, University of Bristol, UK http://www.bristol.ac.uk/
*
* This package is Free Software and part of Redland http://librdf.org/
*
* It is licensed under the following three licenses as alternatives:
* 1. GNU Lesser General Public License (LGPL) V2.1 or any newer version
* 2. GNU General Public License (GPL) V2 or any newer version
* 3. Apache License, V2.0 or any newer version
*
* You may not use this file except in compliance with at least one of
* the above three licenses.
*
* See LICENSE.html or LICENSE.txt at the top of this package for the
* complete terms and further detail along with the license texts for
* the licenses in COPYING.LIB, COPYING and LICENSE-2.0.txt respectively.
*
*
*/
#ifdef HAVE_CONFIG_H
#include <rdf_config.h>
#endif
#ifdef WIN32
#include <win32_rdf_config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h> /* for abort() as used in errors */
#endif
#include <redland.h>
#include <rdf_types.h>
/* private structures */
struct librdf_hash_memory_node_value_s
{
struct librdf_hash_memory_node_value_s* next;
void *value;
size_t value_len;
};
typedef struct librdf_hash_memory_node_value_s librdf_hash_memory_node_value;
struct librdf_hash_memory_node_s
{
struct librdf_hash_memory_node_s* next;
void *key;
size_t key_len;
u32 hash_key;
librdf_hash_memory_node_value *values;
int values_count;
};
typedef struct librdf_hash_memory_node_s librdf_hash_memory_node;
typedef struct
{
/* the hash object */
librdf_hash* hash;
/* An array pointing to a list of nodes (buckets) */
librdf_hash_memory_node** nodes;
/* this many buckets used */
int size;
/* this many keys */
int keys;
/* this many values */
int values;
/* total array size */
int capacity;
/* array load factor expressed out of 1000.
* Always true: (size/capacity * 1000) < load_factor,
* or in the code: size * 1000 < load_factor * capacity
*/
int load_factor;
} librdf_hash_memory_context;
/* default load_factor out of 1000 */
static const int librdf_hash_default_load_factor=750;
/* starting capacity - MUST BE POWER OF 2 */
static const int librdf_hash_initial_capacity=8;
/* prototypes for local functions */
static librdf_hash_memory_node* librdf_hash_memory_find_node(librdf_hash_memory_context* hash, void *key, size_t key_len, int *bucket, librdf_hash_memory_node** prev);
static void librdf_free_hash_memory_node(librdf_hash_memory_node* node);
static int librdf_hash_memory_expand_size(librdf_hash_memory_context* hash);
/* Implementing the hash cursor */
static int librdf_hash_memory_cursor_init(void *cursor_context, void *hash_context);
static int librdf_hash_memory_cursor_get(void* context, librdf_hash_datum* key, librdf_hash_datum* value, unsigned int flags);
static void librdf_hash_memory_cursor_finish(void* context);
/* functions implementing the API */
static int librdf_hash_memory_create(librdf_hash* new_hash, void* context);
static int librdf_hash_memory_destroy(void* context);
static int librdf_hash_memory_open(void* context, const char *identifier, int mode, int is_writable, int is_new, librdf_hash* options);
static int librdf_hash_memory_close(void* context);
static int librdf_hash_memory_clone(librdf_hash* new_hash, void *new_context, char *new_identifier, void* old_context);
static int librdf_hash_memory_values_count(void *context);
static int librdf_hash_memory_put(void* context, librdf_hash_datum *key, librdf_hash_datum *data);
static int librdf_hash_memory_exists(void* context, librdf_hash_datum *key, librdf_hash_datum *value);
static int librdf_hash_memory_delete_key(void* context, librdf_hash_datum *key);
static int librdf_hash_memory_delete_key_value(void* context, librdf_hash_datum *key, librdf_hash_datum *value);
static int librdf_hash_memory_sync(void* context);
static int librdf_hash_memory_get_fd(void* context);
static void librdf_hash_memory_register_factory(librdf_hash_factory *factory);
/*
* perldelta 5.8.0 says under *Performance Enhancements*
*
* Hashes now use Bob Jenkins "One-at-a-Time" hashing key algorithm
* http://burtleburtle.net/bob/hash/doobs.html This algorithm is
* reasonably fast while producing a much better spread of values
* than the old hashing algorithm ...
*
* Changed here to hash the string backwards to help do URIs better
*
*/
#define ONE_AT_A_TIME_HASH(hash,str,len) \
do { \
register const unsigned char *c_oneat = (unsigned char*)str+len-1; \
register int i_oneat = len; \
register u32 hash_oneat = 0; \
while (i_oneat--) { \
hash_oneat += *c_oneat--; \
hash_oneat += (hash_oneat << 10); \
hash_oneat ^= (hash_oneat >> 6); \
} \
hash_oneat += (hash_oneat << 3); \
hash_oneat ^= (hash_oneat >> 11); \
(hash) = (hash_oneat + (hash_oneat << 15)); \
} while(0)
/* helper functions */
/**
* librdf_hash_memory_find_node:
* @hash: the memory hash context
* @key: key string
* @key_len: key string length
* @user_bucket: pointer to store bucket
* @prev: pointer to store previous node
*
* Find the node for the given key or value.
*
* If value is not NULL and value_len is non 0, the value will also be
* compared in the search.
*
* If user_bucket is not NULL, the bucket used will be returned. if
* prev is no NULL, the previous node in the list will be returned.
*
* Return value: #librdf_hash_memory_node of content or NULL on failure
**/
static librdf_hash_memory_node*
librdf_hash_memory_find_node(librdf_hash_memory_context* hash,
void *key, size_t key_len,
int *user_bucket,
librdf_hash_memory_node** prev)
{
librdf_hash_memory_node* node;
int bucket;
u32 hash_key;
/* empty hash */
if(!hash->capacity)
return NULL;
ONE_AT_A_TIME_HASH(hash_key, key, key_len);
if(prev)
*prev=NULL;
/* find slot in table */
bucket=hash_key & (hash->capacity - 1);
if(user_bucket)
*user_bucket=bucket;
/* check if there is a list present */
node=hash->nodes[bucket];
if(!node)
/* no list there */
return NULL;
/* walk the list */
while(node) {
if(key_len == node->key_len && !memcmp(key, node->key, key_len))
break;
if(prev)
*prev=node;
node=node->next;
}
return node;
}
static void
librdf_free_hash_memory_node(librdf_hash_memory_node* node)
{
if(node->key)
LIBRDF_FREE(cstring, node->key);
if(node->values) {
librdf_hash_memory_node_value *vnode, *next;
/* Empty the list of values */
for(vnode=node->values; vnode; vnode=next) {
next=vnode->next;
if(vnode->value)
LIBRDF_FREE(cstring, vnode->value);
LIBRDF_FREE(librdf_hash_memory_node_value, vnode);
}
}
LIBRDF_FREE(librdf_hash_memory_node, node);
}
static int
librdf_hash_memory_expand_size(librdf_hash_memory_context* hash) {
int required_capacity=0;
librdf_hash_memory_node **new_nodes;
int i;
if (hash->capacity) {
/* big enough */
if((1000 * hash->keys) < (hash->load_factor * hash->capacity))
return 0;
/* grow hash (keeping it a power of two) */
required_capacity=hash->capacity << 1;
} else {
required_capacity=librdf_hash_initial_capacity;
}
/* allocate new table */
new_nodes=(librdf_hash_memory_node**)LIBRDF_CALLOC(librdf_hash_memory_nodes,
required_capacity,
sizeof(librdf_hash_memory_node*));
if(!new_nodes)
return 1;
/* it is a new hash empty hash - we are done */
if(!hash->size) {
hash->capacity=required_capacity;
hash->nodes=new_nodes;
return 0;
}
for(i=0; i<hash->capacity; i++) {
librdf_hash_memory_node *node=hash->nodes[i];
/* walk all attached nodes */
while(node) {
librdf_hash_memory_node *next;
int bucket;
next=node->next;
/* find slot in new table */
bucket=node->hash_key & (required_capacity - 1);
node->next=new_nodes[bucket];
new_nodes[bucket]=node;
node=next;
}
}
/* now free old table */
LIBRDF_FREE(librdf_hash_memory_nodes, hash->nodes);
/* attach new one */
hash->capacity=required_capacity;
hash->nodes=new_nodes;
return 0;
}
/* functions implementing hash api */
/**
* librdf_hash_memory_create:
* @hash: #librdf_hash hash
* @context: memory hash contxt
*
* Create a new memory hash.
*
* Return value: non 0 on failure
**/
static int
librdf_hash_memory_create(librdf_hash* hash, void* context)
{
librdf_hash_memory_context* hcontext=(librdf_hash_memory_context*)context;
hcontext->hash=hash;
hcontext->load_factor=librdf_hash_default_load_factor;
return librdf_hash_memory_expand_size(hcontext);
}
/**
* librdf_hash_memory_destroy:
* @context: memory hash context
*
* Destroy a memory hash.
*
* Return value: non 0 on failure
**/
static int
librdf_hash_memory_destroy(void* context)
{
librdf_hash_memory_context* hcontext=(librdf_hash_memory_context*)context;
if(hcontext->nodes) {
int i;
for(i=0; i<hcontext->capacity; i++) {
librdf_hash_memory_node *node=hcontext->nodes[i];
/* this entry is used */
if(node) {
librdf_hash_memory_node *next;
/* free all attached nodes */
while(node) {
next=node->next;
librdf_free_hash_memory_node(node);
node=next;
}
}
}
LIBRDF_FREE(librdf_hash_memory_nodes, hcontext->nodes);
}
return 0;
}
/**
* librdf_hash_memory_open:
* @context: memory hash context
* @identifier: identifier - not used
* @mode: access mode - not used
* @is_writable: is hash writable? - not used
* @is_new: is hash new? - not used
* @options: #librdf_hash of options - not used
*
* Open memory hash with given parameters.
*
* Return value: non 0 on failure
**/
static int
librdf_hash_memory_open(void* context, const char *identifier,
int mode, int is_writable, int is_new,
librdf_hash* options)
{
/* NOP */
return 0;
}
/**
* librdf_hash_memory_close:
* @context: memory hash context
*
* Close the hash.
*
* Return value: non 0 on failure
**/
static int
librdf_hash_memory_close(void* context)
{
/* NOP */
return 0;
}
static int
librdf_hash_memory_clone(librdf_hash *hash, void* context, char *new_identifer,
void *old_context)
{
librdf_hash_memory_context* hcontext=(librdf_hash_memory_context*)context;
librdf_hash_memory_context* old_hcontext=(librdf_hash_memory_context*)old_context;
librdf_hash_datum *key, *value;
librdf_iterator *iterator;
int status=0;
/* copy data fields that might change */
hcontext->hash=hash;
hcontext->load_factor=old_hcontext->load_factor;
/* Don't need to deal with new_identifier - not used for memory hashes */
/* Use higher level functions to iterator this data
* on the other hand, maybe this is a good idea since that
* code is tested and works
*/
key=librdf_new_hash_datum(hash->world, NULL, 0);
value=librdf_new_hash_datum(hash->world, NULL, 0);
iterator=librdf_hash_get_all(old_hcontext->hash, key, value);
while(!librdf_iterator_end(iterator)) {
librdf_hash_datum* k= (librdf_hash_datum*)librdf_iterator_get_key(iterator);
librdf_hash_datum* v= (librdf_hash_datum*)librdf_iterator_get_value(iterator);
if(librdf_hash_memory_put(hcontext, k, v)) {
status=1;
break;
}
librdf_iterator_next(iterator);
}
if(iterator)
librdf_free_iterator(iterator);
librdf_free_hash_datum(value);
librdf_free_hash_datum(key);
return status;
}
/**
* librdf_hash_memory_values_count:
* @context: memory hash cursor context
*
* Get the number of values in the hash.
*
* Return value: number of values in the hash or <0 on failure
**/
static int
librdf_hash_memory_values_count(void *context)
{
librdf_hash_memory_context* hash=(librdf_hash_memory_context*)context;
return hash->values;
}
typedef struct {
librdf_hash_memory_context* hash;
int current_bucket;
librdf_hash_memory_node* current_node;
librdf_hash_memory_node_value *current_value;
} librdf_hash_memory_cursor_context;
/**
* librdf_hash_memory_cursor_init:
* @cursor_context: hash cursor context
* @hash_context: hash to operate over
*
* Initialise a new hash cursor.
*
* Return value: non 0 on failure
**/
static int
librdf_hash_memory_cursor_init(void *cursor_context, void *hash_context)
{
librdf_hash_memory_cursor_context *cursor=(librdf_hash_memory_cursor_context*)cursor_context;
cursor->hash = (librdf_hash_memory_context*)hash_context;
return 0;
}
/**
* librdf_hash_memory_cursor_get:
* @context: memory hash cursor context
* @key: pointer to key to use
* @value: pointer to value to use
* @flags: flags
*
* Retrieve a hash value for the given key.
*
* Return value: non 0 on failure
**/
static int
librdf_hash_memory_cursor_get(void* context,
librdf_hash_datum *key,
librdf_hash_datum *value,
unsigned int flags)
{
librdf_hash_memory_cursor_context *cursor=(librdf_hash_memory_cursor_context*)context;
librdf_hash_memory_node_value *vnode=NULL;
librdf_hash_memory_node *node;
/* First step, make sure cursor->current_node points to a valid node,
if possible */
/* Move to start of hash if necessary */
if(flags == LIBRDF_HASH_CURSOR_FIRST) {
int i;
cursor->current_node=NULL;
/* find first used bucket (with keys) */
cursor->current_bucket=0;
for(i=0; i< cursor->hash->capacity; i++)
if((cursor->current_node=cursor->hash->nodes[i])) {
cursor->current_bucket=i;
break;
}
if(cursor->current_node)
cursor->current_value=cursor->current_node->values;
}
/* If still have no current node, try to find it from the key */
if(!cursor->current_node && key && key->data) {
cursor->current_node=librdf_hash_memory_find_node(cursor->hash,
(char*)key->data,
key->size,
NULL, NULL);
if(cursor->current_node)
cursor->current_value=cursor->current_node->values;
}
/* If still have no node, failed */
if(!cursor->current_node)
return 1;
/* Check for end of values */
switch(flags) {
case LIBRDF_HASH_CURSOR_SET:
/* If key does not exist, failed above, so test if there are values */
/* FALLTHROUGH */
case LIBRDF_HASH_CURSOR_NEXT_VALUE:
/* If want values and have reached end of values list, end */
if(!cursor->current_value)
return 1;
break;
case LIBRDF_HASH_CURSOR_FIRST:
case LIBRDF_HASH_CURSOR_NEXT:
/* If have reached last bucket, end */
if(cursor->current_bucket >= cursor->hash->capacity)
return 1;
break;
default:
librdf_log(cursor->hash->hash->world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
"Unknown hash method flag %d", flags);
return 1;
}
/* Ok, there is data, retrieve it */
switch(flags) {
case LIBRDF_HASH_CURSOR_SET:
/* FALLTHROUGH */
case LIBRDF_HASH_CURSOR_NEXT_VALUE:
vnode=cursor->current_value;
/* copy value */
value->data=vnode->value;
value->size=vnode->value_len;
/* move on */
cursor->current_value=vnode->next;
break;
case LIBRDF_HASH_CURSOR_FIRST:
case LIBRDF_HASH_CURSOR_NEXT:
node=cursor->current_node;
/* get key */
key->data= node->key;
key->size= node->key_len;
/* if want values, walk through them */
if(value) {
vnode=cursor->current_value;
/* get value */
value->data=vnode->value;
value->size=vnode->value_len;
/* move on */
cursor->current_value=vnode->next;
/* stop here if there are more values, otherwise need next
* key & values so drop through and move to the next node
*/
if(cursor->current_value)
break;
}
/* move on to next node in current bucket */
if(!(node=cursor->current_node->next)) {
int i;
/* end of list - move to next used bucket */
for(i=cursor->current_bucket+1; i< cursor->hash->capacity; i++)
if((node=cursor->hash->nodes[i])) {
cursor->current_bucket=i;
break;
}
}
if((cursor->current_node=node))
cursor->current_value=node->values;
break;
default:
librdf_log(cursor->hash->hash->world,
0, LIBRDF_LOG_ERROR, LIBRDF_FROM_HASH, NULL,
"Unknown hash method flag %d", flags);
return 1;
}
return 0;
}
/**
* librdf_hash_memory_cursor_finished:
* @context: hash memory get iterator context
*
* Finish the serialisation of the hash memory get.
*
**/
static void
librdf_hash_memory_cursor_finish(void* context)
{
/* librdf_hash_memory_cursor_context *cursor=(librdf_hash_memory_cursor_context*)context; */
}
/**
* librdf_hash_memory_put:
* @context: memory hash context
* @key: pointer to key to store
* @value: pointer to value to store
*
* - Store a key/value pair in the hash.
*
* Return value: non 0 on failure
**/
static int
librdf_hash_memory_put(void* context, librdf_hash_datum *key,
librdf_hash_datum *value)
{
librdf_hash_memory_context* hash=(librdf_hash_memory_context*)context;
librdf_hash_memory_node *node;
librdf_hash_memory_node_value *vnode;
u32 hash_key;
void *new_key=NULL;
void *new_value;
int bucket= (-1);
int is_new_node;
/* ensure there is enough space in the hash */
if (librdf_hash_memory_expand_size(hash))
return 1;
/* find node for key */
node=librdf_hash_memory_find_node(hash,
key->data, key->size,
NULL, NULL);
is_new_node=(node == NULL);
/* not found - new key */
if(is_new_node) {
ONE_AT_A_TIME_HASH(hash_key, key->data, key->size);
bucket=hash_key & (hash->capacity - 1);
/* allocate new node */
node=(librdf_hash_memory_node*)LIBRDF_CALLOC(librdf_hash_memory_node, 1,
sizeof(librdf_hash_memory_node));
if(!node)
return 1;
node->hash_key=hash_key;
/* allocate key for new node */
new_key=LIBRDF_MALLOC(cstring, key->size);
if(!new_key) {
LIBRDF_FREE(librdf_hash_memory_node, node);
return 1;
}
/* copy new key */
memcpy(new_key, key->data, key->size);
node->key=new_key;
node->key_len=key->size;
}
/* always allocate new value */
new_value=LIBRDF_MALLOC(cstring, value->size);
if(!new_value) {
if(is_new_node) {
LIBRDF_FREE(cstring, new_key);
LIBRDF_FREE(librdf_hash_memory_node, node);
}
return 1;
}
/* always allocate new librdf_hash_memory_node_value */
vnode=(librdf_hash_memory_node_value*)LIBRDF_CALLOC(librdf_hash_memory_node_value, 1, sizeof(librdf_hash_memory_node_value));
if(!vnode) {
LIBRDF_FREE(cstring, new_value);
if(is_new_node) {
LIBRDF_FREE(cstring, new_key);
LIBRDF_FREE(librdf_hash_memory_node, node);
}
return 1;
}
/* if we get here, all allocations succeeded */
/* put new value node in list */
vnode->next=node->values;
node->values=vnode;
/* note that in counter */
node->values_count++;
/* copy new value */
memcpy(new_value, value->data, value->size);
vnode->value=new_value;
vnode->value_len=value->size;
/* now update buckets and hash counts */
if(is_new_node) {
node->next=hash->nodes[bucket];
hash->nodes[bucket]=node;
hash->keys++;
}
hash->values++;
/* Only increase bucket count use when previous value was NULL */
if(!node->next)
hash->size++;
return 0;
}
/**
* librdf_hash_memory_exists:
* @context: memory hash context
* @key: key
* @value: value
*
* Test the existence of a key in the hash.
*
* Return value: >0 if the key/value exists in the hash, 0 if not, <0 on failure
**/
static int
librdf_hash_memory_exists(void* context,
librdf_hash_datum *key, librdf_hash_datum *value)
{
librdf_hash_memory_context* hash=(librdf_hash_memory_context*)context;
librdf_hash_memory_node* node;
librdf_hash_memory_node_value *vnode;
node=librdf_hash_memory_find_node(hash,
(char*)key->data, key->size,
NULL, NULL);
/* key not found */
if(!node)
return 0;
/* no value wanted */
if(!value)
return 1;
/* search for value in list of values */
for(vnode=node->values; vnode; vnode=vnode->next) {
if(value->size == vnode->value_len &&
!memcmp(value->data, vnode->value, value->size))
break;
}
return (vnode != NULL);
}
/**
* librdf_hash_memory_delete_key_value:
* @context: memory hash context
* @key: pointer to key to delete
* @value: pointer to value to delete
*
* - Delete a key/value pair from the hash.
*
* Return value: non 0 on failure
**/
static int
librdf_hash_memory_delete_key_value(void* context, librdf_hash_datum *key,
librdf_hash_datum *value)
{
librdf_hash_memory_context* hash=(librdf_hash_memory_context*)context;
librdf_hash_memory_node *node, *prev, *next;
librdf_hash_memory_node_value *vnode, *vprev;
int bucket;
node=librdf_hash_memory_find_node(hash,
(char*)key->data, key->size,
&bucket, &prev);
/* key not found anywhere */
if(!node)
return 1;
/* search for value in list of values */
vnode=node->values;
vprev=NULL;
while(vnode) {
if(value->size == vnode->value_len &&
!memcmp(value->data, vnode->value, value->size))
break;
vprev=vnode;
vnode=vnode->next;
}
/* key/value combination not found */
if(!vnode)
return 1;
/* found - delete it from list */
if(!vprev) {
/* at start of list so delete from there */
node->values=vnode->next;
} else
vprev->next=vnode->next;
/* free value and value node */
if(vnode->value)
LIBRDF_FREE(librdf_hash_memory_node_value, vnode->value);
LIBRDF_FREE(librdf_hash_memory_node_value, vnode);
/* update hash counts */
hash->values--;
/* check if last value was removed */
if(node->values)
/* no, so return success */
return 0;
/* yes - all values gone so need to delete entire key node */
if(!prev) {
/* is at start of list, so delete from there */
if(!(hash->nodes[bucket]=node->next))
/* hash bucket occupancy is one less if bucket is now empty */
hash->size--;
next=NULL;
} else
next=prev->next=node->next;
/* free node */
librdf_free_hash_memory_node(node);
/* see if there are remaining values for this key */
if(!next) {
/* no - so was last value for that key, reduce key count */
hash->keys--;
} else {
int found=0;
node=next;
while(node) {
if(key->size == node->key_len && !memcmp(key, node->key, key->size)){
found=1;
break;
}
node=node->next;
}
/* no further key values found - so was last value for that key */
if(!found)
hash->keys--;
}
return 0;
}
/**
* librdf_hash_memory_delete_key:
* @context: memory hash context
* @key: pointer to key to delete
*
* - Delete a key and all its values from the hash.
*
* Return value: non 0 on failure
**/
static int
librdf_hash_memory_delete_key(void* context, librdf_hash_datum *key)
{
librdf_hash_memory_context* hash=(librdf_hash_memory_context*)context;
librdf_hash_memory_node *node, *prev;
int bucket;
node=librdf_hash_memory_find_node(hash,
(char*)key->data, key->size,
&bucket, &prev);
/* not found anywhere */
if(!node)
return 1;
/* search list from here */
if(!prev) {
/* is at start of list, so delete from there */
if(!(hash->nodes[bucket]=node->next))
/* hash bucket occupancy is one less if bucket is now empty */
hash->size--;
} else
prev->next=node->next;
/* update hash counts */
hash->keys--;
hash->values-= node->values_count;
/* free node */
librdf_free_hash_memory_node(node);
return 0;
}
/**
* librdf_hash_memory_sync:
* @context: memory hash context
*
* Flush the hash to disk.
*
* Not used
*
* Return value: 0
**/
static int
librdf_hash_memory_sync(void* context)
{
/* Not applicable */
return 0;
}
/**
* librdf_hash_memory_get_fd:
* @context: memory hash context
*
* Get the file descriptor representing the hash.
*
* Not used
*
* Return value: -1
**/
static int
librdf_hash_memory_get_fd(void* context)
{
/* Not applicable */
return -1;
}
/* local function to register memory hash functions */
/**
* librdf_hash_memory_register_factory:
* @factory: hash factory prototype
*
* Register the memory hash module with the hash factory.
*
**/
static void
librdf_hash_memory_register_factory(librdf_hash_factory *factory)
{
factory->context_length = sizeof(librdf_hash_memory_context);
factory->cursor_context_length = sizeof(librdf_hash_memory_cursor_context);
factory->create = librdf_hash_memory_create;
factory->destroy = librdf_hash_memory_destroy;
factory->open = librdf_hash_memory_open;
factory->close = librdf_hash_memory_close;
factory->clone = librdf_hash_memory_clone;
factory->values_count = librdf_hash_memory_values_count;
factory->put = librdf_hash_memory_put;
factory->exists = librdf_hash_memory_exists;
factory->delete_key = librdf_hash_memory_delete_key;
factory->delete_key_value = librdf_hash_memory_delete_key_value;
factory->sync = librdf_hash_memory_sync;
factory->get_fd = librdf_hash_memory_get_fd;
factory->cursor_init = librdf_hash_memory_cursor_init;
factory->cursor_get = librdf_hash_memory_cursor_get;
factory->cursor_finish = librdf_hash_memory_cursor_finish;
}
/**
* librdf_init_hash_memory:
* @world: redland world object
*
* Initialise the memory hash module.
*
* Initialises the memory hash module and sets the default hash load factor.
*
* The recommended and current default value is 0.75, i.e. 750/1000.
* To use the default value (whatever it is) use a value less than 0.
**/
void
librdf_init_hash_memory(librdf_world *world)
{
/* use default load factor */
if(world->hash_load_factor <= 0 || world->hash_load_factor > 999)
world->hash_load_factor=librdf_hash_default_load_factor;
librdf_hash_register_factory(world,
"memory", &librdf_hash_memory_register_factory);
}