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 : :
596 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
66 nathan@postgresql.or 47 :GNC 1 : init_tdr_dsm(void *ptr)
48 : : {
49 : 1 : TestDSMRegistryStruct *dsm = (TestDSMRegistryStruct *) ptr;
50 : :
3 51 : 1 : LWLockInitialize(&dsm->lck, LWLockNewTrancheId("test_dsm_registry"));
66 52 : 1 : dsm->val = 0;
596 nathan@postgresql.or 53 :CBC 1 : }
54 : :
55 : : static void
56 : 4 : tdr_attach_shmem(void)
57 : : {
58 : : bool found;
59 : :
66 nathan@postgresql.or 60 :GNC 4 : tdr_dsm = GetNamedDSMSegment("test_dsm_registry_dsm",
61 : : sizeof(TestDSMRegistryStruct),
62 : : init_tdr_dsm,
63 : : &found);
64 : :
65 [ + + ]: 4 : if (tdr_dsa == NULL)
66 : 2 : tdr_dsa = GetNamedDSA("test_dsm_registry_dsa", &found);
67 : :
68 [ + + ]: 4 : if (tdr_hash == NULL)
69 : 2 : tdr_hash = GetNamedDSHash("test_dsm_registry_hash", &dsh_params, &found);
596 nathan@postgresql.or 70 :CBC 4 : }
71 : :
66 72 : 2 : PG_FUNCTION_INFO_V1(set_val_in_shmem);
73 : : Datum
74 : 1 : set_val_in_shmem(PG_FUNCTION_ARGS)
75 : : {
596 76 : 1 : tdr_attach_shmem();
77 : :
66 nathan@postgresql.or 78 :GNC 1 : LWLockAcquire(&tdr_dsm->lck, LW_EXCLUSIVE);
79 : 1 : tdr_dsm->val = PG_GETARG_INT32(0);
80 : 1 : LWLockRelease(&tdr_dsm->lck);
81 : :
596 nathan@postgresql.or 82 :CBC 1 : PG_RETURN_VOID();
83 : : }
84 : :
66 85 : 2 : PG_FUNCTION_INFO_V1(get_val_in_shmem);
86 : : Datum
87 : 1 : get_val_in_shmem(PG_FUNCTION_ARGS)
88 : : {
89 : : int ret;
90 : :
596 91 : 1 : tdr_attach_shmem();
92 : :
66 nathan@postgresql.or 93 :GNC 1 : LWLockAcquire(&tdr_dsm->lck, LW_SHARED);
94 : 1 : ret = tdr_dsm->val;
95 : 1 : LWLockRelease(&tdr_dsm->lck);
96 : :
92 nathan@postgresql.or 97 :CBC 1 : PG_RETURN_INT32(ret);
98 : : }
99 : :
66 nathan@postgresql.or 100 :GNC 2 : PG_FUNCTION_INFO_V1(set_val_in_hash);
101 : : Datum
102 : 1 : set_val_in_hash(PG_FUNCTION_ARGS)
103 : : {
104 : : TestDSMRegistryHashEntry *entry;
105 : 1 : char *key = TextDatumGetCString(PG_GETARG_DATUM(0));
106 : 1 : char *val = TextDatumGetCString(PG_GETARG_DATUM(1));
107 : : bool found;
108 : :
109 [ - + ]: 1 : if (strlen(key) >= offsetof(TestDSMRegistryHashEntry, val))
66 nathan@postgresql.or 110 [ # # ]:UNC 0 : ereport(ERROR,
111 : : (errmsg("key too long")));
112 : :
66 nathan@postgresql.or 113 :GNC 1 : tdr_attach_shmem();
114 : :
115 : 1 : entry = dshash_find_or_insert(tdr_hash, key, &found);
116 [ - + ]: 1 : if (found)
66 nathan@postgresql.or 117 :UNC 0 : dsa_free(tdr_dsa, entry->val);
118 : :
66 nathan@postgresql.or 119 :GNC 1 : entry->val = dsa_allocate(tdr_dsa, strlen(val) + 1);
120 : 1 : strcpy(dsa_get_address(tdr_dsa, entry->val), val);
121 : :
122 : 1 : dshash_release_lock(tdr_hash, entry);
123 : :
124 : 1 : PG_RETURN_VOID();
125 : : }
126 : :
127 : 2 : PG_FUNCTION_INFO_V1(get_val_in_hash);
128 : : Datum
129 : 1 : get_val_in_hash(PG_FUNCTION_ARGS)
130 : : {
131 : : TestDSMRegistryHashEntry *entry;
132 : 1 : char *key = TextDatumGetCString(PG_GETARG_DATUM(0));
133 : 1 : text *val = NULL;
134 : :
135 : 1 : tdr_attach_shmem();
136 : :
137 : 1 : entry = dshash_find(tdr_hash, key, false);
138 [ - + ]: 1 : if (entry == NULL)
66 nathan@postgresql.or 139 :UNC 0 : PG_RETURN_NULL();
140 : :
66 nathan@postgresql.or 141 :GNC 1 : val = cstring_to_text(dsa_get_address(tdr_dsa, entry->val));
142 : :
143 : 1 : dshash_release_lock(tdr_hash, entry);
144 : :
145 : 1 : PG_RETURN_TEXT_P(val);
146 : : }
|