LCOV - code coverage report
Current view: top level - src/test/modules/test_dsa - test_dsa.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 96.2 % 53 51
Test Date: 2026-03-24 02:15:55 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit

            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/freepage.h"
      20              : #include "utils/resowner.h"
      21              : 
      22            1 : PG_MODULE_MAGIC;
      23              : 
      24              : static void
      25            1 : init_tranche(void *ptr, void *arg)
      26              : {
      27            1 :     int        *tranche_id = (int *) ptr;
      28              : 
      29            1 :     *tranche_id = LWLockNewTrancheId("test_dsa");
      30            1 : }
      31              : 
      32              : /* Test basic DSA functionality */
      33            2 : PG_FUNCTION_INFO_V1(test_dsa_basic);
      34              : Datum
      35            1 : test_dsa_basic(PG_FUNCTION_ARGS)
      36              : {
      37              :     int        *tranche_id;
      38              :     bool        found;
      39              :     dsa_area   *a;
      40              :     dsa_pointer p[100];
      41              : 
      42            1 :     tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
      43              :                                     init_tranche, &found, NULL);
      44              : 
      45            1 :     a = dsa_create(*tranche_id);
      46          101 :     for (int i = 0; i < 100; i++)
      47              :     {
      48          100 :         p[i] = dsa_allocate(a, 1000);
      49          100 :         snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
      50              :     }
      51              : 
      52          101 :     for (int i = 0; i < 100; i++)
      53              :     {
      54              :         char        buf[100];
      55              : 
      56          100 :         snprintf(buf, 100, "foobar%d", i);
      57          100 :         if (strcmp(dsa_get_address(a, p[i]), buf) != 0)
      58            0 :             elog(ERROR, "no match");
      59              :     }
      60              : 
      61          101 :     for (int i = 0; i < 100; i++)
      62              :     {
      63          100 :         dsa_free(a, p[i]);
      64              :     }
      65              : 
      66            1 :     dsa_detach(a);
      67              : 
      68            1 :     PG_RETURN_VOID();
      69              : }
      70              : 
      71              : /* Test using DSA across different resource owners */
      72            2 : PG_FUNCTION_INFO_V1(test_dsa_resowners);
      73              : Datum
      74            1 : test_dsa_resowners(PG_FUNCTION_ARGS)
      75              : {
      76              :     int        *tranche_id;
      77              :     bool        found;
      78              :     dsa_area   *a;
      79              :     dsa_pointer p[10000];
      80              :     ResourceOwner oldowner;
      81              :     ResourceOwner childowner;
      82              : 
      83            1 :     tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
      84              :                                     init_tranche, &found, NULL);
      85              : 
      86              :     /* Create DSA in parent resource owner */
      87            1 :     a = dsa_create(*tranche_id);
      88              : 
      89              :     /*
      90              :      * Switch to child resource owner, and do a bunch of allocations in the
      91              :      * DSA
      92              :      */
      93            1 :     oldowner = CurrentResourceOwner;
      94            1 :     childowner = ResourceOwnerCreate(oldowner, "test_dsa temp owner");
      95            1 :     CurrentResourceOwner = childowner;
      96              : 
      97        10001 :     for (int i = 0; i < 10000; i++)
      98              :     {
      99        10000 :         p[i] = dsa_allocate(a, 1000);
     100        10000 :         snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
     101              :     }
     102              : 
     103              :     /* Also test freeing, by freeing some of the allocations. */
     104          501 :     for (int i = 0; i < 500; i++)
     105          500 :         dsa_free(a, p[i]);
     106              : 
     107              :     /* Release the child resource owner */
     108            1 :     CurrentResourceOwner = oldowner;
     109            1 :     ResourceOwnerRelease(childowner,
     110              :                          RESOURCE_RELEASE_BEFORE_LOCKS,
     111              :                          true, false);
     112            1 :     ResourceOwnerRelease(childowner,
     113              :                          RESOURCE_RELEASE_LOCKS,
     114              :                          true, false);
     115            1 :     ResourceOwnerRelease(childowner,
     116              :                          RESOURCE_RELEASE_AFTER_LOCKS,
     117              :                          true, false);
     118            1 :     ResourceOwnerDelete(childowner);
     119              : 
     120            1 :     dsa_detach(a);
     121              : 
     122            1 :     PG_RETURN_VOID();
     123              : }
     124              : 
     125              : /*
     126              :  * test_dsa_allocate
     127              :  *
     128              :  * Test DSA allocation across a range of sizes to exercise the pagemap
     129              :  * sizing logic in make_new_segment().  A fresh DSA is created for each
     130              :  * iteration so that each allocation triggers a new segment creation,
     131              :  * including the odd-sized segment path.
     132              :  */
     133            2 : PG_FUNCTION_INFO_V1(test_dsa_allocate);
     134              : Datum
     135            2 : test_dsa_allocate(PG_FUNCTION_ARGS)
     136              : {
     137            2 :     int         start_num_pages = PG_GETARG_INT32(0);
     138            2 :     int         end_num_pages = PG_GETARG_INT32(1);
     139            2 :     int         step = PG_GETARG_INT32(2);
     140              :     size_t      usable_pages;
     141              :     int        *tranche_id;
     142              :     bool        found;
     143              :     dsa_area   *a;
     144              :     dsa_pointer dp;
     145              : 
     146            2 :     if (start_num_pages > end_num_pages)
     147            0 :         elog(ERROR, "incorrect start and end parameters");
     148              : 
     149            2 :     tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
     150              :                                     init_tranche, &found, NULL);
     151              : 
     152           13 :     for (usable_pages = start_num_pages; usable_pages < end_num_pages; usable_pages += step)
     153              :     {
     154           11 :         a = dsa_create(*tranche_id);
     155           11 :         dp = dsa_allocate(a, usable_pages * FPM_PAGE_SIZE);
     156              : 
     157           11 :         dsa_free(a, dp);
     158           11 :         dsa_detach(a);
     159              :     }
     160              : 
     161            2 :     PG_RETURN_VOID();
     162              : }
        

Generated by: LCOV version 2.0-1