LCOV - code coverage report
Current view: top level - contrib/bloom - blscan.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 56 60 93.3 %
Date: 2019-09-19 02:07:14 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * blscan.c
       4             :  *      Bloom index scan functions.
       5             :  *
       6             :  * Copyright (c) 2016-2019, PostgreSQL Global Development Group
       7             :  *
       8             :  * IDENTIFICATION
       9             :  *    contrib/bloom/blscan.c
      10             :  *
      11             :  *-------------------------------------------------------------------------
      12             :  */
      13             : #include "postgres.h"
      14             : 
      15             : #include "access/relscan.h"
      16             : #include "pgstat.h"
      17             : #include "miscadmin.h"
      18             : #include "storage/bufmgr.h"
      19             : #include "storage/lmgr.h"
      20             : #include "utils/memutils.h"
      21             : #include "utils/rel.h"
      22             : 
      23             : #include "bloom.h"
      24             : 
      25             : /*
      26             :  * Begin scan of bloom index.
      27             :  */
      28             : IndexScanDesc
      29          30 : blbeginscan(Relation r, int nkeys, int norderbys)
      30             : {
      31             :     IndexScanDesc scan;
      32             :     BloomScanOpaque so;
      33             : 
      34          30 :     scan = RelationGetIndexScan(r, nkeys, norderbys);
      35             : 
      36          30 :     so = (BloomScanOpaque) palloc(sizeof(BloomScanOpaqueData));
      37          30 :     initBloomState(&so->state, scan->indexRelation);
      38          30 :     so->sign = NULL;
      39             : 
      40          30 :     scan->opaque = so;
      41             : 
      42          30 :     return scan;
      43             : }
      44             : 
      45             : /*
      46             :  * Rescan a bloom index.
      47             :  */
      48             : void
      49          30 : blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
      50             :          ScanKey orderbys, int norderbys)
      51             : {
      52          30 :     BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
      53             : 
      54          30 :     if (so->sign)
      55           0 :         pfree(so->sign);
      56          30 :     so->sign = NULL;
      57             : 
      58          30 :     if (scankey && scan->numberOfKeys > 0)
      59             :     {
      60          30 :         memmove(scan->keyData, scankey,
      61          30 :                 scan->numberOfKeys * sizeof(ScanKeyData));
      62             :     }
      63          30 : }
      64             : 
      65             : /*
      66             :  * End scan of bloom index.
      67             :  */
      68             : void
      69          30 : blendscan(IndexScanDesc scan)
      70             : {
      71          30 :     BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
      72             : 
      73          30 :     if (so->sign)
      74          30 :         pfree(so->sign);
      75          30 :     so->sign = NULL;
      76          30 : }
      77             : 
      78             : /*
      79             :  * Insert all matching tuples into a bitmap.
      80             :  */
      81             : int64
      82          30 : blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
      83             : {
      84          30 :     int64       ntids = 0;
      85          30 :     BlockNumber blkno = BLOOM_HEAD_BLKNO,
      86             :                 npages;
      87             :     int         i;
      88             :     BufferAccessStrategy bas;
      89          30 :     BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
      90             : 
      91          30 :     if (so->sign == NULL)
      92             :     {
      93             :         /* New search: have to calculate search signature */
      94          30 :         ScanKey     skey = scan->keyData;
      95             : 
      96          30 :         so->sign = palloc0(sizeof(BloomSignatureWord) * so->state.opts.bloomLength);
      97             : 
      98          70 :         for (i = 0; i < scan->numberOfKeys; i++)
      99             :         {
     100             :             /*
     101             :              * Assume bloom-indexable operators to be strict, so nothing could
     102             :              * be found for NULL key.
     103             :              */
     104          40 :             if (skey->sk_flags & SK_ISNULL)
     105             :             {
     106           0 :                 pfree(so->sign);
     107           0 :                 so->sign = NULL;
     108           0 :                 return 0;
     109             :             }
     110             : 
     111             :             /* Add next value to the signature */
     112          40 :             signValue(&so->state, so->sign, skey->sk_argument,
     113          40 :                       skey->sk_attno - 1);
     114             : 
     115          40 :             skey++;
     116             :         }
     117             :     }
     118             : 
     119             :     /*
     120             :      * We're going to read the whole index. This is why we use appropriate
     121             :      * buffer access strategy.
     122             :      */
     123          30 :     bas = GetAccessStrategy(BAS_BULKREAD);
     124          30 :     npages = RelationGetNumberOfBlocks(scan->indexRelation);
     125             : 
     126         204 :     for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
     127             :     {
     128             :         Buffer      buffer;
     129             :         Page        page;
     130             : 
     131         174 :         buffer = ReadBufferExtended(scan->indexRelation, MAIN_FORKNUM,
     132             :                                     blkno, RBM_NORMAL, bas);
     133             : 
     134         174 :         LockBuffer(buffer, BUFFER_LOCK_SHARE);
     135         174 :         page = BufferGetPage(buffer);
     136         174 :         TestForOldSnapshot(scan->xs_snapshot, scan->indexRelation, page);
     137             : 
     138         174 :         if (!PageIsNew(page) && !BloomPageIsDeleted(page))
     139             :         {
     140             :             OffsetNumber offset,
     141         132 :                         maxOffset = BloomPageGetMaxOffset(page);
     142             : 
     143       64680 :             for (offset = 1; offset <= maxOffset; offset++)
     144             :             {
     145       64548 :                 BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset);
     146       64548 :                 bool        res = true;
     147             : 
     148             :                 /* Check index signature with scan signature */
     149      102932 :                 for (i = 0; i < so->state.opts.bloomLength; i++)
     150             :                 {
     151       99492 :                     if ((itup->sign[i] & so->sign[i]) != so->sign[i])
     152             :                     {
     153       61108 :                         res = false;
     154       61108 :                         break;
     155             :                     }
     156             :                 }
     157             : 
     158             :                 /* Add matching tuples to bitmap */
     159       64548 :                 if (res)
     160             :                 {
     161        3440 :                     tbm_add_tuples(tbm, &itup->heapPtr, 1, true);
     162        3440 :                     ntids++;
     163             :                 }
     164             :             }
     165             :         }
     166             : 
     167         174 :         UnlockReleaseBuffer(buffer);
     168         174 :         CHECK_FOR_INTERRUPTS();
     169             :     }
     170          30 :     FreeAccessStrategy(bas);
     171             : 
     172          30 :     return ntids;
     173             : }

Generated by: LCOV version 1.13