summaryrefslogtreecommitdiff
path: root/src/include/utils/hsearch.h
blob: 93742aef063d1dbf6cb11c01aefdc9669727f878 (plain)
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
/*-------------------------------------------------------------------------
 *
 * hsearch.h
 *	  for hash tables, particularly hash tables in shared memory
 *
 *
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * $Id: hsearch.h,v 1.18 2001/01/24 19:43:28 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
#ifndef HSEARCH_H
#define HSEARCH_H


/*
 * Constants
 *
 * A hash table has a top-level "directory", each of whose entries points
 * to a "segment" of ssize bucket headers.	The maximum number of hash
 * buckets is thus dsize * ssize (but dsize may be expansible).  Of course,
 * the number of records in the table can be larger, but we don't want a
 * whole lot of records per bucket or performance goes down.
 *
 * In a hash table allocated in shared memory, the directory cannot be
 * expanded because it must stay at a fixed address.  The directory size
 * should be selected using hash_select_dirsize (and you'd better have
 * a good idea of the maximum number of entries!).	For non-shared hash
 * tables, the initial directory size can be left at the default.
 */
#define DEF_SEGSIZE			   256
#define DEF_SEGSIZE_SHIFT	   8/* must be log2(DEF_SEGSIZE) */
#define DEF_DIRSIZE			   256
#define DEF_FFACTOR			   1/* default fill factor */

#define PRIME1				   37		/* for the hash function */
#define PRIME2				   1048583


/*
 * Hash bucket is actually bigger than this.  Key field can have
 * variable length and a variable length data field follows it.
 */
typedef struct element
{
	unsigned long next;			/* secret from user */
	long		key;
} ELEMENT;

typedef unsigned long BUCKET_INDEX;

/* segment is an array of bucket pointers */
typedef BUCKET_INDEX *SEGMENT;
typedef unsigned long SEG_OFFSET;

typedef struct hashhdr
{
	long		dsize;			/* Directory Size */
	long		ssize;			/* Segment Size --- must be power of 2 */
	long		sshift;			/* Segment shift */
	long		max_bucket;		/* ID of Maximum bucket in use */
	long		high_mask;		/* Mask to modulo into entire table */
	long		low_mask;		/* Mask to modulo into lower half of table */
	long		ffactor;		/* Fill factor */
	long		nkeys;			/* Number of keys in hash table */
	long		nsegs;			/* Number of allocated segments */
	long		keysize;		/* hash key length in bytes */
	long		datasize;		/* elem data length in bytes */
	long		max_dsize;		/* 'dsize' limit if directory is fixed
								 * size */
	BUCKET_INDEX freeBucketIndex;		/* index of first free bucket */
#ifdef HASH_STATISTICS
	long		accesses;
	long		collisions;
#endif
} HHDR;

typedef struct htab
{
	HHDR	   *hctl;			/* shared control information */
	long		(*hash) ();		/* Hash Function */
	char	   *segbase;		/* segment base address for calculating
								 * pointer values */
	SEG_OFFSET *dir;			/* 'directory' of segm starts */
	void	   *(*alloc) (Size);	/* memory allocator */
} HTAB;

typedef struct hashctl
{
	long		ssize;			/* Segment Size */
	long		dsize;			/* Dirsize Size */
	long		ffactor;		/* Fill factor */
	long		(*hash) ();		/* Hash Function */
	long		keysize;		/* hash key length in bytes */
	long		datasize;		/* elem data length in bytes */
	long		max_dsize;		/* limit to dsize if directory size is
								 * limited */
	long	   *segbase;		/* base for calculating bucket + seg ptrs */
	void	   *(*alloc) (Size);	/* memory allocation function */
	long	   *dir;			/* directory if allocated already */
	long	   *hctl;			/* location of header information in shd
								 * mem */
} HASHCTL;

/* Flags to indicate action for hctl */
#define HASH_SEGMENT	0x002	/* Setting segment size */
#define HASH_DIRSIZE	0x004	/* Setting directory size */
#define HASH_FFACTOR	0x008	/* Setting fill factor */
#define HASH_FUNCTION	0x010	/* Set user defined hash function */
#define HASH_ELEM		0x020	/* Setting key/data size */
#define HASH_SHARED_MEM 0x040	/* Setting shared mem const */
#define HASH_ATTACH		0x080	/* Do not initialize hctl */
#define HASH_ALLOC		0x100	/* Setting memory allocator */


/* seg_alloc assumes that INVALID_INDEX is 0 */
#define INVALID_INDEX			(0)
#define NO_MAX_DSIZE			(-1)
/* number of hash buckets allocated at once */
#define BUCKET_ALLOC_INCR		(30)

/* hash_search operations */
typedef enum
{
	HASH_FIND,
	HASH_ENTER,
	HASH_REMOVE,
	HASH_FIND_SAVE,
	HASH_REMOVE_SAVED
} HASHACTION;

/* hash_seq status (should be considered an opaque type by callers) */
typedef struct
{
	HTAB   *hashp;
	long	curBucket;
	BUCKET_INDEX curIndex;
} HASH_SEQ_STATUS;

/*
 * prototypes from functions in dynahash.c
 */
extern HTAB *hash_create(int nelem, HASHCTL *info, int flags);
extern void hash_destroy(HTAB *hashp);
extern void hash_stats(char *where, HTAB *hashp);
extern long *hash_search(HTAB *hashp, char *keyPtr, HASHACTION action,
			bool *foundPtr);
extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp);
extern long *hash_seq_search(HASH_SEQ_STATUS *status);
extern long hash_estimate_size(long num_entries, long keysize, long datasize);
extern long hash_select_dirsize(long num_entries);

/*
 * prototypes from functions in hashfn.c
 */
extern long string_hash(char *key, int keysize);
extern long tag_hash(int *key, int keysize);

#endif	 /* HSEARCH_H */