Line data Source code
1 : /*--------------------------------------------------------------------------
2 : *
3 : * test_dsa.c
4 : * Test dynamic shared memory areas (DSAs)
5 : *
6 : * Copyright (c) 2022-2026, PostgreSQL Global Development Group
7 : *
8 : * IDENTIFICATION
9 : * src/test/modules/test_dsa/test_dsa.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/dsa.h"
19 : #include "utils/resowner.h"
20 :
21 0 : PG_MODULE_MAGIC;
22 :
23 : static void
24 0 : init_tranche(void *ptr, void *arg)
25 : {
26 0 : int *tranche_id = (int *) ptr;
27 :
28 0 : *tranche_id = LWLockNewTrancheId("test_dsa");
29 0 : }
30 :
31 : /* Test basic DSA functionality */
32 0 : PG_FUNCTION_INFO_V1(test_dsa_basic);
33 : Datum
34 0 : test_dsa_basic(PG_FUNCTION_ARGS)
35 : {
36 0 : int *tranche_id;
37 0 : bool found;
38 0 : dsa_area *a;
39 0 : dsa_pointer p[100];
40 :
41 0 : tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
42 : init_tranche, &found, NULL);
43 :
44 0 : a = dsa_create(*tranche_id);
45 0 : for (int i = 0; i < 100; i++)
46 : {
47 0 : p[i] = dsa_allocate(a, 1000);
48 0 : snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
49 0 : }
50 :
51 0 : for (int i = 0; i < 100; i++)
52 : {
53 0 : char buf[100];
54 :
55 0 : snprintf(buf, 100, "foobar%d", i);
56 0 : if (strcmp(dsa_get_address(a, p[i]), buf) != 0)
57 0 : elog(ERROR, "no match");
58 0 : }
59 :
60 0 : for (int i = 0; i < 100; i++)
61 : {
62 0 : dsa_free(a, p[i]);
63 0 : }
64 :
65 0 : dsa_detach(a);
66 :
67 0 : PG_RETURN_VOID();
68 0 : }
69 :
70 : /* Test using DSA across different resource owners */
71 0 : PG_FUNCTION_INFO_V1(test_dsa_resowners);
72 : Datum
73 0 : test_dsa_resowners(PG_FUNCTION_ARGS)
74 : {
75 0 : int *tranche_id;
76 0 : bool found;
77 0 : dsa_area *a;
78 0 : dsa_pointer p[10000];
79 0 : ResourceOwner oldowner;
80 0 : ResourceOwner childowner;
81 :
82 0 : tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
83 : init_tranche, &found, NULL);
84 :
85 : /* Create DSA in parent resource owner */
86 0 : a = dsa_create(*tranche_id);
87 :
88 : /*
89 : * Switch to child resource owner, and do a bunch of allocations in the
90 : * DSA
91 : */
92 0 : oldowner = CurrentResourceOwner;
93 0 : childowner = ResourceOwnerCreate(oldowner, "test_dsa temp owner");
94 0 : CurrentResourceOwner = childowner;
95 :
96 0 : for (int i = 0; i < 10000; i++)
97 : {
98 0 : p[i] = dsa_allocate(a, 1000);
99 0 : snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
100 0 : }
101 :
102 : /* Also test freeing, by freeing some of the allocations. */
103 0 : for (int i = 0; i < 500; i++)
104 0 : dsa_free(a, p[i]);
105 :
106 : /* Release the child resource owner */
107 0 : CurrentResourceOwner = oldowner;
108 0 : ResourceOwnerRelease(childowner,
109 : RESOURCE_RELEASE_BEFORE_LOCKS,
110 : true, false);
111 0 : ResourceOwnerRelease(childowner,
112 : RESOURCE_RELEASE_LOCKS,
113 : true, false);
114 0 : ResourceOwnerRelease(childowner,
115 : RESOURCE_RELEASE_AFTER_LOCKS,
116 : true, false);
117 0 : ResourceOwnerDelete(childowner);
118 :
119 0 : dsa_detach(a);
120 :
121 0 : PG_RETURN_VOID();
122 0 : }
|