LTP GCOV extension - code coverage report
Current view: directory - access/gin - ginutil.c
Test: unnamed
Date: 2008-07-03 Instrumented lines: 80
Code covered: 75.0 % Executed lines: 60
Legend: not executed executed

       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * ginutil.c
       4                 :  *        utilities routines for the postgres inverted index access method.
       5                 :  *
       6                 :  *
       7                 :  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
       8                 :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *                      $PostgreSQL: pgsql/src/backend/access/gin/ginutil.c,v 1.12 2007/11/15 22:25:14 momjian Exp $
      12                 :  *-------------------------------------------------------------------------
      13                 :  */
      14                 : 
      15                 : #include "postgres.h"
      16                 : #include "access/genam.h"
      17                 : #include "access/gin.h"
      18                 : #include "access/heapam.h"
      19                 : #include "access/reloptions.h"
      20                 : #include "storage/freespace.h"
      21                 : 
      22                 : void
      23                 : initGinState(GinState *state, Relation index)
      24              33 : {
      25              33 :         if (index->rd_att->natts != 1)
      26               0 :                 elog(ERROR, "numberOfAttributes %d != 1",
      27                 :                          index->rd_att->natts);
      28                 : 
      29              33 :         state->tupdesc = index->rd_att;
      30                 : 
      31              33 :         fmgr_info_copy(&(state->compareFn),
      32                 :                                    index_getprocinfo(index, 1, GIN_COMPARE_PROC),
      33                 :                                    CurrentMemoryContext);
      34              33 :         fmgr_info_copy(&(state->extractValueFn),
      35                 :                                    index_getprocinfo(index, 1, GIN_EXTRACTVALUE_PROC),
      36                 :                                    CurrentMemoryContext);
      37              33 :         fmgr_info_copy(&(state->extractQueryFn),
      38                 :                                    index_getprocinfo(index, 1, GIN_EXTRACTQUERY_PROC),
      39                 :                                    CurrentMemoryContext);
      40              33 :         fmgr_info_copy(&(state->consistentFn),
      41                 :                                    index_getprocinfo(index, 1, GIN_CONSISTENT_PROC),
      42                 :                                    CurrentMemoryContext);
      43              33 : }
      44                 : 
      45                 : /*
      46                 :  * Allocate a new page (either by recycling, or by extending the index file)
      47                 :  * The returned buffer is already pinned and exclusive-locked
      48                 :  * Caller is responsible for initializing the page by calling GinInitBuffer
      49                 :  */
      50                 : 
      51                 : Buffer
      52                 : GinNewBuffer(Relation index)
      53              66 : {
      54                 :         Buffer          buffer;
      55                 :         bool            needLock;
      56                 : 
      57                 :         /* First, try to get a page from FSM */
      58                 :         for (;;)
      59                 :         {
      60              66 :                 BlockNumber blkno = GetFreeIndexPage(&index->rd_node);
      61                 : 
      62              66 :                 if (blkno == InvalidBlockNumber)
      63              66 :                         break;
      64                 : 
      65               0 :                 buffer = ReadBuffer(index, blkno);
      66                 : 
      67                 :                 /*
      68                 :                  * We have to guard against the possibility that someone else already
      69                 :                  * recycled this page; the buffer may be locked if so.
      70                 :                  */
      71               0 :                 if (ConditionalLockBuffer(buffer))
      72                 :                 {
      73               0 :                         Page            page = BufferGetPage(buffer);
      74                 : 
      75               0 :                         if (PageIsNew(page))
      76               0 :                                 return buffer;  /* OK to use, if never initialized */
      77                 : 
      78               0 :                         if (GinPageIsDeleted(page))
      79               0 :                                 return buffer;  /* OK to use */
      80                 : 
      81               0 :                         LockBuffer(buffer, GIN_UNLOCK);
      82                 :                 }
      83                 : 
      84                 :                 /* Can't use it, so release buffer and try again */
      85               0 :                 ReleaseBuffer(buffer);
      86               0 :         }
      87                 : 
      88                 :         /* Must extend the file */
      89              66 :         needLock = !RELATION_IS_LOCAL(index);
      90              66 :         if (needLock)
      91               0 :                 LockRelationForExtension(index, ExclusiveLock);
      92                 : 
      93              66 :         buffer = ReadBuffer(index, P_NEW);
      94              66 :         LockBuffer(buffer, GIN_EXCLUSIVE);
      95                 : 
      96              66 :         if (needLock)
      97               0 :                 UnlockRelationForExtension(index, ExclusiveLock);
      98                 : 
      99              66 :         return buffer;
     100                 : }
     101                 : 
     102                 : void
     103                 : GinInitPage(Page page, uint32 f, Size pageSize)
     104             108 : {
     105                 :         GinPageOpaque opaque;
     106                 : 
     107             108 :         PageInit(page, pageSize, sizeof(GinPageOpaqueData));
     108                 : 
     109             108 :         opaque = GinPageGetOpaque(page);
     110             108 :         memset(opaque, 0, sizeof(GinPageOpaqueData));
     111             108 :         opaque->flags = f;
     112             108 :         opaque->rightlink = InvalidBlockNumber;
     113             108 : }
     114                 : 
     115                 : void
     116                 : GinInitBuffer(Buffer b, uint32 f)
     117              24 : {
     118              24 :         GinInitPage(BufferGetPage(b), f, BufferGetPageSize(b));
     119              24 : }
     120                 : 
     121                 : int
     122                 : compareEntries(GinState *ginstate, Datum a, Datum b)
     123          308432 : {
     124          308432 :         return DatumGetInt32(
     125                 :                                                  FunctionCall2(
     126                 :                                                                            &ginstate->compareFn,
     127                 :                                                                            a, b
     128                 :                                                                            )
     129                 :                 );
     130                 : }
     131                 : 
     132                 : typedef struct
     133                 : {
     134                 :         FmgrInfo   *cmpDatumFunc;
     135                 :         bool       *needUnique;
     136                 : } cmpEntriesData;
     137                 : 
     138                 : static int
     139                 : cmpEntries(const Datum *a, const Datum *b, cmpEntriesData *arg)
     140           30676 : {
     141           30676 :         int                     res = DatumGetInt32(FunctionCall2(arg->cmpDatumFunc,
     142                 :                                                                                                   *a, *b));
     143                 : 
     144           30676 :         if (res == 0)
     145              21 :                 *(arg->needUnique) = TRUE;
     146                 : 
     147           30676 :         return res;
     148                 : }
     149                 : 
     150                 : Datum *
     151                 : extractEntriesS(GinState *ginstate, Datum value, int32 *nentries,
     152                 :                                 bool *needUnique)
     153             712 : {
     154                 :         Datum      *entries;
     155                 : 
     156             712 :         entries = (Datum *) DatumGetPointer(FunctionCall2(
     157                 :                                                                                                    &ginstate->extractValueFn,
     158                 :                                                                                                           value,
     159                 :                                                                                                         PointerGetDatum(nentries)
     160                 :                                                                                                           ));
     161                 : 
     162             712 :         if (entries == NULL)
     163               9 :                 *nentries = 0;
     164                 : 
     165             712 :         *needUnique = FALSE;
     166             712 :         if (*nentries > 1)
     167                 :         {
     168                 :                 cmpEntriesData arg;
     169                 : 
     170             687 :                 arg.cmpDatumFunc = &ginstate->compareFn;
     171             687 :                 arg.needUnique = needUnique;
     172             687 :                 qsort_arg(entries, *nentries, sizeof(Datum),
     173                 :                                   (qsort_arg_comparator) cmpEntries, (void *) &arg);
     174                 :         }
     175                 : 
     176             712 :         return entries;
     177                 : }
     178                 : 
     179                 : 
     180                 : Datum *
     181                 : extractEntriesSU(GinState *ginstate, Datum value, int32 *nentries)
     182             712 : {
     183                 :         bool            needUnique;
     184                 :         Datum      *entries = extractEntriesS(ginstate, value, nentries,
     185             712 :                                                                                   &needUnique);
     186                 : 
     187             712 :         if (needUnique)
     188                 :         {
     189                 :                 Datum      *ptr,
     190                 :                                    *res;
     191                 : 
     192              19 :                 ptr = res = entries;
     193                 : 
     194             189 :                 while (ptr - entries < *nentries)
     195                 :                 {
     196             151 :                         if (compareEntries(ginstate, *ptr, *res) != 0)
     197             113 :                                 *(++res) = *ptr++;
     198                 :                         else
     199              38 :                                 ptr++;
     200                 :                 }
     201                 : 
     202              19 :                 *nentries = res + 1 - entries;
     203                 :         }
     204                 : 
     205             712 :         return entries;
     206                 : }
     207                 : 
     208                 : /*
     209                 :  * It's analog of PageGetTempPage(), but copies whole page
     210                 :  */
     211                 : Page
     212                 : GinPageGetCopyPage(Page page)
     213              42 : {
     214              42 :         Size            pageSize = PageGetPageSize(page);
     215                 :         Page            tmppage;
     216                 : 
     217              42 :         tmppage = (Page) palloc(pageSize);
     218              42 :         memcpy(tmppage, page, pageSize);
     219                 : 
     220              42 :         return tmppage;
     221                 : }
     222                 : 
     223                 : Datum
     224                 : ginoptions(PG_FUNCTION_ARGS)
     225               0 : {
     226               0 :         Datum           reloptions = PG_GETARG_DATUM(0);
     227               0 :         bool            validate = PG_GETARG_BOOL(1);
     228                 :         bytea      *result;
     229                 : 
     230                 :         /*
     231                 :          * It's not clear that fillfactor is useful for GIN, but for the moment
     232                 :          * we'll accept it anyway.  (It won't do anything...)
     233                 :          */
     234                 : #define GIN_MIN_FILLFACTOR                      10
     235                 : #define GIN_DEFAULT_FILLFACTOR          100
     236                 : 
     237               0 :         result = default_reloptions(reloptions, validate,
     238                 :                                                                 GIN_MIN_FILLFACTOR,
     239                 :                                                                 GIN_DEFAULT_FILLFACTOR);
     240               0 :         if (result)
     241               0 :                 PG_RETURN_BYTEA_P(result);
     242               0 :         PG_RETURN_NULL();
     243                 : }

Generated by: LTP GCOV extension version 1.5