1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-12 05:01:15 +03:00

Massive commit to run PGINDENT on all *.c and *.h files.

This commit is contained in:
Bruce Momjian
1997-09-07 05:04:48 +00:00
parent 8fecd4febf
commit 1ccd423235
687 changed files with 150775 additions and 136888 deletions

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* buf_init.c--
* buffer manager initialization routines
* buffer manager initialization routines
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.10 1997/07/28 00:54:33 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.11 1997/09/07 04:48:15 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,98 +35,103 @@
#include "utils/dynahash.h"
#include "utils/hsearch.h"
#include "utils/memutils.h"
#include "executor/execdebug.h" /* for NDirectFileRead */
#include "executor/execdebug.h" /* for NDirectFileRead */
#include "catalog/catalog.h"
/*
* if BMTRACE is defined, we trace the last 200 buffer allocations and
* deallocations in a circular buffer in shared memory.
* if BMTRACE is defined, we trace the last 200 buffer allocations and
* deallocations in a circular buffer in shared memory.
*/
#ifdef BMTRACE
bmtrace *TraceBuf;
long *CurTraceBuf;
#define BMT_LIMIT 200
#endif /* BMTRACE */
int ShowPinTrace = 0;
bmtrace *TraceBuf;
long *CurTraceBuf;
int NBuffers = NDBUFS; /* NDBUFS defined in miscadmin.h */
int Data_Descriptors;
int Free_List_Descriptor;
int Lookup_List_Descriptor;
int Num_Descriptors;
#define BMT_LIMIT 200
#endif /* BMTRACE */
int ShowPinTrace = 0;
int NBuffers = NDBUFS; /* NDBUFS defined in miscadmin.h */
int Data_Descriptors;
int Free_List_Descriptor;
int Lookup_List_Descriptor;
int Num_Descriptors;
BufferDesc *BufferDescriptors;
BufferBlock BufferBlocks;
BufferDesc *BufferDescriptors;
BufferBlock BufferBlocks;
#ifndef HAS_TEST_AND_SET
long *NWaitIOBackendP;
long *NWaitIOBackendP;
#endif
extern IpcSemaphoreId WaitIOSemId;
extern IpcSemaphoreId WaitIOSemId;
long *PrivateRefCount; /* also used in freelist.c */
long *LastRefCount; /* refcounts of last ExecMain level */
long *CommitInfoNeedsSave; /* to write buffers where we have filled in */
/* t_tmin (or t_tmax) */
long *PrivateRefCount;/* also used in freelist.c */
long *LastRefCount; /* refcounts of last ExecMain level */
long *CommitInfoNeedsSave; /* to write buffers where we have
* filled in */
/* t_tmin (or t_tmax) */
/*
* Data Structures:
* buffers live in a freelist and a lookup data structure.
*
* buffers live in a freelist and a lookup data structure.
*
*
* Buffer Lookup:
* Two important notes. First, the buffer has to be
* available for lookup BEFORE an IO begins. Otherwise
* a second process trying to read the buffer will
* allocate its own copy and the buffeer pool will
* become inconsistent.
* Two important notes. First, the buffer has to be
* available for lookup BEFORE an IO begins. Otherwise
* a second process trying to read the buffer will
* allocate its own copy and the buffeer pool will
* become inconsistent.
*
* Buffer Replacement:
* see freelist.c. A buffer cannot be replaced while in
* use either by data manager or during IO.
* see freelist.c. A buffer cannot be replaced while in
* use either by data manager or during IO.
*
* WriteBufferBack:
* currently, a buffer is only written back at the time
* it is selected for replacement. It should
* be done sooner if possible to reduce latency of
* BufferAlloc(). Maybe there should be a daemon process.
* currently, a buffer is only written back at the time
* it is selected for replacement. It should
* be done sooner if possible to reduce latency of
* BufferAlloc(). Maybe there should be a daemon process.
*
* Synchronization/Locking:
*
* BufMgrLock lock -- must be acquired before manipulating the
* buffer queues (lookup/freelist). Must be released
* before exit and before doing any IO.
* BufMgrLock lock -- must be acquired before manipulating the
* buffer queues (lookup/freelist). Must be released
* before exit and before doing any IO.
*
* IO_IN_PROGRESS -- this is a flag in the buffer descriptor.
* It must be set when an IO is initiated and cleared at
* the end of the IO. It is there to make sure that one
* process doesn't start to use a buffer while another is
* faulting it in. see IOWait/IOSignal.
* It must be set when an IO is initiated and cleared at
* the end of the IO. It is there to make sure that one
* process doesn't start to use a buffer while another is
* faulting it in. see IOWait/IOSignal.
*
* refcount -- A buffer is pinned during IO and immediately
* after a BufferAlloc(). A buffer is always either pinned
* or on the freelist but never both. The buffer must be
* released, written, or flushed before the end of
* transaction.
* refcount -- A buffer is pinned during IO and immediately
* after a BufferAlloc(). A buffer is always either pinned
* or on the freelist but never both. The buffer must be
* released, written, or flushed before the end of
* transaction.
*
* PrivateRefCount -- Each buffer also has a private refcount the keeps
* track of the number of times the buffer is pinned in the current
* processes. This is used for two purposes, first, if we pin a
* a buffer more than once, we only need to change the shared refcount
* once, thus only lock the buffer pool once, second, when a transaction
* aborts, it should only unpin the buffers exactly the number of times it
* has pinned them, so that it will not blow away buffers of another
* backend.
* track of the number of times the buffer is pinned in the current
* processes. This is used for two purposes, first, if we pin a
* a buffer more than once, we only need to change the shared refcount
* once, thus only lock the buffer pool once, second, when a transaction
* aborts, it should only unpin the buffers exactly the number of times it
* has pinned them, so that it will not blow away buffers of another
* backend.
*
*/
SPINLOCK BufMgrLock;
SPINLOCK BufMgrLock;
long int ReadBufferCount;
long int ReadLocalBufferCount;
long int BufferHitCount;
long int LocalBufferHitCount;
long int BufferFlushCount;
long int LocalBufferFlushCount;
long int ReadBufferCount;
long int ReadLocalBufferCount;
long int BufferHitCount;
long int LocalBufferHitCount;
long int BufferFlushCount;
long int LocalBufferFlushCount;
/*
@@ -138,111 +143,121 @@ long int LocalBufferFlushCount;
void
InitBufferPool(IPCKey key)
{
bool foundBufs,foundDescs;
int i;
/* check padding of BufferDesc and BufferHdr */
/* we need both checks because a sbufdesc_padded > PADDED_SBUFDESC_SIZE
will shrink sbufdesc to the required size, which is bad */
if (sizeof(struct sbufdesc) != PADDED_SBUFDESC_SIZE ||
sizeof(struct sbufdesc_unpadded) > PADDED_SBUFDESC_SIZE)
elog(WARN,"Internal error: sbufdesc does not have the proper size, "
"contact the Postgres developers");
if (sizeof(struct sbufdesc_unpadded) <= PADDED_SBUFDESC_SIZE/2)
elog(WARN,"Internal error: sbufdesc is greatly over-sized, "
"contact the Postgres developers");
bool foundBufs,
foundDescs;
int i;
/* check padding of BufferDesc and BufferHdr */
Data_Descriptors = NBuffers;
Free_List_Descriptor = Data_Descriptors;
Lookup_List_Descriptor = Data_Descriptors + 1;
Num_Descriptors = Data_Descriptors + 1;
SpinAcquire(BufMgrLock);
#ifdef BMTRACE
CurTraceBuf = (long *) ShmemInitStruct("Buffer trace",
(BMT_LIMIT * sizeof(bmtrace)) + sizeof(long),
&foundDescs);
if (!foundDescs)
memset(CurTraceBuf, 0, (BMT_LIMIT * sizeof(bmtrace)) + sizeof(long));
TraceBuf = (bmtrace *) &(CurTraceBuf[1]);
#endif
BufferDescriptors = (BufferDesc *)
ShmemInitStruct("Buffer Descriptors",
Num_Descriptors*sizeof(BufferDesc),&foundDescs);
BufferBlocks = (BufferBlock)
ShmemInitStruct("Buffer Blocks",
NBuffers*BLCKSZ,&foundBufs);
#ifndef HAS_TEST_AND_SET
{
bool foundNWaitIO;
NWaitIOBackendP = (long *)ShmemInitStruct("#Backends Waiting IO",
sizeof(long),
&foundNWaitIO);
if (!foundNWaitIO)
*NWaitIOBackendP = 0;
}
#endif
if (foundDescs || foundBufs) {
/* both should be present or neither */
Assert(foundDescs && foundBufs);
} else {
BufferDesc *buf;
unsigned long block;
buf = BufferDescriptors;
block = (unsigned long) BufferBlocks;
/*
* link the buffers into a circular, doubly-linked list to
* initialize free list. Still don't know anything about
* replacement strategy in this file.
* we need both checks because a sbufdesc_padded >
* PADDED_SBUFDESC_SIZE will shrink sbufdesc to the required size,
* which is bad
*/
for (i = 0; i < Data_Descriptors; block+=BLCKSZ,buf++,i++) {
Assert(ShmemIsValid((unsigned long)block));
buf->freeNext = i+1;
buf->freePrev = i-1;
CLEAR_BUFFERTAG(&(buf->tag));
buf->data = MAKE_OFFSET(block);
buf->flags = (BM_DELETED | BM_FREE | BM_VALID);
buf->refcount = 0;
buf->buf_id = i;
#ifdef HAS_TEST_AND_SET
S_INIT_LOCK(&(buf->io_in_progress_lock));
if (sizeof(struct sbufdesc) != PADDED_SBUFDESC_SIZE ||
sizeof(struct sbufdesc_unpadded) > PADDED_SBUFDESC_SIZE)
elog(WARN, "Internal error: sbufdesc does not have the proper size, "
"contact the Postgres developers");
if (sizeof(struct sbufdesc_unpadded) <= PADDED_SBUFDESC_SIZE / 2)
elog(WARN, "Internal error: sbufdesc is greatly over-sized, "
"contact the Postgres developers");
Data_Descriptors = NBuffers;
Free_List_Descriptor = Data_Descriptors;
Lookup_List_Descriptor = Data_Descriptors + 1;
Num_Descriptors = Data_Descriptors + 1;
SpinAcquire(BufMgrLock);
#ifdef BMTRACE
CurTraceBuf = (long *) ShmemInitStruct("Buffer trace",
(BMT_LIMIT * sizeof(bmtrace)) + sizeof(long),
&foundDescs);
if (!foundDescs)
memset(CurTraceBuf, 0, (BMT_LIMIT * sizeof(bmtrace)) + sizeof(long));
TraceBuf = (bmtrace *) & (CurTraceBuf[1]);
#endif
}
/* close the circular queue */
BufferDescriptors[0].freePrev = Data_Descriptors-1;
BufferDescriptors[Data_Descriptors-1].freeNext = 0;
}
/* Init the rest of the module */
InitBufTable();
InitFreeList(!foundDescs);
SpinRelease(BufMgrLock);
BufferDescriptors = (BufferDesc *)
ShmemInitStruct("Buffer Descriptors",
Num_Descriptors * sizeof(BufferDesc), &foundDescs);
BufferBlocks = (BufferBlock)
ShmemInitStruct("Buffer Blocks",
NBuffers * BLCKSZ, &foundBufs);
#ifndef HAS_TEST_AND_SET
{
int status;
WaitIOSemId = IpcSemaphoreCreate(IPCKeyGetWaitIOSemaphoreKey(key),
1, IPCProtection, 0, 1, &status);
}
{
bool foundNWaitIO;
NWaitIOBackendP = (long *) ShmemInitStruct("#Backends Waiting IO",
sizeof(long),
&foundNWaitIO);
if (!foundNWaitIO)
*NWaitIOBackendP = 0;
}
#endif
PrivateRefCount = (long *) calloc(NBuffers, sizeof(long));
LastRefCount = (long *) calloc(NBuffers, sizeof(long));
CommitInfoNeedsSave = (long *) calloc(NBuffers, sizeof(long));
if (foundDescs || foundBufs)
{
/* both should be present or neither */
Assert(foundDescs && foundBufs);
}
else
{
BufferDesc *buf;
unsigned long block;
buf = BufferDescriptors;
block = (unsigned long) BufferBlocks;
/*
* link the buffers into a circular, doubly-linked list to
* initialize free list. Still don't know anything about
* replacement strategy in this file.
*/
for (i = 0; i < Data_Descriptors; block += BLCKSZ, buf++, i++)
{
Assert(ShmemIsValid((unsigned long) block));
buf->freeNext = i + 1;
buf->freePrev = i - 1;
CLEAR_BUFFERTAG(&(buf->tag));
buf->data = MAKE_OFFSET(block);
buf->flags = (BM_DELETED | BM_FREE | BM_VALID);
buf->refcount = 0;
buf->buf_id = i;
#ifdef HAS_TEST_AND_SET
S_INIT_LOCK(&(buf->io_in_progress_lock));
#endif
}
/* close the circular queue */
BufferDescriptors[0].freePrev = Data_Descriptors - 1;
BufferDescriptors[Data_Descriptors - 1].freeNext = 0;
}
/* Init the rest of the module */
InitBufTable();
InitFreeList(!foundDescs);
SpinRelease(BufMgrLock);
#ifndef HAS_TEST_AND_SET
{
int status;
WaitIOSemId = IpcSemaphoreCreate(IPCKeyGetWaitIOSemaphoreKey(key),
1, IPCProtection, 0, 1, &status);
}
#endif
PrivateRefCount = (long *) calloc(NBuffers, sizeof(long));
LastRefCount = (long *) calloc(NBuffers, sizeof(long));
CommitInfoNeedsSave = (long *) calloc(NBuffers, sizeof(long));
}
/* -----------------------------------------------------
@@ -255,43 +270,41 @@ InitBufferPool(IPCKey key)
int
BufferShmemSize()
{
int size = 0;
int nbuckets;
int nsegs;
int tmp;
nbuckets = 1 << (int)my_log2((NBuffers - 1) / DEF_FFACTOR + 1);
nsegs = 1 << (int)my_log2((nbuckets - 1) / DEF_SEGSIZE + 1);
/* size of shmem binding table */
size += MAXALIGN(my_log2(BTABLE_SIZE) * sizeof(void *)); /* HTAB->dir */
size += MAXALIGN(sizeof(HHDR)); /* HTAB->hctl */
size += MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
size += BUCKET_ALLOC_INCR *
(MAXALIGN(sizeof(BUCKET_INDEX)) +
MAXALIGN(BTABLE_KEYSIZE) +
MAXALIGN(BTABLE_DATASIZE));
/* size of buffer descriptors */
size += MAXALIGN((NBuffers + 1) * sizeof(BufferDesc));
/* size of data pages */
size += NBuffers * MAXALIGN(BLCKSZ);
/* size of buffer hash table */
size += MAXALIGN(my_log2(NBuffers) * sizeof(void *)); /* HTAB->dir */
size += MAXALIGN(sizeof(HHDR)); /* HTAB->hctl */
size += nsegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
tmp = (int)ceil((double)NBuffers/BUCKET_ALLOC_INCR);
size += tmp * BUCKET_ALLOC_INCR *
(MAXALIGN(sizeof(BUCKET_INDEX)) +
MAXALIGN(sizeof(BufferTag)) +
MAXALIGN(sizeof(Buffer)));
int size = 0;
int nbuckets;
int nsegs;
int tmp;
nbuckets = 1 << (int) my_log2((NBuffers - 1) / DEF_FFACTOR + 1);
nsegs = 1 << (int) my_log2((nbuckets - 1) / DEF_SEGSIZE + 1);
/* size of shmem binding table */
size += MAXALIGN(my_log2(BTABLE_SIZE) * sizeof(void *)); /* HTAB->dir */
size += MAXALIGN(sizeof(HHDR)); /* HTAB->hctl */
size += MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
size += BUCKET_ALLOC_INCR *
(MAXALIGN(sizeof(BUCKET_INDEX)) +
MAXALIGN(BTABLE_KEYSIZE) +
MAXALIGN(BTABLE_DATASIZE));
/* size of buffer descriptors */
size += MAXALIGN((NBuffers + 1) * sizeof(BufferDesc));
/* size of data pages */
size += NBuffers * MAXALIGN(BLCKSZ);
/* size of buffer hash table */
size += MAXALIGN(my_log2(NBuffers) * sizeof(void *)); /* HTAB->dir */
size += MAXALIGN(sizeof(HHDR)); /* HTAB->hctl */
size += nsegs * MAXALIGN(DEF_SEGSIZE * sizeof(SEGMENT));
tmp = (int) ceil((double) NBuffers / BUCKET_ALLOC_INCR);
size += tmp * BUCKET_ALLOC_INCR *
(MAXALIGN(sizeof(BUCKET_INDEX)) +
MAXALIGN(sizeof(BufferTag)) +
MAXALIGN(sizeof(Buffer)));
#ifdef BMTRACE
size += (BMT_LIMIT * sizeof(bmtrace)) + sizeof(long);
size += (BMT_LIMIT * sizeof(bmtrace)) + sizeof(long);
#endif
return size;
return size;
}

