ha0ha.ic 6.46 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
/************************************************************************
The hash table with external chains

(c) 1994-1997 Innobase Oy

Created 8/18/1994 Heikki Tuuri
*************************************************************************/

#include "ut0rnd.h"
#include "mem0mem.h"

/* The hash table external chain node */

typedef struct ha_node_struct ha_node_t;

struct ha_node_struct {
	ha_node_t* next; /* next chain node or NULL if none */
	void*	data;	/* pointer to the data */
	ulint	fold;	/* fold value for the data */
};

/***************************************************************
Deletes a hash node. */

void
ha_delete_hash_node(
/*================*/
	hash_table_t*	table,		/* in: hash table */
	ha_node_t*	del_node);	/* in: node to be deleted */

/**********************************************************************
Gets a hash node data. */
UNIV_INLINE
void*
ha_node_get_data(
/*=============*/
				/* out: pointer to the data */
	ha_node_t*	node)	/* in: hash chain node */
{
	return(node->data);
}

/**********************************************************************
Sets hash node data. */
UNIV_INLINE
void
ha_node_set_data(
/*=============*/
	ha_node_t*	node,	/* in: hash chain node */
	void*		data)	/* in: pointer to the data */
{
	node->data = data;
}

/**********************************************************************
Gets the next node in a hash chain. */
UNIV_INLINE
ha_node_t*
ha_chain_get_next(
/*==============*/
				/* out: next node, NULL if none */
	hash_table_t*	table,	/* in: hash table */
	ha_node_t*	node)	/* in: hash chain node */
{
	ut_ad(table);

	return(node->next);
}

/**********************************************************************
Gets the first node in a hash chain. */
UNIV_INLINE
ha_node_t*
ha_chain_get_first(
/*===============*/
				/* out: first node, NULL if none */
	hash_table_t*	table,	/* in: hash table */
	ulint		fold)	/* in: fold value determining the chain */
{
	return(hash_get_nth_cell(table, hash_calc_hash(fold, table))->node);
}

/*****************************************************************
Looks for an element in a hash table. */
UNIV_INLINE
ha_node_t*
ha_search(
/*======*/
				/* out: pointer to the first hash table node
				in chain having the fold number, NULL if not
				found */
	hash_table_t*	table,	/* in: hash table */
	ulint		fold)	/* in: folded value of the searched data */
{
	ha_node_t*	node;

	ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));

	node = ha_chain_get_first(table, fold);

	while (node) {
		if (node->fold == fold) {

			return(node);
		}

		node = ha_chain_get_next(table, node);
	}

	return(NULL);
}

/*****************************************************************
Looks for an element in a hash table. */
UNIV_INLINE
void*
ha_search_and_get_data(
/*===================*/
				/* out: pointer to the data of the first hash
				table node in chain having the fold number,
				NULL if not found */
	hash_table_t*	table,	/* in: hash table */
	ulint		fold)	/* in: folded value of the searched data */
{
	ha_node_t*	node;

	ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));

	node = ha_chain_get_first(table, fold);

	while (node) {
		if (node->fold == fold) {

			return(node->data);
		}

		node = ha_chain_get_next(table, node);
	}

	return(NULL);
}

/*****************************************************************
Returns the next matching hash table node in chain. */
UNIV_INLINE
ha_node_t*
ha_next(
/*====*/
				/* out: pointer to the next hash table node
				in chain with the fold value, NULL if not
				found */
	hash_table_t*	table,	/* in: hash table */
	ha_node_t*	node)	/* in: hash table node */
{
	ulint	fold;

	fold = node->fold;

	ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));

	node = ha_chain_get_next(table, node);

	while (node) {
		if (node->fold == fold) {

			return(node);
		}

		node = ha_chain_get_next(table, node);
	}

	return(NULL);
}

/*************************************************************
Looks for an element when we know the pointer to the data. */
UNIV_INLINE
ha_node_t*
ha_search_with_data(
/*================*/
				/* out: pointer to the hash table node, NULL
				if not found in the table */
	hash_table_t*	table,	/* in: hash table */
	ulint		fold,	/* in: folded value of the searched data */
	void*		data)	/* in: pointer to the data */
{
	ha_node_t*	node;

	ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));

	node = ha_chain_get_first(table, fold);

	while (node) {
		if (node->data == data) {

			return(node);
		}

		node = ha_chain_get_next(table, node);
	}

	return(NULL);
}

/*************************************************************
Looks for an element when we know the pointer to the data, and updates
the pointer to data, if found. */
UNIV_INLINE
void
ha_search_and_update_if_found(
/*==========================*/
	hash_table_t*	table,	/* in: hash table */
	ulint		fold,	/* in: folded value of the searched data */
	void*		data,	/* in: pointer to the data */
	void*		new_data)/* in: new pointer to the data */
{
	ha_node_t*	node;

	ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));

	node = ha_search_with_data(table, fold, data);

	if (node) {
		node->data = new_data;
	}
}

/*************************************************************
Looks for an element when we know the pointer to the data, and deletes
it from the hash table, if found. */
UNIV_INLINE
ibool
ha_search_and_delete_if_found(
/*==========================*/
				/* out: TRUE if found */
	hash_table_t*	table,	/* in: hash table */
	ulint		fold,	/* in: folded value of the searched data */
	void*		data)	/* in: pointer to the data */
{
	ha_node_t*	node;

	ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));

	node = ha_search_with_data(table, fold, data);

	if (node) {
		ha_delete_hash_node(table, node);

		return(TRUE);
	}

	return(FALSE);
}

/*****************************************************************
Reserves the necessary hash table mutex and inserts an entry into the hash
table. */
UNIV_INLINE
ibool
ha_insert_for_fold_mutex(
/*=====================*/
				/* out: TRUE if succeed, FALSE if no more
				memory could be allocated */
	hash_table_t*	table,	/* in: hash table */
	ulint		fold,	/* in: folded value of data; if a node with
				the same fold value already exists, it is
				updated to point to the same data, and no new
				node is created! */
	void*		data)	/* in: data, must not be NULL */
{
	ibool	ret;

	hash_mutex_enter(table, fold);

	ret = ha_insert_for_fold(table, fold, data);

	hash_mutex_exit(table, fold);

	return(ret);
}