Commit 48adc0b3 authored by Jan Wieck's avatar Jan Wieck

Replacement of the buffer replacement strategy with an ARC

algorithm adopted for PostgreSQL.

Jan
parent 27e8ef05
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.265 2003/11/12 21:15:51 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.266 2003/11/13 00:40:00 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include "commands/vacuum.h" #include "commands/vacuum.h"
#include "executor/executor.h" #include "executor/executor.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/buf_internals.h"
#include "storage/freespace.h" #include "storage/freespace.h"
#include "storage/sinval.h" #include "storage/sinval.h"
#include "storage/smgr.h" #include "storage/smgr.h"
...@@ -310,8 +311,16 @@ vacuum(VacuumStmt *vacstmt) ...@@ -310,8 +311,16 @@ vacuum(VacuumStmt *vacstmt)
else else
old_context = MemoryContextSwitchTo(anl_context); old_context = MemoryContextSwitchTo(anl_context);
/*
* Tell the buffer replacement strategy that vacuum is
* causing the IO
*/
StrategyHintVacuum(true);
analyze_rel(relid, vacstmt); analyze_rel(relid, vacstmt);
StrategyHintVacuum(false);
if (vacstmt->vacuum) if (vacstmt->vacuum)
CommitTransactionCommand(); CommitTransactionCommand();
else else
...@@ -749,6 +758,12 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ...@@ -749,6 +758,12 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
SetQuerySnapshot(); /* might be needed for functions in SetQuerySnapshot(); /* might be needed for functions in
* indexes */ * indexes */
/*
* Tell the cache replacement strategy that vacuum is causing
* all following IO
*/
StrategyHintVacuum(true);
/* /*
* Check for user-requested abort. Note we want this to be inside a * Check for user-requested abort. Note we want this to be inside a
* transaction, so xact.c doesn't issue useless WARNING. * transaction, so xact.c doesn't issue useless WARNING.
...@@ -763,6 +778,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ...@@ -763,6 +778,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
ObjectIdGetDatum(relid), ObjectIdGetDatum(relid),
0, 0, 0)) 0, 0, 0))
{ {
StrategyHintVacuum(false);
CommitTransactionCommand(); CommitTransactionCommand();
return true; /* okay 'cause no data there */ return true; /* okay 'cause no data there */
} }
...@@ -796,6 +812,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ...@@ -796,6 +812,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
(errmsg("skipping \"%s\" --- only table or database owner can vacuum it", (errmsg("skipping \"%s\" --- only table or database owner can vacuum it",
RelationGetRelationName(onerel)))); RelationGetRelationName(onerel))));
relation_close(onerel, lmode); relation_close(onerel, lmode);
StrategyHintVacuum(false);
CommitTransactionCommand(); CommitTransactionCommand();
return false; return false;
} }
...@@ -810,6 +827,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ...@@ -810,6 +827,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
(errmsg("skipping \"%s\" --- cannot vacuum indexes, views, or special system tables", (errmsg("skipping \"%s\" --- cannot vacuum indexes, views, or special system tables",
RelationGetRelationName(onerel)))); RelationGetRelationName(onerel))));
relation_close(onerel, lmode); relation_close(onerel, lmode);
StrategyHintVacuum(false);
CommitTransactionCommand(); CommitTransactionCommand();
return false; return false;
} }
...@@ -824,6 +842,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ...@@ -824,6 +842,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
if (isOtherTempNamespace(RelationGetNamespace(onerel))) if (isOtherTempNamespace(RelationGetNamespace(onerel)))
{ {
relation_close(onerel, lmode); relation_close(onerel, lmode);
StrategyHintVacuum(false);
CommitTransactionCommand(); CommitTransactionCommand();
return true; /* assume no long-lived data in temp return true; /* assume no long-lived data in temp
* tables */ * tables */
...@@ -863,6 +882,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind) ...@@ -863,6 +882,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, char expected_relkind)
/* /*
* Complete the transaction and free all temporary memory used. * Complete the transaction and free all temporary memory used.
*/ */
StrategyHintVacuum(false);
CommitTransactionCommand(); CommitTransactionCommand();
/* /*
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.54 2003/08/04 02:40:03 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.55 2003/11/13 00:40:01 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,9 +48,6 @@ long *CurTraceBuf; ...@@ -48,9 +48,6 @@ long *CurTraceBuf;
int ShowPinTrace = 0; int ShowPinTrace = 0;
int Data_Descriptors; int Data_Descriptors;
int Free_List_Descriptor;
int Lookup_List_Descriptor;
int Num_Descriptors;
BufferDesc *BufferDescriptors; BufferDesc *BufferDescriptors;
Block *BufferBlockPointers; Block *BufferBlockPointers;
...@@ -133,9 +130,6 @@ InitBufferPool(void) ...@@ -133,9 +130,6 @@ InitBufferPool(void)
int i; int i;
Data_Descriptors = NBuffers; Data_Descriptors = NBuffers;
Free_List_Descriptor = Data_Descriptors;
Lookup_List_Descriptor = Data_Descriptors + 1;
Num_Descriptors = Data_Descriptors + 1;
/* /*
* It's probably not really necessary to grab the lock --- if there's * It's probably not really necessary to grab the lock --- if there's
...@@ -156,7 +150,7 @@ InitBufferPool(void) ...@@ -156,7 +150,7 @@ InitBufferPool(void)
BufferDescriptors = (BufferDesc *) BufferDescriptors = (BufferDesc *)
ShmemInitStruct("Buffer Descriptors", ShmemInitStruct("Buffer Descriptors",
Num_Descriptors * sizeof(BufferDesc), &foundDescs); Data_Descriptors * sizeof(BufferDesc), &foundDescs);
BufferBlocks = (char *) BufferBlocks = (char *)
ShmemInitStruct("Buffer Blocks", ShmemInitStruct("Buffer Blocks",
...@@ -176,16 +170,14 @@ InitBufferPool(void) ...@@ -176,16 +170,14 @@ InitBufferPool(void)
block = BufferBlocks; block = BufferBlocks;
/* /*
* link the buffers into a circular, doubly-linked list to * link the buffers into a single linked list. This will become the
* initialize free list, and initialize the buffer headers. Still * LiFo list of unused buffers returned by StragegyGetBuffer().
* don't know anything about replacement strategy in this file.
*/ */
for (i = 0; i < Data_Descriptors; block += BLCKSZ, buf++, i++) for (i = 0; i < Data_Descriptors; block += BLCKSZ, buf++, i++)
{ {
Assert(ShmemIsValid((unsigned long) block)); Assert(ShmemIsValid((unsigned long) block));
buf->freeNext = i + 1; buf->bufNext = i + 1;
buf->freePrev = i - 1;
CLEAR_BUFFERTAG(&(buf->tag)); CLEAR_BUFFERTAG(&(buf->tag));
buf->buf_id = i; buf->buf_id = i;
...@@ -199,14 +191,12 @@ InitBufferPool(void) ...@@ -199,14 +191,12 @@ InitBufferPool(void)
buf->wait_backend_id = 0; buf->wait_backend_id = 0;
} }
/* close the circular queue */ /* Correct last entry */
BufferDescriptors[0].freePrev = Data_Descriptors - 1; BufferDescriptors[Data_Descriptors - 1].bufNext = -1;
BufferDescriptors[Data_Descriptors - 1].freeNext = 0;
} }
/* Init other shared buffer-management stuff */ /* Init other shared buffer-management stuff */
InitBufTable(); StrategyInitialize(!foundDescs);
InitFreeList(!foundDescs);
LWLockRelease(BufMgrLock); LWLockRelease(BufMgrLock);
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.29 2003/08/04 02:40:03 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.30 2003/11/13 00:40:01 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -38,7 +38,7 @@ static HTAB *SharedBufHash; ...@@ -38,7 +38,7 @@ static HTAB *SharedBufHash;
* Initialize shmem hash table for mapping buffers * Initialize shmem hash table for mapping buffers
*/ */
void void
InitBufTable(void) InitBufTable(int size)
{ {
HASHCTL info; HASHCTL info;
...@@ -50,7 +50,7 @@ InitBufTable(void) ...@@ -50,7 +50,7 @@ InitBufTable(void)
info.hash = tag_hash; info.hash = tag_hash;
SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table", SharedBufHash = ShmemInitHash("Shared Buffer Lookup Table",
NBuffers, NBuffers, size, size,
&info, &info,
HASH_ELEM | HASH_FUNCTION); HASH_ELEM | HASH_FUNCTION);
...@@ -58,79 +58,63 @@ InitBufTable(void) ...@@ -58,79 +58,63 @@ InitBufTable(void)
elog(FATAL, "could not initialize shared buffer hash table"); elog(FATAL, "could not initialize shared buffer hash table");
} }
BufferDesc * /*
* BufTableLookup
*/
int
BufTableLookup(BufferTag *tagPtr) BufTableLookup(BufferTag *tagPtr)
{ {
BufferLookupEnt *result; BufferLookupEnt *result;
if (tagPtr->blockNum == P_NEW) if (tagPtr->blockNum == P_NEW)
return NULL; return -1;
result = (BufferLookupEnt *) result = (BufferLookupEnt *)
hash_search(SharedBufHash, (void *) tagPtr, HASH_FIND, NULL); hash_search(SharedBufHash, (void *) tagPtr, HASH_FIND, NULL);
if (!result) if (!result)
return NULL; return -1;
return &(BufferDescriptors[result->id]); return result->id;
} }
/* /*
* BufTableDelete * BufTableDelete
*/ */
bool bool
BufTableDelete(BufferDesc *buf) BufTableInsert(BufferTag *tagPtr, Buffer buf_id)
{ {
BufferLookupEnt *result; BufferLookupEnt *result;
bool found;
/*
* buffer not initialized or has been removed from table already.
* BM_DELETED keeps us from removing buffer twice.
*/
if (buf->flags & BM_DELETED)
return TRUE;
buf->flags |= BM_DELETED;
result = (BufferLookupEnt *) result = (BufferLookupEnt *)
hash_search(SharedBufHash, (void *) &(buf->tag), HASH_REMOVE, NULL); hash_search(SharedBufHash, (void *) tagPtr, HASH_ENTER, &found);
if (!result) /* shouldn't happen */ if (!result)
elog(ERROR, "shared buffer hash table corrupted"); ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory")));
/* if (found) /* found something else in the table? */
* Clear the buffer's tag. This doesn't matter for the hash table, elog(ERROR, "shared buffer hash table corrupted");
* since the buffer is already removed from it, but it ensures that
* sequential searches through the buffer table won't think the buffer
* is still valid for its old page.
*/
buf->tag.rnode.relNode = InvalidOid;
buf->tag.rnode.tblNode = InvalidOid;
result->id = buf_id;
return TRUE; return TRUE;
} }
/*
* BufTableDelete
*/
bool bool
BufTableInsert(BufferDesc *buf) BufTableDelete(BufferTag *tagPtr)
{ {
BufferLookupEnt *result; BufferLookupEnt *result;
bool found;
/* cannot insert it twice */
Assert(buf->flags & BM_DELETED);
buf->flags &= ~(BM_DELETED);
result = (BufferLookupEnt *) result = (BufferLookupEnt *)
hash_search(SharedBufHash, (void *) &(buf->tag), HASH_ENTER, &found); hash_search(SharedBufHash, (void *) tagPtr, HASH_REMOVE, NULL);
if (!result)
ereport(ERROR,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of shared memory")));
if (found) /* found something else in the table? */ if (!result) /* shouldn't happen */
elog(ERROR, "shared buffer hash table corrupted"); elog(ERROR, "shared buffer hash table corrupted");
result->id = buf->buf_id;
return TRUE; return TRUE;
} }
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.141 2003/09/25 06:58:01 petere Exp $ * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.142 2003/11/13 00:40:01 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -260,12 +260,8 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum, ...@@ -260,12 +260,8 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
if (status == SM_FAIL) if (status == SM_FAIL)
{ {
/* IO Failed. cleanup the data structures and go home */ /* IO Failed. cleanup the data structures and go home */
StrategyInvalidateBuffer(bufHdr);
if (!BufTableDelete(bufHdr))
{
LWLockRelease(BufMgrLock);
elog(FATAL, "buffer table broken after I/O error");
}
/* remember that BufferAlloc() pinned the buffer */ /* remember that BufferAlloc() pinned the buffer */
UnpinBuffer(bufHdr); UnpinBuffer(bufHdr);
...@@ -318,7 +314,7 @@ BufferAlloc(Relation reln, ...@@ -318,7 +314,7 @@ BufferAlloc(Relation reln,
INIT_BUFFERTAG(&newTag, reln, blockNum); INIT_BUFFERTAG(&newTag, reln, blockNum);
/* see if the block is in the buffer pool already */ /* see if the block is in the buffer pool already */
buf = BufTableLookup(&newTag); buf = StrategyBufferLookup(&newTag, false);
if (buf != NULL) if (buf != NULL)
{ {
/* /*
...@@ -379,7 +375,7 @@ BufferAlloc(Relation reln, ...@@ -379,7 +375,7 @@ BufferAlloc(Relation reln,
inProgress = FALSE; inProgress = FALSE;
for (buf = (BufferDesc *) NULL; buf == (BufferDesc *) NULL;) for (buf = (BufferDesc *) NULL; buf == (BufferDesc *) NULL;)
{ {
buf = GetFreeBuffer(); buf = StrategyGetBuffer();
/* GetFreeBuffer will abort if it can't find a free buffer */ /* GetFreeBuffer will abort if it can't find a free buffer */
Assert(buf); Assert(buf);
...@@ -492,7 +488,7 @@ BufferAlloc(Relation reln, ...@@ -492,7 +488,7 @@ BufferAlloc(Relation reln,
* we haven't gotten around to insert the new tag into the * we haven't gotten around to insert the new tag into the
* buffer table. So we need to check here. -ay 3/95 * buffer table. So we need to check here. -ay 3/95
*/ */
buf2 = BufTableLookup(&newTag); buf2 = StrategyBufferLookup(&newTag, true);
if (buf2 != NULL) if (buf2 != NULL)
{ {
/* /*
...@@ -535,29 +531,12 @@ BufferAlloc(Relation reln, ...@@ -535,29 +531,12 @@ BufferAlloc(Relation reln,
*/ */
/* /*
* Change the name of the buffer in the lookup table: * Tell the buffer replacement strategy that we are replacing the
* * buffer content. Then rename the buffer.
* Need to update the lookup table before the read starts. If someone
* comes along looking for the buffer while we are reading it in, we
* don't want them to allocate a new buffer. For the same reason, we
* didn't want to erase the buf table entry for the buffer we were
* writing back until now, either.
*/ */
StrategyReplaceBuffer(buf, reln, blockNum);
if (!BufTableDelete(buf))
{
LWLockRelease(BufMgrLock);
elog(FATAL, "buffer wasn't in the buffer hash table");
}
INIT_BUFFERTAG(&(buf->tag), reln, blockNum); INIT_BUFFERTAG(&(buf->tag), reln, blockNum);
if (!BufTableInsert(buf))
{
LWLockRelease(BufMgrLock);
elog(FATAL, "buffer in buffer hash table twice");
}
/* /*
* Buffer contents are currently invalid. Have to mark IO IN PROGRESS * Buffer contents are currently invalid. Have to mark IO IN PROGRESS
* so no one fiddles with them until the read completes. If this * so no one fiddles with them until the read completes. If this
...@@ -709,13 +688,28 @@ BufferSync(void) ...@@ -709,13 +688,28 @@ BufferSync(void)
BufferDesc *bufHdr; BufferDesc *bufHdr;
ErrorContextCallback errcontext; ErrorContextCallback errcontext;
int num_buffer_dirty;
int *buffer_dirty;
/* Setup error traceback support for ereport() */ /* Setup error traceback support for ereport() */
errcontext.callback = buffer_write_error_callback; errcontext.callback = buffer_write_error_callback;
errcontext.arg = NULL; errcontext.arg = NULL;
errcontext.previous = error_context_stack; errcontext.previous = error_context_stack;
error_context_stack = &errcontext; error_context_stack = &errcontext;
for (i = 0, bufHdr = BufferDescriptors; i < NBuffers; i++, bufHdr++) /*
* Get a list of all currently dirty buffers and how many there are.
* We do not flush buffers that get dirtied after we started. They
* have to wait until the next checkpoint.
*/
buffer_dirty = (int *)palloc(NBuffers * sizeof(int));
num_buffer_dirty = 0;
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
num_buffer_dirty = StrategyDirtyBufferList(buffer_dirty, NBuffers);
LWLockRelease(BufMgrLock);
for (i = 0; i < num_buffer_dirty; i++)
{ {
Buffer buffer; Buffer buffer;
int status; int status;
...@@ -723,10 +717,11 @@ BufferSync(void) ...@@ -723,10 +717,11 @@ BufferSync(void)
XLogRecPtr recptr; XLogRecPtr recptr;
Relation reln; Relation reln;
errcontext.arg = bufHdr;
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
bufHdr = &BufferDescriptors[buffer_dirty[i]];
errcontext.arg = bufHdr;
if (!(bufHdr->flags & BM_VALID)) if (!(bufHdr->flags & BM_VALID))
{ {
LWLockRelease(BufMgrLock); LWLockRelease(BufMgrLock);
...@@ -855,6 +850,8 @@ BufferSync(void) ...@@ -855,6 +850,8 @@ BufferSync(void)
RelationDecrementReferenceCount(reln); RelationDecrementReferenceCount(reln);
} }
pfree(buffer_dirty);
/* Pop the error context stack */ /* Pop the error context stack */
error_context_stack = errcontext.previous; error_context_stack = errcontext.previous;
} }
...@@ -959,9 +956,9 @@ AtEOXact_Buffers(bool isCommit) ...@@ -959,9 +956,9 @@ AtEOXact_Buffers(bool isCommit)
if (isCommit) if (isCommit)
elog(WARNING, elog(WARNING,
"buffer refcount leak: [%03d] (freeNext=%d, freePrev=%d, " "buffer refcount leak: [%03d] (bufNext=%d, "
"rel=%u/%u, blockNum=%u, flags=0x%x, refcount=%d %ld)", "rel=%u/%u, blockNum=%u, flags=0x%x, refcount=%d %ld)",
i, buf->freeNext, buf->freePrev, i, buf->bufNext,
buf->tag.rnode.tblNode, buf->tag.rnode.relNode, buf->tag.rnode.tblNode, buf->tag.rnode.relNode,
buf->tag.blockNum, buf->flags, buf->tag.blockNum, buf->flags,
buf->refcount, PrivateRefCount[i]); buf->refcount, PrivateRefCount[i]);
...@@ -1229,7 +1226,7 @@ recheck: ...@@ -1229,7 +1226,7 @@ recheck:
/* /*
* And mark the buffer as no longer occupied by this rel. * And mark the buffer as no longer occupied by this rel.
*/ */
BufTableDelete(bufHdr); StrategyInvalidateBuffer(bufHdr);
} }
} }
...@@ -1295,7 +1292,7 @@ recheck: ...@@ -1295,7 +1292,7 @@ recheck:
/* /*
* And mark the buffer as no longer occupied by this page. * And mark the buffer as no longer occupied by this page.
*/ */
BufTableDelete(bufHdr); StrategyInvalidateBuffer(bufHdr);
} }
} }
...@@ -1543,7 +1540,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock) ...@@ -1543,7 +1540,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock)
return -2; return -2;
} }
if (bufHdr->tag.blockNum >= firstDelBlock) if (bufHdr->tag.blockNum >= firstDelBlock)
BufTableDelete(bufHdr); StrategyInvalidateBuffer(bufHdr);
} }
} }
......
This diff is collapsed.
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Written by Peter Eisentraut <peter_e@gmx.net>. * Written by Peter Eisentraut <peter_e@gmx.net>.
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.166 2003/11/07 21:27:38 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.167 2003/11/13 00:40:01 wieck Exp $
* *
*-------------------------------------------------------------------- *--------------------------------------------------------------------
*/ */
...@@ -73,6 +73,7 @@ extern int CheckPointTimeout; ...@@ -73,6 +73,7 @@ extern int CheckPointTimeout;
extern int CommitDelay; extern int CommitDelay;
extern int CommitSiblings; extern int CommitSiblings;
extern char *preload_libraries_string; extern char *preload_libraries_string;
extern int BufferStrategyStatInterval;
#ifdef HAVE_SYSLOG #ifdef HAVE_SYSLOG
extern char *Syslog_facility; extern char *Syslog_facility;
...@@ -1190,6 +1191,15 @@ static struct config_int ConfigureNamesInt[] = ...@@ -1190,6 +1191,15 @@ static struct config_int ConfigureNamesInt[] =
-1, -1, INT_MAX / 1000, NULL, NULL -1, -1, INT_MAX / 1000, NULL, NULL
}, },
{
{"buffer_strategy_status_interval", PGC_POSTMASTER, RESOURCES_MEM,
gettext_noop("Interval to report buffer strategy status in seconds"),
NULL
},
&BufferStrategyStatInterval,
0, 0, 600, NULL, NULL
},
/* End-of-list marker */ /* End-of-list marker */
{ {
{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL {NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#shared_buffers = 1000 # min 16, at least max_connections*2, 8KB each #shared_buffers = 1000 # min 16, at least max_connections*2, 8KB each
#sort_mem = 1024 # min 64, size in KB #sort_mem = 1024 # min 64, size in KB
#vacuum_mem = 8192 # min 1024, size in KB #vacuum_mem = 8192 # min 1024, size in KB
#buffer_strategy_status_interval = 0 # 0-600 seconds
# - Free Space Map - # - Free Space Map -
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: miscadmin.h,v 1.134 2003/09/24 18:54:01 tgl Exp $ * $Id: miscadmin.h,v 1.135 2003/11/13 00:40:01 wieck Exp $
* *
* NOTES * NOTES
* some of the information in this file should be moved to * some of the information in this file should be moved to
...@@ -96,6 +96,13 @@ extern void ProcessInterrupts(void); ...@@ -96,6 +96,13 @@ extern void ProcessInterrupts(void);
CritSectionCount--; \ CritSectionCount--; \
} while(0) } while(0)
#define PG_DELAY(_msec) \
{ \
struct timeval delay; \
delay.tv_sec = (_msec) / 1000; \
delay.tv_usec = ((_msec) % 1000) * 1000; \
(void) select(0, NULL, NULL, NULL, &delay); \
}
/***************************************************************************** /*****************************************************************************
* globals.h -- * * globals.h -- *
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: buf_internals.h,v 1.61 2003/08/04 02:40:14 momjian Exp $ * $Id: buf_internals.h,v 1.62 2003/11/13 00:40:02 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -72,17 +72,29 @@ typedef struct buftag ...@@ -72,17 +72,29 @@ typedef struct buftag
(a)->rnode = (xx_reln)->rd_node \ (a)->rnode = (xx_reln)->rd_node \
) )
#define BUFFERTAG_EQUALS(a,xx_reln,xx_blockNum) \
( \
(a)->rnode.tblNode == (xx_reln)->rd_node.tblNode && \
(a)->rnode.relNode == (xx_reln)->rd_node.relNode && \
(a)->blockNum == (xx_blockNum) \
)
#define BUFFERTAGS_EQUAL(a,b) \
( \
(a)->rnode.tblNode == (b)->rnode.tblNode && \
(a)->rnode.relNode == (b)->rnode.relNode && \
(a)->blockNum == (b)->blockNum \
)
/* /*
* BufferDesc -- shared buffer cache metadata for a single * BufferDesc -- shared buffer cache metadata for a single
* shared buffer descriptor. * shared buffer descriptor.
*/ */
typedef struct sbufdesc typedef struct sbufdesc
{ {
Buffer freeNext; /* links for freelist chain */ Buffer bufNext; /* link in freelist chain */
Buffer freePrev;
SHMEM_OFFSET data; /* pointer to data in buf pool */ SHMEM_OFFSET data; /* pointer to data in buf pool */
/* tag and id must be together for table lookup (still true?) */ /* tag and id must be together for table lookup */
BufferTag tag; /* file/block identifier */ BufferTag tag; /* file/block identifier */
int buf_id; /* buffer's index number (from 0) */ int buf_id; /* buffer's index number (from 0) */
...@@ -107,6 +119,7 @@ typedef struct sbufdesc ...@@ -107,6 +119,7 @@ typedef struct sbufdesc
#define BufferDescriptorGetBuffer(bdesc) ((bdesc)->buf_id + 1) #define BufferDescriptorGetBuffer(bdesc) ((bdesc)->buf_id + 1)
/* /*
* Each backend has its own BufferLocks[] array holding flag bits * Each backend has its own BufferLocks[] array holding flag bits
* showing what locks it has set on each buffer. * showing what locks it has set on each buffer.
...@@ -167,14 +180,19 @@ extern long int LocalBufferFlushCount; ...@@ -167,14 +180,19 @@ extern long int LocalBufferFlushCount;
/*freelist.c*/ /*freelist.c*/
extern void PinBuffer(BufferDesc *buf); extern void PinBuffer(BufferDesc *buf);
extern void UnpinBuffer(BufferDesc *buf); extern void UnpinBuffer(BufferDesc *buf);
extern BufferDesc *GetFreeBuffer(void); extern BufferDesc *StrategyBufferLookup(BufferTag *tagPtr, bool recheck);
extern void InitFreeList(bool init); extern BufferDesc *StrategyGetBuffer(void);
extern void StrategyReplaceBuffer(BufferDesc *buf, Relation rnode, BlockNumber blockNum);
extern void StrategyInvalidateBuffer(BufferDesc *buf);
extern void StrategyHintVacuum(bool vacuum_active);
extern int StrategyDirtyBufferList(int *buffer_dirty, int max_buffers);
extern void StrategyInitialize(bool init);
/* buf_table.c */ /* buf_table.c */
extern void InitBufTable(void); extern void InitBufTable(int size);
extern BufferDesc *BufTableLookup(BufferTag *tagPtr); extern int BufTableLookup(BufferTag *tagPtr);
extern bool BufTableDelete(BufferDesc *buf); extern bool BufTableInsert(BufferTag *tagPtr, Buffer buf_id);
extern bool BufTableInsert(BufferDesc *buf); extern bool BufTableDelete(BufferTag *tagPtr);
/* bufmgr.c */ /* bufmgr.c */
extern BufferDesc *BufferDescriptors; extern BufferDesc *BufferDescriptors;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment