PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 "storage/subsystems.h"
#include "utils/builtins.h"
#include "utils/memutils.h"
#include "utils/tuplestore.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

static void DSMRegistryShmemRequest (void *arg)
 
static void DSMRegistryShmemInit (void *arg)
 
static void init_dsm_registry (void)
 
voidGetNamedDSMSegment (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
 
const ShmemCallbacks DSMRegistryShmemCallbacks
 
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

◆ NamedDSHState

◆ NamedDSMState

Enumeration Type Documentation

◆ DSMREntryType

Enumerator
DSMR_ENTRY_TYPE_DSM 
DSMR_ENTRY_TYPE_DSA 
DSMR_ENTRY_TYPE_DSH 

Definition at line 88 of file dsm_registry.c.

89{
DSMREntryType
@ DSMR_ENTRY_TYPE_DSM
@ DSMR_ENTRY_TYPE_DSA
@ DSMR_ENTRY_TYPE_DSH

Function Documentation

◆ DSMRegistryShmemInit()

static void DSMRegistryShmemInit ( void arg)
static

Definition at line 136 of file dsm_registry.c.

137{
140}
#define DSA_HANDLE_INVALID
Definition dsa.h:139
#define DSHASH_HANDLE_INVALID
Definition dshash.h:27
static DSMRegistryCtxStruct * DSMRegistryCtx
dshash_table_handle dshh

References DSA_HANDLE_INVALID, DSMRegistryCtxStruct::dsah, DSHASH_HANDLE_INVALID, DSMRegistryCtxStruct::dshh, and DSMRegistryCtx.

◆ DSMRegistryShmemRequest()

static void DSMRegistryShmemRequest ( void arg)
static

Definition at line 127 of file dsm_registry.c.

128{
129 ShmemRequestStruct(.name = "DSM Registry Data",
130 .size = sizeof(DSMRegistryCtxStruct),
131 .ptr = (void **) &DSMRegistryCtx,
132 );
133}
#define ShmemRequestStruct(...)
Definition shmem.h:176
const char * name

References DSMRegistryCtx, name, and ShmemRequestStruct.

◆ GetNamedDSA()

dsa_area * GetNamedDSA ( const char name,
bool found 
)

Definition at line 279 of file dsm_registry.c.

280{
281 DSMRegistryEntry *entry;
282 MemoryContext oldcontext;
283 dsa_area *ret;
285
286 Assert(found);
287
288 if (!name || *name == '\0')
290 (errmsg("DSA name cannot be empty")));
291
294 (errmsg("DSA name too long")));
295
296 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
298
299 /* Connect to the registry. */
301
303 state = &entry->dsa;
304 if (!(*found))
305 {
306 entry->type = DSMR_ENTRY_TYPE_DSA;
307 state->handle = DSA_HANDLE_INVALID;
308 state->tranche = -1;
309 }
310 else if (entry->type != DSMR_ENTRY_TYPE_DSA)
312 (errmsg("requested DSA does not match type of existing entry")));
313
314 if (state->tranche == -1)
315 {
316 *found = false;
317
318 /* Initialize the LWLock tranche for the DSA. */
319 state->tranche = LWLockNewTrancheId(name);
320 }
321
322 if (state->handle == DSA_HANDLE_INVALID)
323 {
324 *found = false;
325
326 /* Initialize the DSA. */
327 ret = dsa_create(state->tranche);
328 dsa_pin(ret);
329 dsa_pin_mapping(ret);
330
331 /* Store handle for other backends to use. */
332 state->handle = dsa_get_handle(ret);
333 }
334 else if (dsa_is_attached(state->handle))
336 (errmsg("requested DSA already attached to current process")));
337 else
338 {
339 /* Attach to existing DSA. */
340 ret = dsa_attach(state->handle);
341 dsa_pin_mapping(ret);
342 }
343
345 MemoryContextSwitchTo(oldcontext);
346
347 return ret;
348}
#define Assert(condition)
Definition c.h:943
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:579
#define dshash_find_or_insert(hash_table, key, found)
Definition dshash.h:109
static void init_dsm_registry(void)
static dshash_table * dsm_registry_table
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
int LWLockNewTrancheId(const char *name)
Definition lwlock.c:562
MemoryContext TopMemoryContext
Definition mcxt.c:166
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static int fb(int x)
NamedDSAState dsa
DSMREntryType type
const char * type

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, fb(), 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 360 of file dsm_registry.c.

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

