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