Commit 48ed48eb authored by vasil's avatar vasil

branches/zip:

Add a type that stores chunks of data in its own storage and avoids
duplicates. Supported methods:

ha_storage_create()
Allocates new storage object.

ha_storage_put()
Copies a given data chunk into the storage and returns pointer to the
copy. If the data chunk is already present, a pointer to the existing
object is returned and the given data chunk is not copied.

ha_storage_empty()
Clears (empties) the storage from all data chunks that are stored in it.

ha_storage_free()
Destroys a storage object. Opposite to ha_storage_create().

Approved by:	Marko
parent dd1f1c3f
......@@ -53,7 +53,10 @@ noinst_HEADERS = include/btr0btr.h include/btr0btr.ic \
include/fsp0fsp.ic include/fut0fut.h \
include/fut0fut.ic include/fut0lst.h \
include/fut0lst.ic include/ha0ha.h \
include/ha0ha.ic include/hash0hash.h \
include/ha0ha.ic \
include/ha0storage.h \
include/ha0storage.ic \
include/hash0hash.h \
include/hash0hash.ic include/ibuf0ibuf.h \
include/ibuf0ibuf.ic include/ibuf0types.h \
include/lock0iter.h \
......@@ -138,7 +141,9 @@ libinnobase_a_SOURCES = btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
dict/dict0load.c dict/dict0mem.c dyn/dyn0dyn.c \
eval/eval0eval.c eval/eval0proc.c \
fil/fil0fil.c fsp/fsp0fsp.c fut/fut0fut.c \
fut/fut0lst.c ha/ha0ha.c ha/hash0hash.c \
fut/fut0lst.c ha/ha0ha.c \
ha/ha0storage.c \
ha/hash0hash.c \
ibuf/ibuf0ibuf.c lock/lock0iter.c \
lock/lock0lock.c \
log/log0log.c log/log0recv.c mach/mach0data.c \
......
/******************************************************
Hash storage.
Provides a data structure that stores chunks of data in
its own storage, avoiding duplicates.
(c) 2007 Innobase Oy
Created September 22, 2007 Vasil Dimov
*******************************************************/
#include "univ.i"
#include "ha0storage.h"
#include "hash0hash.h"
#include "mem0mem.h"
#include "ut0rnd.h"
#ifdef UNIV_NONINL
#include "ha0storage.ic"
#endif
/***********************************************************************
Retrieves a data from a storage. If it is present, a pointer to the
stored copy of data is returned, otherwise NULL is returned. */
static
void*
ha_storage_get(
/*===========*/
ha_storage_t* storage, /* in: hash storage */
const void* data, /* in: data to check for */
ulint data_len) /* in: data length */
{
ha_storage_node_t* node;
ulint fold;
/* avoid repetitive calls to ut_fold_binary() in the HASH_SEARCH
macro */
fold = ut_fold_binary(data, data_len);
#define IS_FOUND \
node->data_len == data_len && memcmp(node->data, data, data_len) == 0
HASH_SEARCH(
next, /* node->"next" */
storage->hash, /* the hash table */
fold, /* key */
ha_storage_node_t*, /* type of node->next */
node, /* auxiliary variable */
IS_FOUND); /* search criteria */
if (node == NULL) {
return(NULL);
}
/* else */
return(node->data);
}
/***********************************************************************
Copies data into the storage and returns a pointer to the copy. If the
same data chunk is already present, then pointer to it is returned.
Data chunks are considered to be equal if len1 == len2 and
memcmp(data1, data2, len1) == 0. */
void*
ha_storage_put(
/*===========*/
ha_storage_t* storage, /* in/out: hash storage */
const void* data, /* in: data to store */
ulint data_len) /* in: data length */
{
void* raw;
ha_storage_node_t* node;
void* data_copy;
ulint fold;
/* check if data chunk is already present */
data_copy = ha_storage_get(storage, data, data_len);
if (data_copy != NULL) {
return(data_copy);
}
/* not present, add it */
/* we put the auxiliary node struct and the data itself in one
continuous block */
raw = mem_heap_alloc(storage->heap,
sizeof(ha_storage_node_t) + data_len);
node = (ha_storage_node_t*) raw;
data_copy = (byte*) raw + sizeof(*node);
memcpy(data_copy, data, data_len);
node->data_len = data_len;
node->data = data_copy;
/* avoid repetitive calls to ut_fold_binary() in the HASH_INSERT
macro */
fold = ut_fold_binary(data, data_len);
HASH_INSERT(
ha_storage_node_t, /* type used in the hash chain */
next, /* node->"next" */
storage->hash, /* the hash table */
fold, /* key */
node); /* add this data to the hash */
return(data_copy);
}
/******************************************************
Hash storage.
Provides a data structure that stores chunks of data in
its own storage, avoiding duplicates.
(c) 2007 Innobase Oy
Created September 22, 2007 Vasil Dimov
*******************************************************/
#ifndef ha0storage_h
#define ha0storage_h
#include "univ.i"
/* This value is used by default by ha_storage_create(). More memory
is allocated later when/if it is needed. */
#define HA_STORAGE_DEFAULT_HEAP_BYTES 1024
/* This value is used by default by ha_storage_create(). It is a
constant per ha_storage's lifetime. */
#define HA_STORAGE_DEFAULT_HASH_CELLS 4096
typedef struct ha_storage_struct ha_storage_t;
/***********************************************************************
Creates a hash storage. If any of the parameters is 0, then a default
value is used. */
UNIV_INLINE
ha_storage_t*
ha_storage_create(
/*==============*/
/* out, own: hash storage */
ulint initial_heap_bytes, /* in: initial heap's size */
ulint initial_hash_cells); /* in: initial number of cells
in the hash table */
/***********************************************************************
Copies string into the storage and returns a pointer to the copy. If the
same string is already present, then pointer to it is returned.
Strings are considered to be equal if strcmp(str1, str2) == 0. */
#define ha_storage_put_str(storage, str) \
ha_storage_put((storage), (str), strlen(str) + 1)
/***********************************************************************
Copies data into the storage and returns a pointer to the copy. If the
same data chunk is already present, then pointer to it is returned.
Data chunks are considered to be equal if len1 == len2 and
memcmp(data1, data2, len1) == 0. */
void*
ha_storage_put(
/*===========*/
ha_storage_t* storage, /* in/out: hash storage */
const void* data, /* in: data to store */
ulint data_len); /* in: data length */
/***********************************************************************
Empties a hash storage, freeing memory occupied by data chunks.
This invalidates any pointers previously returned by ha_storage_put().
The hash storage is not invalidated itself and can be used again. */
UNIV_INLINE
void
ha_storage_empty(
/*=============*/
ha_storage_t** storage); /* in/out: hash storage */
/***********************************************************************
Frees a hash storage and everything it contains, it cannot be used after
this call.
This invalidates any pointers previously returned by ha_storage_put().
*/
UNIV_INLINE
void
ha_storage_free(
/*============*/
ha_storage_t* storage); /* in/out: hash storage */
#ifndef UNIV_NONINL
#include "ha0storage.ic"
#endif
#endif /* ha0storage_h */
/******************************************************
Hash storage.
Provides a data structure that stores chunks of data in
its own storage, avoiding duplicates.
(c) 2007 Innobase Oy
Created September 24, 2007 Vasil Dimov
*******************************************************/
#include "univ.i"
#include "ha0storage.h"
#include "hash0hash.h"
#include "mem0mem.h"
struct ha_storage_struct {
mem_heap_t* heap; /* storage from which memory is
allocated */
hash_table_t* hash; /* hash table used to avoid
duplicates */
};
/* Objects of this type are put in the hash */
typedef struct ha_storage_node_struct ha_storage_node_t;
struct ha_storage_node_struct {
ulint data_len;/* length of the data */
void* data; /* pointer to data */
ha_storage_node_t* next; /* next node in hash chain */
};
/***********************************************************************
Creates a hash storage. If any of the parameters is 0, then a default
value is used. */
UNIV_INLINE
ha_storage_t*
ha_storage_create(
/*==============*/
/* out, own: hash storage */
ulint initial_heap_bytes, /* in: initial heap's size */
ulint initial_hash_cells) /* in: initial number of cells
in the hash table */
{
ha_storage_t* storage;
mem_heap_t* heap;
if (initial_heap_bytes == 0) {
initial_heap_bytes = HA_STORAGE_DEFAULT_HEAP_BYTES;
}
if (initial_hash_cells == 0) {
initial_hash_cells = HA_STORAGE_DEFAULT_HASH_CELLS;
}
/* we put "storage" within "storage->heap" */
heap = mem_heap_create(sizeof(ha_storage_t)
+ initial_heap_bytes);
storage = (ha_storage_t*) mem_heap_alloc(heap,
sizeof(ha_storage_t));
storage->heap = heap;
storage->hash = hash_create(initial_hash_cells);
return(storage);
}
/***********************************************************************
Empties a hash storage, freeing memory occupied by data chunks.
This invalidates any pointers previously returned by ha_storage_put().
The hash storage is not invalidated itself and can be used again. */
UNIV_INLINE
void
ha_storage_empty(
/*=============*/
ha_storage_t** storage) /* in/out: hash storage */
{
ha_storage_t temp_storage;
temp_storage.heap = (*storage)->heap;
temp_storage.hash = (*storage)->hash;
/* order is important because the pointer temp_storage.hash is
within the heap */
hash_table_clear(temp_storage.hash);
mem_heap_empty(temp_storage.heap);
*storage = (ha_storage_t*) mem_heap_alloc(temp_storage.heap,
sizeof(ha_storage_t));
(*storage)->heap = temp_storage.heap;
(*storage)->hash = temp_storage.hash;
}
/***********************************************************************
Frees a hash storage and everything it contains, it cannot be used after
this call.
This invalidates any pointers previously returned by ha_storage_put().
*/
UNIV_INLINE
void
ha_storage_free(
/*============*/
ha_storage_t* storage) /* in/out: hash storage */
{
/* order is important because the pointer storage->hash is
within the heap */
hash_table_free(storage->hash);
mem_heap_free(storage->heap);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment