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, void *arg), bool *found, void *arg)
 
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:832

References MAXALIGN.

Referenced by CalculateShmemSize(), and DSMRegistryShmemInit().

◆ GetNamedDSA()

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

Definition at line 276 of file dsm_registry.c.

277{
278 DSMRegistryEntry *entry;
279 MemoryContext oldcontext;
280 dsa_area *ret;
282
283 Assert(found);
284
285 if (!name || *name == '\0')
287 (errmsg("DSA name cannot be empty")));
288
289 if (strlen(name) >= offsetof(DSMRegistryEntry, type))
291 (errmsg("DSA name too long")));
292
293 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
295
296 /* Connect to the registry. */
298
300 state = &entry->dsa;
301 if (!(*found))
302 {
303 entry->type = DSMR_ENTRY_TYPE_DSA;
304 state->handle = DSA_HANDLE_INVALID;
305 state->tranche = -1;
306 }
307 else if (entry->type != DSMR_ENTRY_TYPE_DSA)
309 (errmsg("requested DSA does not match type of existing entry")));
310
311 if (state->tranche == -1)
312 {
313 *found = false;
314
315 /* Initialize the LWLock tranche for the DSA. */
316 state->tranche = LWLockNewTrancheId(name);
317 }
318
319 if (state->handle == DSA_HANDLE_INVALID)
320 {
321 *found = false;
322
323 /* Initialize the DSA. */
324 ret = dsa_create(state->tranche);
325 dsa_pin(ret);
326 dsa_pin_mapping(ret);
327
328 /* Store handle for other backends to use. */
329 state->handle = dsa_get_handle(ret);
330 }
331 else if (dsa_is_attached(state->handle))
333 (errmsg("requested DSA already attached to current process")));
334 else
335 {
336 /* Attach to existing DSA. */
337 ret = dsa_attach(state->handle);
338 dsa_pin_mapping(ret);
339 }
340
342 MemoryContextSwitchTo(oldcontext);
343
344 return ret;
345}
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(), test_custom_stats_var_create(), test_custom_stats_var_from_serialized_data(), test_custom_stats_var_report(), and test_custom_stats_var_to_serialized_data().

◆ GetNamedDSHash()

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

Definition at line 357 of file dsm_registry.c.

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

Definition at line 187 of file dsm_registry.c.

190{
191 DSMRegistryEntry *entry;
192 MemoryContext oldcontext;
193 void *ret;
195 dsm_segment *seg;
196
197 Assert(found);
198
199 if (!name || *name == '\0')
201 (errmsg("DSM segment name cannot be empty")));
202
203 if (strlen(name) >= offsetof(DSMRegistryEntry, type))
205 (errmsg("DSM segment name too long")));
206
207 if (size == 0)
209 (errmsg("DSM segment size must be nonzero")));
210
211 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
213
214 /* Connect to the registry. */
216
218 state = &entry->dsm;
219 if (!(*found))
220 {
221 entry->type = DSMR_ENTRY_TYPE_DSM;
222 state->handle = DSM_HANDLE_INVALID;
223 state->size = size;
224 }
225 else if (entry->type != DSMR_ENTRY_TYPE_DSM)
227 (errmsg("requested DSM segment does not match type of existing entry")));
228 else if (state->size != size)
230 (errmsg("requested DSM segment size does not match size of existing segment")));
231
232 if (state->handle == DSM_HANDLE_INVALID)
233 {
234 *found = false;
235
236 /* Initialize the segment. */
237 seg = dsm_create(size, 0);
238
239 if (init_callback)
240 (*init_callback) (dsm_segment_address(seg), arg);
241
242 dsm_pin_segment(seg);
243 dsm_pin_mapping(seg);
244 state->handle = dsm_segment_handle(seg);
245 }
246 else
247 {
248 /* If the existing segment is not already attached, attach it now. */
249 seg = dsm_find_mapping(state->handle);
250 if (seg == NULL)
251 {
252 seg = dsm_attach(state->handle);
253 if (seg == NULL)
254 elog(ERROR, "could not map dynamic shared memory segment");
255
256 dsm_pin_mapping(seg);
257 }
258 }
259
260 ret = dsm_segment_address(seg);
262 MemoryContextSwitchTo(oldcontext);
263
264 return ret;
265}
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
void * arg
NamedDSMState dsm
Definition: dsm_registry.c:98

References arg, 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:1178
void LWLockRelease(LWLock *lock)
Definition: lwlock.c:1898
@ 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 448 of file dsm_registry.c.

449{
450 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
451 DSMRegistryEntry *entry;
452 MemoryContext oldcontext;
453 dshash_seq_status status;
454
456
457 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
460 MemoryContextSwitchTo(oldcontext);
461
462 dshash_seq_init(&status, dsm_registry_table, false);
463 while ((entry = dshash_seq_next(&status)) != NULL)
464 {
465 Datum vals[3];
466 bool nulls[3] = {0};
467
468 vals[0] = CStringGetTextDatum(entry->name);
469 vals[1] = CStringGetTextDatum(DSMREntryTypeNames[entry->type]);
470
471 /* Be careful to only return the sizes of initialized entries. */
472 if (entry->type == DSMR_ENTRY_TYPE_DSM &&
473 entry->dsm.handle != DSM_HANDLE_INVALID)
474 vals[2] = Int64GetDatum(entry->dsm.size);
475 else if (entry->type == DSMR_ENTRY_TYPE_DSA &&
476 entry->dsa.handle != DSA_HANDLE_INVALID)
477 vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsa.handle));
478 else if (entry->type == DSMR_ENTRY_TYPE_DSH &&
479 entry->dsh.dsa_handle !=DSA_HANDLE_INVALID)
480 vals[2] = Int64GetDatum(dsa_get_total_size_from_handle(entry->dsh.dsa_handle));
481 else
482 nulls[2] = true;
483
484 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, vals, nulls);
485 }
486 dshash_seq_term(&status);
487
488 return (Datum) 0;
489}
#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:423
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().