usr/src/cmd/fs.d/nfs/mountd/hashset.c
author Pavan Mettu - Oracle Corporation - Menlo Park United States <Pavan.Mettu@Oracle.COM>
Wed, 11 Aug 2010 17:11:30 -0500
changeset 13092 fcc1e406c13f
parent 11211 a6230133d60c
permissions -rw-r--r--
6975309 PSARC2007_393 Move /etc/default/{nfs/autofs} parameters to SMF PSARC 2007/393 converting /etc/default/{nfs,autofs} to SMF properties
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
11211
a6230133d60c 6882460 Hundreds of NFSv3 client mounts followed by immediate reads causes timeouts
Thomas Haynes <Thomas.Haynes@Sun.COM>
parents: 0
diff changeset
     5
 * Common Development and Distribution License (the "License").
a6230133d60c 6882460 Hundreds of NFSv3 client mounts followed by immediate reads causes timeouts
Thomas Haynes <Thomas.Haynes@Sun.COM>
parents: 0
diff changeset
     6
 * You may not use this file except in compliance with the License.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 */
11211
a6230133d60c 6882460 Hundreds of NFSv3 client mounts followed by immediate reads causes timeouts
Thomas Haynes <Thomas.Haynes@Sun.COM>
parents: 0
diff changeset
    21
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
11211
a6230133d60c 6882460 Hundreds of NFSv3 client mounts followed by immediate reads causes timeouts
Thomas Haynes <Thomas.Haynes@Sun.COM>
parents: 0
diff changeset
    23
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
a6230133d60c 6882460 Hundreds of NFSv3 client mounts followed by immediate reads causes timeouts
Thomas Haynes <Thomas.Haynes@Sun.COM>
parents: 0
diff changeset
    24
 * Use is subject to license terms.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
#include <stdio.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
#include <stdlib.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
#include <string.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
#include "hashset.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
#include "mountd.h"
11211
a6230133d60c 6882460 Hundreds of NFSv3 client mounts followed by immediate reads causes timeouts
Thomas Haynes <Thomas.Haynes@Sun.COM>
parents: 0
diff changeset
    32
