/* * Update index metapage's lastUsedPages info from local cache, if possible * * Updating meta page isn't critical for index working, so * 1 use ConditionalLockBuffer to improve concurrency * 2 don't WAL-log metabuffer changes to decrease WAL traffic */ void SpGistUpdateMetaPage(Relation index) { SpGistCache *cache = (SpGistCache *) index->rd_amcache; if (cache != NULL) { Buffer metabuffer; SpGistMetaPageData *metadata; metabuffer = ReadBuffer(index, SPGIST_METAPAGE_BLKNO); if (ConditionalLockBuffer(metabuffer)) { metadata = SpGistPageGetMeta(BufferGetPage(metabuffer)); metadata->lastUsedPages = cache->lastUsedPages; MarkBufferDirty(metabuffer); UnlockReleaseBuffer(metabuffer); } else { ReleaseBuffer(metabuffer); } } }
void SpGistInitMetabuffer(Buffer b, Relation index) { SpGistMetaPageData *metadata; Page page = BufferGetPage(b); SpGistInitPage(page, SPGIST_META, BufferGetPageSize(b)); metadata = SpGistPageGetMeta(page); memset(metadata, 0, sizeof(SpGistMetaPageData)); metadata->magickNumber = SPGIST_MAGICK_NUMBER; }
/* * Initialize metadata page */ void SpGistInitMetapage(Page page) { SpGistMetaPageData *metadata; int i; SpGistInitPage(page, SPGIST_META); metadata = SpGistPageGetMeta(page); memset(metadata, 0, sizeof(SpGistMetaPageData)); metadata->magicNumber = SPGIST_MAGIC_NUMBER; /* initialize last-used-page cache to empty */ for (i = 0; i < SPGIST_CACHED_PAGES; i++) metadata->lastUsedPages.cachedPage[i].blkno = InvalidBlockNumber; }
/* * Initialize metadata page */ void SpGistInitMetapage(Page page) { SpGistMetaPageData *metadata; SpGistInitPage(page, SPGIST_META); metadata = SpGistPageGetMeta(page); memset(metadata, 0, sizeof(SpGistMetaPageData)); metadata->magicNumber = SPGIST_MAGIC_NUMBER; /* initialize last-used-page cache to empty */ metadata->lastUsedPages.innerPage[0].blkno = InvalidBlockNumber; metadata->lastUsedPages.innerPage[1].blkno = InvalidBlockNumber; metadata->lastUsedPages.innerPage[2].blkno = InvalidBlockNumber; metadata->lastUsedPages.leafPage.blkno = InvalidBlockNumber; }
/* * Fetch local cache of AM-specific info about the index, initializing it * if necessary */ SpGistCache * spgGetCache(Relation index) { SpGistCache *cache; if (index->rd_amcache == NULL) { Oid atttype; spgConfigIn in; FmgrInfo *procinfo; Buffer metabuffer; SpGistMetaPageData *metadata; cache = MemoryContextAllocZero(index->rd_indexcxt, sizeof(SpGistCache)); /* SPGiST doesn't support multi-column indexes */ Assert(index->rd_att->natts == 1); /* * Get the actual data type of the indexed column from the index * tupdesc. We pass this to the opclass config function so that * polymorphic opclasses are possible. */ atttype = index->rd_att->attrs[0]->atttypid; /* Call the config function to get config info for the opclass */ in.attType = atttype; procinfo = index_getprocinfo(index, 1, SPGIST_CONFIG_PROC); FunctionCall2Coll(procinfo, index->rd_indcollation[0], PointerGetDatum(&in), PointerGetDatum(&cache->config)); /* Get the information we need about each relevant datatype */ fillTypeDesc(&cache->attType, atttype); fillTypeDesc(&cache->attPrefixType, cache->config.prefixType); fillTypeDesc(&cache->attLabelType, cache->config.labelType); /* Last, get the lastUsedPages data from the metapage */ metabuffer = ReadBuffer(index, SPGIST_METAPAGE_BLKNO); LockBuffer(metabuffer, BUFFER_LOCK_SHARE); metadata = SpGistPageGetMeta(BufferGetPage(metabuffer)); if (metadata->magicNumber != SPGIST_MAGIC_NUMBER) elog(ERROR, "index \"%s\" is not an SP-GiST index", RelationGetRelationName(index)); cache->lastUsedPages = metadata->lastUsedPages; UnlockReleaseBuffer(metabuffer); index->rd_amcache = (void *) cache; } else { /* assume it's up to date */ cache = (SpGistCache *) index->rd_amcache; } return cache; }