Age Owner Branch data TLA Line data Source code
1 : : /*--------------------------------------------------------------------------
2 : : *
3 : : * test_dsm_registry.c
4 : : * Test the dynamic shared memory registry.
5 : : *
6 : : * Copyright (c) 2024-2025, PostgreSQL Global Development Group
7 : : *
8 : : * IDENTIFICATION
9 : : * src/test/modules/test_dsm_registry/test_dsm_registry.c
10 : : *
11 : : * -------------------------------------------------------------------------
12 : : */
13 : : #include "postgres.h"
14 : :
15 : : #include "fmgr.h"
16 : : #include "storage/dsm_registry.h"
17 : : #include "storage/lwlock.h"
18 : : #include "utils/builtins.h"
19 : :
699 nathan@postgresql.or 20 :CBC 2 : PG_MODULE_MAGIC;
21 : :
22 : : typedef struct TestDSMRegistryStruct
23 : : {
24 : : int val;
25 : : LWLock lck;
26 : : } TestDSMRegistryStruct;
27 : :
28 : : typedef struct TestDSMRegistryHashEntry
29 : : {
30 : : char key[64];
31 : : dsa_pointer val;
32 : : } TestDSMRegistryHashEntry;
33 : :
34 : : static TestDSMRegistryStruct *tdr_dsm;
35 : : static dsa_area *tdr_dsa;
36 : : static dshash_table *tdr_hash;
37 : :
38 : : static const dshash_parameters dsh_params = {
39 : : offsetof(TestDSMRegistryHashEntry, val),
40 : : sizeof(TestDSMRegistryHashEntry),
41 : : dshash_strcmp,
42 : : dshash_strhash,
43 : : dshash_strcpy
44 : : };
45 : :
46 : : static void
3 nathan@postgresql.or 47 :GNC 1 : init_tdr_dsm(void *ptr, void *arg)
48 : : {
169 49 : 1 : TestDSMRegistryStruct *dsm = (TestDSMRegistryStruct *) ptr;
50 : :
3 51 [ - + ]: 1 : if ((int) (intptr_t) arg != 5432)
3 nathan@postgresql.or 52 [ # # ]:UNC 0 : elog(ERROR, "unexpected arg value %d", (int) (intptr_t) arg);
53 : :
106 nathan@postgresql.or 54 :GNC 1 : LWLockInitialize(&dsm->lck, LWLockNewTrancheId("test_dsm_registry"));
169 55 : 1 : dsm->val = 0;
699 nathan@postgresql.or 56 :CBC 1 : }
57 : :
58 : : static void
59 : 4 : tdr_attach_shmem(void)
60 : : {
61 : : bool found;
62 : :
169 nathan@postgresql.or 63 :GNC 4 : tdr_dsm = GetNamedDSMSegment("test_dsm_registry_dsm",
64 : : sizeof(TestDSMRegistryStruct),
65 : : init_tdr_dsm,
66 : : &found, (void *) (intptr_t) 5432);
67 : :
68 [ + + ]: 4 : if (tdr_dsa == NULL)
69 : 2 : tdr_dsa = GetNamedDSA("test_dsm_registry_dsa", &found);
70 : :
71 [ + + ]: 4 : if (tdr_hash == NULL)
72 : 2 : tdr_hash = GetNamedDSHash("test_dsm_registry_hash", &dsh_params, &found);
699 nathan@postgresql.or 73 :CBC 4 : }
74 : :
169 75 : 2 : PG_FUNCTION_INFO_V1(set_val_in_shmem);
76 : : Datum
77 : 1 : set_val_in_shmem(PG_FUNCTION_ARGS)
78 : : {
699 79 : 1 : tdr_attach_shmem();
80 : :
169 nathan@postgresql.or 81 :GNC 1 : LWLockAcquire(&tdr_dsm->lck, LW_EXCLUSIVE);
82 : 1 : tdr_dsm->val = PG_GETARG_INT32(0);
83 : 1 : LWLockRelease(&tdr_dsm->lck);
84 : :
699 nathan@postgresql.or 85 :CBC 1 : PG_RETURN_VOID();
86 : : }
87 : :
169 88 : 2 : PG_FUNCTION_INFO_V1(get_val_in_shmem);
89 : : Datum
90 : 1 : get_val_in_shmem(PG_FUNCTION_ARGS)
91 : : {
92 : : int ret;
93 : :
699 94 : 1 : tdr_attach_shmem();
95 : :
169 nathan@postgresql.or 96 :GNC 1 : LWLockAcquire(&tdr_dsm->lck, LW_SHARED);
97 : 1 : ret = tdr_dsm->val;
98 : 1 : LWLockRelease(&tdr_dsm->lck);
99 : :
195 nathan@postgresql.or 100 :CBC 1 : PG_RETURN_INT32(ret);
101 : : }
102 : :
169 nathan@postgresql.or 103 :GNC 2 : PG_FUNCTION_INFO_V1(set_val_in_hash);
104 : : Datum
105 : 1 : set_val_in_hash(PG_FUNCTION_ARGS)
106 : : {
107 : : TestDSMRegistryHashEntry *entry;
108 : 1 : char *key = TextDatumGetCString(PG_GETARG_DATUM(0));
109 : 1 : char *val = TextDatumGetCString(PG_GETARG_DATUM(1));
110 : : bool found;
111 : :
112 [ - + ]: 1 : if (strlen(key) >= offsetof(TestDSMRegistryHashEntry, val))
169 nathan@postgresql.or 113 [ # # ]:UNC 0 : ereport(ERROR,
114 : : (errmsg("key too long")));
115 : :
169 nathan@postgresql.or 116 :GNC 1 : tdr_attach_shmem();
117 : :
118 : 1 : entry = dshash_find_or_insert(tdr_hash, key, &found);
119 [ - + ]: 1 : if (found)
169 nathan@postgresql.or 120 :UNC 0 : dsa_free(tdr_dsa, entry->val);
121 : :
169 nathan@postgresql.or 122 :GNC 1 : entry->val = dsa_allocate(tdr_dsa, strlen(val) + 1);
123 : 1 : strcpy(dsa_get_address(tdr_dsa, entry->val), val);
124 : :
125 : 1 : dshash_release_lock(tdr_hash, entry);
126 : :
127 : 1 : PG_RETURN_VOID();
128 : : }
129 : :
130 : 2 : PG_FUNCTION_INFO_V1(get_val_in_hash);
131 : : Datum
132 : 1 : get_val_in_hash(PG_FUNCTION_ARGS)
133 : : {
134 : : TestDSMRegistryHashEntry *entry;
135 : 1 : char *key = TextDatumGetCString(PG_GETARG_DATUM(0));
136 : 1 : text *val = NULL;
137 : :
138 : 1 : tdr_attach_shmem();
139 : :
140 : 1 : entry = dshash_find(tdr_hash, key, false);
141 [ - + ]: 1 : if (entry == NULL)
169 nathan@postgresql.or 142 :UNC 0 : PG_RETURN_NULL();
143 : :
169 nathan@postgresql.or 144 :GNC 1 : val = cstring_to_text(dsa_get_address(tdr_dsa, entry->val));
145 : :
146 : 1 : dshash_release_lock(tdr_hash, entry);
147 : :
148 : 1 : PG_RETURN_TEXT_P(val);
149 : : }
|