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