References Assert, dsa_attach(), dsa_create, dsa_get_handle(), DSA_HANDLE_INVALID, dsa_is_attached(), dsa_pin(), dsa_pin_mapping(), DSMRegistryEntry::dsh, 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, fb(), init_dsm_registry(), LWLockNewTrancheId(), memcpy(), MemoryContextSwitchTo(), name, TopMemoryContext, 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 190 of file dsm_registry.c.

193{
194 DSMRegistryEntry *entry;
195 MemoryContext oldcontext;
196 void *ret;
198 dsm_segment *seg;
199
200 Assert(found);
201
202 if (!name || *name == '\0')
204 (errmsg("DSM segment name cannot be empty")));
205
208 (errmsg("DSM segment name too long")));
209
210 if (size == 0)
212 (errmsg("DSM segment size must be nonzero")));
213
214 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
216
217 /* Connect to the registry. */
219
221 state = &entry->dsm;
222 if (!(*found))
223 {
224 entry->type = DSMR_ENTRY_TYPE_DSM;
225 state->handle = DSM_HANDLE_INVALID;
226 state->size = size;
227 }
228 else if (entry->type != DSMR_ENTRY_TYPE_DSM)
230 (errmsg("requested DSM segment does not match type of existing entry")));
231 else if (state->size != size)
233 (errmsg("requested DSM segment size does not match size of existing segment")));
234
235 if (state->handle == DSM_HANDLE_INVALID)
236 {
237 *found = false;
238
239 /* Initialize the segment. */
240 seg = dsm_create(size, 0);
241
242 if (init_callback)
243 (*init_callback) (dsm_segment_address(seg), arg);
244
245 dsm_pin_segment(seg);
246 dsm_pin_mapping(seg);
247 state->handle = dsm_segment_handle(seg);
248 }
249 else
250 {
251 /* If the existing segment is not already attached, attach it now. */
252 seg = dsm_find_mapping(state->handle);
253 if (seg == NULL)
254 {
255 seg = dsm_attach(state->handle);
256 if (seg == NULL)
257 elog(ERROR, "could not map dynamic shared memory segment");
258
259 dsm_pin_mapping(seg);
260 }
261 }
262
263 ret = dsm_segment_address(seg);
265 MemoryContextSwitchTo(oldcontext);
266
267 return ret;
268}
dsm_handle dsm_segment_handle(dsm_segment *seg)
Definition dsm.c:1131
void dsm_pin_mapping(dsm_segment *seg)
Definition dsm.c:923
void dsm_pin_segment(dsm_segment *seg)
Definition dsm.c:963
void * dsm_segment_address(dsm_segment *seg)
Definition dsm.c:1103
dsm_segment * dsm_create(Size size, int flags)
Definition dsm.c:524
dsm_segment * dsm_attach(dsm_handle h)
Definition dsm.c:673
dsm_segment * dsm_find_mapping(dsm_handle handle)
Definition dsm.c:1084
#define DSM_HANDLE_INVALID
Definition dsm_impl.h:58
Datum arg
Definition elog.c:1322
#define elog(elevel,...)
Definition elog.h:228
NamedDSMState dsm

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, fb(), init_dsm_registry(), MemoryContextSwitchTo(), name, TopMemoryContext, DSMRegistryEntry::type, and type.

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

◆ init_dsm_registry()

static void init_dsm_registry ( void  )
static

Definition at line 148 of file dsm_registry.c.

149{
150 /* Quick exit if we already did this. */
152 return;
153
154 /* Otherwise, use a lock to ensure only one process creates the table. */
156
158 {
159 /* Initialize dynamic shared hash table for registry. */
162
165
166 /* Store handles in shared memory for other backends to use. */
169 }
170 else
171 {
172 /* Attach to existing dynamic shared hash table. */
177 }
178
180}
static dsa_area * dsm_registry_dsa
static const dshash_parameters dsh_params
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1150
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1767
@ LW_EXCLUSIVE
Definition lwlock.h:104

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, fb(), 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 451 of file dsm_registry.c.

