aboutsummaryrefslogtreecommitdiff
path: root/src/test/modules/test_dsa/test_dsa.c
blob: cd24d0f48736d6f4286ab97d6fc3a3ae6b91040d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/*--------------------------------------------------------------------------
 *
 * test_dsa.c
 *		Test dynamic shared memory areas (DSAs)
 *
 * Copyright (c) 2022-2025, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *		src/test/modules/test_dsa/test_dsa.c
 *
 * -------------------------------------------------------------------------
 */
#include "postgres.h"

#include "fmgr.h"
#include "storage/lwlock.h"
#include "utils/dsa.h"
#include "utils/resowner.h"

PG_MODULE_MAGIC;

/* Test basic DSA functionality */
PG_FUNCTION_INFO_V1(test_dsa_basic);
Datum
test_dsa_basic(PG_FUNCTION_ARGS)
{
	int			tranche_id;
	dsa_area   *a;
	dsa_pointer p[100];

	/* XXX: this tranche is leaked */
	tranche_id = LWLockNewTrancheId();
	LWLockRegisterTranche(tranche_id, "test_dsa");

	a = dsa_create(tranche_id);
	for (int i = 0; i < 100; i++)
	{
		p[i] = dsa_allocate(a, 1000);
		snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
	}

	for (int i = 0; i < 100; i++)
	{
		char		buf[100];

		snprintf(buf, 100, "foobar%d", i);
		if (strcmp(dsa_get_address(a, p[i]), buf) != 0)
			elog(ERROR, "no match");
	}

	for (int i = 0; i < 100; i++)
	{
		dsa_free(a, p[i]);
	}

	dsa_detach(a);

	PG_RETURN_VOID();
}

/* Test using DSA across different resource owners */
PG_FUNCTION_INFO_V1(test_dsa_resowners);
Datum
test_dsa_resowners(PG_FUNCTION_ARGS)
{
	int			tranche_id;
	dsa_area   *a;
	dsa_pointer p[10000];
	ResourceOwner oldowner;
	ResourceOwner childowner;

	/* XXX: this tranche is leaked */
	tranche_id = LWLockNewTrancheId();
	LWLockRegisterTranche(tranche_id, "test_dsa");

	/* Create DSA in parent resource owner */
	a = dsa_create(tranche_id);

	/*
	 * Switch to child resource owner, and do a bunch of allocations in the
	 * DSA
	 */
	oldowner = CurrentResourceOwner;
	childowner = ResourceOwnerCreate(oldowner, "test_dsa temp owner");
	CurrentResourceOwner = childowner;

	for (int i = 0; i < 10000; i++)
	{
		p[i] = dsa_allocate(a, 1000);
		snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
	}

	/* Also test freeing, by freeing some of the allocations. */
	for (int i = 0; i < 500; i++)
		dsa_free(a, p[i]);

	/* Release the child resource owner */
	CurrentResourceOwner = oldowner;
	ResourceOwnerRelease(childowner,
						 RESOURCE_RELEASE_BEFORE_LOCKS,
						 true, false);
	ResourceOwnerRelease(childowner,
						 RESOURCE_RELEASE_LOCKS,
						 true, false);
	ResourceOwnerRelease(childowner,
						 RESOURCE_RELEASE_AFTER_LOCKS,
						 true, false);
	ResourceOwnerDelete(childowner);

	dsa_detach(a);

	PG_RETURN_VOID();
}