LCOV - code coverage report
Current view: top level - src/test/modules/test_slru - test_slru.c (source / functions) Hit Total Coverage
Test: PostgreSQL 16beta1 Lines: 91 94 96.8 %
Date: 2023-06-01 12:12:28 Functions: 24 24 100.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-2023, 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           2 : PG_MODULE_MAGIC;
      26             : 
      27             : /*
      28             :  * SQL-callable entry points
      29             :  */
      30           4 : PG_FUNCTION_INFO_V1(test_slru_page_write);
      31           4 : PG_FUNCTION_INFO_V1(test_slru_page_writeall);
      32           4 : PG_FUNCTION_INFO_V1(test_slru_page_read);
      33           4 : PG_FUNCTION_INFO_V1(test_slru_page_readonly);
      34           4 : PG_FUNCTION_INFO_V1(test_slru_page_exists);
      35           4 : PG_FUNCTION_INFO_V1(test_slru_page_sync);
      36           4 : PG_FUNCTION_INFO_V1(test_slru_page_delete);
      37           4 : PG_FUNCTION_INFO_V1(test_slru_page_truncate);
      38           4 : PG_FUNCTION_INFO_V1(test_slru_delete_all);
      39             : 
      40             : /* Number of SLRU page slots */
      41             : #define NUM_TEST_BUFFERS        16
      42             : 
      43             : /* SLRU control lock */
      44             : LWLock      TestSLRULock;
      45             : #define TestSLRULock (&TestSLRULock)
      46             : 
      47             : static SlruCtlData TestSlruCtlData;
      48             : #define TestSlruCtl         (&TestSlruCtlData)
      49             : 
      50             : static shmem_request_hook_type prev_shmem_request_hook = NULL;
      51             : static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
      52             : 
      53             : static bool
      54           2 : test_slru_scan_cb(SlruCtl ctl, char *filename, int segpage, void *data)
      55             : {
      56           2 :     elog(NOTICE, "Calling test_slru_scan_cb()");
      57           2 :     return SlruScanDirCbDeleteAll(ctl, filename, segpage, data);
      58             : }
      59             : 
      60             : Datum
      61          98 : test_slru_page_write(PG_FUNCTION_ARGS)
      62             : {
      63          98 :     int         pageno = PG_GETARG_INT32(0);
      64          98 :     char       *data = text_to_cstring(PG_GETARG_TEXT_PP(1));
      65             :     int         slotno;
      66             : 
      67          98 :     LWLockAcquire(TestSLRULock, LW_EXCLUSIVE);
      68             : 
      69          98 :     slotno = SimpleLruZeroPage(TestSlruCtl, pageno);
      70             : 
      71             :     /* these should match */
      72             :     Assert(TestSlruCtl->shared->page_number[slotno] == pageno);
      73             : 
      74             :     /* mark the page as dirty so as it would get written */
      75          98 :     TestSlruCtl->shared->page_dirty[slotno] = true;
      76          98 :     TestSlruCtl->shared->page_status[slotno] = SLRU_PAGE_VALID;
      77             : 
      78             :     /* write given data to the page, up to the limit of the page */
      79          98 :     strncpy(TestSlruCtl->shared->page_buffer[slotno], data,
      80             :             BLCKSZ - 1);
      81             : 
      82          98 :     SimpleLruWritePage(TestSlruCtl, slotno);
      83          98 :     LWLockRelease(TestSLRULock);
      84             : 
      85          98 :     PG_RETURN_VOID();
      86             : }
      87             : 
      88             : Datum
      89           2 : test_slru_page_writeall(PG_FUNCTION_ARGS)
      90             : {
      91           2 :     SimpleLruWriteAll(TestSlruCtl, true);
      92           2 :     PG_RETURN_VOID();
      93             : }
      94             : 
      95             : Datum
      96           4 : test_slru_page_read(PG_FUNCTION_ARGS)
      97             : {
      98           4 :     int         pageno = PG_GETARG_INT32(0);
      99           4 :     bool        write_ok = PG_GETARG_BOOL(1);
     100           4 :     char       *data = NULL;
     101             :     int         slotno;
     102             : 
     103             :     /* find page in buffers, reading it if necessary */
     104           4 :     LWLockAcquire(TestSLRULock, LW_EXCLUSIVE);
     105           4 :     slotno = SimpleLruReadPage(TestSlruCtl, pageno,
     106             :                                write_ok, InvalidTransactionId);
     107           4 :     data = (char *) TestSlruCtl->shared->page_buffer[slotno];
     108           4 :     LWLockRelease(TestSLRULock);
     109             : 
     110           4 :     PG_RETURN_TEXT_P(cstring_to_text(data));
     111             : }
     112             : 
     113             : Datum
     114           4 : test_slru_page_readonly(PG_FUNCTION_ARGS)
     115             : {
     116           4 :     int         pageno = PG_GETARG_INT32(0);
     117           4 :     char       *data = NULL;
     118             :     int         slotno;
     119             : 
     120             :     /* find page in buffers, reading it if necessary */
     121           4 :     slotno = SimpleLruReadPage_ReadOnly(TestSlruCtl,
     122             :                                         pageno,
     123             :                                         InvalidTransactionId);
     124             :     Assert(LWLockHeldByMe(TestSLRULock));
     125           4 :     data = (char *) TestSlruCtl->shared->page_buffer[slotno];
     126           4 :     LWLockRelease(TestSLRULock);
     127             : 
     128           4 :     PG_RETURN_TEXT_P(cstring_to_text(data));
     129             : }
     130             : 
     131             : Datum
     132          18 : test_slru_page_exists(PG_FUNCTION_ARGS)
     133             : {
     134          18 :     int         pageno = PG_GETARG_INT32(0);
     135             :     bool        found;
     136             : 
     137          18 :     LWLockAcquire(TestSLRULock, LW_EXCLUSIVE);
     138          18 :     found = SimpleLruDoesPhysicalPageExist(TestSlruCtl, pageno);
     139          18 :     LWLockRelease(TestSLRULock);
     140             : 
     141          18 :     PG_RETURN_BOOL(found);
     142             : }
     143             : 
     144             : Datum
     145           2 : test_slru_page_sync(PG_FUNCTION_ARGS)
     146             : {
     147           2 :     int         pageno = PG_GETARG_INT32(0);
     148             :     FileTag     ftag;
     149             :     char        path[MAXPGPATH];
     150             : 
     151             :     /* note that this flushes the full file a segment is located in */
     152           2 :     ftag.segno = pageno / SLRU_PAGES_PER_SEGMENT;
     153           2 :     SlruSyncFileTag(TestSlruCtl, &ftag, path);
     154             : 
     155           2 :     elog(NOTICE, "Called SlruSyncFileTag() for segment %u on path %s",
     156             :          ftag.segno, path);
     157             : 
     158           2 :     PG_RETURN_VOID();
     159             : }
     160             : 
     161             : Datum
     162           2 : test_slru_page_delete(PG_FUNCTION_ARGS)
     163             : {
     164           2 :     int         pageno = PG_GETARG_INT32(0);
     165             :     FileTag     ftag;
     166             : 
     167           2 :     ftag.segno = pageno / SLRU_PAGES_PER_SEGMENT;
     168           2 :     SlruDeleteSegment(TestSlruCtl, ftag.segno);
     169             : 
     170           2 :     elog(NOTICE, "Called SlruDeleteSegment() for segment %u", ftag.segno);
     171             : 
     172           2 :     PG_RETURN_VOID();
     173             : }
     174             : 
     175             : Datum
     176           2 : test_slru_page_truncate(PG_FUNCTION_ARGS)
     177             : {
     178           2 :     int         pageno = PG_GETARG_INT32(0);
     179             : 
     180           2 :     SimpleLruTruncate(TestSlruCtl, pageno);
     181           2 :     PG_RETURN_VOID();
     182             : }
     183             : 
     184             : Datum
     185           2 : test_slru_delete_all(PG_FUNCTION_ARGS)
     186             : {
     187             :     /* this calls SlruScanDirCbDeleteAll() internally, ensuring deletion */
     188           2 :     SlruScanDirectory(TestSlruCtl, test_slru_scan_cb, NULL);
     189             : 
     190           2 :     PG_RETURN_VOID();
     191             : }
     192             : 
     193             : /*
     194             :  * Module load callbacks and initialization.
     195             :  */
     196             : 
     197             : static void
     198           2 : test_slru_shmem_request(void)
     199             : {
     200           2 :     if (prev_shmem_request_hook)
     201           0 :         prev_shmem_request_hook();
     202             : 
     203             :     /* reserve shared memory for the test SLRU */
     204           2 :     RequestAddinShmemSpace(SimpleLruShmemSize(NUM_TEST_BUFFERS, 0));
     205           2 : }
     206             : 
     207             : static bool
     208          22 : test_slru_page_precedes_logically(int page1, int page2)
     209             : {
     210          22 :     return page1 < page2;
     211             : }
     212             : 
     213             : static void
     214           2 : test_slru_shmem_startup(void)
     215             : {
     216           2 :     const char  slru_dir_name[] = "pg_test_slru";
     217             :     int         test_tranche_id;
     218             : 
     219           2 :     if (prev_shmem_startup_hook)
     220           0 :         prev_shmem_startup_hook();
     221             : 
     222             :     /*
     223             :      * Create the SLRU directory if it does not exist yet, from the root of
     224             :      * the data directory.
     225             :      */
     226           2 :     (void) MakePGDirectory(slru_dir_name);
     227             : 
     228             :     /* initialize the SLRU facility */
     229           2 :     test_tranche_id = LWLockNewTrancheId();
     230           2 :     LWLockRegisterTranche(test_tranche_id, "test_slru_tranche");
     231           2 :     LWLockInitialize(TestSLRULock, test_tranche_id);
     232             : 
     233           2 :     TestSlruCtl->PagePrecedes = test_slru_page_precedes_logically;
     234           2 :     SimpleLruInit(TestSlruCtl, "TestSLRU",
     235             :                   NUM_TEST_BUFFERS, 0, TestSLRULock, slru_dir_name,
     236             :                   test_tranche_id, SYNC_HANDLER_NONE);
     237           2 : }
     238             : 
     239             : void
     240           2 : _PG_init(void)
     241             : {
     242           2 :     if (!process_shared_preload_libraries_in_progress)
     243           0 :         ereport(ERROR,
     244             :                 (errmsg("cannot load \"%s\" after startup", "test_slru"),
     245             :                  errdetail("\"%s\" must be loaded with shared_preload_libraries.",
     246             :                            "test_slru")));
     247             : 
     248           2 :     prev_shmem_request_hook = shmem_request_hook;
     249           2 :     shmem_request_hook = test_slru_shmem_request;
     250             : 
     251           2 :     prev_shmem_startup_hook = shmem_startup_hook;
     252           2 :     shmem_startup_hook = test_slru_shmem_startup;
     253           2 : }

Generated by: LCOV version 1.14