LCOV - code coverage report
Current view: top level - src/backend/access/brin - brin_xlog.c (source / functions) Hit Total Coverage
Test: PostgreSQL 12beta1 Lines: 0 143 0.0 %
Date: 2019-06-16 14:06:46 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * brin_xlog.c
       3             :  *      XLog replay routines for BRIN indexes
       4             :  *
       5             :  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
       6             :  * Portions Copyright (c) 1994, Regents of the University of California
       7             :  *
       8             :  * IDENTIFICATION
       9             :  *    src/backend/access/brin/brin_xlog.c
      10             :  */
      11             : #include "postgres.h"
      12             : 
      13             : #include "access/brin_page.h"
      14             : #include "access/brin_pageops.h"
      15             : #include "access/brin_xlog.h"
      16             : #include "access/bufmask.h"
      17             : #include "access/xlogutils.h"
      18             : 
      19             : 
      20             : /*
      21             :  * xlog replay routines
      22             :  */
      23             : static void
      24           0 : brin_xlog_createidx(XLogReaderState *record)
      25             : {
      26           0 :     XLogRecPtr  lsn = record->EndRecPtr;
      27           0 :     xl_brin_createidx *xlrec = (xl_brin_createidx *) XLogRecGetData(record);
      28             :     Buffer      buf;
      29             :     Page        page;
      30             : 
      31             :     /* create the index' metapage */
      32           0 :     buf = XLogInitBufferForRedo(record, 0);
      33             :     Assert(BufferIsValid(buf));
      34           0 :     page = (Page) BufferGetPage(buf);
      35           0 :     brin_metapage_init(page, xlrec->pagesPerRange, xlrec->version);
      36           0 :     PageSetLSN(page, lsn);
      37           0 :     MarkBufferDirty(buf);
      38           0 :     UnlockReleaseBuffer(buf);
      39           0 : }
      40             : 
      41             : /*
      42             :  * Common part of an insert or update. Inserts the new tuple and updates the
      43             :  * revmap.
      44             :  */
      45             : static void
      46           0 : brin_xlog_insert_update(XLogReaderState *record,
      47             :                         xl_brin_insert *xlrec)
      48             : {
      49           0 :     XLogRecPtr  lsn = record->EndRecPtr;
      50             :     Buffer      buffer;
      51             :     BlockNumber regpgno;
      52             :     Page        page;
      53             :     XLogRedoAction action;
      54             : 
      55             :     /*
      56             :      * If we inserted the first and only tuple on the page, re-initialize the
      57             :      * page from scratch.
      58             :      */
      59           0 :     if (XLogRecGetInfo(record) & XLOG_BRIN_INIT_PAGE)
      60             :     {
      61           0 :         buffer = XLogInitBufferForRedo(record, 0);
      62           0 :         page = BufferGetPage(buffer);
      63           0 :         brin_page_init(page, BRIN_PAGETYPE_REGULAR);
      64           0 :         action = BLK_NEEDS_REDO;
      65             :     }
      66             :     else
      67             :     {
      68           0 :         action = XLogReadBufferForRedo(record, 0, &buffer);
      69             :     }
      70             : 
      71             :     /* need this page's blkno to store in revmap */
      72           0 :     regpgno = BufferGetBlockNumber(buffer);
      73             : 
      74             :     /* insert the index item into the page */
      75           0 :     if (action == BLK_NEEDS_REDO)
      76             :     {
      77             :         OffsetNumber offnum;
      78             :         BrinTuple  *tuple;
      79             :         Size        tuplen;
      80             : 
      81           0 :         tuple = (BrinTuple *) XLogRecGetBlockData(record, 0, &tuplen);
      82             : 
      83             :         Assert(tuple->bt_blkno == xlrec->heapBlk);
      84             : 
      85           0 :         page = (Page) BufferGetPage(buffer);
      86           0 :         offnum = xlrec->offnum;
      87           0 :         if (PageGetMaxOffsetNumber(page) + 1 < offnum)
      88           0 :             elog(PANIC, "brin_xlog_insert_update: invalid max offset number");
      89             : 
      90           0 :         offnum = PageAddItem(page, (Item) tuple, tuplen, offnum, true, false);
      91           0 :         if (offnum == InvalidOffsetNumber)
      92           0 :             elog(PANIC, "brin_xlog_insert_update: failed to add tuple");
      93             : 
      94           0 :         PageSetLSN(page, lsn);
      95           0 :         MarkBufferDirty(buffer);
      96             :     }
      97           0 :     if (BufferIsValid(buffer))
      98           0 :         UnlockReleaseBuffer(buffer);
      99             : 
     100             :     /* update the revmap */
     101           0 :     action = XLogReadBufferForRedo(record, 1, &buffer);
     102           0 :     if (action == BLK_NEEDS_REDO)
     103             :     {
     104             :         ItemPointerData tid;
     105             : 
     106           0 :         ItemPointerSet(&tid, regpgno, xlrec->offnum);
     107           0 :         page = (Page) BufferGetPage(buffer);
     108             : 
     109           0 :         brinSetHeapBlockItemptr(buffer, xlrec->pagesPerRange, xlrec->heapBlk,
     110             :                                 tid);
     111           0 :         PageSetLSN(page, lsn);
     112           0 :         MarkBufferDirty(buffer);
     113             :     }
     114           0 :     if (BufferIsValid(buffer))
     115           0 :         UnlockReleaseBuffer(buffer);
     116             : 
     117             :     /* XXX no FSM updates here ... */
     118           0 : }
     119             : 
     120             : /*
     121             :  * replay a BRIN index insertion
     122             :  */
     123             : static void
     124           0 : brin_xlog_insert(XLogReaderState *record)
     125             : {
     126           0 :     xl_brin_insert *xlrec = (xl_brin_insert *) XLogRecGetData(record);
     127             : 
     128           0 :     brin_xlog_insert_update(record, xlrec);
     129           0 : }
     130             : 
     131             : /*
     132             :  * replay a BRIN index update
     133             :  */
     134             : static void
     135           0 : brin_xlog_update(XLogReaderState *record)
     136             : {
     137           0 :     XLogRecPtr  lsn = record->EndRecPtr;
     138           0 :     xl_brin_update *xlrec = (xl_brin_update *) XLogRecGetData(record);
     139             :     Buffer      buffer;
     140             :     XLogRedoAction action;
     141             : 
     142             :     /* First remove the old tuple */
     143           0 :     action = XLogReadBufferForRedo(record, 2, &buffer);
     144           0 :     if (action == BLK_NEEDS_REDO)
     145             :     {
     146             :         Page        page;
     147             :         OffsetNumber offnum;
     148             : 
     149           0 :         page = (Page) BufferGetPage(buffer);
     150             : 
     151           0 :         offnum = xlrec->oldOffnum;
     152             : 
     153           0 :         PageIndexTupleDeleteNoCompact(page, offnum);
     154             : 
     155           0 :         PageSetLSN(page, lsn);
     156           0 :         MarkBufferDirty(buffer);
     157             :     }
     158             : 
     159             :     /* Then insert the new tuple and update revmap, like in an insertion. */
     160           0 :     brin_xlog_insert_update(record, &xlrec->insert);
     161             : 
     162           0 :     if (BufferIsValid(buffer))
     163           0 :         UnlockReleaseBuffer(buffer);
     164           0 : }
     165             : 
     166             : /*
     167             :  * Update a tuple on a single page.
     168             :  */
     169             : static void
     170           0 : brin_xlog_samepage_update(XLogReaderState *record)
     171             : {
     172           0 :     XLogRecPtr  lsn = record->EndRecPtr;
     173             :     xl_brin_samepage_update *xlrec;
     174             :     Buffer      buffer;
     175             :     XLogRedoAction action;
     176             : 
     177           0 :     xlrec = (xl_brin_samepage_update *) XLogRecGetData(record);
     178           0 :     action = XLogReadBufferForRedo(record, 0, &buffer);
     179           0 :     if (action == BLK_NEEDS_REDO)
     180             :     {
     181             :         Size        tuplen;
     182             :         BrinTuple  *brintuple;
     183             :         Page        page;
     184             :         OffsetNumber offnum;
     185             : 
     186           0 :         brintuple = (BrinTuple *) XLogRecGetBlockData(record, 0, &tuplen);
     187             : 
     188           0 :         page = (Page) BufferGetPage(buffer);
     189             : 
     190           0 :         offnum = xlrec->offnum;
     191             : 
     192           0 :         if (!PageIndexTupleOverwrite(page, offnum, (Item) brintuple, tuplen))
     193           0 :             elog(PANIC, "brin_xlog_samepage_update: failed to replace tuple");
     194             : 
     195           0 :         PageSetLSN(page, lsn);
     196           0 :         MarkBufferDirty(buffer);
     197             :     }
     198           0 :     if (BufferIsValid(buffer))
     199           0 :         UnlockReleaseBuffer(buffer);
     200             : 
     201             :     /* XXX no FSM updates here ... */
     202           0 : }
     203             : 
     204             : /*
     205             :  * Replay a revmap page extension
     206             :  */
     207             : static void
     208           0 : brin_xlog_revmap_extend(XLogReaderState *record)
     209             : {
     210           0 :     XLogRecPtr  lsn = record->EndRecPtr;
     211             :     xl_brin_revmap_extend *xlrec;
     212             :     Buffer      metabuf;
     213             :     Buffer      buf;
     214             :     Page        page;
     215             :     BlockNumber targetBlk;
     216             :     XLogRedoAction action;
     217             : 
     218           0 :     xlrec = (xl_brin_revmap_extend *) XLogRecGetData(record);
     219             : 
     220           0 :     XLogRecGetBlockTag(record, 1, NULL, NULL, &targetBlk);
     221             :     Assert(xlrec->targetBlk == targetBlk);
     222             : 
     223             :     /* Update the metapage */
     224           0 :     action = XLogReadBufferForRedo(record, 0, &metabuf);
     225           0 :     if (action == BLK_NEEDS_REDO)
     226             :     {
     227             :         Page        metapg;
     228             :         BrinMetaPageData *metadata;
     229             : 
     230           0 :         metapg = BufferGetPage(metabuf);
     231           0 :         metadata = (BrinMetaPageData *) PageGetContents(metapg);
     232             : 
     233             :         Assert(metadata->lastRevmapPage == xlrec->targetBlk - 1);
     234           0 :         metadata->lastRevmapPage = xlrec->targetBlk;
     235             : 
     236           0 :         PageSetLSN(metapg, lsn);
     237             : 
     238             :         /*
     239             :          * Set pd_lower just past the end of the metadata.  This is essential,
     240             :          * because without doing so, metadata will be lost if xlog.c
     241             :          * compresses the page.  (We must do this here because pre-v11
     242             :          * versions of PG did not set the metapage's pd_lower correctly, so a
     243             :          * pg_upgraded index might contain the wrong value.)
     244             :          */
     245           0 :         ((PageHeader) metapg)->pd_lower =
     246           0 :             ((char *) metadata + sizeof(BrinMetaPageData)) - (char *) metapg;
     247             : 
     248           0 :         MarkBufferDirty(metabuf);
     249             :     }
     250             : 
     251             :     /*
     252             :      * Re-init the target block as a revmap page.  There's never a full- page
     253             :      * image here.
     254             :      */
     255             : 
     256           0 :     buf = XLogInitBufferForRedo(record, 1);
     257           0 :     page = (Page) BufferGetPage(buf);
     258           0 :     brin_page_init(page, BRIN_PAGETYPE_REVMAP);
     259             : 
     260           0 :     PageSetLSN(page, lsn);
     261           0 :     MarkBufferDirty(buf);
     262             : 
     263           0 :     UnlockReleaseBuffer(buf);
     264           0 :     if (BufferIsValid(metabuf))
     265           0 :         UnlockReleaseBuffer(metabuf);
     266           0 : }
     267             : 
     268             : static void
     269           0 : brin_xlog_desummarize_page(XLogReaderState *record)
     270             : {
     271           0 :     XLogRecPtr  lsn = record->EndRecPtr;
     272             :     xl_brin_desummarize *xlrec;
     273             :     Buffer      buffer;
     274             :     XLogRedoAction action;
     275             : 
     276           0 :     xlrec = (xl_brin_desummarize *) XLogRecGetData(record);
     277             : 
     278             :     /* Update the revmap */
     279           0 :     action = XLogReadBufferForRedo(record, 0, &buffer);
     280           0 :     if (action == BLK_NEEDS_REDO)
     281             :     {
     282             :         ItemPointerData iptr;
     283             : 
     284           0 :         ItemPointerSetInvalid(&iptr);
     285           0 :         brinSetHeapBlockItemptr(buffer, xlrec->pagesPerRange, xlrec->heapBlk, iptr);
     286             : 
     287           0 :         PageSetLSN(BufferGetPage(buffer), lsn);
     288           0 :         MarkBufferDirty(buffer);
     289             :     }
     290           0 :     if (BufferIsValid(buffer))
     291           0 :         UnlockReleaseBuffer(buffer);
     292             : 
     293             :     /* remove the leftover entry from the regular page */
     294           0 :     action = XLogReadBufferForRedo(record, 1, &buffer);
     295           0 :     if (action == BLK_NEEDS_REDO)
     296             :     {
     297           0 :         Page        regPg = BufferGetPage(buffer);
     298             : 
     299           0 :         PageIndexTupleDeleteNoCompact(regPg, xlrec->regOffset);
     300             : 
     301           0 :         PageSetLSN(regPg, lsn);
     302           0 :         MarkBufferDirty(buffer);
     303             :     }
     304           0 :     if (BufferIsValid(buffer))
     305           0 :         UnlockReleaseBuffer(buffer);
     306           0 : }
     307             : 
     308             : void
     309           0 : brin_redo(XLogReaderState *record)
     310             : {
     311           0 :     uint8       info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
     312             : 
     313           0 :     switch (info & XLOG_BRIN_OPMASK)
     314             :     {
     315             :         case XLOG_BRIN_CREATE_INDEX:
     316           0 :             brin_xlog_createidx(record);
     317           0 :             break;
     318             :         case XLOG_BRIN_INSERT:
     319           0 :             brin_xlog_insert(record);
     320           0 :             break;
     321             :         case XLOG_BRIN_UPDATE:
     322           0 :             brin_xlog_update(record);
     323           0 :             break;
     324             :         case XLOG_BRIN_SAMEPAGE_UPDATE:
     325           0 :             brin_xlog_samepage_update(record);
     326           0 :             break;
     327             :         case XLOG_BRIN_REVMAP_EXTEND:
     328           0 :             brin_xlog_revmap_extend(record);
     329           0 :             break;
     330             :         case XLOG_BRIN_DESUMMARIZE:
     331           0 :             brin_xlog_desummarize_page(record);
     332           0 :             break;
     333             :         default:
     334           0 :             elog(PANIC, "brin_redo: unknown op code %u", info);
     335             :     }
     336           0 : }
     337             : 
     338             : /*
     339             :  * Mask a BRIN page before doing consistency checks.
     340             :  */
     341             : void
     342           0 : brin_mask(char *pagedata, BlockNumber blkno)
     343             : {
     344           0 :     Page        page = (Page) pagedata;
     345           0 :     PageHeader  pagehdr = (PageHeader) page;
     346             : 
     347           0 :     mask_page_lsn_and_checksum(page);
     348             : 
     349           0 :     mask_page_hint_bits(page);
     350             : 
     351             :     /*
     352             :      * Regular brin pages contain unused space which needs to be masked.
     353             :      * Similarly for meta pages, but mask it only if pd_lower appears to have
     354             :      * been set correctly.
     355             :      */
     356           0 :     if (BRIN_IS_REGULAR_PAGE(page) ||
     357           0 :         (BRIN_IS_META_PAGE(page) && pagehdr->pd_lower > SizeOfPageHeaderData))
     358             :     {
     359           0 :         mask_unused_space(page);
     360             :     }
     361           0 : }

Generated by: LCOV version 1.13