LCOV - code coverage report
Current view: top level - src/backend/access/brin - brin_xlog.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 0 143 0.0 %
Date: 2017-09-29 13:40:31 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-2017, 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           0 :     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           0 :         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           0 :     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           0 :         Assert(metadata->lastRevmapPage == xlrec->targetBlk - 1);
     234           0 :         metadata->lastRevmapPage = xlrec->targetBlk;
     235             : 
     236           0 :         PageSetLSN(metapg, lsn);
     237           0 :         MarkBufferDirty(metabuf);
     238             :     }
     239             : 
     240             :     /*
     241             :      * Re-init the target block as a revmap page.  There's never a full- page
     242             :      * image here.
     243             :      */
     244             : 
     245           0 :     buf = XLogInitBufferForRedo(record, 1);
     246           0 :     page = (Page) BufferGetPage(buf);
     247           0 :     brin_page_init(page, BRIN_PAGETYPE_REVMAP);
     248             : 
     249           0 :     PageSetLSN(page, lsn);
     250           0 :     MarkBufferDirty(buf);
     251             : 
     252           0 :     UnlockReleaseBuffer(buf);
     253           0 :     if (BufferIsValid(metabuf))
     254           0 :         UnlockReleaseBuffer(metabuf);
     255           0 : }
     256             : 
     257             : static void
     258           0 : brin_xlog_desummarize_page(XLogReaderState *record)
     259             : {
     260           0 :     XLogRecPtr  lsn = record->EndRecPtr;
     261             :     xl_brin_desummarize *xlrec;
     262             :     Buffer      buffer;
     263             :     XLogRedoAction action;
     264             : 
     265           0 :     xlrec = (xl_brin_desummarize *) XLogRecGetData(record);
     266             : 
     267             :     /* Update the revmap */
     268           0 :     action = XLogReadBufferForRedo(record, 0, &buffer);
     269           0 :     if (action == BLK_NEEDS_REDO)
     270             :     {
     271             :         ItemPointerData iptr;
     272             : 
     273           0 :         ItemPointerSetInvalid(&iptr);
     274           0 :         brinSetHeapBlockItemptr(buffer, xlrec->pagesPerRange, xlrec->heapBlk, iptr);
     275             : 
     276           0 :         PageSetLSN(BufferGetPage(buffer), lsn);
     277           0 :         MarkBufferDirty(buffer);
     278             :     }
     279           0 :     if (BufferIsValid(buffer))
     280           0 :         UnlockReleaseBuffer(buffer);
     281             : 
     282             :     /* remove the leftover entry from the regular page */
     283           0 :     action = XLogReadBufferForRedo(record, 1, &buffer);
     284           0 :     if (action == BLK_NEEDS_REDO)
     285             :     {
     286           0 :         Page        regPg = BufferGetPage(buffer);
     287             : 
     288           0 :         PageIndexTupleDeleteNoCompact(regPg, xlrec->regOffset);
     289             : 
     290           0 :         PageSetLSN(regPg, lsn);
     291           0 :         MarkBufferDirty(buffer);
     292             :     }
     293           0 :     if (BufferIsValid(buffer))
     294           0 :         UnlockReleaseBuffer(buffer);
     295           0 : }
     296             : 
     297             : void
     298           0 : brin_redo(XLogReaderState *record)
     299             : {
     300           0 :     uint8       info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
     301             : 
     302           0 :     switch (info & XLOG_BRIN_OPMASK)
     303             :     {
     304             :         case XLOG_BRIN_CREATE_INDEX:
     305           0 :             brin_xlog_createidx(record);
     306           0 :             break;
     307             :         case XLOG_BRIN_INSERT:
     308           0 :             brin_xlog_insert(record);
     309           0 :             break;
     310             :         case XLOG_BRIN_UPDATE:
     311           0 :             brin_xlog_update(record);
     312           0 :             break;
     313             :         case XLOG_BRIN_SAMEPAGE_UPDATE:
     314           0 :             brin_xlog_samepage_update(record);
     315           0 :             break;
     316             :         case XLOG_BRIN_REVMAP_EXTEND:
     317           0 :             brin_xlog_revmap_extend(record);
     318           0 :             break;
     319             :         case XLOG_BRIN_DESUMMARIZE:
     320           0 :             brin_xlog_desummarize_page(record);
     321           0 :             break;
     322             :         default:
     323           0 :             elog(PANIC, "brin_redo: unknown op code %u", info);
     324             :     }
     325           0 : }
     326             : 
     327             : /*
     328             :  * Mask a BRIN page before doing consistency checks.
     329             :  */
     330             : void
     331           0 : brin_mask(char *pagedata, BlockNumber blkno)
     332             : {
     333           0 :     Page        page = (Page) pagedata;
     334             : 
     335           0 :     mask_page_lsn(page);
     336             : 
     337           0 :     mask_page_hint_bits(page);
     338             : 
     339           0 :     if (BRIN_IS_REGULAR_PAGE(page))
     340             :     {
     341             :         /* Regular brin pages contain unused space which needs to be masked. */
     342           0 :         mask_unused_space(page);
     343             :     }
     344           0 : }

Generated by: LCOV version 1.11