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

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

80{
DSMREntryType
@ DSMR_ENTRY_TYPE_DSM
@ DSMR_ENTRY_TYPE_DSA
@ DSMR_ENTRY_TYPE_DSH

Function Documentation

◆ DSMRegistryShmemInit()

void DSMRegistryShmemInit ( void  )

Definition at line 124 of file dsm_registry.c.

125{
126 bool found;
127
129 ShmemInitStruct("DSM Registry Data",
131 &found);
132
133 if (!found)
134 {
137 }
138}
#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:381
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 118 of file dsm_registry.c.

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

References MAXALIGN.

Referenced by CalculateShmemSize(), and DSMRegistryShmemInit().

◆ GetNamedDSA()

dsa_area * GetNamedDSA ( const char name,
bool found 
)

Definition at line 277 of file dsm_registry.c.

278{
279 DSMRegistryEntry *entry;
280 MemoryContext oldcontext;
281 dsa_area *ret;
283
284 Assert(found);
285
286 if (!name || *name == '\0')
288 (errmsg("DSA name cannot be empty")));
289
292 (errmsg("DSA name too long")));
293
294 /* Be sure any local memory allocated by DSM/DSA routines is persistent. */
296
297 /* Connect to the registry. */
299
301 state = &entry->dsa;
302 if (!(*found))
303 {
304 entry->type = DSMR_ENTRY_TYPE_DSA;
305 state->handle = DSA_HANDLE_INVALID;
306 state->tranche = -1;
307 }
308 else if (entry->type != DSMR_ENTRY_TYPE_DSA)
310 (errmsg("requested DSA does not match type of existing entry")));
311
312 if (state->tranche == -1)
313 {
314 *found = false;
315
316 /* Initialize the LWLock tranche for the DSA. */
317 state->tranche = LWLockNewTrancheId(name);
318 }
319
320 if (state->handle == DSA_HANDLE_INVALID)
321 {
322 *found = false;
323
324 /* Initialize the DSA. */
325 ret = dsa_create(state->tranche);
326 dsa_pin(ret);
327 dsa_pin_mapping(ret);
328
329 /* Store handle for other backends to use. */
330 state->handle = dsa_get_handle(ret);
331 }
332 else if (dsa_is_attached(state->handle))
334 (errmsg("requested DSA already attached to current process")));
335 else
336 {
337 /* Attach to existing DSA. */
338 ret = dsa_attach(state->handle);
339 dsa_pin_mapping(ret);
340 }
341
343 MemoryContextSwitchTo(oldcontext);
344
345 return ret;
346}
#define Assert(condition)
Definition c.h:945
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:39
#define ereport(elevel,...)
Definition elog.h:150
int LWLockNewTrancheId(const char *name)
Definition lwlock.c:597
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
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 358 of file dsm_registry.c.

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

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

◆ init_dsm_registry()

static void init_dsm_registry ( void  )
static

Definition at line 146 of file dsm_registry.c.

147{
148 /* Quick exit if we already did this. */
150 return;
151
152 /* Otherwise, use a lock to ensure only one process creates the table. */
154
156 {
157 /* Initialize dynamic shared hash table for registry. */
160
163
164 /* Store handles in shared memory for other backends to use. */
167 }
168 else
169 {
170 /* Attach to existing dynamic shared hash table. */
175 }
176
178}
static dsa_area * dsm_registry_dsa
static const dshash_parameters dsh_params
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
Definition lwlock.c:1177
void LWLockRelease(LWLock *lock)
Definition lwlock.c:1794
@ 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 449 of file dsm_registry.c.

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

Referenced by init_dsm_registry().

◆ dsm_registry_dsa

dsa_area* dsm_registry_dsa
static

Definition at line 114 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 58 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 86 of file dsm_registry.c.

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

Referenced by pg_get_dsm_registry_allocations().