452{
453 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
454 DSMRegistryEntry *entry;
455 MemoryContext oldcontext;
456 dshash_seq_status status;
457
459
460 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
463 MemoryContextSwitchTo(oldcontext);
464
465 dshash_seq_init(&status, dsm_registry_table, false);
466 while ((entry = dshash_seq_next(&status)) != NULL)
467 {
468 Datum vals[3];
469 bool nulls[3] = {0};
470
471 vals[0] = CStringGetTextDatum(entry->name);
473
474 /* Be careful to only return the sizes of initialized entries. */
475 if (entry->type == DSMR_ENTRY_TYPE_DSM &&
476 entry->dsm.handle != DSM_HANDLE_INVALID)
477 vals[2] = Int64GetDatum(entry->dsm.size);
478 else if (entry->type == DSMR_ENTRY_TYPE_DSA &&
479 entry->dsa.handle != DSA_HANDLE_INVALID)
481 else if (entry->type == DSMR_ENTRY_TYPE_DSH &&
484 else
485 nulls[2] = true;
486
487 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, vals, nulls);
488 }
489 dshash_seq_term(&status);
490
491 return (Datum) 0;
492}
#define CStringGetTextDatum(s)
Definition builtins.h:98
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:659
void dshash_seq_term(dshash_seq_status *status)
Definition dshash.c:768
void * dshash_seq_next(dshash_seq_status *status)
Definition dshash.c:678
static const char *const DSMREntryTypeNames[]
void InitMaterializedSRF(FunctionCallInfo fcinfo, uint32 flags)
Definition funcapi.c:76
#define MAT_SRF_USE_EXPECTED_DESC
Definition funcapi.h:296
static Datum Int64GetDatum(int64 X)
Definition postgres.h:413
uint64_t Datum
Definition postgres.h:70
char name[NAMEDATALEN]
dsa_handle handle
dsa_handle dsa_handle
dsm_handle handle
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785

References CStringGetTextDatum, DSMRegistryEntry::dsa, dsa_get_total_size_from_handle(), NamedDSHState::dsa_handle, DSA_HANDLE_INVALID, DSMRegistryEntry::dsh, dshash_seq_init(), dshash_seq_next(), dshash_seq_term(), DSMRegistryEntry::dsm, DSM_HANDLE_INVALID, dsm_registry_table, DSMR_ENTRY_TYPE_DSA, DSMR_ENTRY_TYPE_DSH, DSMR_ENTRY_TYPE_DSM, DSMREntryTypeNames, fb(), NamedDSMState::handle, NamedDSAState::handle, init_dsm_registry(), InitMaterializedSRF(), Int64GetDatum(), MAT_SRF_USE_EXPECTED_DESC, MemoryContextSwitchTo(), DSMRegistryEntry::name, NamedDSMState::size, TopMemoryContext, tuplestore_putvalues(), and DSMRegistryEntry::type.

Variable Documentation

◆ dsh_params

const dshash_parameters dsh_params
static
Initial value:
= {
}
void dshash_strcpy(void *dest, const void *src, size_t size, void *arg)
Definition dshash.c:643
dshash_hash dshash_strhash(const void *v, size_t size, void *arg)
Definition dshash.c:632
int dshash_strcmp(const void *a, const void *b, size_t size, void *arg)
Definition dshash.c:620

Definition at line 114 of file dsm_registry.c.

Referenced by init_dsm_registry().

◆ dsm_registry_dsa

dsa_area* dsm_registry_dsa
static

Definition at line 123 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 59 of file dsm_registry.c.

Referenced by DSMRegistryShmemInit(), DSMRegistryShmemRequest(), and init_dsm_registry().

◆ DSMRegistryShmemCallbacks

const ShmemCallbacks DSMRegistryShmemCallbacks
Initial value:
= {
.request_fn = DSMRegistryShmemRequest,
}
static void DSMRegistryShmemRequest(void *arg)
static void DSMRegistryShmemInit(void *arg)

Definition at line 64 of file dsm_registry.c.

64 {
65 .request_fn = DSMRegistryShmemRequest,
66 .init_fn = DSMRegistryShmemInit,
67};

◆ 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 95 of file dsm_registry.c.

96{
97 [DSMR_ENTRY_TYPE_DSM] = "segment",
98 [DSMR_ENTRY_TYPE_DSA] = "area",
99 [DSMR_ENTRY_TYPE_DSH] = "hash",
100};

Referenced by pg_get_dsm_registry_allocations().