PostgreSQL Source Code git master
dsm_registry.c File Reference
#include "postgres.h"
#include "funcapi.h"
#include "lib/dshash.h"
#include "storage/dsm_registry.h"
#include "storage/lwlock.h"
#include "storage/shmem.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
Include dependency graph for dsm_registry.c:

Go to the source code of this file.

Data Structures

struct  DSMRegistryCtxStruct
 
struct  NamedDSMState
 
struct  NamedDSAState
 
struct  NamedDSHState
 
struct  DSMRegistryEntry
 

Typedefs

typedef struct DSMRegistryCtxStruct DSMRegistryCtxStruct
 
typedef struct NamedDSMState NamedDSMState
 
typedef struct NamedDSAState NamedDSAState
 
typedef struct NamedDSHState NamedDSHState
 
typedef enum DSMREntryType DSMREntryType
 
typedef struct DSMRegistryEntry DSMRegistryEntry
 

Enumerations

enum  DSMREntryType { DSMR_ENTRY_TYPE_DSM , DSMR_ENTRY_TYPE_DSA , DSMR_ENTRY_TYPE_DSH }
 

Functions

Size DSMRegistryShmemSize (void)
 
void DSMRegistryShmemInit (void)
 
static void init_dsm_registry (void)
 
void * GetNamedDSMSegment (const char *name, size_t size, void(*init_callback)(void *ptr), bool *found)
 
dsa_areaGetNamedDSA (const char *name, bool *found)
 
dshash_tableGetNamedDSHash (const char *name, const dshash_parameters *params, bool *found)
 
Datum pg_get_dsm_registry_allocations (PG_FUNCTION_ARGS)
 

Variables

static DSMRegistryCtxStructDSMRegistryCtx
 
static const char *const DSMREntryTypeNames []
 
static const dshash_parameters dsh_params
 
static dsa_areadsm_registry_dsa
 
static dshash_tabledsm_registry_table
 

Typedef Documentation

◆ DSMRegistryCtxStruct

◆ DSMRegistryEntry

◆ DSMREntryType

◆ NamedDSAState

typedef struct NamedDSAState NamedDSAState

◆ NamedDSHState

typedef struct NamedDSHState NamedDSHState

◆ NamedDSMState

typedef struct NamedDSMState NamedDSMState

Enumeration Type Documentation

◆ DSMREntryType

Enumerator
DSMR_ENTRY_TYPE_DSM 
DSMR_ENTRY_TYPE_DSA 
DSMR_ENTRY_TYPE_DSH 

Definition at line 78 of file dsm_registry.c.

