PostgreSQL Source Code git master
Loading...
Searching...
No Matches
shmem_hash.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * shmem_hash.c
4 * hash table implementation in shared memory
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 * A shared memory hash table implementation on top of the named, fixed-size
10 * shared memory areas managed by shmem.c. Each hash table has its own free
11 * list, so hash buckets can be reused when an item is deleted.
12 *
13 * IDENTIFICATION
14 * src/backend/storage/ipc/shmem_hash.c
15 *
16 *-------------------------------------------------------------------------
17 */
18
19#include "postgres.h"
20
21#include "storage/shmem.h"
23#include "utils/memutils.h"
24
25/*
26 * A very simple allocator used to carve out different parts of a hash table
27 * from a previously allocated contiguous shared memory area.
28 */
30{
31 char *next; /* start of free space in the area */
32 char *end; /* end of the shmem area */
34
35static void *ShmemHashAlloc(Size size, void *alloc_arg);
36
37/*
38 * ShmemRequestHash -- Request a shared memory hash table.
39 *
40 * Similar to ShmemRequestStruct(), but requests a hash table instead of an
41 * opaque area.
42 */
43void
45{
47
48 Assert(options->name != NULL);
49
51 sizeof(ShmemHashOpts));
53
54 /* Set options for the fixed-size area holding the hash table */
55 options_copy->base.name = options->name;
56 options_copy->base.size = hash_estimate_size(options_copy->nelems,
57 options_copy->hash_info.entrysize);
58
60}
61
62void
64{
66 int hash_flags = options->hash_flags;
67 HTAB *htab;
68
69 options->hash_info.hctl = location;
70 htab = shmem_hash_create(location, options->base.size, false,
71 options->name,
72 options->nelems, &options->hash_info, hash_flags);
73
74 if (options->ptr)
75 *options->ptr = htab;
76}
77
78void
80{
82 int hash_flags = options->hash_flags;
83 HTAB *htab;
84
85 /* attach to it rather than allocate and initialize new space */
86 hash_flags |= HASH_ATTACH;
87 options->hash_info.hctl = location;
88 Assert(options->hash_info.hctl != NULL);
89 htab = shmem_hash_create(location, options->base.size, true,
90 options->name,
91 options->nelems, &options->hash_info, hash_flags);
92
93 if (options->ptr)
94 *options->ptr = htab;
95}
96
97/*
98 * ShmemInitHash -- Create and initialize, or attach to, a
99 * shared memory hash table.
100 *
101 * We assume caller is doing some kind of synchronization
102 * so that two processes don't try to create/initialize the same
103 * table at once. (In practice, all creations are done in the postmaster
104 * process; child processes should always be attaching to existing tables.)
105 *
106 * nelems is the maximum number of hashtable entries.
107 *
108 * *infoP and hash_flags must specify at least the entry sizes and key
109 * comparison semantics (see hash_create()). Flag bits and values specific
110 * to shared-memory hash tables are added here, except that callers may
111 * choose to specify HASH_PARTITION.
112 *
113 * Note: This is a legacy interface, kept for backwards compatibility with
114 * extensions. Use ShmemRequestHash() in new code!
115 */
116HTAB *
117ShmemInitHash(const char *name, /* table string name for shmem index */
118 int64 nelems, /* size of the table */
119 HASHCTL *infoP, /* info about key and bucket size */
120 int hash_flags) /* info about infoP */
121{
122 bool found;
123 size_t size;
124 void *location;
125
126 size = hash_estimate_size(nelems, infoP->entrysize);
127
128 /*
129 * Look it up in the shmem index or allocate.
130 *
131 * NOTE: The area is requested internally as SHMEM_KIND_STRUCT instead of
132 * SHMEM_KIND_HASH. That's correct because we do the hash table
133 * initialization by calling shmem_hash_create() ourselves. (We don't
134 * expose the request kind to users; if we did, that would be confusing.)
135 */
136 location = ShmemInitStruct(name, size, &found);
137
138 return shmem_hash_create(location, size, found,
139 name, nelems, infoP, hash_flags);
140}
141
142/*
143 * Initialize or attach to a shared hash table in the given shmem region.
144 *
145 * This is exposed to allow InitShmemAllocator() to share the logic for
146 * bootstrapping the ShmemIndex hash table.
147 */
148HTAB *
149shmem_hash_create(void *location, size_t size, bool found,
150 const char *name, int64 nelems, HASHCTL *infoP, int hash_flags)
151{
153
154 /*
155 * Hash tables allocated in shared memory have a fixed directory and have
156 * all elements allocated upfront. We don't support growing because we'd
157 * need to grow the underlying shmem region with it.
158 *
159 * The shared memory allocator must be specified too.
160 */
161 infoP->alloc = ShmemHashAlloc;
162 infoP->alloc_arg = NULL;
164
165 /*
166 * if it already exists, attach to it rather than allocate and initialize
167 * new space
168 */
169 if (!found)
170 {
171 allocator.next = (char *) location;
172 allocator.end = (char *) location + size;
173 infoP->alloc_arg = &allocator;
174 }
175 else
176 {
177 /* Pass location of hashtable header to hash_create */
178 infoP->hctl = (HASHHDR *) location;
179 hash_flags |= HASH_ATTACH;
180 }
181
182 return hash_create(name, nelems, infoP, hash_flags);
183}
184
185/*
186 * ShmemHashAlloc -- alloc callback for shared memory hash tables
187 *
188 * Carve out the allocation from a pre-allocated region. All shared memory
189 * hash tables are initialized with HASH_FIXED_SIZE, so all the allocations
190 * happen upfront during initialization and no locking is required.
191 */
192static void *
193ShmemHashAlloc(Size size, void *alloc_arg)
194{
196 void *result;
197
198 size = MAXALIGN(size);
199
200 if (allocator->end - allocator->next < size)
201 return NULL;
202 result = allocator->next;
203 allocator->next += size;
204
205 return result;
206}
#define MAXALIGN(LEN)
Definition c.h:896
#define Assert(condition)
Definition c.h:943
int64_t int64
Definition c.h:621
size_t Size
Definition c.h:689
uint32 result
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
Size hash_estimate_size(int64 num_entries, Size entrysize)
Definition dynahash.c:763
HTAB * hash_create(const char *tabname, int64 nelem, const HASHCTL *info, int flags)
Definition dynahash.c:360
#define HASH_ALLOC
Definition hsearch.h:96
#define HASH_ATTACH
Definition hsearch.h:99
#define HASH_SHARED_MEM
Definition hsearch.h:98
#define HASH_FIXED_SIZE
Definition hsearch.h:100
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition mcxt.c:1232
MemoryContext TopMemoryContext
Definition mcxt.c:166
static int fb(int x)
void ShmemRequestInternal(ShmemStructOpts *options, ShmemRequestKind kind)
Definition shmem.c:336
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:1006
HTAB * shmem_hash_create(void *location, size_t size, bool found, const char *name, int64 nelems, HASHCTL *infoP, int hash_flags)
Definition shmem_hash.c:149
void ShmemRequestHashWithOpts(const ShmemHashOpts *options)
Definition shmem_hash.c:44
static void * ShmemHashAlloc(Size size, void *alloc_arg)
Definition shmem_hash.c:193
HTAB * ShmemInitHash(const char *name, int64 nelems, HASHCTL *infoP, int hash_flags)
Definition shmem_hash.c:117
void shmem_hash_attach(void *location, ShmemStructOpts *base_options)
Definition shmem_hash.c:79
void shmem_hash_init(void *location, ShmemStructOpts *base_options)
Definition shmem_hash.c:63
@ SHMEM_KIND_HASH
const char * name