#include <sys/sdt.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
 * HASHSET is hash table managing pointers to a set of keys
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
 * (set is a collection without duplicates). The public interface
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
 * of the HASHSET is similar to the java.util.Set interface.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
 * Unlike the libc `hsearch' based hash table, this implementation
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
 * does allow multiple instances of HASHSET within a single application,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
 * and the HASHSET_ITERATOR allows to iterate through the entire set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
 * using h_next().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 * HASHSET does not store actual keys but only pointers to keys. Hence the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 * data remains intact when HASHSET grows (resizes itself). HASHSET accesses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 * the actual key data only through the hash and equal functions given
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 * as arguments to h_create.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
 * Hash collisions are resolved with linked lists.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
typedef struct HashSetEntry {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
	uint_t e_hash;		/* Hash value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
	const void *e_key;	/* Pointer to a key */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
	struct HashSetEntry *e_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
} ENTRY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
struct HashSet {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
	ENTRY **h_table;	/* Pointer to an array of ENTRY'ies */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
	uint_t h_tableSize;	/* Size of the array */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
	uint_t h_count;		/* Current count */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
	uint_t h_threshold;	/* loadFactor threshold */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
	float  h_loadFactor;	/* Current loadFactor (h_count/h_tableSize( */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
	uint_t (*h_hash) (const void *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
	int    (*h_equal) (const void *, const void *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
struct HashSetIterator {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
	HASHSET i_h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
	uint_t i_indx;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
	ENTRY *i_e;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
	uint_t i_coll;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
static void rehash(HASHSET h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
#define	DEFAULT_INITIALCAPACITY	1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
#define	DEFAULT_LOADFACTOR	0.75
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
 *  Create a HASHSET
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
 *  - HASHSET is a hash table of pointers to keys
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
 *  - duplicate keys are not allowed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
 *  - the HASHSET is opaque and can be accessed only through the h_ functions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
 *  - two keys k1 and k2 are considered equal if the result of equal(k1, k2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
 *    is non-zero
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
 *  - the function hash(key) is used to compute hash values for keys; if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
 *    keys are "equal" the values returned by the hash function must be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
 *    identical.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
HASHSET
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
h_create(uint_t (*hash) (const void *),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
    int    (*equal) (const void *, const void *),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
    uint_t initialCapacity,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
    float loadFactor)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
	HASHSET h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
	if (initialCapacity == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
		initialCapacity = DEFAULT_INITIALCAPACITY;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
	if (loadFactor < 0.0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
		loadFactor = DEFAULT_LOADFACTOR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
	h = exmalloc(sizeof (*h));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
	if (h == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
	h->h_table = exmalloc(initialCapacity * sizeof (ENTRY *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
	(void) memset(h->h_table, 0, initialCapacity * sizeof (ENTRY *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
	if (h->h_table == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
		free(h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
		return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
	h->h_tableSize = initialCapacity;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
	h->h_hash = hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
	h->h_equal = equal;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
	h->h_loadFactor = loadFactor;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
	h->h_threshold = (uint_t)(initialCapacity * loadFactor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
	h->h_count = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
	return (h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
 *  Return a pointer to a matching key
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
const void *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
h_get(const HASHSET h, void *key)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
	uint_t hash = h->h_hash(key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
	uint_t i = hash % h->h_tableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	ENTRY *e;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	for (e = h->h_table[i]; e; e = e->e_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
		if (e->e_hash == hash && h->h_equal(e->e_key, key))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
			return (e->e_key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
 *  Rehash (grow) HASHSET
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
 *  - called when loadFactor exceeds threshold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
 *  - new size is 2*old_size+1
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
static void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
rehash(HASHSET h)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
	uint_t i = h->h_tableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
	uint_t newtabSize = 2 * i + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
	ENTRY **newtab = exmalloc(newtabSize * sizeof (ENTRY *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
	(void) memset(newtab, 0, newtabSize * sizeof (ENTRY *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
	while (i--) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
		ENTRY *e, *next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
		for (e = h->h_table[i]; e; e = next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
			uint_t k = e->e_hash % newtabSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
			next = (ENTRY *) e->e_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
			e->e_next = (ENTRY *) newtab[k];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
			newtab[k] = e;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
	h->h_threshold = (uint_t)(newtabSize * h->h_loadFactor);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
	h->h_tableSize = newtabSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
	free(h->h_table);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
	h->h_table = newtab;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
 *  Store a key into a HASHSET
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
 *  - if there is already an "equal" key then the new key will not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
 *    be stored and the function returns a pointer to an existing key
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
 *  - otherwise the function stores pointer to the new key and return NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
const void *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
h_put(HASHSET h, const void *key)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
	uint_t hash = h->h_hash(key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
	uint_t indx = hash % h->h_tableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
	ENTRY *e;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
	for (e = h->h_table[indx]; e; e = e->e_next)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
		if (e->e_hash == hash && h->h_equal(e->e_key, key))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
			return (key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
	if (h->h_count >= h->h_threshold) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
		rehash(h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
		indx = hash % h->h_tableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	e = exmalloc(sizeof (ENTRY));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	e->e_hash = hash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	e->e_key = (void *) key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
	e->e_next = h->h_table[indx];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
	h->h_table[indx] = e;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
	h->h_count++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
11211
a6230133d60c 6882460 Hundreds of NFSv3 client mounts followed by immediate reads causes timeouts
Thomas Haynes <Thomas.Haynes@Sun.COM>
parents: 0
diff changeset
   211
	DTRACE_PROBE2(mountd, hashset, h->h_count, h->h_loadFactor);
a6230133d60c 6882460 Hundreds of NFSv3 client mounts followed by immediate reads causes timeouts
Thomas Haynes <Thomas.Haynes@Sun.COM>
parents: 0
diff changeset
   212
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
 *  Delete a key
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
 *  - if there is no "equal" key in the HASHSET the fuction returns NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
 *  - otherwise the function returns a pointer to the deleted key
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
const void *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
h_delete(HASHSET h, const void *key)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
	uint_t hash = h->h_hash(key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
	uint_t indx = hash % h->h_tableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
	ENTRY *e, *prev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
	for (e = h->h_table[indx], prev = NULL; e; prev = e, e = e->e_next) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
		if (e->e_hash == hash && h->h_equal(e->e_key, key)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
			key = e->e_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
			if (prev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
				prev->e_next = e->e_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
			else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
				h->h_table[indx] = e->e_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
			free(e);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
			return (key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
 *  Return an opaque HASHSET_ITERATOR (to be used in h_next())
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
HASHSET_ITERATOR
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
h_iterator(HASHSET h)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
	HASHSET_ITERATOR i = exmalloc(sizeof (*i));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
	i->i_h = h;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	i->i_indx = h->h_tableSize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
	i->i_e = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
	i->i_coll = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
	return (i);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
 * Return a pointer to a next key
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
const void *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
h_next(HASHSET_ITERATOR i)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
	const void *key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
	while (i->i_e == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
		if (i->i_indx-- == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
			return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
		i->i_e = i->i_h->h_table[i->i_indx];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
	key = i->i_e->e_key;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
	i->i_e = i->i_e->e_next;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
	if (i->i_e)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
		i->i_coll++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
	return (key);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
}