79{
DSMREntryType
Definition: dsm_registry.c:79
@ DSMR_ENTRY_TYPE_DSM
Definition: dsm_registry.c:80
@ DSMR_ENTRY_TYPE_DSA
Definition: dsm_registry.c:81
@ DSMR_ENTRY_TYPE_DSH
Definition: dsm_registry.c:82

Function Documentation

◆ DSMRegistryShmemInit()

void DSMRegistryShmemInit ( void  )

Definition at line 123 of file dsm_registry.c.

124{
125 bool found;
126
128 ShmemInitStruct("DSM Registry Data",
130 &found);
131
132 if (!found)
133 {
136 }
137}
#define DSA_HANDLE_INVALID
Definition: dsa.h:139
#define DSHASH_HANDLE_INVALID
Definition: dshash.h:27
static DSMRegistryCtxStruct * DSMRegistryCtx
Definition: dsm_registry.c:57
Size DSMRegistryShmemSize(void)
Definition: dsm_registry.c:117
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition: shmem.c:389
dshash_table_handle dshh
Definition: dsm_registry.c:54

References DSA_HANDLE_INVALID, DSMRegistryCtxStruct::dsah, DSHASH_HANDLE_INVALID, DSMRegistryCtxStruct::dshh, DSMRegistryCtx, DSMRegistryShmemSize(), and ShmemInitStruct().

Referenced by CreateOrAttachShmemStructs().

◆ DSMRegistryShmemSize()

Size DSMRegistryShmemSize ( void  )

Definition at line 117 of file dsm_registry.c.

118{
119 return MAXALIGN(sizeof(DSMRegistryCtxStruct));
120}
#define MAXALIGN(LEN)
Definition: c.h:813

References MAXALIGN.

Referenced by CalculateShmemSize(), and DSMRegistryShmemInit().

◆ GetNamedDSA()

dsa_area * GetNamedDSA ( const char *  name,
bool *  found 
)

Definition at line 274 of file dsm_registry.c.

275{
276 DSMRegistryEntry *entry;
277 MemoryContext oldcontext;
278 dsa_area *ret;
280
281 Assert(found);
282
283 if (!name || *name == '\0')
285 (errmsg("DSA name cannot be empty")));
286
287 if (strlen(name) >= offsetof(DSMRegistryEntry, type))
289 (errmsg("DSA name too long")));
290
291 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
293
294 /* Connect to the registry. */
296
298 state = &entry->dsa;
299 if (!(*found))
300 {
301 entry->type = DSMR_ENTRY_TYPE_DSA;
302 state->handle = DSA_HANDLE_INVALID;
303 state->tranche = -1;
304 }
305 else if (entry->type != DSMR_ENTRY_TYPE_DSA)
307 (errmsg("requested DSA does not match type of existing entry")));
308
309 if (state->tranche == -1)
310 {
311 *found = false;
312
313 /* Initialize the LWLock tranche for the DSA. */
314 state->tranche = LWLockNewTrancheId(name);
315 }
316
317 if (state->handle == DSA_HANDLE_INVALID)
318 {
319 *found = false;
320
321 /* Initialize the DSA. */
322 ret = dsa_create(state->tranche);
323 dsa_pin(ret);
324 dsa_pin_mapping(ret);
325
326 /* Store handle for other backends to use. */
327 state->handle = dsa_get_handle(ret);
328 }
329 else if (dsa_is_attached(state->handle))
331 (errmsg("requested DSA already attached to current process")));
332 else
333 {
334 /* Attach to existing DSA. */
335 ret = dsa_attach(state->handle);
336 dsa_pin_mapping(ret);
337 }
338
340 MemoryContextSwitchTo(oldcontext);
341
342 return ret;
343}
dsa_area * dsa_attach(dsa_handle handle)
Definition: dsa.c:510
void dsa_pin_mapping(dsa_area *area)
Definition: dsa.c:650
dsa_handle dsa_get_handle(dsa_area *area)
Definition: dsa.c:498
bool dsa_is_attached(dsa_handle handle)
Definition: dsa.c:540
void dsa_pin(dsa_area *area)
Definition: dsa.c:990
#define dsa_create(tranche_id)
Definition: dsa.h:117
void dshash_release_lock(dshash_table *hash_table, void *entry)
Definition: dshash.c:560
void * dshash_find_or_insert(dshash_table *hash_table, const void *key, bool *found)
Definition: dshash.c:435
static void init_dsm_registry(void)
Definition: dsm_registry.c:145
static dshash_table * dsm_registry_table
Definition: dsm_registry.c:114
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
Assert(PointerIsAligned(start, uint64))
int LWLockNewTrancheId(const char *name)
Definition: lwlock.c:596
MemoryContext TopMemoryContext
Definition: mcxt.c:166
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
NamedDSAState dsa
Definition: dsm_registry.c:99
DSMREntryType type
Definition: dsm_registry.c:95
Definition: dsa.c:348
Definition: regguts.h:323
const char * type
const char * name

References Assert(), DSMRegistryEntry::dsa, dsa_attach(), dsa_create, dsa_get_handle(), DSA_HANDLE_INVALID, dsa_is_attached(), dsa_pin(), dsa_pin_mapping(), dshash_find_or_insert(), dshash_release_lock(), dsm_registry_table, DSMR_ENTRY_TYPE_DSA, ereport, errmsg(), ERROR, init_dsm_registry(), LWLockNewTrancheId(), MemoryContextSwitchTo(), name, TopMemoryContext, DSMRegistryEntry::type, and type.

Referenced by tdr_attach_shmem().

◆ GetNamedDSHash()

dshash_table * GetNamedDSHash ( const char *  name,
const dshash_parameters params,
bool *  found 
)

Definition at line 355 of file dsm_registry.c.