View File

@@ -1,13 +1,13 @@
/*-------------------------------------------------------------------------
*
* buf_table.c--
* routines for finding buffers in the buffer pool.
* routines for finding buffers in the buffer pool.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.4 1997/08/19 21:32:34 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_table.c,v 1.5 1997/09/07 04:48:17 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,30 +16,31 @@
*
* Data Structures:
*
* Buffers are identified by their BufferTag (buf.h). This
* Buffers are identified by their BufferTag (buf.h). This
* file contains routines for allocating a shmem hash table to
* map buffer tags to buffer descriptors.
*
* Synchronization:
*
* All routines in this file assume buffer manager spinlock is
* held by their caller.
*
* All routines in this file assume buffer manager spinlock is
* held by their caller.
*/
#include "postgres.h"
#include "storage/bufmgr.h"
#include "storage/buf_internals.h" /* where the declarations go */
#include "storage/buf_internals.h" /* where the declarations go */
#include "storage/shmem.h"
#include "storage/spin.h"
#include "utils/hsearch.h"
static HTAB *SharedBufHash;
static HTAB *SharedBufHash;
typedef struct lookup {
BufferTag key;
Buffer id;
} LookupEnt;
typedef struct lookup
{
BufferTag key;
Buffer id;
} LookupEnt;
/*
* Initialize shmem hash table for mapping buffers
@@ -47,109 +48,116 @@ typedef struct lookup {
void
InitBufTable()
{
HASHCTL info;
int hash_flags;
/* assume lock is held */
/* BufferTag maps to Buffer */
info.keysize = sizeof(BufferTag);
info.datasize = sizeof(Buffer);
info.hash = tag_hash;
hash_flags = (HASH_ELEM | HASH_FUNCTION);
SharedBufHash = (HTAB *) ShmemInitHash("Shared Buf Lookup Table",
NBuffers,NBuffers,
&info,hash_flags);
if (! SharedBufHash) {
elog(FATAL,"couldn't initialize shared buffer pool Hash Tbl");
exit(1);
}
HASHCTL info;
int hash_flags;
/* assume lock is held */
/* BufferTag maps to Buffer */
info.keysize = sizeof(BufferTag);
info.datasize = sizeof(Buffer);
info.hash = tag_hash;
hash_flags = (HASH_ELEM | HASH_FUNCTION);
SharedBufHash = (HTAB *) ShmemInitHash("Shared Buf Lookup Table",
NBuffers, NBuffers,
&info, hash_flags);
if (!SharedBufHash)
{
elog(FATAL, "couldn't initialize shared buffer pool Hash Tbl");
exit(1);
}
}
BufferDesc *
BufTableLookup(BufferTag *tagPtr)
BufferDesc *
BufTableLookup(BufferTag * tagPtr)
{
LookupEnt * result;
bool found;
if (tagPtr->blockNum == P_NEW)
return(NULL);
result = (LookupEnt *)
hash_search(SharedBufHash,(char *) tagPtr,HASH_FIND,&found);
if (! result){
elog(WARN,"BufTableLookup: BufferLookup table corrupted");
return(NULL);
}
if (! found) {
return(NULL);
}
return(&(BufferDescriptors[result->id]));
LookupEnt *result;
bool found;
if (tagPtr->blockNum == P_NEW)
return (NULL);
result = (LookupEnt *)
hash_search(SharedBufHash, (char *) tagPtr, HASH_FIND, &found);
if (!result)
{
elog(WARN, "BufTableLookup: BufferLookup table corrupted");
return (NULL);
}
if (!found)
{
return (NULL);
}
return (&(BufferDescriptors[result->id]));
}
/*
* BufTableDelete
*/
bool
BufTableDelete(BufferDesc *buf)
BufTableDelete(BufferDesc * buf)
{
LookupEnt * 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 = (LookupEnt *)
hash_search(SharedBufHash,(char *) &(buf->tag),HASH_REMOVE,&found);
if (! (result && found)) {
elog(WARN,"BufTableDelete: BufferLookup table corrupted");
return(FALSE);
}
return(TRUE);
LookupEnt *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 = (LookupEnt *)
hash_search(SharedBufHash, (char *) &(buf->tag), HASH_REMOVE, &found);
if (!(result && found))
{
elog(WARN, "BufTableDelete: BufferLookup table corrupted");
return (FALSE);
}
return (TRUE);
}
bool
BufTableInsert(BufferDesc *buf)
BufTableInsert(BufferDesc * buf)
{
LookupEnt * result;
bool found;
/* cannot insert it twice */
Assert (buf->flags & BM_DELETED);
buf->flags &= ~(BM_DELETED);
result = (LookupEnt *)
hash_search(SharedBufHash,(char *) &(buf->tag),HASH_ENTER,&found);
if (! result) {
Assert(0);
elog(WARN,"BufTableInsert: BufferLookup table corrupted");
return(FALSE);
}
/* found something else in the table ! */
if (found) {
Assert(0);
elog(WARN,"BufTableInsert: BufferLookup table corrupted");
return(FALSE);
}
result->id = buf->buf_id;
return(TRUE);
LookupEnt *result;
bool found;
/* cannot insert it twice */
Assert(buf->flags & BM_DELETED);
buf->flags &= ~(BM_DELETED);
result = (LookupEnt *)
hash_search(SharedBufHash, (char *) &(buf->tag), HASH_ENTER, &found);
if (!result)
{
Assert(0);
elog(WARN, "BufTableInsert: BufferLookup table corrupted");
return (FALSE);
}
/* found something else in the table ! */
if (found)
{
Assert(0);
elog(WARN, "BufTableInsert: BufferLookup table corrupted");
return (FALSE);
}
result->id = buf->buf_id;
return (TRUE);
}
/* prints out collision stats for the buf table */
@@ -157,8 +165,9 @@ BufTableInsert(BufferDesc *buf)
void
DBG_LookupListCheck(int nlookup)
{
nlookup = 10;
hash_stats("Shared",SharedBufHash);
nlookup = 10;
hash_stats("Shared", SharedBufHash);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,14 @@
/*-------------------------------------------------------------------------
*
* freelist.c--
* routines for manipulating the buffer pool's replacement strategy
* freelist.
* routines for manipulating the buffer pool's replacement strategy
* freelist.
*
* Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/freelist.c,v 1.4 1997/08/19 21:32:44 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/freelist.c,v 1.5 1997/09/07 04:48:22 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,23 +16,23 @@
* OLD COMMENTS
*
* Data Structures:
* SharedFreeList is a circular queue. Notice that this
* is a shared memory queue so the next/prev "ptrs" are
* buffer ids, not addresses.
* SharedFreeList is a circular queue. Notice that this
* is a shared memory queue so the next/prev "ptrs" are
* buffer ids, not addresses.
*
* Sync: all routines in this file assume that the buffer
* semaphore has been acquired by the caller.
* semaphore has been acquired by the caller.
*/
#include <stdio.h>
#include "postgres.h"
#include "storage/bufmgr.h"
#include "storage/buf_internals.h" /* where declarations go */
#include "storage/buf_internals.h" /* where declarations go */
#include "storage/spin.h"
static BufferDesc *SharedFreeList;
static BufferDesc *SharedFreeList;
/* only actually used in debugging. The lock
* should be acquired before calling the freelist manager.
@@ -40,40 +40,40 @@ static BufferDesc *SharedFreeList;
extern SPINLOCK BufMgrLock;
#define IsInQueue(bf) \
Assert((bf->freeNext != INVALID_DESCRIPTOR));\
Assert((bf->freePrev != INVALID_DESCRIPTOR));\
Assert((bf->flags & BM_FREE))
Assert((bf->freeNext != INVALID_DESCRIPTOR));\
Assert((bf->freePrev != INVALID_DESCRIPTOR));\
Assert((bf->flags & BM_FREE))
#define NotInQueue(bf) \
Assert((bf->freeNext == INVALID_DESCRIPTOR));\
Assert((bf->freePrev == INVALID_DESCRIPTOR));\
Assert(! (bf->flags & BM_FREE))
Assert((bf->freeNext == INVALID_DESCRIPTOR));\
Assert((bf->freePrev == INVALID_DESCRIPTOR));\
Assert(! (bf->flags & BM_FREE))
/*
* AddBufferToFreelist --
* AddBufferToFreelist --
*
* In theory, this is the only routine that needs to be changed
* if the buffer replacement strategy changes. Just change
* if the buffer replacement strategy changes. Just change
* the manner in which buffers are added to the freelist queue.
* Currently, they are added on an LRU basis.
*/
void
AddBufferToFreelist(BufferDesc *bf)
AddBufferToFreelist(BufferDesc * bf)
{
#ifdef BMTRACE
_bm_trace(bf->tag.relId.dbId, bf->tag.relId.relId, bf->tag.blockNum,
BufferDescriptorGetBuffer(bf), BMT_DEALLOC);
#endif /* BMTRACE */
NotInQueue(bf);
/* change bf so it points to inFrontOfNew and its successor */
bf->freePrev = SharedFreeList->freePrev;
bf->freeNext = Free_List_Descriptor;
/* insert new into chain */
BufferDescriptors[bf->freeNext].freePrev = bf->buf_id;
BufferDescriptors[bf->freePrev].freeNext = bf->buf_id;
_bm_trace(bf->tag.relId.dbId, bf->tag.relId.relId, bf->tag.blockNum,
BufferDescriptorGetBuffer(bf), BMT_DEALLOC);
#endif /* BMTRACE */
NotInQueue(bf);
/* change bf so it points to inFrontOfNew and its successor */
bf->freePrev = SharedFreeList->freePrev;
bf->freeNext = Free_List_Descriptor;
/* insert new into chain */
BufferDescriptors[bf->freeNext].freePrev = bf->buf_id;
BufferDescriptors[bf->freePrev].freeNext = bf->buf_id;
}
#undef PinBuffer
@@ -82,47 +82,52 @@ AddBufferToFreelist(BufferDesc *bf)
* PinBuffer -- make buffer unavailable for replacement.
*/
void
PinBuffer(BufferDesc *buf)
PinBuffer(BufferDesc * buf)
{
long b;
/* Assert (buf->refcount < 25); */
if (buf->refcount == 0) {
IsInQueue(buf);
/* remove from freelist queue */
BufferDescriptors[buf->freeNext].freePrev = buf->freePrev;
BufferDescriptors[buf->freePrev].freeNext = buf->freeNext;
buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR;
/* mark buffer as no longer free */
buf->flags &= ~BM_FREE;
} else {
NotInQueue(buf);
}
b = BufferDescriptorGetBuffer(buf) - 1;
Assert(PrivateRefCount[b] >= 0);
if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0)
buf->refcount++;
PrivateRefCount[b]++;
long b;
/* Assert (buf->refcount < 25); */
if (buf->refcount == 0)
{
IsInQueue(buf);
/* remove from freelist queue */
BufferDescriptors[buf->freeNext].freePrev = buf->freePrev;
BufferDescriptors[buf->freePrev].freeNext = buf->freeNext;
buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR;
/* mark buffer as no longer free */
buf->flags &= ~BM_FREE;
}
else
{
NotInQueue(buf);
}
b = BufferDescriptorGetBuffer(buf) - 1;
Assert(PrivateRefCount[b] >= 0);
if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0)
buf->refcount++;
PrivateRefCount[b]++;
}
#ifdef NOT_USED
void
PinBuffer_Debug(char *file, int line, BufferDesc *buf)
PinBuffer_Debug(char *file, int line, BufferDesc * buf)
{
PinBuffer(buf);
if (ShowPinTrace) {
Buffer buffer = BufferDescriptorGetBuffer(buf);
fprintf(stderr, "PIN(Pin) %ld relname = %s, blockNum = %d, \
PinBuffer(buf);
if (ShowPinTrace)
{
Buffer buffer = BufferDescriptorGetBuffer(buf);
fprintf(stderr, "PIN(Pin) %ld relname = %s, blockNum = %d, \
refcount = %ld, file: %s, line: %d\n",
buffer, buf->sb_relname, buf->tag.blockNum,
PrivateRefCount[buffer - 1], file, line);
}
buffer, buf->sb_relname, buf->tag.blockNum,
PrivateRefCount[buffer - 1], file, line);
}
}
#endif
#undef UnpinBuffer
@@ -131,95 +136,102 @@ refcount = %ld, file: %s, line: %d\n",
* UnpinBuffer -- make buffer available for replacement.
*/
void
UnpinBuffer(BufferDesc *buf)
UnpinBuffer(BufferDesc * buf)
{
long b = BufferDescriptorGetBuffer(buf) - 1;
Assert(buf->refcount);
Assert(PrivateRefCount[b] > 0);
PrivateRefCount[b]--;
if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0)
buf->refcount--;
NotInQueue(buf);
if (buf->refcount == 0) {
AddBufferToFreelist(buf);
buf->flags |= BM_FREE;
} else {
/* do nothing */
}
long b = BufferDescriptorGetBuffer(buf) - 1;
Assert(buf->refcount);
Assert(PrivateRefCount[b] > 0);
PrivateRefCount[b]--;
if (PrivateRefCount[b] == 0 && LastRefCount[b] == 0)
buf->refcount--;
NotInQueue(buf);
if (buf->refcount == 0)
{
AddBufferToFreelist(buf);
buf->flags |= BM_FREE;
}
else
{
/* do nothing */
}
}
#ifdef NOT_USED
void
UnpinBuffer_Debug(char *file, int line, BufferDesc *buf)
UnpinBuffer_Debug(char *file, int line, BufferDesc * buf)
{
UnpinBuffer(buf);
if (ShowPinTrace) {
Buffer buffer = BufferDescriptorGetBuffer(buf);
fprintf(stderr, "UNPIN(Unpin) %ld relname = %s, blockNum = %d, \
UnpinBuffer(buf);
if (ShowPinTrace)
{
Buffer buffer = BufferDescriptorGetBuffer(buf);
fprintf(stderr, "UNPIN(Unpin) %ld relname = %s, blockNum = %d, \
refcount = %ld, file: %s, line: %d\n",
buffer, buf->sb_relname, buf->tag.blockNum,
PrivateRefCount[buffer - 1], file, line);
}
buffer, buf->sb_relname, buf->tag.blockNum,
PrivateRefCount[buffer - 1], file, line);
}
}
#endif
/*
* GetFreeBuffer() -- get the 'next' buffer from the freelist.
*
*/
BufferDesc *
BufferDesc *
GetFreeBuffer()
{
BufferDesc *buf;
if (Free_List_Descriptor == SharedFreeList->freeNext) {
/* queue is empty. All buffers in the buffer pool are pinned. */
elog(WARN,"out of free buffers: time to abort !\n");
return(NULL);
}
buf = &(BufferDescriptors[SharedFreeList->freeNext]);
/* remove from freelist queue */
BufferDescriptors[buf->freeNext].freePrev = buf->freePrev;
BufferDescriptors[buf->freePrev].freeNext = buf->freeNext;
buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR;
buf->flags &= ~(BM_FREE);
return(buf);
BufferDesc *buf;
if (Free_List_Descriptor == SharedFreeList->freeNext)
{
/* queue is empty. All buffers in the buffer pool are pinned. */
elog(WARN, "out of free buffers: time to abort !\n");
return (NULL);
}
buf = &(BufferDescriptors[SharedFreeList->freeNext]);
/* remove from freelist queue */
BufferDescriptors[buf->freeNext].freePrev = buf->freePrev;
BufferDescriptors[buf->freePrev].freeNext = buf->freeNext;
buf->freeNext = buf->freePrev = INVALID_DESCRIPTOR;
buf->flags &= ~(BM_FREE);
return (buf);
}
/*
* InitFreeList -- initialize the dummy buffer descriptor used
* as a freelist head.
* as a freelist head.
*
* Assume: All of the buffers are already linked in a circular
* queue. Only called by postmaster and only during
* initialization.
* queue. Only called by postmaster and only during
* initialization.
*/
void
InitFreeList(bool init)
{
SharedFreeList = &(BufferDescriptors[Free_List_Descriptor]);
if (init) {
/* we only do this once, normally the postmaster */
SharedFreeList->data = INVALID_OFFSET;
SharedFreeList->flags = 0;
SharedFreeList->flags &= ~(BM_VALID | BM_DELETED | BM_FREE);
SharedFreeList->buf_id = Free_List_Descriptor;
/* insert it into a random spot in the circular queue */
SharedFreeList->freeNext = BufferDescriptors[0].freeNext;
SharedFreeList->freePrev = 0;
BufferDescriptors[SharedFreeList->freeNext].freePrev =
BufferDescriptors[SharedFreeList->freePrev].freeNext =
Free_List_Descriptor;
}
SharedFreeList = &(BufferDescriptors[Free_List_Descriptor]);
if (init)
{
/* we only do this once, normally the postmaster */
SharedFreeList->data = INVALID_OFFSET;
SharedFreeList->flags = 0;
SharedFreeList->flags &= ~(BM_VALID | BM_DELETED | BM_FREE);
SharedFreeList->buf_id = Free_List_Descriptor;
/* insert it into a random spot in the circular queue */
SharedFreeList->freeNext = BufferDescriptors[0].freeNext;
SharedFreeList->freePrev = 0;
BufferDescriptors[SharedFreeList->freeNext].freePrev =
BufferDescriptors[SharedFreeList->freePrev].freeNext =
Free_List_Descriptor;
}
}
@@ -230,67 +242,78 @@ InitFreeList(bool init)
void
DBG_FreeListCheck(int nfree)
{
int i;
BufferDesc *buf;
buf = &(BufferDescriptors[SharedFreeList->freeNext]);
for (i=0;i<nfree;i++,buf = &(BufferDescriptors[buf->freeNext])) {
if (! (buf->flags & (BM_FREE))){
if (buf != SharedFreeList) {
printf("\tfree list corrupted: %d flags %x\n",
buf->buf_id,buf->flags);
} else {
printf("\tfree list corrupted: too short -- %d not %d\n",
i,nfree);
}
int i;
BufferDesc *buf;
buf = &(BufferDescriptors[SharedFreeList->freeNext]);
for (i = 0; i < nfree; i++, buf = &(BufferDescriptors[buf->freeNext]))
{
if (!(buf->flags & (BM_FREE)))
{
if (buf != SharedFreeList)
{
printf("\tfree list corrupted: %d flags %x\n",
buf->buf_id, buf->flags);
}
else
{
printf("\tfree list corrupted: too short -- %d not %d\n",
i, nfree);
}
}
if ((BufferDescriptors[buf->freeNext].freePrev != buf->buf_id) ||
(BufferDescriptors[buf->freePrev].freeNext != buf->buf_id))
{
printf("\tfree list links corrupted: %d %ld %ld\n",
buf->buf_id, buf->freePrev, buf->freeNext);
}
}
if ((BufferDescriptors[buf->freeNext].freePrev != buf->buf_id) ||
(BufferDescriptors[buf->freePrev].freeNext != buf->buf_id)) {
printf("\tfree list links corrupted: %d %ld %ld\n",
buf->buf_id,buf->freePrev,buf->freeNext);
if (buf != SharedFreeList)
{
printf("\tfree list corrupted: %d-th buffer is %d\n",
nfree, buf->buf_id);
}
}
if (buf != SharedFreeList) {
printf("\tfree list corrupted: %d-th buffer is %d\n",
nfree,buf->buf_id);
}
}
#endif
#ifdef NOT_USED
/*
* PrintBufferFreeList -
* prints the buffer free list, for debugging
* prints the buffer free list, for debugging
*/
static void
PrintBufferFreeList()
{
BufferDesc *buf;
BufferDesc *buf;
if (SharedFreeList->freeNext == Free_List_Descriptor) {
printf("free list is empty.\n");
return;
}
buf = &(BufferDescriptors[SharedFreeList->freeNext]);
for (;;) {
int i = (buf - BufferDescriptors);
printf("[%-2d] (%s, %d) flags=0x%x, refcnt=%d %ld, nxt=%ld prv=%ld)\n",
i, buf->sb_relname, buf->tag.blockNum,
buf->flags, buf->refcount, PrivateRefCount[i],
buf->freeNext, buf->freePrev);
if (buf->freeNext == Free_List_Descriptor)
break;
if (SharedFreeList->freeNext == Free_List_Descriptor)
{
printf("free list is empty.\n");
return;
}
buf = &(BufferDescriptors[buf->freeNext]);
}
buf = &(BufferDescriptors[SharedFreeList->freeNext]);
for (;;)
{
int i = (buf - BufferDescriptors);
printf("[%-2d] (%s, %d) flags=0x%x, refcnt=%d %ld, nxt=%ld prv=%ld)\n",
i, buf->sb_relname, buf->tag.blockNum,
buf->flags, buf->refcount, PrivateRefCount[i],
buf->freeNext, buf->freePrev);
if (buf->freeNext == Free_List_Descriptor)
break;
buf = &(BufferDescriptors[buf->freeNext]);
}
}
#endif

View File

@@ -1,21 +1,21 @@
/*-------------------------------------------------------------------------
*
* localbuf.c--
* local buffer manager. Fast buffer manager for temporary tables
* or special cases when the operation is not visible to other backends.
* local buffer manager. Fast buffer manager for temporary tables
* or special cases when the operation is not visible to other backends.
*
* When a relation is being created, the descriptor will have rd_islocal
* set to indicate that the local buffer manager should be used. During
* the same transaction the relation is being created, any inserts or
* selects from the newly created relation will use the local buffer
* pool. rd_islocal is reset at the end of a transaction (commit/abort).
* This is useful for queries like SELECT INTO TABLE and create index.
* When a relation is being created, the descriptor will have rd_islocal
* set to indicate that the local buffer manager should be used. During
* the same transaction the relation is being created, any inserts or
* selects from the newly created relation will use the local buffer
* pool. rd_islocal is reset at the end of a transaction (commit/abort).
* This is useful for queries like SELECT INTO TABLE and create index.
*
* Copyright (c) 1994-5, Regents of the University of California
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.8 1997/07/28 00:54:48 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.9 1997/09/07 04:48:23 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -45,252 +45,262 @@
#include "utils/hsearch.h"
#include "utils/memutils.h"
#include "utils/relcache.h"
#include "executor/execdebug.h" /* for NDirectFileRead */
#include "executor/execdebug.h" /* for NDirectFileRead */
#include "catalog/catalog.h"
extern long int LocalBufferFlushCount;
int NLocBuffer = 64;
BufferDesc *LocalBufferDescriptors = NULL;
long *LocalRefCount = NULL;
int NLocBuffer = 64;
BufferDesc *LocalBufferDescriptors = NULL;
long *LocalRefCount = NULL;
static int nextFreeLocalBuf = 0;
static int nextFreeLocalBuf = 0;
/*#define LBDEBUG*/
/*
* LocalBufferAlloc -
* allocate a local buffer. We do round robin allocation for now.
* allocate a local buffer. We do round robin allocation for now.
*/
BufferDesc *
LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
BufferDesc *
LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool * foundPtr)
{
int i;
BufferDesc *bufHdr = (BufferDesc *) NULL;
int i;
BufferDesc *bufHdr = (BufferDesc *) NULL;
if (blockNum == P_NEW) {
blockNum = reln->rd_nblocks;
reln->rd_nblocks++;
}
if (blockNum == P_NEW)
{
blockNum = reln->rd_nblocks;
reln->rd_nblocks++;
}
/* a low tech search for now -- not optimized for scans */
for (i=0; i < NLocBuffer; i++) {
if (LocalBufferDescriptors[i].tag.relId.relId == reln->rd_id &&
LocalBufferDescriptors[i].tag.blockNum == blockNum) {
/* a low tech search for now -- not optimized for scans */
for (i = 0; i < NLocBuffer; i++)
{
if (LocalBufferDescriptors[i].tag.relId.relId == reln->rd_id &&
LocalBufferDescriptors[i].tag.blockNum == blockNum)
{
#ifdef LBDEBUG
fprintf(stderr, "LB ALLOC (%d,%d) %d\n",
reln->rd_id, blockNum, -i-1);
#endif
LocalRefCount[i]++;
*foundPtr = TRUE;
return &LocalBufferDescriptors[i];
fprintf(stderr, "LB ALLOC (%d,%d) %d\n",
reln->rd_id, blockNum, -i - 1);
#endif
LocalRefCount[i]++;
*foundPtr = TRUE;
return &LocalBufferDescriptors[i];
}
}
}
#ifdef LBDEBUG
fprintf(stderr, "LB ALLOC (%d,%d) %d\n",
reln->rd_id, blockNum, -nextFreeLocalBuf-1);
#endif
/* need to get a new buffer (round robin for now) */
for(i=0; i < NLocBuffer; i++) {
int b = (nextFreeLocalBuf + i) % NLocBuffer;
fprintf(stderr, "LB ALLOC (%d,%d) %d\n",
reln->rd_id, blockNum, -nextFreeLocalBuf - 1);
#endif
if (LocalRefCount[b]==0) {
bufHdr = &LocalBufferDescriptors[b];
LocalRefCount[b]++;
nextFreeLocalBuf = (b + 1) % NLocBuffer;
break;
/* need to get a new buffer (round robin for now) */
for (i = 0; i < NLocBuffer; i++)
{
int b = (nextFreeLocalBuf + i) % NLocBuffer;
if (LocalRefCount[b] == 0)
{
bufHdr = &LocalBufferDescriptors[b];
LocalRefCount[b]++;
nextFreeLocalBuf = (b + 1) % NLocBuffer;
break;
}
}
}
if (bufHdr==NULL)
elog(WARN, "no empty local buffer.");
if (bufHdr == NULL)
elog(WARN, "no empty local buffer.");
/*
* this buffer is not referenced but it might still be dirty (the
* last transaction to touch it doesn't need its contents but has
* not flushed it). if that's the case, write it out before
* reusing it!
*/
if (bufHdr->flags & BM_DIRTY) {
Relation bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
/*
* this buffer is not referenced but it might still be dirty (the last
* transaction to touch it doesn't need its contents but has not
* flushed it). if that's the case, write it out before reusing it!
*/
if (bufHdr->flags & BM_DIRTY)
{
Relation bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
Assert(bufrel != NULL);
/* flush this page */
smgrwrite(bufrel->rd_rel->relsmgr, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data));
LocalBufferFlushCount++;
}
Assert(bufrel != NULL);
/*
* it's all ours now.
*/
bufHdr->tag.relId.relId = reln->rd_id;
bufHdr->tag.blockNum = blockNum;
bufHdr->flags &= ~BM_DIRTY;
/* flush this page */
smgrwrite(bufrel->rd_rel->relsmgr, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data));
LocalBufferFlushCount++;
}
/*
* lazy memory allocation. (see MAKE_PTR for why we need to do
* MAKE_OFFSET.)
*/
if (bufHdr->data == (SHMEM_OFFSET)0) {
char *data = (char *)malloc(BLCKSZ);
/*
* it's all ours now.
*/
bufHdr->tag.relId.relId = reln->rd_id;
bufHdr->tag.blockNum = blockNum;
bufHdr->flags &= ~BM_DIRTY;
bufHdr->data = MAKE_OFFSET(data);
}
*foundPtr = FALSE;
return bufHdr;
/*
* lazy memory allocation. (see MAKE_PTR for why we need to do
* MAKE_OFFSET.)
*/
if (bufHdr->data == (SHMEM_OFFSET) 0)
{
char *data = (char *) malloc(BLCKSZ);
bufHdr->data = MAKE_OFFSET(data);
}
*foundPtr = FALSE;
return bufHdr;
}
/*
* WriteLocalBuffer -
* writes out a local buffer
* writes out a local buffer
*/
int
WriteLocalBuffer(Buffer buffer, bool release)
{
int bufid;
int bufid;
Assert(BufferIsLocal(buffer));
Assert(BufferIsLocal(buffer));
#ifdef LBDEBUG
fprintf(stderr, "LB WRITE %d\n", buffer);
#endif
bufid = - (buffer + 1);
LocalBufferDescriptors[bufid].flags |= BM_DIRTY;
fprintf(stderr, "LB WRITE %d\n", buffer);
#endif
if (release) {
Assert(LocalRefCount[bufid] > 0);
LocalRefCount[bufid]--;
}
bufid = -(buffer + 1);
LocalBufferDescriptors[bufid].flags |= BM_DIRTY;
return true;
if (release)
{
Assert(LocalRefCount[bufid] > 0);
LocalRefCount[bufid]--;
}
return true;
}
/*
* FlushLocalBuffer -
* flushes a local buffer
* flushes a local buffer
*/
int
FlushLocalBuffer(Buffer buffer, bool release)
{
int bufid;
Relation bufrel;
BufferDesc *bufHdr;
int bufid;
Relation bufrel;
BufferDesc *bufHdr;
Assert(BufferIsLocal(buffer));
Assert(BufferIsLocal(buffer));
#ifdef LBDEBUG
fprintf(stderr, "LB FLUSH %d\n", buffer);
#endif
fprintf(stderr, "LB FLUSH %d\n", buffer);
#endif
bufid = - (buffer + 1);
bufHdr = &LocalBufferDescriptors[bufid];
bufHdr->flags &= ~BM_DIRTY;
bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
bufid = -(buffer + 1);
bufHdr = &LocalBufferDescriptors[bufid];
bufHdr->flags &= ~BM_DIRTY;
bufrel = RelationIdCacheGetRelation(bufHdr->tag.relId.relId);
Assert(bufrel != NULL);
smgrflush(bufrel->rd_rel->relsmgr, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data));
LocalBufferFlushCount++;
Assert(bufrel != NULL);
smgrflush(bufrel->rd_rel->relsmgr, bufrel, bufHdr->tag.blockNum,
(char *) MAKE_PTR(bufHdr->data));
LocalBufferFlushCount++;
Assert(LocalRefCount[bufid] > 0);
if ( release )
LocalRefCount[bufid]--;
return true;
Assert(LocalRefCount[bufid] > 0);
if (release)
LocalRefCount[bufid]--;
return true;
}
/*
* InitLocalBuffer -
* init the local buffer cache. Since most queries (esp. multi-user ones)
* don't involve local buffers, we delay allocating memory for actual the
* buffer until we need it.
* init the local buffer cache. Since most queries (esp. multi-user ones)
* don't involve local buffers, we delay allocating memory for actual the
* buffer until we need it.
*/
void
InitLocalBuffer(void)
{
int i;
/*
* these aren't going away. I'm not gonna use palloc.
*/
LocalBufferDescriptors =
(BufferDesc *)malloc(sizeof(BufferDesc) * NLocBuffer);
memset(LocalBufferDescriptors, 0, sizeof(BufferDesc) * NLocBuffer);
nextFreeLocalBuf = 0;
for (i = 0; i < NLocBuffer; i++) {
BufferDesc *buf = &LocalBufferDescriptors[i];
int i;
/*
* negative to indicate local buffer. This is tricky: shared buffers
* start with 0. We have to start with -2. (Note that the routine
* BufferDescriptorGetBuffer adds 1 to buf_id so our first buffer id
* is -1.)
* these aren't going away. I'm not gonna use palloc.
*/
buf->buf_id = - i - 2;
}
LocalBufferDescriptors =
(BufferDesc *) malloc(sizeof(BufferDesc) * NLocBuffer);
memset(LocalBufferDescriptors, 0, sizeof(BufferDesc) * NLocBuffer);
nextFreeLocalBuf = 0;
LocalRefCount =
(long *)malloc(sizeof(long) * NLocBuffer);
memset(LocalRefCount, 0, sizeof(long) * NLocBuffer);
for (i = 0; i < NLocBuffer; i++)
{
BufferDesc *buf = &LocalBufferDescriptors[i];
/*
* negative to indicate local buffer. This is tricky: shared
* buffers start with 0. We have to start with -2. (Note that the
* routine BufferDescriptorGetBuffer adds 1 to buf_id so our first
* buffer id is -1.)
*/
buf->buf_id = -i - 2;
}
LocalRefCount =
(long *) malloc(sizeof(long) * NLocBuffer);
memset(LocalRefCount, 0, sizeof(long) * NLocBuffer);
}
/*
* LocalBufferSync -
* flush all dirty buffers in the local buffer cache. Since the buffer
* cache is only used for keeping relations visible during a transaction,
* we will not need these buffers again.
* flush all dirty buffers in the local buffer cache. Since the buffer
* cache is only used for keeping relations visible during a transaction,
* we will not need these buffers again.
*/
void
LocalBufferSync(void)
{
int i;
for (i = 0; i < NLocBuffer; i++) {
BufferDesc *buf = &LocalBufferDescriptors[i];
Relation bufrel;
int i;
if (buf->flags & BM_DIRTY) {
for (i = 0; i < NLocBuffer; i++)
{
BufferDesc *buf = &LocalBufferDescriptors[i];
Relation bufrel;
if (buf->flags & BM_DIRTY)
{
#ifdef LBDEBUG
fprintf(stderr, "LB SYNC %d\n", -i-1);
#endif
bufrel = RelationIdCacheGetRelation(buf->tag.relId.relId);
fprintf(stderr, "LB SYNC %d\n", -i - 1);
#endif
bufrel = RelationIdCacheGetRelation(buf->tag.relId.relId);
Assert(bufrel != NULL);
smgrwrite(bufrel->rd_rel->relsmgr, bufrel, buf->tag.blockNum,
(char *) MAKE_PTR(buf->data));
LocalBufferFlushCount++;
Assert(bufrel != NULL);
buf->tag.relId.relId = InvalidOid;
buf->flags &= ~BM_DIRTY;
smgrwrite(bufrel->rd_rel->relsmgr, bufrel, buf->tag.blockNum,
(char *) MAKE_PTR(buf->data));
LocalBufferFlushCount++;
buf->tag.relId.relId = InvalidOid;
buf->flags &= ~BM_DIRTY;
}
}
}
memset(LocalRefCount, 0, sizeof(long) * NLocBuffer);
nextFreeLocalBuf = 0;
memset(LocalRefCount, 0, sizeof(long) * NLocBuffer);
nextFreeLocalBuf = 0;
}
void
ResetLocalBufferPool(void)
{
int i;
int i;
for (i = 0; i < NLocBuffer; i++)
{
BufferDesc *buf = &LocalBufferDescriptors[i];
for (i = 0; i < NLocBuffer; i++)
{
BufferDesc *buf = &LocalBufferDescriptors[i];
buf->tag.relId.relId = InvalidOid;
buf->flags &= ~BM_DIRTY;
buf->buf_id = - i - 2;
}
buf->tag.relId.relId = InvalidOid;
buf->flags &= ~BM_DIRTY;
buf->buf_id = -i - 2;
}
memset(LocalRefCount, 0, sizeof(long) * NLocBuffer);
nextFreeLocalBuf = 0;
memset(LocalRefCount, 0, sizeof(long) * NLocBuffer);
nextFreeLocalBuf = 0;
}