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