356{
357 DSMRegistryEntry *entry;
358 MemoryContext oldcontext;
359 dshash_table *ret;
360 NamedDSHState *dsh_state;
361
362 Assert(params);
363 Assert(found);
364
365 if (!name || *name == '\0')
367 (errmsg("DSHash name cannot be empty")));
368
369 if (strlen(name) >= offsetof(DSMRegistryEntry, type))
371 (errmsg("DSHash name too long")));
372
373 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
375
376 /* Connect to the registry. */
378
380 dsh_state = &entry->dsh;
381 if (!(*found))
382 {
383 entry->type = DSMR_ENTRY_TYPE_DSH;
384 dsh_state->dsa_handle = DSA_HANDLE_INVALID;
386 dsh_state->tranche = -1;
387 }
388 else if (entry->type != DSMR_ENTRY_TYPE_DSH)
390 (errmsg("requested DSHash does not match type of existing entry")));
391
392 if (dsh_state->tranche == -1)
393 {
394 *found = false;
395
396 /* Initialize the LWLock tranche for the hash table. */
397 dsh_state->tranche = LWLockNewTrancheId(name);
398 }
399
400 if (dsh_state->dsa_handle == DSA_HANDLE_INVALID)
401 {
402 dshash_parameters params_copy;
403 dsa_area *dsa;
404
405 *found = false;
406
407 /* Initialize the DSA for the hash table. */
408 dsa = dsa_create(dsh_state->tranche);
409
410 /* Initialize the dshash table. */
411 memcpy(&params_copy, params, sizeof(dshash_parameters));
412 params_copy.tranche_id = dsh_state->tranche;
413 ret = dshash_create(dsa, &params_copy, NULL);
414
415 dsa_pin(dsa);
416 dsa_pin_mapping(dsa);
417
418 /* Store handles for other backends to use. */
419 dsh_state->dsa_handle = dsa_get_handle(dsa);
421 }
422 else if (dsa_is_attached(dsh_state->dsa_handle))
424 (errmsg("requested DSHash already attached to current process")));
425 else
426 {
427 dsa_area *dsa;
428
429 /* XXX: Should we verify params matches what table was created with? */
430
431 /* Attach to existing DSA for the hash table. */
432 dsa = dsa_attach(dsh_state->dsa_handle);
433 dsa_pin_mapping(dsa);
434
435 /* Attach to existing dshash table. */
436 ret = dshash_attach(dsa, params, dsh_state->dsh_handle, NULL);
437 }
438
440 MemoryContextSwitchTo(oldcontext);
441
442 return ret;
443}
dshash_table_handle dshash_get_hash_table_handle(dshash_table *hash_table)
Definition: dshash.c:369
dshash_table * dshash_attach(dsa_area *area, const dshash_parameters *params, dshash_table_handle handle, void *arg)
Definition: dshash.c:272
dshash_table * dshash_create(dsa_area *area, const dshash_parameters *params, void *arg)
Definition: dshash.c:208
NamedDSHState dsh
Definition: dsm_registry.c:100
dsa_handle dsa_handle
Definition: dsm_registry.c:73
dshash_table_handle dsh_handle
Definition: dsm_registry.c:74

References Assert(), dsa_attach(), dsa_create, dsa_get_handle(), NamedDSHState::dsa_handle, DSA_HANDLE_INVALID, dsa_is_attached(), dsa_pin(), dsa_pin_mapping(), DSMRegistryEntry::dsh, NamedDSHState::dsh_handle, dshash_attach(), dshash_create(), dshash_find_or_insert(), dshash_get_hash_table_handle(), DSHASH_HANDLE_INVALID, dshash_release_lock(), dsm_registry_table, DSMR_ENTRY_TYPE_DSH, ereport, errmsg(), ERROR, init_dsm_registry(), LWLockNewTrancheId(), MemoryContextSwitchTo(), name, TopMemoryContext, NamedDSHState::tranche, dshash_parameters::tranche_id, DSMRegistryEntry::type, and type.

Referenced by tdr_attach_shmem().

◆ GetNamedDSMSegment()

void * GetNamedDSMSegment ( const char *  name,
size_t  size,
void(*)(void *ptr)  init_callback,
bool *  found 
)

Definition at line 186 of file dsm_registry.c.

