LCOV - code coverage report
Current view: top level - src/test/modules/test_slru - test_slru.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 122 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 24 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*--------------------------------------------------------------------------
       2              :  *
       3              :  * test_slru.c
       4              :  *              Test correctness of SLRU functions.
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7              :  * Portions Copyright (c) 1994, Regents of the University of California
       8              :  *
       9              :  * IDENTIFICATION
      10              :  *              src/test/modules/test_slru/test_slru.c
      11              :  *
      12              :  * -------------------------------------------------------------------------
      13              :  */
      14              : 
      15              : #include "postgres.h"
      16              : 
      17              : #include "access/slru.h"
      18              : #include "access/transam.h"
      19              : #include "miscadmin.h"
      20              : #include "storage/fd.h"
      21              : #include "storage/ipc.h"
      22              : #include "storage/shmem.h"
      23              : #include "utils/builtins.h"
      24              : 
      25            0 : PG_MODULE_MAGIC;
      26              : 
      27              : /*
      28              :  * SQL-callable entry points
      29              :  */
      30            0 : PG_FUNCTION_INFO_V1(test_slru_page_write);
      31            0 : PG_FUNCTION_INFO_V1(test_slru_page_writeall);
      32            0 : PG_FUNCTION_INFO_V1(test_slru_page_read);
      33            0 : PG_FUNCTION_INFO_V1(test_slru_page_readonly);
      34            0 : PG_FUNCTION_INFO_V1(test_slru_page_exists);
      35            0 : PG_FUNCTION_INFO_V1(test_slru_page_sync);
      36            0 : PG_FUNCTION_INFO_V1(test_slru_page_delete);
      37            0 : PG_FUNCTION_INFO_V1(test_slru_page_truncate);
      38            0 : PG_FUNCTION_INFO_V1(test_slru_delete_all);
      39              : 
      40              : /* Number of SLRU page slots */
      41              : #define NUM_TEST_BUFFERS                16
      42              : 
      43              : static SlruCtlData TestSlruCtlData;
      44              : #define TestSlruCtl                     (&TestSlruCtlData)
      45              : 
      46              : static shmem_request_hook_type prev_shmem_request_hook = NULL;
      47              : static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
      48              : 
      49              : static bool
      50            0 : test_slru_scan_cb(SlruCtl ctl, char *filename, int64 segpage, void *data)
      51              : {
      52            0 :         elog(NOTICE, "Calling test_slru_scan_cb()");
      53            0 :         return SlruScanDirCbDeleteAll(ctl, filename, segpage, data);
      54              : }
      55              : 
      56              : Datum
      57            0 : test_slru_page_write(PG_FUNCTION_ARGS)
      58              : {
      59            0 :         int64           pageno = PG_GETARG_INT64(0);
      60            0 :         char       *data = text_to_cstring(PG_GETARG_TEXT_PP(1));
      61            0 :         int                     slotno;
      62            0 :         LWLock     *lock = SimpleLruGetBankLock(TestSlruCtl, pageno);
      63              : 
      64            0 :         LWLockAcquire(lock, LW_EXCLUSIVE);
      65            0 :         slotno = SimpleLruZeroPage(TestSlruCtl, pageno);
      66              : 
      67              :         /* these should match */
      68            0 :         Assert(TestSlruCtl->shared->page_number[slotno] == pageno);
      69              : 
      70              :         /* mark the page as dirty so as it would get written */
      71            0 :         TestSlruCtl->shared->page_dirty[slotno] = true;
      72            0 :         TestSlruCtl->shared->page_status[slotno] = SLRU_PAGE_VALID;
      73              : 
      74              :         /* write given data to the page, up to the limit of the page */
      75            0 :         strncpy(TestSlruCtl->shared->page_buffer[slotno], data,
      76              :                         BLCKSZ - 1);
      77              : 
      78            0 :         SimpleLruWritePage(TestSlruCtl, slotno);
      79            0 :         LWLockRelease(lock);
      80              : 
      81            0 :         PG_RETURN_VOID();
      82            0 : }
      83              : 
      84              : Datum
      85            0 : test_slru_page_writeall(PG_FUNCTION_ARGS)
      86              : {
      87            0 :         SimpleLruWriteAll(TestSlruCtl, true);
      88            0 :         PG_RETURN_VOID();
      89              : }
      90              : 
      91              : Datum
      92            0 : test_slru_page_read(PG_FUNCTION_ARGS)
      93              : {
      94            0 :         int64           pageno = PG_GETARG_INT64(0);
      95            0 :         bool            write_ok = PG_GETARG_BOOL(1);
      96            0 :         char       *data = NULL;
      97            0 :         int                     slotno;
      98            0 :         LWLock     *lock = SimpleLruGetBankLock(TestSlruCtl, pageno);
      99              : 
     100              :         /* find page in buffers, reading it if necessary */
     101            0 :         LWLockAcquire(lock, LW_EXCLUSIVE);
     102            0 :         slotno = SimpleLruReadPage(TestSlruCtl, pageno,
     103            0 :                                                            write_ok, InvalidTransactionId);
     104            0 :         data = (char *) TestSlruCtl->shared->page_buffer[slotno];
     105            0 :         LWLockRelease(lock);
     106              : 
     107            0 :         PG_RETURN_TEXT_P(cstring_to_text(data));
     108            0 : }
     109              : 
     110              : Datum
     111            0 : test_slru_page_readonly(PG_FUNCTION_ARGS)
     112              : {
     113            0 :         int64           pageno = PG_GETARG_INT64(0);
     114            0 :         char       *data = NULL;
     115            0 :         int                     slotno;
     116            0 :         LWLock     *lock = SimpleLruGetBankLock(TestSlruCtl, pageno);
     117              : 
     118              :         /* find page in buffers, reading it if necessary */
     119            0 :         slotno = SimpleLruReadPage_ReadOnly(TestSlruCtl,
     120            0 :                                                                                 pageno,
     121              :                                                                                 InvalidTransactionId);
     122            0 :         Assert(LWLockHeldByMe(lock));
     123            0 :         data = (char *) TestSlruCtl->shared->page_buffer[slotno];
     124            0 :         LWLockRelease(lock);
     125              : 
     126            0 :         PG_RETURN_TEXT_P(cstring_to_text(data));
     127            0 : }
     128              : 
     129              : Datum
     130            0 : test_slru_page_exists(PG_FUNCTION_ARGS)
     131              : {
     132            0 :         int64           pageno = PG_GETARG_INT64(0);
     133            0 :         bool            found;
     134            0 :         LWLock     *lock = SimpleLruGetBankLock(TestSlruCtl, pageno);
     135              : 
     136            0 :         LWLockAcquire(lock, LW_EXCLUSIVE);
     137            0 :         found = SimpleLruDoesPhysicalPageExist(TestSlruCtl, pageno);
     138            0 :         LWLockRelease(lock);
     139              : 
     140            0 :         PG_RETURN_BOOL(found);
     141            0 : }
     142              : 
     143              : Datum
     144            0 : test_slru_page_sync(PG_FUNCTION_ARGS)
     145              : {
     146            0 :         int64           pageno = PG_GETARG_INT64(0);
     147            0 :         FileTag         ftag;
     148            0 :         char            path[MAXPGPATH];
     149              : 
     150              :         /* note that this flushes the full file a segment is located in */
     151            0 :         ftag.segno = pageno / SLRU_PAGES_PER_SEGMENT;
     152            0 :         SlruSyncFileTag(TestSlruCtl, &ftag, path);
     153              : 
     154            0 :         elog(NOTICE, "Called SlruSyncFileTag() for segment %" PRIu64 " on path %s",
     155              :                  ftag.segno, path);
     156              : 
     157            0 :         PG_RETURN_VOID();
     158            0 : }
     159              : 
     160              : Datum
     161            0 : test_slru_page_delete(PG_FUNCTION_ARGS)
     162              : {
     163            0 :         int64           pageno = PG_GETARG_INT64(0);
     164            0 :         FileTag         ftag;
     165              : 
     166            0 :         ftag.segno = pageno / SLRU_PAGES_PER_SEGMENT;
     167            0 :         SlruDeleteSegment(TestSlruCtl, ftag.segno);
     168              : 
     169            0 :         elog(NOTICE, "Called SlruDeleteSegment() for segment %" PRIu64,
     170              :                  ftag.segno);
     171              : 
     172            0 :         PG_RETURN_VOID();
     173            0 : }
     174              : 
     175              : Datum
     176            0 : test_slru_page_truncate(PG_FUNCTION_ARGS)
     177              : {
     178            0 :         int64           pageno = PG_GETARG_INT64(0);
     179              : 
     180            0 :         SimpleLruTruncate(TestSlruCtl, pageno);
     181            0 :         PG_RETURN_VOID();
     182            0 : }
     183              : 
     184              : Datum
     185            0 : test_slru_delete_all(PG_FUNCTION_ARGS)
     186              : {
     187              :         /* this calls SlruScanDirCbDeleteAll() internally, ensuring deletion */
     188            0 :         SlruScanDirectory(TestSlruCtl, test_slru_scan_cb, NULL);
     189              : 
     190            0 :         PG_RETURN_VOID();
     191              : }
     192              : 
     193              : /*
     194              :  * Module load callbacks and initialization.
     195              :  */
     196              : 
     197              : static void
     198            0 : test_slru_shmem_request(void)
     199              : {
     200            0 :         if (prev_shmem_request_hook)
     201            0 :                 prev_shmem_request_hook();
     202              : 
     203              :         /* reserve shared memory for the test SLRU */
     204            0 :         RequestAddinShmemSpace(SimpleLruShmemSize(NUM_TEST_BUFFERS, 0));
     205            0 : }
     206              : 
     207              : static bool
     208            0 : test_slru_page_precedes_logically(int64 page1, int64 page2)
     209              : {
     210            0 :         return page1 < page2;
     211              : }
     212              : 
     213              : static void
     214            0 : test_slru_shmem_startup(void)
     215              : {
     216              :         /*
     217              :          * Short segments names are well tested elsewhere so in this test we are
     218              :          * focusing on long names.
     219              :          */
     220            0 :         const bool      long_segment_names = true;
     221            0 :         const char      slru_dir_name[] = "pg_test_slru";
     222            0 :         int                     test_tranche_id = -1;
     223            0 :         int                     test_buffer_tranche_id = -1;
     224              : 
     225            0 :         if (prev_shmem_startup_hook)
     226            0 :                 prev_shmem_startup_hook();
     227              : 
     228              :         /*
     229              :          * Create the SLRU directory if it does not exist yet, from the root of
     230              :          * the data directory.
     231              :          */
     232            0 :         (void) MakePGDirectory(slru_dir_name);
     233              : 
     234              :         /*
     235              :          * Initialize the SLRU facility.  In EXEC_BACKEND builds, the
     236              :          * shmem_startup_hook is called in the postmaster and in each backend, but
     237              :          * we only need to generate the LWLock tranches once.  Note that these
     238              :          * tranche ID variables are not used by SimpleLruInit() when
     239              :          * IsUnderPostmaster is true.
     240              :          */
     241            0 :         if (!IsUnderPostmaster)
     242              :         {
     243            0 :                 test_tranche_id = LWLockNewTrancheId("test_slru_tranche");
     244            0 :                 test_buffer_tranche_id = LWLockNewTrancheId("test_buffer_tranche");
     245            0 :         }
     246              : 
     247            0 :         TestSlruCtl->PagePrecedes = test_slru_page_precedes_logically;
     248            0 :         SimpleLruInit(TestSlruCtl, "TestSLRU",
     249            0 :                                   NUM_TEST_BUFFERS, 0, slru_dir_name,
     250            0 :                                   test_buffer_tranche_id, test_tranche_id, SYNC_HANDLER_NONE,
     251              :                                   long_segment_names);
     252            0 : }
     253              : 
     254              : void
     255            0 : _PG_init(void)
     256              : {
     257            0 :         if (!process_shared_preload_libraries_in_progress)
     258            0 :                 ereport(ERROR,
     259              :                                 (errmsg("cannot load \"%s\" after startup", "test_slru"),
     260              :                                  errdetail("\"%s\" must be loaded with \"shared_preload_libraries\".",
     261              :                                                    "test_slru")));
     262              : 
     263            0 :         prev_shmem_request_hook = shmem_request_hook;
     264            0 :         shmem_request_hook = test_slru_shmem_request;
     265              : 
     266            0 :         prev_shmem_startup_hook = shmem_startup_hook;
     267            0 :         shmem_startup_hook = test_slru_shmem_startup;
     268            0 : }
        

Generated by: LCOV version 2.3.2-1