1/*****************************************************************************
2
3Copyright (c) 2007, 2009, Oracle and/or its affiliates. All Rights Reserved.
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License, version 2.0,
7as published by the Free Software Foundation.
8
9This program is also distributed with certain software (including
10but not limited to OpenSSL) that is licensed under separate terms,
11as designated in a particular file or component or in included license
12documentation.  The authors of MySQL hereby grant you an additional
13permission to link the program and your derivative works with the
14separately licensed software that they have included with MySQL.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License, version 2.0, for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
24
25*****************************************************************************/
26
27/**************************************************//**
28@file include/ha0storage.ic
29Hash storage.
30Provides a data structure that stores chunks of data in
31its own storage, avoiding duplicates.
32
33Created September 24, 2007 Vasil Dimov
34*******************************************************/
35
36#include "univ.i"
37#include "ha0storage.h"
38#include "hash0hash.h"
39#include "mem0mem.h"
40
41/** Hash storage for strings */
42struct ha_storage_t {
43	mem_heap_t*	heap;	/*!< memory heap from which memory is
44				allocated */
45	hash_table_t*	hash;	/*!< hash table used to avoid
46				duplicates */
47};
48
49/** Objects of this type are stored in ha_storage_t */
50struct ha_storage_node_t {
51	ulint			data_len;/*!< length of the data */
52	const void*		data;	/*!< pointer to data */
53	ha_storage_node_t*	next;	/*!< next node in hash chain */
54};
55
56/*******************************************************************//**
57Creates a hash storage. If any of the parameters is 0, then a default
58value is used.
59@return	own: hash storage */
60UNIV_INLINE
61ha_storage_t*
62ha_storage_create(
63/*==============*/
64	ulint	initial_heap_bytes,	/*!< in: initial heap's size */
65	ulint	initial_hash_cells)	/*!< in: initial number of cells
66					in the hash table */
67{
68	ha_storage_t*	storage;
69	mem_heap_t*	heap;
70
71	if (initial_heap_bytes == 0) {
72
73		initial_heap_bytes = HA_STORAGE_DEFAULT_HEAP_BYTES;
74	}
75
76	if (initial_hash_cells == 0) {
77
78		initial_hash_cells = HA_STORAGE_DEFAULT_HASH_CELLS;
79	}
80
81	/* we put "storage" within "storage->heap" */
82
83	heap = mem_heap_create(sizeof(ha_storage_t)
84			       + initial_heap_bytes);
85
86	storage = (ha_storage_t*) mem_heap_alloc(heap,
87						 sizeof(ha_storage_t));
88
89	storage->heap = heap;
90	storage->hash = hash_create(initial_hash_cells);
91
92	return(storage);
93}
94
95/*******************************************************************//**
96Empties a hash storage, freeing memory occupied by data chunks.
97This invalidates any pointers previously returned by ha_storage_put().
98The hash storage is not invalidated itself and can be used again. */
99UNIV_INLINE
100void
101ha_storage_empty(
102/*=============*/
103	ha_storage_t**	storage)	/*!< in/out: hash storage */
104{
105	ha_storage_t	temp_storage;
106
107	temp_storage.heap = (*storage)->heap;
108	temp_storage.hash = (*storage)->hash;
109
110	hash_table_clear(temp_storage.hash);
111	mem_heap_empty(temp_storage.heap);
112
113	*storage = (ha_storage_t*) mem_heap_alloc(temp_storage.heap,
114						  sizeof(ha_storage_t));
115
116	(*storage)->heap = temp_storage.heap;
117	(*storage)->hash = temp_storage.hash;
118}
119
120/*******************************************************************//**
121Frees a hash storage and everything it contains, it cannot be used after
122this call.
123This invalidates any pointers previously returned by ha_storage_put(). */
124UNIV_INLINE
125void
126ha_storage_free(
127/*============*/
128	ha_storage_t*	storage)	/*!< in, own: hash storage */
129{
130	/* order is important because the pointer storage->hash is
131	within the heap */
132	hash_table_free(storage->hash);
133	mem_heap_free(storage->heap);
134}
135
136/*******************************************************************//**
137Gets the size of the memory used by a storage.
138@return	bytes used */
139UNIV_INLINE
140ulint
141ha_storage_get_size(
142/*================*/
143	const ha_storage_t*	storage)	/*!< in: hash storage */
144{
145	ulint	ret;
146
147	ret = mem_heap_get_size(storage->heap);
148
149	/* this assumes hash->heap and hash->heaps are NULL */
150	ret += sizeof(hash_table_t);
151	ret += sizeof(hash_cell_t) * hash_get_n_cells(storage->hash);
152
153	return(ret);
154}
155