#include "postgres.h" #include "catalog/catalog.h" #include "catalog/namespace.h" #include "catalog/pg_type.h" #include "funcapi.h" #include "miscadmin.h" #include "storage/bufmgr.h" #include "utils/builtins.h" #include "utils/rel.h" #include "storage/bufmgr.h" #include "access/relation.h" #include "utils/varlena.h" PG_MODULE_MAGIC; PG_FUNCTION_INFO_V1(test_bufmgr); #define MAX_BLK_ENTRIES 200 #define MAX_BUFFER_ENTRIES 128 #define INVALID_BUFID -1 static Relation test_rel = NULL; static int blkno2bufid[MAX_BLK_ENTRIES]; static void read_unpin_block (uint32 blkno); static Buffer read_pin_block (uint32 blkno); static void unpin_block (uint32 blkno); static void InitTestBufferPool (Relation rel); static Relation InitTest (text *relname); static void read_unpin_block (uint32 blkno) { Buffer buf; int bufid; if (blkno >= RelationGetNumberOfBlocksInFork(test_rel, MAIN_FORKNUM)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("block number %u is out of range for relation \"%s\"", blkno, RelationGetRelationName(test_rel)))); buf = ReadBuffer(test_rel, blkno); ReleaseBuffer(buf); bufid = buf - 1; elog(NOTICE,"test_bufmgr read_unpin_block blkno %u bufid %d", blkno, bufid); } static Buffer read_pin_block (uint32 blkno) { Buffer buf; int bufid; if (blkno >= RelationGetNumberOfBlocksInFork(test_rel, MAIN_FORKNUM)) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("block number %u is out of range for relation \"%s\"", blkno, RelationGetRelationName(test_rel)))); Assert (blkno < MAX_BLK_ENTRIES); buf = ReadBuffer(test_rel, blkno); bufid = buf - 1; blkno2bufid[blkno] = bufid; elog(NOTICE,"test_bufmgr read_pin_block blkno %u bufid %d", blkno, bufid); return buf; } static void unpin_block (uint32 blkno) { int bufid; Buffer buf; Assert (blkno < MAX_BLK_ENTRIES); bufid = blkno2bufid[blkno]; elog(NOTICE,"test_bufmgr unpin_block blkno %u bufid %d", blkno, bufid); Assert (bufid != INVALID_BUFID); buf = bufid + 1; ReleaseBuffer(buf); } static void InitTestBufferPool (Relation rel) { int i; int bufid; uint32 blkno; Buffer buf; /* read and pin NBuffers blocks starting from blkno NBuffers */ for (i = 0; i < NBuffers; i++) { blkno = NBuffers + i; buf = ReadBuffer(rel, blkno); } /* read and pin NBuffers blocks starting from blkno 0 */ for (bufid = 0; bufid < NBuffers; bufid++) { buf = bufid + 1; ReleaseBuffer(buf); /* unpin bufid for it to become the only victim buffer frame */ blkno = bufid; buf = ReadBuffer(rel, blkno); } /* read and unpin NBuffers blocks starting from blkno 0 */ for (bufid = 0; bufid < NBuffers; bufid++) { blkno = bufid; buf = ReadBuffer(rel, blkno); ReleaseBuffer(buf); } /* unpin blocks 0 to NBuffers-1 */ for (bufid = 0; bufid < NBuffers; bufid++) { buf = bufid + 1; ReleaseBuffer(buf); } } static Relation InitTest (text *relname) { RangeVar *relrv; Relation rel; int i; if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to use raw functions")))); relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname)); rel = relation_openrv(relrv, RowExclusiveLock); /* Check that this relation has storage */ if (rel->rd_rel->relkind == RELKIND_VIEW) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot get raw page from view \"%s\"", RelationGetRelationName(rel)))); if (rel->rd_rel->relkind == RELKIND_COMPOSITE_TYPE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot get raw page from composite type \"%s\"", RelationGetRelationName(rel)))); if (rel->rd_rel->relkind == RELKIND_FOREIGN_TABLE) ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), errmsg("cannot get raw page from foreign table \"%s\"", RelationGetRelationName(rel)))); /* * Reject attempts to read non-local temporary relations; we would be * likely to get wrong data since we have no visibility into the owning * session's local buffers. */ if (RELATION_IS_OTHER_TEMP(rel)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot access temporary tables of other sessions"))); for (i=0; i