188{
189 DSMRegistryEntry *entry;
190 MemoryContext oldcontext;
191 void *ret;
193 dsm_segment *seg;
194
195 Assert(found);
196
197 if (!name || *name == '\0')
199 (errmsg("DSM segment name cannot be empty")));
200
201 if (strlen(name) >= offsetof(DSMRegistryEntry, type))
203 (errmsg("DSM segment name too long")));
204
205 if (size == 0)
207 (errmsg("DSM segment size must be nonzero")));
208
209 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
211
212 /* Connect to the registry. */
214
216 state = &entry->dsm;
217 if (!(*found))
218 {
219 entry->type = DSMR_ENTRY_TYPE_DSM;
220 state->handle = DSM_HANDLE_INVALID;
221 state->size = size;
222 }
223 else if (entry->type != DSMR_ENTRY_TYPE_DSM)
225 (errmsg("requested DSM segment does not match type of existing entry")));
226 else if (state->size != size)
228 (errmsg("requested DSM segment size does not match size of existing segment")));
229
230 if (state->handle == DSM_HANDLE_INVALID)
231 {
232 *found = false;
233
234 /* Initialize the segment. */
235 seg = dsm_create(size, 0);
236
237 if (init_callback)
238 (*init_callback) (dsm_segment_address(seg));
239
240 dsm_pin_segment(seg);
241 dsm_pin_mapping(seg);
242 state->handle = dsm_segment_handle(seg);
243 }
244 else
245 {
246 /* If the existing segment is not already attached, attach it now. */
247 seg = dsm_find_mapping(state->handle);
248 if (seg == NULL)
249 {
250 seg = dsm_attach(state->handle);
251 if (seg == NULL)
252 elog(ERROR, "could not map dynamic shared memory segment");
253
254 dsm_pin_mapping(seg);
255 }
256 }
257
258 ret = dsm_segment_address(seg);
260 MemoryContextSwitchTo(oldcontext);
261
262 return ret;
263}
dsm_handle dsm_segment_handle(dsm_segment *seg)
Definition: dsm.c:1123
void dsm_pin_mapping(dsm_segment *seg)
Definition: dsm.c:915
void dsm_pin_segment(dsm_segment *seg)
Definition: dsm.c:955
void * dsm_segment_address(dsm_segment *seg)
Definition: dsm.c:1095
dsm_segment * dsm_create(Size size, int flags)
Definition: dsm.c:516
dsm_segment * dsm_attach(dsm_handle h)
Definition: dsm.c:665
dsm_segment * dsm_find_mapping(dsm_handle handle)
Definition: dsm.c:1076
#define DSM_HANDLE_INVALID
Definition: dsm_impl.h:58
#define elog(elevel,...)
Definition: elog.h:226
NamedDSMState dsm
Definition: dsm_registry.c:98

References Assert(), dshash_find_or_insert(), dshash_release_lock(), DSMRegistryEntry::dsm, dsm_attach(), dsm_create(), dsm_find_mapping(), DSM_HANDLE_INVALID, dsm_pin_mapping(), dsm_pin_segment(), dsm_registry_table, dsm_segment_address(), dsm_segment_handle(), DSMR_ENTRY_TYPE_DSM, elog, ereport, errmsg(), ERROR, init_dsm_registry(), MemoryContextSwitchTo(), name, TopMemoryContext, DSMRegistryEntry::type, and type.

Referenced by apw_init_shmem(), injection_init_shmem(), tdr_attach_shmem(), test_dsa_basic(), and test_dsa_resowners().

◆ init_dsm_registry()

static void init_dsm_registry ( void  )
static

Definition at line 145 of file dsm_registry.c.

146{
147 /* Quick exit if we already did this. */
149 return;
150
151 /* Otherwise, use a lock to ensure only one process creates the table. */
152 LWLockAcquire(DSMRegistryLock, LW_EXCLUSIVE);
153
155 {
156 /* Initialize dynamic shared hash table for registry. */
157 dsm_registry_dsa = dsa_create(LWTRANCHE_DSM_REGISTRY_DSA);
159
162
163 /* Store handles in shared memory for other backends to use. */
166 }
167 else
168 {
169 /* Attach to existing dynamic shared hash table. */
173 DSMRegistryCtx->dshh, NULL);
174 }
175
176 LWLockRelease(DSMRegistryLock);
177}
static dsa_area * dsm_registry_dsa
Definition: dsm_registry.c:113
static const dshash_parameters dsh_params
Definition: dsm_registry.c:104
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition: lwlock.c:1174
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1894
@ LW_EXCLUSIVE
Definition: lwlock.h:112

References dsa_attach(), dsa_create, dsa_get_handle(), dsa_pin(), dsa_pin_mapping(), DSMRegistryCtxStruct::dsah, dsh_params, dshash_attach(), dshash_create(), dshash_get_hash_table_handle(), DSHASH_HANDLE_INVALID, DSMRegistryCtxStruct::dshh, dsm_registry_dsa, dsm_registry_table, DSMRegistryCtx, LW_EXCLUSIVE, LWLockAcquire(), and LWLockRelease().

Referenced by GetNamedDSA(), GetNamedDSHash(), GetNamedDSMSegment(), and pg_get_dsm_registry_allocations().

◆ pg_get_dsm_registry_allocations()

Datum pg_get_dsm_registry_allocations ( PG_FUNCTION_ARGS  )

Definition at line 446 of file dsm_registry.c.

