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 "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)
 
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
 
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 78 of file dsm_registry.c.

79{
DSMREntryType
@ DSMR_ENTRY_TYPE_DSM
@ DSMR_ENTRY_TYPE_DSA
@ DSMR_ENTRY_TYPE_DSH

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
Size DSMRegistryShmemSize(void)
void * ShmemInitStruct(const char *name, Size size, bool *foundPtr)
Definition shmem.c:378
dshash_table_handle dshh

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:826

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
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}
#define Assert(condition)
Definition c.h:873
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)
static dshash_table * dsm_registry_table
int errmsg(const char *fmt,...)
Definition elog.c:1080
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:150
int LWLockNewTrancheId(const char *name)
Definition lwlock.c:596
MemoryContext TopMemoryContext
Definition mcxt.c:166
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:124
static int fb(int x)
NamedDSAState dsa
DSMREntryType type
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, 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 357 of file dsm_registry.c.

358{
359 DSMRegistryEntry *entry;
360 MemoryContext oldcontext;
361 dshash_table *ret;
363
364 Assert(params);
365 Assert(found);
366
367 if (!name || *name == '\0')
369 (errmsg("DSHash name cannot be empty")));
370
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;
387 dsh_state->dsh_handle = DSHASH_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. */
400 }
401
402 if (dsh_state->dsa_handle == DSA_HANDLE_INVALID)
403 {
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);
422 dsh_state->dsh_handle = dshash_get_hash_table_handle(ret);
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

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(), 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 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
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

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(), 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. */
153
155 {
156 /* Initialize dynamic shared hash table for registry. */
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. */
174 }
175
177}
static dsa_area * dsm_registry_dsa
static const dshash_parameters dsh_params
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1176
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1793
@ 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, 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 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);
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)
478 else if (entry->type == DSMR_ENTRY_TYPE_DSH &&
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[]
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
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:784

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: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

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.

86{
87 [DSMR_ENTRY_TYPE_DSM] = "segment",
88 [DSMR_ENTRY_TYPE_DSA] = "area",
89 [DSMR_ENTRY_TYPE_DSH] = "hash",
90};

Referenced by pg_get_dsm_registry_allocations().