mirror of
https://github.com/MariaDB/server.git
synced 2025-01-23 23:34:34 +01:00
48ed48eb49
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
111 lines
2.7 KiB
C
111 lines
2.7 KiB
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);
|
|
}
|