447{
448 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
449 DSMRegistryEntry *entry;
450 MemoryContext oldcontext;
451 dshash_seq_status status;
452
454
455 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
458 MemoryContextSwitchTo(oldcontext);
459
460 dshash_seq_init(&status, dsm_registry_table, false);
461 while ((entry = dshash_seq_next(&status)) != NULL)
462 {
463 Datum vals[3];
464 bool nulls[3] = {0};
465
466 vals[0] = CStringGetTextDatum(entry->name);
467 vals[1] = CStringGetTextDatum(DSMREntryTypeNames[entry->type]);
468
469 /* Be careful to only return the sizes of initialized entries. */
470 if (entry->type == DSMR_ENTRY_TYPE_DSM &&
471 entry->dsm.handle != DSM_HANDLE_INVALID)
472 vals[2] = Int64GetDatum(entry->dsm.size);
473 else if (entry->type == DSMR_ENTRY_TYPE_DSA &&
474 entry->dsa.handle != DSA_HANDLE_INVALID)
475 vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsa.handle));
476 else if (entry->type == DSMR_ENTRY_TYPE_DSH &&
477 entry->dsh.dsa_handle !=DSA_HANDLE_INVALID)
478 vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsh.dsa_handle));
479 else
480 nulls[2] = true;
481
482 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, vals, nulls);
483 }
484 dshash_seq_term(&status);
485
486 return (Datum) 0;
487}
#define CStringGetTextDatum(s)
Definition: builtins.h:97
size_t dsa_get_total_size_from_handle(dsa_handle handle)
Definition: dsa.c:1058
void dshash_seq_init(dshash_seq_status *status, dshash_table *hash_table, bool exclusive)
Definition: dshash.c:640
void dshash_seq_term(dshash_seq_status *status)
Definition: dshash.c:749
void * dshash_seq_next(dshash_seq_status *status)
Definition: dshash.c:659
static const char *const DSMREntryTypeNames[]
Definition: dsm_registry.c:85
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
#define MAT_SRF_USE_EXPECTED_DESC
Definition: funcapi.h:296
static Datum Int64GetDatum(int64 X)
Definition: postgres.h:403
uint64_t Datum
Definition: postgres.h:70
TupleDesc setDesc
Definition: execnodes.h:364
Tuplestorestate * setResult
Definition: execnodes.h:363
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:784

References CStringGetTextDatum, dsa_get_total_size_from_handle(), DSA_HANDLE_INVALID, dshash_seq_init(), dshash_seq_next(), dshash_seq_term(), DSM_HANDLE_INVALID, dsm_registry_table, DSMR_ENTRY_TYPE_DSA, DSMR_ENTRY_TYPE_DSH, DSMR_ENTRY_TYPE_DSM, DSMREntryTypeNames, init_dsm_registry(), InitMaterializedSRF(), Int64GetDatum(), MAT_SRF_USE_EXPECTED_DESC, MemoryContextSwitchTo(), ReturnSetInfo::setDesc, ReturnSetInfo::setResult, TopMemoryContext, and tuplestore_putvalues().

Variable Documentation

◆ dsh_params

const dshash_parameters dsh_params
static
Initial value:
= {
offsetof(DSMRegistryEntry, type),
LWTRANCHE_DSM_REGISTRY_HASH
}
void dshash_strcpy(void *dest, const void *src, size_t size, void *arg)
Definition: dshash.c:624
dshash_hash dshash_strhash(const void *v, size_t size, void *arg)
Definition: dshash.c:613
int dshash_strcmp(const void *a, const void *b, size_t size, void *arg)
Definition: dshash.c:601
struct DSMRegistryEntry DSMRegistryEntry

Definition at line 104 of file dsm_registry.c.

Referenced by init_dsm_registry().

◆ dsm_registry_dsa

dsa_area* dsm_registry_dsa
static

Definition at line 113 of file dsm_registry.c.

Referenced by init_dsm_registry().

◆ dsm_registry_table

dshash_table* dsm_registry_table
static

◆ DSMRegistryCtx

DSMRegistryCtxStruct* DSMRegistryCtx
static

Definition at line 57 of file dsm_registry.c.

Referenced by DSMRegistryShmemInit(), and init_dsm_registry().

◆ DSMREntryTypeNames

const char* const DSMREntryTypeNames[]
static
Initial value:
=
{
[DSMR_ENTRY_TYPE_DSM] = "segment",
[DSMR_ENTRY_TYPE_DSA] = "area",
[DSMR_ENTRY_TYPE_DSH] = "hash",
}

Definition at line 85 of file dsm_registry.c.

Referenced by pg_get_dsm_registry_allocations().