mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Pgindent run for 8.0.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.67 2004/08/29 04:12:47 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/buf_init.c,v 1.68 2004/08/29 05:06:47 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -59,7 +59,7 @@ long int LocalBufferFlushCount;
|
||||
*
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
@@ -112,9 +112,9 @@ InitBufferPool(void)
|
||||
char *block;
|
||||
|
||||
/*
|
||||
* It's probably not really necessary to grab the lock --- if there's
|
||||
* anyone else attached to the shmem at this point, we've got
|
||||
* problems.
|
||||
* It's probably not really necessary to grab the lock --- if
|
||||
* there's anyone else attached to the shmem at this point, we've
|
||||
* got problems.
|
||||
*/
|
||||
LWLockAcquire(BufMgrLock, LW_EXCLUSIVE);
|
||||
|
||||
@@ -122,8 +122,9 @@ InitBufferPool(void)
|
||||
block = BufferBlocks;
|
||||
|
||||
/*
|
||||
* link the buffers into a single linked list. This will become the
|
||||
* LIFO list of unused buffers returned by StrategyGetBuffer().
|
||||
* link the buffers into a single linked list. This will become
|
||||
* the LIFO list of unused buffers returned by
|
||||
* StrategyGetBuffer().
|
||||
*/
|
||||
for (i = 0; i < NBuffers; block += BLCKSZ, buf++, i++)
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* routines for finding buffers in the buffer pool.
|
||||
*
|
||||
* NOTE: these days, what this table actually provides is a mapping from
|
||||
* BufferTags to CDB indexes, not directly to buffers. The function names
|
||||
* BufferTags to CDB indexes, not directly to buffers. The function names
|
||||
* are thus slight misnomers.
|
||||
*
|
||||
* Note: all routines in this file assume that the BufMgrLock is held
|
||||
@@ -16,7 +16,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/buf_table.c,v 1.36 2004/08/29 04:12:47 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/buf_table.c,v 1.37 2004/08/29 05:06:47 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.174 2004/08/29 04:12:47 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/bufmgr.c,v 1.175 2004/08/29 05:06:47 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -58,7 +58,7 @@
|
||||
bool zero_damaged_pages = false;
|
||||
|
||||
#ifdef NOT_USED
|
||||
bool ShowPinTrace = false;
|
||||
bool ShowPinTrace = false;
|
||||
#endif
|
||||
|
||||
long NDirectFileRead; /* some I/O's are direct file access.
|
||||
@@ -143,6 +143,7 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
|
||||
{
|
||||
ReadBufferCount++;
|
||||
pgstat_count_buffer_read(&reln->pgstat_info, reln);
|
||||
|
||||
/*
|
||||
* lookup the buffer. IO_IN_PROGRESS is set if the requested
|
||||
* block is not currently in memory.
|
||||
@@ -174,11 +175,11 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
|
||||
* it, if it's a shared buffer.
|
||||
*
|
||||
* Note: if smgrextend fails, we will end up with a buffer that is
|
||||
* allocated but not marked BM_VALID. P_NEW will still select the same
|
||||
* block number (because the relation didn't get any longer on disk)
|
||||
* and so future attempts to extend the relation will find the same
|
||||
* buffer (if it's not been recycled) but come right back here to try
|
||||
* smgrextend again.
|
||||
* allocated but not marked BM_VALID. P_NEW will still select the
|
||||
* same block number (because the relation didn't get any longer on
|
||||
* disk) and so future attempts to extend the relation will find the
|
||||
* same buffer (if it's not been recycled) but come right back here to
|
||||
* try smgrextend again.
|
||||
*/
|
||||
Assert(!(bufHdr->flags & BM_VALID));
|
||||
|
||||
@@ -196,10 +197,11 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
|
||||
if (!PageHeaderIsValid((PageHeader) MAKE_PTR(bufHdr->data)))
|
||||
{
|
||||
/*
|
||||
* During WAL recovery, the first access to any data page should
|
||||
* overwrite the whole page from the WAL; so a clobbered page
|
||||
* header is not reason to fail. Hence, when InRecovery we may
|
||||
* always act as though zero_damaged_pages is ON.
|
||||
* During WAL recovery, the first access to any data page
|
||||
* should overwrite the whole page from the WAL; so a
|
||||
* clobbered page header is not reason to fail. Hence, when
|
||||
* InRecovery we may always act as though zero_damaged_pages
|
||||
* is ON.
|
||||
*/
|
||||
if (zero_damaged_pages || InRecovery)
|
||||
{
|
||||
@@ -212,8 +214,8 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum,
|
||||
else
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_DATA_CORRUPTED),
|
||||
errmsg("invalid page header in block %u of relation \"%s\"",
|
||||
blockNum, RelationGetRelationName(reln))));
|
||||
errmsg("invalid page header in block %u of relation \"%s\"",
|
||||
blockNum, RelationGetRelationName(reln))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,9 +350,9 @@ BufferAlloc(Relation reln,
|
||||
* if someone were writing it.
|
||||
*
|
||||
* Note: it's okay to grab the io_in_progress lock while holding
|
||||
* BufMgrLock. All code paths that acquire this lock pin the
|
||||
* buffer first; since no one had it pinned (it just came off the
|
||||
* free list), no one else can have the lock.
|
||||
* BufMgrLock. All code paths that acquire this lock pin the
|
||||
* buffer first; since no one had it pinned (it just came off
|
||||
* the free list), no one else can have the lock.
|
||||
*/
|
||||
StartBufferIO(buf, false);
|
||||
|
||||
@@ -364,23 +366,23 @@ BufferAlloc(Relation reln,
|
||||
|
||||
/*
|
||||
* Somebody could have allocated another buffer for the same
|
||||
* block we are about to read in. While we flush out the
|
||||
* dirty buffer, we don't hold the lock and someone could have
|
||||
* block we are about to read in. While we flush out the dirty
|
||||
* buffer, we don't hold the lock and someone could have
|
||||
* allocated another buffer for the same block. The problem is
|
||||
* we haven't yet inserted the new tag into the buffer table.
|
||||
* So we need to check here. -ay 3/95
|
||||
*
|
||||
* Another reason we have to do this is to update cdb_found_index,
|
||||
* since the CDB could have disappeared from B1/B2 list while
|
||||
* we were writing.
|
||||
* Another reason we have to do this is to update
|
||||
* cdb_found_index, since the CDB could have disappeared from
|
||||
* B1/B2 list while we were writing.
|
||||
*/
|
||||
buf2 = StrategyBufferLookup(&newTag, true, &cdb_found_index);
|
||||
if (buf2 != NULL)
|
||||
{
|
||||
/*
|
||||
* Found it. Someone has already done what we were about to
|
||||
* do. We'll just handle this as if it were found in the
|
||||
* buffer pool in the first place. First, give up the
|
||||
* Found it. Someone has already done what we were about
|
||||
* to do. We'll just handle this as if it were found in
|
||||
* the buffer pool in the first place. First, give up the
|
||||
* buffer we were planning to use.
|
||||
*/
|
||||
TerminateBufferIO(buf, 0);
|
||||
@@ -404,8 +406,9 @@ BufferAlloc(Relation reln,
|
||||
if (!(buf->flags & BM_VALID))
|
||||
{
|
||||
/*
|
||||
* If we get here, previous attempts to read the buffer
|
||||
* must have failed ... but we shall bravely try again.
|
||||
* If we get here, previous attempts to read the
|
||||
* buffer must have failed ... but we shall
|
||||
* bravely try again.
|
||||
*/
|
||||
*foundPtr = FALSE;
|
||||
StartBufferIO(buf, true);
|
||||
@@ -441,8 +444,8 @@ BufferAlloc(Relation reln,
|
||||
|
||||
/*
|
||||
* Tell the buffer replacement strategy that we are replacing the
|
||||
* buffer content. Then rename the buffer. Clearing BM_VALID here
|
||||
* is necessary, clearing the dirtybits is just paranoia.
|
||||
* buffer content. Then rename the buffer. Clearing BM_VALID here is
|
||||
* necessary, clearing the dirtybits is just paranoia.
|
||||
*/
|
||||
StrategyReplaceBuffer(buf, &newTag, cdb_found_index, cdb_replace_index);
|
||||
buf->tag = newTag;
|
||||
@@ -685,9 +688,9 @@ BufferSync(int percent, int maxpages)
|
||||
NBuffers);
|
||||
|
||||
/*
|
||||
* If called by the background writer, we are usually asked to
|
||||
* only write out some portion of dirty buffers now, to prevent
|
||||
* the IO storm at checkpoint time.
|
||||
* If called by the background writer, we are usually asked to only
|
||||
* write out some portion of dirty buffers now, to prevent the IO
|
||||
* storm at checkpoint time.
|
||||
*/
|
||||
if (percent > 0)
|
||||
{
|
||||
@@ -702,8 +705,8 @@ BufferSync(int percent, int maxpages)
|
||||
|
||||
/*
|
||||
* Loop over buffers to be written. Note the BufMgrLock is held at
|
||||
* loop top, but is released and reacquired within FlushBuffer,
|
||||
* so we aren't holding it long.
|
||||
* loop top, but is released and reacquired within FlushBuffer, so we
|
||||
* aren't holding it long.
|
||||
*/
|
||||
for (i = 0; i < num_buffer_dirty; i++)
|
||||
{
|
||||
@@ -712,8 +715,8 @@ BufferSync(int percent, int maxpages)
|
||||
/*
|
||||
* Check it is still the same page and still needs writing.
|
||||
*
|
||||
* We can check bufHdr->cntxDirty here *without* holding any lock
|
||||
* on buffer context as long as we set this flag in access methods
|
||||
* We can check bufHdr->cntxDirty here *without* holding any lock on
|
||||
* buffer context as long as we set this flag in access methods
|
||||
* *before* logging changes with XLogInsert(): if someone will set
|
||||
* cntxDirty just after our check we don't worry because of our
|
||||
* checkpoint.redo points before log record for upcoming changes
|
||||
@@ -860,7 +863,7 @@ AtEOXact_Buffers(bool isCommit)
|
||||
if (isCommit)
|
||||
elog(WARNING,
|
||||
"buffer refcount leak: [%03d] "
|
||||
"(rel=%u/%u/%u, blockNum=%u, flags=0x%x, refcount=%u %d)",
|
||||
"(rel=%u/%u/%u, blockNum=%u, flags=0x%x, refcount=%u %d)",
|
||||
i,
|
||||
buf->tag.rnode.spcNode, buf->tag.rnode.dbNode,
|
||||
buf->tag.rnode.relNode,
|
||||
@@ -1009,12 +1012,12 @@ FlushBuffer(BufferDesc *buf, SMgrRelation reln)
|
||||
XLogFlush(recptr);
|
||||
|
||||
/*
|
||||
* Now it's safe to write buffer to disk. Note that no one else
|
||||
* should have been able to write it while we were busy with
|
||||
* locking and log flushing because caller has set the IO flag.
|
||||
* Now it's safe to write buffer to disk. Note that no one else should
|
||||
* have been able to write it while we were busy with locking and log
|
||||
* flushing because caller has set the IO flag.
|
||||
*
|
||||
* It would be better to clear BM_JUST_DIRTIED right here, but we'd
|
||||
* have to reacquire the BufMgrLock and it doesn't seem worth it.
|
||||
* It would be better to clear BM_JUST_DIRTIED right here, but we'd have
|
||||
* to reacquire the BufMgrLock and it doesn't seem worth it.
|
||||
*/
|
||||
smgrwrite(reln,
|
||||
buf->tag.blockNum,
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/freelist.c,v 1.46 2004/08/29 04:12:47 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/freelist.c,v 1.47 2004/08/29 05:06:47 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -26,15 +26,15 @@
|
||||
|
||||
|
||||
/* GUC variable: time in seconds between statistics reports */
|
||||
int DebugSharedBuffers = 0;
|
||||
int DebugSharedBuffers = 0;
|
||||
|
||||
/* Pointers to shared state */
|
||||
static BufferStrategyControl *StrategyControl = NULL;
|
||||
static BufferStrategyCDB *StrategyCDB = NULL;
|
||||
static BufferStrategyControl *StrategyControl = NULL;
|
||||
static BufferStrategyCDB *StrategyCDB = NULL;
|
||||
|
||||
/* Backend-local state about whether currently vacuuming */
|
||||
static bool strategy_hint_vacuum = false;
|
||||
static TransactionId strategy_vacuum_xid;
|
||||
static bool strategy_hint_vacuum = false;
|
||||
static TransactionId strategy_vacuum_xid;
|
||||
|
||||
|
||||
#define T1_TARGET (StrategyControl->target_T1_size)
|
||||
@@ -47,7 +47,7 @@ static TransactionId strategy_vacuum_xid;
|
||||
/*
|
||||
* Macro to remove a CDB from whichever list it currently is on
|
||||
*/
|
||||
#define STRAT_LIST_REMOVE(cdb) \
|
||||
#define STRAT_LIST_REMOVE(cdb) \
|
||||
do { \
|
||||
Assert((cdb)->list >= 0 && (cdb)->list < STRAT_NUM_LISTS); \
|
||||
if ((cdb)->prev < 0) \
|
||||
@@ -71,7 +71,7 @@ do { \
|
||||
if (StrategyControl->listTail[(l)] < 0) \
|
||||
{ \
|
||||
(cdb)->prev = (cdb)->next = -1; \
|
||||
StrategyControl->listHead[(l)] = \
|
||||
StrategyControl->listHead[(l)] = \
|
||||
StrategyControl->listTail[(l)] = \
|
||||
((cdb) - StrategyCDB); \
|
||||
} \
|
||||
@@ -79,9 +79,9 @@ do { \
|
||||
{ \
|
||||
(cdb)->next = -1; \
|
||||
(cdb)->prev = StrategyControl->listTail[(l)]; \
|
||||
StrategyCDB[StrategyControl->listTail[(l)]].next = \
|
||||
StrategyCDB[StrategyControl->listTail[(l)]].next = \
|
||||
((cdb) - StrategyCDB); \
|
||||
StrategyControl->listTail[(l)] = \
|
||||
StrategyControl->listTail[(l)] = \
|
||||
((cdb) - StrategyCDB); \
|
||||
} \
|
||||
StrategyControl->listSize[(l)]++; \
|
||||
@@ -97,7 +97,7 @@ do { \
|
||||
if (StrategyControl->listHead[(l)] < 0) \
|
||||
{ \
|
||||
(cdb)->prev = (cdb)->next = -1; \
|
||||
StrategyControl->listHead[(l)] = \
|
||||
StrategyControl->listHead[(l)] = \
|
||||
StrategyControl->listTail[(l)] = \
|
||||
((cdb) - StrategyCDB); \
|
||||
} \
|
||||
@@ -105,9 +105,9 @@ do { \
|
||||
{ \
|
||||
(cdb)->prev = -1; \
|
||||
(cdb)->next = StrategyControl->listHead[(l)]; \
|
||||
StrategyCDB[StrategyControl->listHead[(l)]].prev = \
|
||||
StrategyCDB[StrategyControl->listHead[(l)]].prev = \
|
||||
((cdb) - StrategyCDB); \
|
||||
StrategyControl->listHead[(l)] = \
|
||||
StrategyControl->listHead[(l)] = \
|
||||
((cdb) - StrategyCDB); \
|
||||
} \
|
||||
StrategyControl->listSize[(l)]++; \
|
||||
@@ -125,9 +125,15 @@ StrategyStatsDump(void)
|
||||
|
||||
if (StrategyControl->stat_report + DebugSharedBuffers < now)
|
||||
{
|
||||
long all_hit, b1_hit, t1_hit, t2_hit, b2_hit;
|
||||
int id, t1_clean, t2_clean;
|
||||
ErrorContextCallback *errcxtold;
|
||||
long all_hit,
|
||||
b1_hit,
|
||||
t1_hit,
|
||||
t2_hit,
|
||||
b2_hit;
|
||||
int id,
|
||||
t1_clean,
|
||||
t2_clean;
|
||||
ErrorContextCallback *errcxtold;
|
||||
|
||||
id = StrategyControl->listHead[STRAT_LIST_T1];
|
||||
t1_clean = 0;
|
||||
@@ -149,9 +155,7 @@ StrategyStatsDump(void)
|
||||
}
|
||||
|
||||
if (StrategyControl->num_lookup == 0)
|
||||
{
|
||||
all_hit = b1_hit = t1_hit = t2_hit = b2_hit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
b1_hit = (StrategyControl->num_hit[STRAT_LIST_B1] * 100 /
|
||||
@@ -202,7 +206,7 @@ BufferDesc *
|
||||
StrategyBufferLookup(BufferTag *tagPtr, bool recheck,
|
||||
int *cdb_found_index)
|
||||
{
|
||||
BufferStrategyCDB *cdb;
|
||||
BufferStrategyCDB *cdb;
|
||||
|
||||
/* Optional stats printout */
|
||||
if (DebugSharedBuffers > 0)
|
||||
@@ -235,8 +239,8 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck,
|
||||
StrategyControl->num_hit[cdb->list]++;
|
||||
|
||||
/*
|
||||
* If this is a T2 hit, we simply move the CDB to the
|
||||
* T2 MRU position and return the found buffer.
|
||||
* If this is a T2 hit, we simply move the CDB to the T2 MRU position
|
||||
* and return the found buffer.
|
||||
*
|
||||
* A CDB in T2 cannot have t1_vacuum set, so we needn't check. However,
|
||||
* if the current process is VACUUM then it doesn't promote to MRU.
|
||||
@@ -253,12 +257,12 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck,
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is a T1 hit, we move the buffer to the T2 MRU only if another
|
||||
* transaction had read it into T1, *and* neither transaction is a VACUUM.
|
||||
* This is required because any UPDATE or DELETE in PostgreSQL does
|
||||
* multiple ReadBuffer(), first during the scan, later during the
|
||||
* heap_update() or heap_delete(). Otherwise move to T1 MRU. VACUUM
|
||||
* doesn't even get to make that happen.
|
||||
* If this is a T1 hit, we move the buffer to the T2 MRU only if
|
||||
* another transaction had read it into T1, *and* neither transaction
|
||||
* is a VACUUM. This is required because any UPDATE or DELETE in
|
||||
* PostgreSQL does multiple ReadBuffer(), first during the scan, later
|
||||
* during the heap_update() or heap_delete(). Otherwise move to T1
|
||||
* MRU. VACUUM doesn't even get to make that happen.
|
||||
*/
|
||||
if (cdb->list == STRAT_LIST_T1)
|
||||
{
|
||||
@@ -274,10 +278,11 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck,
|
||||
{
|
||||
STRAT_LIST_REMOVE(cdb);
|
||||
STRAT_MRU_INSERT(cdb, STRAT_LIST_T1);
|
||||
|
||||
/*
|
||||
* If a non-VACUUM process references a page recently loaded
|
||||
* by VACUUM, clear the stigma; the state will now be the
|
||||
* same as if this process loaded it originally.
|
||||
* If a non-VACUUM process references a page recently
|
||||
* loaded by VACUUM, clear the stigma; the state will now
|
||||
* be the same as if this process loaded it originally.
|
||||
*/
|
||||
if (cdb->t1_vacuum)
|
||||
{
|
||||
@@ -297,9 +302,9 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck,
|
||||
* adjust the T1target.
|
||||
*
|
||||
* Now for this really to end up as a B1 or B2 cache hit, we must have
|
||||
* been flushing for quite some time as the block not only must have been
|
||||
* read, but also traveled through the queue and evicted from the T cache
|
||||
* again already.
|
||||
* been flushing for quite some time as the block not only must have
|
||||
* been read, but also traveled through the queue and evicted from the
|
||||
* T cache again already.
|
||||
*
|
||||
* VACUUM re-reads shouldn't adjust the target either.
|
||||
*/
|
||||
@@ -307,26 +312,26 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck,
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Adjust the target size of the T1 cache depending on if this is
|
||||
* a B1 or B2 hit.
|
||||
* Adjust the target size of the T1 cache depending on if this is a B1
|
||||
* or B2 hit.
|
||||
*/
|
||||
switch (cdb->list)
|
||||
{
|
||||
case STRAT_LIST_B1:
|
||||
|
||||
/*
|
||||
* B1 hit means that the T1 cache is probably too
|
||||
* small. Adjust the T1 target size and continue
|
||||
* below.
|
||||
* B1 hit means that the T1 cache is probably too small.
|
||||
* Adjust the T1 target size and continue below.
|
||||
*/
|
||||
T1_TARGET = Min(T1_TARGET + Max(B2_LENGTH / B1_LENGTH, 1),
|
||||
NBuffers);
|
||||
break;
|
||||
|
||||
case STRAT_LIST_B2:
|
||||
/*
|
||||
* B2 hit means that the T2 cache is probably too
|
||||
* small. Adjust the T1 target size and continue
|
||||
* below.
|
||||
|
||||
/*
|
||||
* B2 hit means that the T2 cache is probably too small.
|
||||
* Adjust the T1 target size and continue below.
|
||||
*/
|
||||
T1_TARGET = Max(T1_TARGET - Max(B1_LENGTH / B2_LENGTH, 1), 0);
|
||||
break;
|
||||
@@ -337,8 +342,8 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck,
|
||||
}
|
||||
|
||||
/*
|
||||
* Even though we had seen the block in the past, its data is
|
||||
* not currently in memory ... cache miss to the bufmgr.
|
||||
* Even though we had seen the block in the past, its data is not
|
||||
* currently in memory ... cache miss to the bufmgr.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
@@ -349,7 +354,7 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck,
|
||||
*
|
||||
* Called by the bufmgr to get the next candidate buffer to use in
|
||||
* BufferAlloc(). The only hard requirement BufferAlloc() has is that
|
||||
* this buffer must not currently be pinned.
|
||||
* this buffer must not currently be pinned.
|
||||
*
|
||||
* *cdb_replace_index is set to the index of the candidate CDB, or -1 if
|
||||
* none (meaning we are using a previously free buffer). This is not
|
||||
@@ -359,8 +364,8 @@ StrategyBufferLookup(BufferTag *tagPtr, bool recheck,
|
||||
BufferDesc *
|
||||
StrategyGetBuffer(int *cdb_replace_index)
|
||||
{
|
||||
int cdb_id;
|
||||
BufferDesc *buf;
|
||||
int cdb_id;
|
||||
BufferDesc *buf;
|
||||
|
||||
if (StrategyControl->listFreeBuffers < 0)
|
||||
{
|
||||
@@ -452,12 +457,12 @@ StrategyGetBuffer(int *cdb_replace_index)
|
||||
/* There is a completely free buffer available - take it */
|
||||
|
||||
/*
|
||||
* Note: This code uses the side effect that a free buffer
|
||||
* can never be pinned or dirty and therefore the call to
|
||||
* Note: This code uses the side effect that a free buffer can
|
||||
* never be pinned or dirty and therefore the call to
|
||||
* StrategyReplaceBuffer() will happen without the bufmgr
|
||||
* releasing the bufmgr-lock in the meantime. That means,
|
||||
* that there will never be any reason to recheck. Otherwise
|
||||
* we would leak shared buffers here!
|
||||
* releasing the bufmgr-lock in the meantime. That means, that
|
||||
* there will never be any reason to recheck. Otherwise we would
|
||||
* leak shared buffers here!
|
||||
*/
|
||||
*cdb_replace_index = -1;
|
||||
buf = &BufferDescriptors[StrategyControl->listFreeBuffers];
|
||||
@@ -493,8 +498,8 @@ void
|
||||
StrategyReplaceBuffer(BufferDesc *buf, BufferTag *newTag,
|
||||
int cdb_found_index, int cdb_replace_index)
|
||||
{
|
||||
BufferStrategyCDB *cdb_found;
|
||||
BufferStrategyCDB *cdb_replace;
|
||||
BufferStrategyCDB *cdb_found;
|
||||
BufferStrategyCDB *cdb_replace;
|
||||
|
||||
if (cdb_found_index >= 0)
|
||||
{
|
||||
@@ -504,7 +509,7 @@ StrategyReplaceBuffer(BufferDesc *buf, BufferTag *newTag,
|
||||
/* Assert that the buffer remembered in cdb_found is the one */
|
||||
/* the buffer manager is currently faulting in */
|
||||
Assert(BUFFERTAGS_EQUAL(cdb_found->buf_tag, *newTag));
|
||||
|
||||
|
||||
if (cdb_replace_index >= 0)
|
||||
{
|
||||
/* We are satisfying it with an evicted T buffer */
|
||||
@@ -512,17 +517,18 @@ StrategyReplaceBuffer(BufferDesc *buf, BufferTag *newTag,
|
||||
|
||||
/* Assert that the buffer remembered in cdb_replace is */
|
||||
/* the one the buffer manager has just evicted */
|
||||
Assert(cdb_replace->list == STRAT_LIST_T1 ||
|
||||
Assert(cdb_replace->list == STRAT_LIST_T1 ||
|
||||
cdb_replace->list == STRAT_LIST_T2);
|
||||
Assert(cdb_replace->buf_id == buf->buf_id);
|
||||
Assert(BUFFERTAGS_EQUAL(cdb_replace->buf_tag, buf->tag));
|
||||
|
||||
/*
|
||||
* Under normal circumstances we move the evicted T list entry to
|
||||
* the corresponding B list. However, T1 entries that exist only
|
||||
* because of VACUUM are just thrown into the unused list instead.
|
||||
* We don't expect them to be touched again by the VACUUM, and if
|
||||
* we put them into B1 then VACUUM would skew T1_target adjusting.
|
||||
* Under normal circumstances we move the evicted T list entry
|
||||
* to the corresponding B list. However, T1 entries that
|
||||
* exist only because of VACUUM are just thrown into the
|
||||
* unused list instead. We don't expect them to be touched
|
||||
* again by the VACUUM, and if we put them into B1 then VACUUM
|
||||
* would skew T1_target adjusting.
|
||||
*/
|
||||
if (cdb_replace->t1_vacuum)
|
||||
{
|
||||
@@ -560,8 +566,8 @@ StrategyReplaceBuffer(BufferDesc *buf, BufferTag *newTag,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* This was a complete cache miss, so we need to create
|
||||
* a new CDB. The goal is to keep T1len+B1len <= c.
|
||||
* This was a complete cache miss, so we need to create a new CDB.
|
||||
* The goal is to keep T1len+B1len <= c.
|
||||
*/
|
||||
if (B1_LENGTH > 0 && (T1_LENGTH + B1_LENGTH) >= NBuffers)
|
||||
{
|
||||
@@ -600,12 +606,12 @@ StrategyReplaceBuffer(BufferDesc *buf, BufferTag *newTag,
|
||||
if (cdb_replace_index >= 0)
|
||||
{
|
||||
/*
|
||||
* The buffer was formerly in a T list, move its CDB
|
||||
* to the corresponding B list
|
||||
* The buffer was formerly in a T list, move its CDB to the
|
||||
* corresponding B list
|
||||
*/
|
||||
cdb_replace = &StrategyCDB[cdb_replace_index];
|
||||
|
||||
Assert(cdb_replace->list == STRAT_LIST_T1 ||
|
||||
Assert(cdb_replace->list == STRAT_LIST_T1 ||
|
||||
cdb_replace->list == STRAT_LIST_T2);
|
||||
Assert(cdb_replace->buf_id == buf->buf_id);
|
||||
Assert(BUFFERTAGS_EQUAL(cdb_replace->buf_tag, buf->tag));
|
||||
@@ -651,9 +657,9 @@ StrategyReplaceBuffer(BufferDesc *buf, BufferTag *newTag,
|
||||
STRAT_MRU_INSERT(cdb_found, STRAT_LIST_T1);
|
||||
|
||||
/*
|
||||
* Remember the Xid when this buffer went onto T1 to avoid
|
||||
* a single UPDATE promoting a newcomer straight into T2.
|
||||
* Also remember if it was loaded for VACUUM.
|
||||
* Remember the Xid when this buffer went onto T1 to avoid a
|
||||
* single UPDATE promoting a newcomer straight into T2. Also
|
||||
* remember if it was loaded for VACUUM.
|
||||
*/
|
||||
cdb_found->t1_xid = GetCurrentTransactionId();
|
||||
cdb_found->t1_vacuum = strategy_hint_vacuum;
|
||||
@@ -671,8 +677,8 @@ StrategyReplaceBuffer(BufferDesc *buf, BufferTag *newTag,
|
||||
void
|
||||
StrategyInvalidateBuffer(BufferDesc *buf)
|
||||
{
|
||||
int cdb_id;
|
||||
BufferStrategyCDB *cdb;
|
||||
int cdb_id;
|
||||
BufferStrategyCDB *cdb;
|
||||
|
||||
/* The buffer cannot be dirty or pinned */
|
||||
Assert(!(buf->flags & BM_DIRTY) || !(buf->flags & BM_VALID));
|
||||
@@ -687,15 +693,15 @@ StrategyInvalidateBuffer(BufferDesc *buf)
|
||||
cdb = &StrategyCDB[cdb_id];
|
||||
|
||||
/*
|
||||
* Remove the CDB from the hashtable and the ARC queue it is
|
||||
* currently on.
|
||||
* Remove the CDB from the hashtable and the ARC queue it is currently
|
||||
* on.
|
||||
*/
|
||||
BufTableDelete(&(cdb->buf_tag));
|
||||
STRAT_LIST_REMOVE(cdb);
|
||||
|
||||
/*
|
||||
* Clear out the CDB's buffer tag and association with the buffer
|
||||
* and add it to the list of unused CDB's
|
||||
* Clear out the CDB's buffer tag and association with the buffer and
|
||||
* add it to the list of unused CDB's
|
||||
*/
|
||||
CLEAR_BUFFERTAG(cdb->buf_tag);
|
||||
cdb->buf_id = -1;
|
||||
@@ -703,9 +709,9 @@ StrategyInvalidateBuffer(BufferDesc *buf)
|
||||
StrategyControl->listUnusedCDB = cdb_id;
|
||||
|
||||
/*
|
||||
* Clear out the buffer's tag and add it to the list of
|
||||
* currently unused buffers. We must do this to ensure that linear
|
||||
* scans of the buffer array don't think the buffer is valid.
|
||||
* Clear out the buffer's tag and add it to the list of currently
|
||||
* unused buffers. We must do this to ensure that linear scans of the
|
||||
* buffer array don't think the buffer is valid.
|
||||
*/
|
||||
CLEAR_BUFFERTAG(buf->tag);
|
||||
buf->flags &= ~(BM_VALID | BM_DIRTY);
|
||||
@@ -743,17 +749,17 @@ int
|
||||
StrategyDirtyBufferList(BufferDesc **buffers, BufferTag *buftags,
|
||||
int max_buffers)
|
||||
{
|
||||
int num_buffer_dirty = 0;
|
||||
int cdb_id_t1;
|
||||
int cdb_id_t2;
|
||||
int buf_id;
|
||||
BufferDesc *buf;
|
||||
int num_buffer_dirty = 0;
|
||||
int cdb_id_t1;
|
||||
int cdb_id_t2;
|
||||
int buf_id;
|
||||
BufferDesc *buf;
|
||||
|
||||
/*
|
||||
* Traverse the T1 and T2 list LRU to MRU in "parallel"
|
||||
* and add all dirty buffers found in that order to the list.
|
||||
* The ARC strategy keeps all used buffers including pinned ones
|
||||
* in the T1 or T2 list. So we cannot miss any dirty buffers.
|
||||
* Traverse the T1 and T2 list LRU to MRU in "parallel" and add all
|
||||
* dirty buffers found in that order to the list. The ARC strategy
|
||||
* keeps all used buffers including pinned ones in the T1 or T2 list.
|
||||
* So we cannot miss any dirty buffers.
|
||||
*/
|
||||
cdb_id_t1 = StrategyControl->listHead[STRAT_LIST_T1];
|
||||
cdb_id_t2 = StrategyControl->listHead[STRAT_LIST_T2];
|
||||
@@ -815,8 +821,8 @@ StrategyDirtyBufferList(BufferDesc **buffers, BufferTag *buftags,
|
||||
void
|
||||
StrategyInitialize(bool init)
|
||||
{
|
||||
bool found;
|
||||
int i;
|
||||
bool found;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Initialize the shared CDB lookup hashtable
|
||||
@@ -841,14 +847,14 @@ StrategyInitialize(bool init)
|
||||
Assert(init);
|
||||
|
||||
/*
|
||||
* Grab the whole linked list of free buffers for our strategy.
|
||||
* We assume it was previously set up by InitBufferPool().
|
||||
* Grab the whole linked list of free buffers for our strategy. We
|
||||
* assume it was previously set up by InitBufferPool().
|
||||
*/
|
||||
StrategyControl->listFreeBuffers = 0;
|
||||
|
||||
/*
|
||||
* We start off with a target T1 list size of
|
||||
* half the available cache blocks.
|
||||
* We start off with a target T1 list size of half the available
|
||||
* cache blocks.
|
||||
*/
|
||||
StrategyControl->target_T1_size = NBuffers / 2;
|
||||
|
||||
@@ -862,7 +868,7 @@ StrategyInitialize(bool init)
|
||||
StrategyControl->listSize[i] = 0;
|
||||
StrategyControl->num_hit[i] = 0;
|
||||
}
|
||||
StrategyControl->num_lookup = 0;
|
||||
StrategyControl->num_lookup = 0;
|
||||
StrategyControl->stat_report = 0;
|
||||
|
||||
/*
|
||||
@@ -879,7 +885,5 @@ StrategyInitialize(bool init)
|
||||
StrategyControl->listUnusedCDB = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert(!init);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.58 2004/08/29 04:12:47 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/buffer/localbuf.c,v 1.59 2004/08/29 05:06:47 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -39,7 +39,7 @@ static int nextFreeLocalBuf = 0;
|
||||
* allocate a local buffer. We do round robin allocation for now.
|
||||
*
|
||||
* API is similar to bufmgr.c's BufferAlloc, except that we do not need
|
||||
* to have the BufMgrLock since this is all local. Also, IO_IN_PROGRESS
|
||||
* to have the BufMgrLock since this is all local. Also, IO_IN_PROGRESS
|
||||
* does not get set.
|
||||
*/
|
||||
BufferDesc *
|
||||
@@ -64,7 +64,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
|
||||
|
||||
LocalRefCount[i]++;
|
||||
ResourceOwnerRememberBuffer(CurrentResourceOwner,
|
||||
BufferDescriptorGetBuffer(bufHdr));
|
||||
BufferDescriptorGetBuffer(bufHdr));
|
||||
if (bufHdr->flags & BM_VALID)
|
||||
*foundPtr = TRUE;
|
||||
else
|
||||
@@ -92,7 +92,7 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr)
|
||||
bufHdr = &LocalBufferDescriptors[b];
|
||||
LocalRefCount[b]++;
|
||||
ResourceOwnerRememberBuffer(CurrentResourceOwner,
|
||||
BufferDescriptorGetBuffer(bufHdr));
|
||||
BufferDescriptorGetBuffer(bufHdr));
|
||||
nextFreeLocalBuf = (b + 1) % NLocBuffer;
|
||||
break;
|
||||
}
|
||||
@@ -245,7 +245,7 @@ AtEOXact_LocalBuffers(bool isCommit)
|
||||
"local buffer leak: [%03d] (rel=%u/%u/%u, blockNum=%u, flags=0x%x, refcount=%u %d)",
|
||||
i,
|
||||
buf->tag.rnode.spcNode, buf->tag.rnode.dbNode,
|
||||
buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags,
|
||||
buf->tag.rnode.relNode, buf->tag.blockNum, buf->flags,
|
||||
buf->refcount, LocalRefCount[i]);
|
||||
|
||||
LocalRefCount[i] = 0;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.111 2004/08/29 04:12:47 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.112 2004/08/29 05:06:47 momjian Exp $
|
||||
*
|
||||
* NOTES:
|
||||
*
|
||||
@@ -57,7 +57,7 @@
|
||||
* and other code that tries to open files without consulting fd.c. This
|
||||
* is the number left free. (While we can be pretty sure we won't get
|
||||
* EMFILE, there's never any guarantee that we won't get ENFILE due to
|
||||
* other processes chewing up FDs. So it's a bad idea to try to open files
|
||||
* other processes chewing up FDs. So it's a bad idea to try to open files
|
||||
* without consulting fd.c. Nonetheless we cannot control all code.)
|
||||
*
|
||||
* Because this is just a fixed setting, we are effectively assuming that
|
||||
@@ -95,7 +95,7 @@ int max_files_per_process = 1000;
|
||||
* Note: the value of max_files_per_process is taken into account while
|
||||
* setting this variable, and so need not be tested separately.
|
||||
*/
|
||||
static int max_safe_fds = 32; /* default if not changed */
|
||||
static int max_safe_fds = 32; /* default if not changed */
|
||||
|
||||
|
||||
/* Debugging.... */
|
||||
@@ -157,21 +157,24 @@ static int nfile = 0;
|
||||
*/
|
||||
#define MAX_ALLOCATED_DESCS 32
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
AllocateDescFile,
|
||||
AllocateDescDir
|
||||
} AllocateDescKind;
|
||||
|
||||
typedef struct {
|
||||
AllocateDescKind kind;
|
||||
union {
|
||||
FILE *file;
|
||||
DIR *dir;
|
||||
} desc;
|
||||
typedef struct
|
||||
{
|
||||
AllocateDescKind kind;
|
||||
union
|
||||
{
|
||||
FILE *file;
|
||||
DIR *dir;
|
||||
} desc;
|
||||
TransactionId create_xid;
|
||||
} AllocateDesc;
|
||||
|
||||
static int numAllocatedDescs = 0;
|
||||
static int numAllocatedDescs = 0;
|
||||
static AllocateDesc allocatedDescs[MAX_ALLOCATED_DESCS];
|
||||
|
||||
/*
|
||||
@@ -280,7 +283,7 @@ count_usable_fds(int *usable_fds, int *already_open)
|
||||
/* dup until failure ... */
|
||||
for (;;)
|
||||
{
|
||||
int thisfd;
|
||||
int thisfd;
|
||||
|
||||
thisfd = dup(0);
|
||||
if (thisfd < 0)
|
||||
@@ -309,12 +312,12 @@ count_usable_fds(int *usable_fds, int *already_open)
|
||||
pfree(fd);
|
||||
|
||||
/*
|
||||
* Return results. usable_fds is just the number of successful dups.
|
||||
* We assume that the system limit is highestfd+1 (remember 0 is a legal
|
||||
* FD number) and so already_open is highestfd+1 - usable_fds.
|
||||
* Return results. usable_fds is just the number of successful dups.
|
||||
* We assume that the system limit is highestfd+1 (remember 0 is a
|
||||
* legal FD number) and so already_open is highestfd+1 - usable_fds.
|
||||
*/
|
||||
*usable_fds = used;
|
||||
*already_open = highestfd+1 - used;
|
||||
*already_open = highestfd + 1 - used;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -328,11 +331,11 @@ set_max_safe_fds(void)
|
||||
int already_open;
|
||||
|
||||
/*
|
||||
* We want to set max_safe_fds to
|
||||
* MIN(usable_fds, max_files_per_process - already_open)
|
||||
* less the slop factor for files that are opened without consulting
|
||||
* fd.c. This ensures that we won't exceed either max_files_per_process
|
||||
* or the experimentally-determined EMFILE limit.
|
||||
* We want to set max_safe_fds to MIN(usable_fds,
|
||||
* max_files_per_process - already_open) less the slop factor for
|
||||
* files that are opened without consulting fd.c. This ensures that
|
||||
* we won't exceed either max_files_per_process or the
|
||||
* experimentally-determined EMFILE limit.
|
||||
*/
|
||||
count_usable_fds(&usable_fds, &already_open);
|
||||
|
||||
@@ -1148,9 +1151,9 @@ AllocateFile(char *name, char *mode)
|
||||
|
||||
/*
|
||||
* The test against MAX_ALLOCATED_DESCS prevents us from overflowing
|
||||
* allocatedFiles[]; the test against max_safe_fds prevents AllocateFile
|
||||
* from hogging every one of the available FDs, which'd lead to infinite
|
||||
* looping.
|
||||
* allocatedFiles[]; the test against max_safe_fds prevents
|
||||
* AllocateFile from hogging every one of the available FDs, which'd
|
||||
* lead to infinite looping.
|
||||
*/
|
||||
if (numAllocatedDescs >= MAX_ALLOCATED_DESCS ||
|
||||
numAllocatedDescs >= max_safe_fds - 1)
|
||||
@@ -1192,7 +1195,7 @@ TryAgain:
|
||||
static int
|
||||
FreeDesc(AllocateDesc *desc)
|
||||
{
|
||||
int result;
|
||||
int result;
|
||||
|
||||
/* Close the underlying object */
|
||||
switch (desc->kind)
|
||||
@@ -1256,16 +1259,16 @@ FreeFile(FILE *file)
|
||||
DIR *
|
||||
AllocateDir(const char *dirname)
|
||||
{
|
||||
DIR *dir;
|
||||
DIR *dir;
|
||||
|
||||
DO_DB(elog(LOG, "AllocateDir: Allocated %d (%s)",
|
||||
numAllocatedDescs, dirname));
|
||||
|
||||
/*
|
||||
* The test against MAX_ALLOCATED_DESCS prevents us from overflowing
|
||||
* allocatedDescs[]; the test against max_safe_fds prevents AllocateDir
|
||||
* from hogging every one of the available FDs, which'd lead to infinite
|
||||
* looping.
|
||||
* allocatedDescs[]; the test against max_safe_fds prevents
|
||||
* AllocateDir from hogging every one of the available FDs, which'd
|
||||
* lead to infinite looping.
|
||||
*/
|
||||
if (numAllocatedDescs >= MAX_ALLOCATED_DESCS ||
|
||||
numAllocatedDescs >= max_safe_fds - 1)
|
||||
@@ -1361,7 +1364,7 @@ closeAllVfds(void)
|
||||
void
|
||||
AtEOSubXact_Files(bool isCommit, TransactionId myXid, TransactionId parentXid)
|
||||
{
|
||||
Index i;
|
||||
Index i;
|
||||
|
||||
if (SizeVfdCache > 0)
|
||||
{
|
||||
@@ -1498,7 +1501,7 @@ RemovePgTempFiles(void)
|
||||
/* no PG_TEMP_FILES_DIR in DataDir in non EXEC_BACKEND case */
|
||||
|| strcmp(db_de->d_name, "..") == 0
|
||||
#endif
|
||||
)
|
||||
)
|
||||
continue;
|
||||
|
||||
snprintf(temp_path, sizeof(temp_path),
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.33 2004/08/29 04:12:47 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/freespace/freespace.c,v 1.34 2004/08/29 05:06:47 momjian Exp $
|
||||
*
|
||||
*
|
||||
* NOTES:
|
||||
@@ -217,7 +217,8 @@ int MaxFSMRelations; /* these are set by guc.c */
|
||||
int MaxFSMPages;
|
||||
|
||||
static FSMHeader *FreeSpaceMap; /* points to FSMHeader in shared memory */
|
||||
static HTAB *FreeSpaceMapRelHash; /* points to (what used to be) FSMHeader->relHash */
|
||||
static HTAB *FreeSpaceMapRelHash; /* points to (what used to be)
|
||||
* FSMHeader->relHash */
|
||||
|
||||
|
||||
static FSMRelation *lookup_fsm_rel(RelFileNode *rel);
|
||||
@@ -265,10 +266,10 @@ InitFreeSpaceMap(void)
|
||||
{
|
||||
HASHCTL info;
|
||||
int nchunks;
|
||||
bool found;
|
||||
bool found;
|
||||
|
||||
/* Create table header */
|
||||
FreeSpaceMap = (FSMHeader *) ShmemInitStruct("Free Space Map Header",sizeof(FSMHeader),&found);
|
||||
FreeSpaceMap = (FSMHeader *) ShmemInitStruct("Free Space Map Header", sizeof(FSMHeader), &found);
|
||||
if (FreeSpaceMap == NULL)
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
@@ -282,10 +283,10 @@ InitFreeSpaceMap(void)
|
||||
info.hash = tag_hash;
|
||||
|
||||
FreeSpaceMapRelHash = ShmemInitHash("Free Space Map Hash",
|
||||
MaxFSMRelations / 10,
|
||||
MaxFSMRelations,
|
||||
&info,
|
||||
(HASH_ELEM | HASH_FUNCTION));
|
||||
MaxFSMRelations / 10,
|
||||
MaxFSMRelations,
|
||||
&info,
|
||||
(HASH_ELEM | HASH_FUNCTION));
|
||||
|
||||
if (!FreeSpaceMapRelHash)
|
||||
ereport(FATAL,
|
||||
@@ -1440,24 +1441,25 @@ compact_fsm_storage(void)
|
||||
|
||||
/*
|
||||
* It's possible that we have to move data down, not up, if the
|
||||
* allocations of previous rels expanded. This normally means that
|
||||
* our allocation expanded too (or at least got no worse), and
|
||||
* ditto for later rels. So there should be room to move all our
|
||||
* data down without dropping any --- but we might have to push down
|
||||
* following rels to acquire the room. We don't want to do the push
|
||||
* more than once, so pack everything against the end of the arena
|
||||
* if so.
|
||||
* allocations of previous rels expanded. This normally means
|
||||
* that our allocation expanded too (or at least got no worse),
|
||||
* and ditto for later rels. So there should be room to move all
|
||||
* our data down without dropping any --- but we might have to
|
||||
* push down following rels to acquire the room. We don't want to
|
||||
* do the push more than once, so pack everything against the end
|
||||
* of the arena if so.
|
||||
*
|
||||
* In corner cases where we are on the short end of a roundoff choice
|
||||
* that we were formerly on the long end of, it's possible that we
|
||||
* have to move down and compress our data too. In fact, even after
|
||||
* pushing down the following rels, there might not be as much space
|
||||
* as we computed for this rel above --- that would imply that some
|
||||
* following rel(s) are also on the losing end of roundoff choices.
|
||||
* We could handle this fairly by doing the per-rel compactions
|
||||
* out-of-order, but that seems like way too much complexity to deal
|
||||
* with a very infrequent corner case. Instead, we simply drop pages
|
||||
* from the end of the current rel's data until it fits.
|
||||
* have to move down and compress our data too. In fact, even
|
||||
* after pushing down the following rels, there might not be as
|
||||
* much space as we computed for this rel above --- that would
|
||||
* imply that some following rel(s) are also on the losing end of
|
||||
* roundoff choices. We could handle this fairly by doing the
|
||||
* per-rel compactions out-of-order, but that seems like way too
|
||||
* much complexity to deal with a very infrequent corner case.
|
||||
* Instead, we simply drop pages from the end of the current rel's
|
||||
* data until it fits.
|
||||
*/
|
||||
if (newChunkIndex > oldChunkIndex)
|
||||
{
|
||||
@@ -1491,12 +1493,14 @@ compact_fsm_storage(void)
|
||||
{
|
||||
/* uh-oh, forcibly cut the allocation to fit */
|
||||
newAlloc = limitChunkIndex - newChunkIndex;
|
||||
|
||||
/*
|
||||
* If newAlloc < 0 at this point, we are moving the rel's
|
||||
* firstChunk into territory currently assigned to a later
|
||||
* rel. This is okay so long as we do not copy any data.
|
||||
* The rels will be back in nondecreasing firstChunk order
|
||||
* at completion of the compaction pass.
|
||||
* If newAlloc < 0 at this point, we are moving the
|
||||
* rel's firstChunk into territory currently assigned
|
||||
* to a later rel. This is okay so long as we do not
|
||||
* copy any data. The rels will be back in
|
||||
* nondecreasing firstChunk order at completion of the
|
||||
* compaction pass.
|
||||
*/
|
||||
if (newAlloc < 0)
|
||||
newAlloc = 0;
|
||||
@@ -1846,7 +1850,7 @@ DumpFreeSpace(void)
|
||||
relNum++;
|
||||
fprintf(stderr, "Map %d: rel %u/%u/%u isIndex %d avgRequest %u lastPageCount %d nextPage %d\nMap= ",
|
||||
relNum,
|
||||
fsmrel->key.spcNode, fsmrel->key.dbNode, fsmrel->key.relNode,
|
||||
fsmrel->key.spcNode, fsmrel->key.dbNode, fsmrel->key.relNode,
|
||||
(int) fsmrel->isIndex, fsmrel->avgRequest,
|
||||
fsmrel->lastPageCount, fsmrel->nextPage);
|
||||
if (fsmrel->isIndex)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipc.c,v 1.88 2004/08/29 04:12:48 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipc.c,v 1.89 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -146,7 +146,7 @@ shmem_exit(int code)
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
on_proc_exit(void (*function) (int code, Datum arg), Datum arg)
|
||||
on_proc_exit(void (*function) (int code, Datum arg), Datum arg)
|
||||
{
|
||||
if (on_proc_exit_index >= MAX_ON_EXITS)
|
||||
ereport(FATAL,
|
||||
@@ -167,7 +167,7 @@ on_proc_exit(void (*function) (int code, Datum arg), Datum arg)
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
on_shmem_exit(void (*function) (int code, Datum arg), Datum arg)
|
||||
on_shmem_exit(void (*function) (int code, Datum arg), Datum arg)
|
||||
{
|
||||
if (on_shmem_exit_index >= MAX_ON_EXITS)
|
||||
ereport(FATAL,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.70 2004/08/29 04:12:48 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.71 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -55,15 +55,16 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
|
||||
int port)
|
||||
{
|
||||
PGShmemHeader *seghdr = NULL;
|
||||
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
int size;
|
||||
int numSemas;
|
||||
int size;
|
||||
int numSemas;
|
||||
|
||||
/*
|
||||
* Size of the Postgres shared-memory block is estimated via
|
||||
* moderately-accurate estimates for the big hogs, plus 100K for the
|
||||
* stuff that's too small to bother with estimating.
|
||||
* moderately-accurate estimates for the big hogs, plus 100K for
|
||||
* the stuff that's too small to bother with estimating.
|
||||
*/
|
||||
size = hash_estimate_size(SHMEM_INDEX_SIZE, sizeof(ShmemIndexEnt));
|
||||
size += BufferShmemSize();
|
||||
@@ -99,9 +100,8 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Attach to the shmem segment.
|
||||
* (this should only ever be reached by EXEC_BACKEND code,
|
||||
* and only then with makePrivate == false)
|
||||
* Attach to the shmem segment. (this should only ever be reached
|
||||
* by EXEC_BACKEND code, and only then with makePrivate == false)
|
||||
*/
|
||||
#ifdef EXEC_BACKEND
|
||||
Assert(!makePrivate);
|
||||
@@ -165,6 +165,7 @@ CreateSharedMemoryAndSemaphores(bool makePrivate,
|
||||
BgWriterShmemInit();
|
||||
|
||||
#ifdef EXEC_BACKEND
|
||||
|
||||
/*
|
||||
* Alloc the win32 shared backend array
|
||||
*/
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.16 2004/08/29 04:12:48 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/pmsignal.c,v 1.17 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -45,9 +45,10 @@ static volatile sig_atomic_t *PMSignalFlags;
|
||||
void
|
||||
PMSignalInit(void)
|
||||
{
|
||||
bool found;
|
||||
bool found;
|
||||
|
||||
PMSignalFlags = (sig_atomic_t *)
|
||||
ShmemInitStruct("PMSignalFlags",NUM_PMSIGNALS * sizeof(sig_atomic_t),&found);
|
||||
ShmemInitStruct("PMSignalFlags", NUM_PMSIGNALS * sizeof(sig_atomic_t), &found);
|
||||
|
||||
if (!found)
|
||||
MemSet(PMSignalFlags, 0, NUM_PMSIGNALS * sizeof(sig_atomic_t));
|
||||
@@ -108,14 +109,14 @@ PostmasterIsAlive(bool amDirectChild)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Use kill() to see if the postmaster is still alive. This can
|
||||
* sometimes give a false positive result, since the postmaster's PID
|
||||
* may get recycled, but it is good enough for existing uses by
|
||||
* indirect children.
|
||||
* Use kill() to see if the postmaster is still alive. This can
|
||||
* sometimes give a false positive result, since the postmaster's
|
||||
* PID may get recycled, but it is good enough for existing uses
|
||||
* by indirect children.
|
||||
*/
|
||||
return (kill(PostmasterPid, 0) == 0);
|
||||
}
|
||||
#else /* WIN32 */
|
||||
#else /* WIN32 */
|
||||
return (WaitForSingleObject(PostmasterHandle, 0) == WAIT_TIMEOUT);
|
||||
#endif /* WIN32 */
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.79 2004/08/29 04:12:48 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.80 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -74,11 +74,14 @@ SHMEM_OFFSET ShmemBase; /* start address of shared memory */
|
||||
|
||||
static SHMEM_OFFSET ShmemEnd; /* end+1 address of shared memory */
|
||||
|
||||
NON_EXEC_STATIC slock_t *ShmemLock; /* spinlock for shared memory allocation */
|
||||
NON_EXEC_STATIC slock_t *ShmemLock; /* spinlock for shared memory
|
||||
* allocation */
|
||||
|
||||
NON_EXEC_STATIC slock_t *ShmemIndexLock; /* spinlock for ShmemIndex */
|
||||
|
||||
NON_EXEC_STATIC void *ShmemIndexAlloc = NULL; /* Memory actually allocated for ShmemIndex */
|
||||
NON_EXEC_STATIC void *ShmemIndexAlloc = NULL; /* Memory actually
|
||||
* allocated for
|
||||
* ShmemIndex */
|
||||
|
||||
static HTAB *ShmemIndex = NULL; /* primary index hashtable for shmem */
|
||||
|
||||
@@ -126,7 +129,7 @@ InitShmemAllocation(void *seghdr, bool init)
|
||||
* Initialize ShmemVariableCache for transaction manager.
|
||||
*/
|
||||
ShmemVariableCache = (VariableCache)
|
||||
ShmemAlloc(sizeof(*ShmemVariableCache));
|
||||
ShmemAlloc(sizeof(*ShmemVariableCache));
|
||||
memset(ShmemVariableCache, 0, sizeof(*ShmemVariableCache));
|
||||
}
|
||||
}
|
||||
@@ -348,11 +351,11 @@ ShmemInitStruct(const char *name, Size size, bool *foundPtr)
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If the shmem index doesn't exist, we are bootstrapping: we must
|
||||
* be trying to init the shmem index itself.
|
||||
* If the shmem index doesn't exist, we are bootstrapping: we
|
||||
* must be trying to init the shmem index itself.
|
||||
*
|
||||
* Notice that the ShmemIndexLock is held until the shmem index has
|
||||
* been completely initialized.
|
||||
* Notice that the ShmemIndexLock is held until the shmem index
|
||||
* has been completely initialized.
|
||||
*/
|
||||
Assert(strcmp(name, "ShmemIndex") == 0);
|
||||
Assert(ShmemBootstrap);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.71 2004/08/29 04:12:48 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.72 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -43,20 +43,19 @@ static long xc_slow_answer = 0;
|
||||
|
||||
static void DisplayXidCache(int code, Datum arg);
|
||||
|
||||
#else /* !XIDCACHE_DEBUG */
|
||||
#else /* !XIDCACHE_DEBUG */
|
||||
|
||||
#define xc_by_recent_xmin_inc() ((void) 0)
|
||||
#define xc_by_main_xid_inc() ((void) 0)
|
||||
#define xc_by_child_xid_inc() ((void) 0)
|
||||
#define xc_slow_answer_inc() ((void) 0)
|
||||
|
||||
#endif /* XIDCACHE_DEBUG */
|
||||
#endif /* XIDCACHE_DEBUG */
|
||||
|
||||
/*
|
||||
* Because backends sitting idle will not be reading sinval events, we
|
||||
* need a way to give an idle backend a swift kick in the rear and make
|
||||
* it catch up before the sinval queue overflows and forces everyone
|
||||
* through a cache reset exercise. This is done by broadcasting SIGUSR1
|
||||
* through a cache reset exercise. This is done by broadcasting SIGUSR1
|
||||
* to all backends when the queue is threatening to become full.
|
||||
*
|
||||
* State for catchup events consists of two flags: one saying whether
|
||||
@@ -107,7 +106,7 @@ InitBackendSharedInvalidationState(void)
|
||||
|
||||
#ifdef XIDCACHE_DEBUG
|
||||
on_proc_exit(DisplayXidCache, (Datum) 0);
|
||||
#endif /* XIDCACHE_DEBUG */
|
||||
#endif /* XIDCACHE_DEBUG */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -148,8 +147,8 @@ ReceiveSharedInvalidMessages(
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
* We can discard any pending catchup event, since we will not exit
|
||||
* this loop until we're fully caught up.
|
||||
* We can discard any pending catchup event, since we will not
|
||||
* exit this loop until we're fully caught up.
|
||||
*/
|
||||
catchupInterruptOccurred = 0;
|
||||
|
||||
@@ -206,7 +205,7 @@ ReceiveSharedInvalidMessages(
|
||||
*
|
||||
* If we are idle (catchupInterruptEnabled is set), we can safely
|
||||
* invoke ProcessCatchupEvent directly. Otherwise, just set a flag
|
||||
* to do it later. (Note that it's quite possible for normal processing
|
||||
* to do it later. (Note that it's quite possible for normal processing
|
||||
* of the current transaction to cause ReceiveSharedInvalidMessages()
|
||||
* to be run later on; in that case the flag will get cleared again,
|
||||
* since there's no longer any reason to do anything.)
|
||||
@@ -283,7 +282,7 @@ CatchupInterruptHandler(SIGNAL_ARGS)
|
||||
* EnableCatchupInterrupt
|
||||
*
|
||||
* This is called by the PostgresMain main loop just before waiting
|
||||
* for a frontend command. We process any pending catchup events,
|
||||
* for a frontend command. We process any pending catchup events,
|
||||
* and enable the signal handler to process future events directly.
|
||||
*
|
||||
* NOTE: the signal handler starts out disabled, and stays so until
|
||||
@@ -302,11 +301,11 @@ EnableCatchupInterrupt(void)
|
||||
* then test the occurred flag. If we see an unserviced interrupt has
|
||||
* occurred, we re-clear the enable flag before going off to do the
|
||||
* service work. (That prevents re-entrant invocation of
|
||||
* ProcessCatchupEvent() if another interrupt occurs.) If an
|
||||
* interrupt comes in between the setting and clearing of
|
||||
* catchupInterruptEnabled, then it will have done the service work and
|
||||
* left catchupInterruptOccurred zero, so we have to check again after
|
||||
* clearing enable. The whole thing has to be in a loop in case
|
||||
* ProcessCatchupEvent() if another interrupt occurs.) If an interrupt
|
||||
* comes in between the setting and clearing of
|
||||
* catchupInterruptEnabled, then it will have done the service work
|
||||
* and left catchupInterruptOccurred zero, so we have to check again
|
||||
* after clearing enable. The whole thing has to be in a loop in case
|
||||
* another interrupt occurs while we're servicing the first. Once we
|
||||
* get out of the loop, enable is set and we know there is no
|
||||
* unserviced interrupt.
|
||||
@@ -322,9 +321,7 @@ EnableCatchupInterrupt(void)
|
||||
break;
|
||||
catchupInterruptEnabled = 0;
|
||||
if (catchupInterruptOccurred)
|
||||
{
|
||||
ProcessCatchupEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +329,7 @@ EnableCatchupInterrupt(void)
|
||||
* DisableCatchupInterrupt
|
||||
*
|
||||
* This is called by the PostgresMain main loop just after receiving
|
||||
* a frontend command. Signal handler execution of catchup events
|
||||
* a frontend command. Signal handler execution of catchup events
|
||||
* is disabled until the next EnableCatchupInterrupt call.
|
||||
*
|
||||
* The SIGUSR2 signal handler also needs to call this, so as to
|
||||
@@ -342,7 +339,7 @@ EnableCatchupInterrupt(void)
|
||||
bool
|
||||
DisableCatchupInterrupt(void)
|
||||
{
|
||||
bool result = (catchupInterruptEnabled != 0);
|
||||
bool result = (catchupInterruptEnabled != 0);
|
||||
|
||||
catchupInterruptEnabled = 0;
|
||||
|
||||
@@ -361,23 +358,23 @@ DisableCatchupInterrupt(void)
|
||||
static void
|
||||
ProcessCatchupEvent(void)
|
||||
{
|
||||
bool notify_enabled;
|
||||
bool notify_enabled;
|
||||
|
||||
/* Must prevent SIGUSR2 interrupt while I am running */
|
||||
notify_enabled = DisableNotifyInterrupt();
|
||||
|
||||
/*
|
||||
* What we need to do here is cause ReceiveSharedInvalidMessages()
|
||||
* to run, which will do the necessary work and also reset the
|
||||
* catchupInterruptOccurred flag. If we are inside a transaction
|
||||
* we can just call AcceptInvalidationMessages() to do this. If we
|
||||
* What we need to do here is cause ReceiveSharedInvalidMessages() to
|
||||
* run, which will do the necessary work and also reset the
|
||||
* catchupInterruptOccurred flag. If we are inside a transaction we
|
||||
* can just call AcceptInvalidationMessages() to do this. If we
|
||||
* aren't, we start and immediately end a transaction; the call to
|
||||
* AcceptInvalidationMessages() happens down inside transaction start.
|
||||
*
|
||||
* It is awfully tempting to just call AcceptInvalidationMessages()
|
||||
* without the rest of the xact start/stop overhead, and I think that
|
||||
* would actually work in the normal case; but I am not sure that things
|
||||
* would clean up nicely if we got an error partway through.
|
||||
* would actually work in the normal case; but I am not sure that
|
||||
* things would clean up nicely if we got an error partway through.
|
||||
*/
|
||||
if (IsTransactionOrTransactionBlock())
|
||||
{
|
||||
@@ -501,27 +498,27 @@ IsBackendPid(int pid)
|
||||
* We can find this out cheaply too.
|
||||
*
|
||||
* 3. Search the SubTrans tree to find the Xid's topmost parent, and then
|
||||
* see if that is running according to PGPROC. This is the slowest, but
|
||||
* see if that is running according to PGPROC. This is the slowest, but
|
||||
* sadly it has to be done always if the other two failed, unless we see
|
||||
* that the cached subxact sets are complete (none have overflowed).
|
||||
*
|
||||
* SInvalLock has to be held while we do 1 and 2. If we save the top Xids
|
||||
* while doing 1, we can release the SInvalLock while we do 3. This buys back
|
||||
* while doing 1, we can release the SInvalLock while we do 3. This buys back
|
||||
* some concurrency (we can't retrieve the main Xids from PGPROC again anyway;
|
||||
* see GetNewTransactionId).
|
||||
*/
|
||||
bool
|
||||
TransactionIdIsInProgress(TransactionId xid)
|
||||
{
|
||||
bool result = false;
|
||||
SISeg *segP = shmInvalBuffer;
|
||||
ProcState *stateP = segP->procState;
|
||||
int i,
|
||||
j;
|
||||
int nxids = 0;
|
||||
TransactionId *xids;
|
||||
TransactionId topxid;
|
||||
bool locked;
|
||||
bool result = false;
|
||||
SISeg *segP = shmInvalBuffer;
|
||||
ProcState *stateP = segP->procState;
|
||||
int i,
|
||||
j;
|
||||
int nxids = 0;
|
||||
TransactionId *xids;
|
||||
TransactionId topxid;
|
||||
bool locked;
|
||||
|
||||
/*
|
||||
* Don't bother checking a very old transaction.
|
||||
@@ -563,8 +560,8 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||
}
|
||||
|
||||
/*
|
||||
* We can ignore main Xids that are younger than the target Xid,
|
||||
* since the target could not possibly be their child.
|
||||
* We can ignore main Xids that are younger than the target
|
||||
* Xid, since the target could not possibly be their child.
|
||||
*/
|
||||
if (TransactionIdPrecedes(xid, pxid))
|
||||
continue;
|
||||
@@ -586,11 +583,11 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the main Xid for step 3. We only need to remember main
|
||||
* Xids that have uncached children. (Note: there is no race
|
||||
* condition here because the overflowed flag cannot be cleared,
|
||||
* only set, while we hold SInvalLock. So we can't miss an Xid
|
||||
* that we need to worry about.)
|
||||
* Save the main Xid for step 3. We only need to remember
|
||||
* main Xids that have uncached children. (Note: there is no
|
||||
* race condition here because the overflowed flag cannot be
|
||||
* cleared, only set, while we hold SInvalLock. So we can't
|
||||
* miss an Xid that we need to worry about.)
|
||||
*/
|
||||
if (proc->subxids.overflowed)
|
||||
xids[nxids++] = pxid;
|
||||
@@ -601,8 +598,8 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||
locked = false;
|
||||
|
||||
/*
|
||||
* If none of the relevant caches overflowed, we know the Xid is
|
||||
* not running without looking at pg_subtrans.
|
||||
* If none of the relevant caches overflowed, we know the Xid is not
|
||||
* running without looking at pg_subtrans.
|
||||
*/
|
||||
if (nxids == 0)
|
||||
goto result_known;
|
||||
@@ -610,10 +607,11 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||
/*
|
||||
* Step 3: have to check pg_subtrans.
|
||||
*
|
||||
* At this point, we know it's either a subtransaction of one of the
|
||||
* Xids in xids[], or it's not running. If it's an already-failed
|
||||
* subtransaction, we want to say "not running" even though its parent may
|
||||
* still be running. So first, check pg_clog to see if it's been aborted.
|
||||
* At this point, we know it's either a subtransaction of one of the Xids
|
||||
* in xids[], or it's not running. If it's an already-failed
|
||||
* subtransaction, we want to say "not running" even though its parent
|
||||
* may still be running. So first, check pg_clog to see if it's been
|
||||
* aborted.
|
||||
*/
|
||||
xc_slow_answer_inc();
|
||||
|
||||
@@ -621,10 +619,10 @@ TransactionIdIsInProgress(TransactionId xid)
|
||||
goto result_known;
|
||||
|
||||
/*
|
||||
* It isn't aborted, so check whether the transaction tree it
|
||||
* belongs to is still running (or, more precisely, whether it
|
||||
* was running when this routine started -- note that we already
|
||||
* released SInvalLock).
|
||||
* It isn't aborted, so check whether the transaction tree it belongs
|
||||
* to is still running (or, more precisely, whether it was running
|
||||
* when this routine started -- note that we already released
|
||||
* SInvalLock).
|
||||
*/
|
||||
topxid = SubTransGetTopmostTransaction(xid);
|
||||
Assert(TransactionIdIsValid(topxid));
|
||||
@@ -677,10 +675,10 @@ GetOldestXmin(bool allDbs)
|
||||
int index;
|
||||
|
||||
/*
|
||||
* Normally we start the min() calculation with our own XID. But
|
||||
* if called by checkpointer, we will not be inside a transaction,
|
||||
* so use next XID as starting point for min() calculation. (Note
|
||||
* that if there are no xacts running at all, that will be the subtrans
|
||||
* Normally we start the min() calculation with our own XID. But if
|
||||
* called by checkpointer, we will not be inside a transaction, so use
|
||||
* next XID as starting point for min() calculation. (Note that if
|
||||
* there are no xacts running at all, that will be the subtrans
|
||||
* truncation point!)
|
||||
*/
|
||||
if (IsTransactionState())
|
||||
@@ -758,9 +756,9 @@ GetSnapshotData(Snapshot snapshot, bool serializable)
|
||||
* lastBackend would be sufficient. But it seems better to do the
|
||||
* malloc while not holding the lock, so we can't look at lastBackend.
|
||||
*
|
||||
* This does open a possibility for avoiding repeated malloc/free:
|
||||
* since MaxBackends does not change at runtime, we can simply reuse
|
||||
* the previous xip array if any. (This relies on the fact that all
|
||||
* This does open a possibility for avoiding repeated malloc/free: since
|
||||
* MaxBackends does not change at runtime, we can simply reuse the
|
||||
* previous xip array if any. (This relies on the fact that all
|
||||
* callers pass static SnapshotData structs.)
|
||||
*/
|
||||
if (snapshot->xip == NULL)
|
||||
@@ -961,7 +959,7 @@ GetUndoRecPtr(void)
|
||||
|
||||
return (urec);
|
||||
}
|
||||
#endif /* NOT_USED */
|
||||
#endif /* NOT_USED */
|
||||
|
||||
/*
|
||||
* BackendIdGetProc - given a BackendId, find its PGPROC structure
|
||||
@@ -1024,19 +1022,20 @@ CountEmptyBackendSlots(void)
|
||||
* XidCacheRemoveRunningXids
|
||||
*
|
||||
* Remove a bunch of TransactionIds from the list of known-running
|
||||
* subtransactions for my backend. Both the specified xid and those in
|
||||
* subtransactions for my backend. Both the specified xid and those in
|
||||
* the xids[] array (of length nxids) are removed from the subxids cache.
|
||||
*/
|
||||
void
|
||||
XidCacheRemoveRunningXids(TransactionId xid, int nxids, TransactionId *xids)
|
||||
{
|
||||
int i, j;
|
||||
int i,
|
||||
j;
|
||||
|
||||
Assert(!TransactionIdEquals(xid, InvalidTransactionId));
|
||||
|
||||
/*
|
||||
* We must hold SInvalLock exclusively in order to remove transactions
|
||||
* from the PGPROC array. (See notes in GetSnapshotData.) It's
|
||||
* from the PGPROC array. (See notes in GetSnapshotData.) It's
|
||||
* possible this could be relaxed since we know this routine is only
|
||||
* used to abort subtransactions, but pending closer analysis we'd
|
||||
* best be conservative.
|
||||
@@ -1044,13 +1043,13 @@ XidCacheRemoveRunningXids(TransactionId xid, int nxids, TransactionId *xids)
|
||||
LWLockAcquire(SInvalLock, LW_EXCLUSIVE);
|
||||
|
||||
/*
|
||||
* Under normal circumstances xid and xids[] will be in increasing order,
|
||||
* as will be the entries in subxids. Scan backwards to avoid O(N^2)
|
||||
* behavior when removing a lot of xids.
|
||||
* Under normal circumstances xid and xids[] will be in increasing
|
||||
* order, as will be the entries in subxids. Scan backwards to avoid
|
||||
* O(N^2) behavior when removing a lot of xids.
|
||||
*/
|
||||
for (i = nxids - 1; i >= 0; i--)
|
||||
{
|
||||
TransactionId anxid = xids[i];
|
||||
TransactionId anxid = xids[i];
|
||||
|
||||
for (j = MyProc->subxids.nxids - 1; j >= 0; j--)
|
||||
{
|
||||
@@ -1087,11 +1086,11 @@ static void
|
||||
DisplayXidCache(int code, Datum arg)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"XidCache: xmin: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n",
|
||||
"XidCache: xmin: %ld, mainxid: %ld, childxid: %ld, slow: %ld\n",
|
||||
xc_by_recent_xmin,
|
||||
xc_by_main_xid,
|
||||
xc_by_child_xid,
|
||||
xc_slow_answer);
|
||||
}
|
||||
|
||||
#endif /* XIDCACHE_DEBUG */
|
||||
#endif /* XIDCACHE_DEBUG */
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.56 2004/08/29 04:12:48 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.57 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -50,11 +50,11 @@ SIBufferInit(int maxBackends)
|
||||
int segSize;
|
||||
SISeg *segP;
|
||||
int i;
|
||||
bool found;
|
||||
bool found;
|
||||
|
||||
/* Allocate space in shared memory */
|
||||
segSize = SInvalShmemSize(maxBackends);
|
||||
shmInvalBuffer = segP = (SISeg *) ShmemInitStruct("shmInvalBuffer",segSize,&found);
|
||||
shmInvalBuffer = segP = (SISeg *) ShmemInitStruct("shmInvalBuffer", segSize, &found);
|
||||
if (found)
|
||||
return;
|
||||
|
||||
@@ -215,8 +215,8 @@ SIInsertDataEntry(SISeg *segP, SharedInvalidationMessage *data)
|
||||
/*
|
||||
* Try to prevent table overflow. When the table is 70% full send a
|
||||
* WAKEN_CHILDREN request to the postmaster. The postmaster will send
|
||||
* a SIGUSR1 signal to all the backends, which will cause sinval.c
|
||||
* to read any pending SI entries.
|
||||
* a SIGUSR1 signal to all the backends, which will cause sinval.c to
|
||||
* read any pending SI entries.
|
||||
*
|
||||
* This should never happen if all the backends are actively executing
|
||||
* queries, but if a backend is sitting idle then it won't be starting
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.105 2004/08/29 04:12:48 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/large_object/inv_api.c,v 1.106 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -171,13 +171,9 @@ inv_create(int flags)
|
||||
retval->offset = 0;
|
||||
|
||||
if (flags & INV_WRITE)
|
||||
{
|
||||
retval->flags = IFS_WRLOCK | IFS_RDLOCK;
|
||||
}
|
||||
else if (flags & INV_READ)
|
||||
{
|
||||
retval->flags = IFS_RDLOCK;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "invalid flags: %d", flags);
|
||||
|
||||
@@ -207,13 +203,9 @@ inv_open(Oid lobjId, int flags)
|
||||
retval->offset = 0;
|
||||
|
||||
if (flags & INV_WRITE)
|
||||
{
|
||||
retval->flags = IFS_WRLOCK | IFS_RDLOCK;
|
||||
}
|
||||
else if (flags & INV_READ)
|
||||
{
|
||||
retval->flags = IFS_RDLOCK;
|
||||
}
|
||||
else
|
||||
elog(ERROR, "invalid flags: %d", flags);
|
||||
|
||||
@@ -238,7 +230,7 @@ inv_close(LargeObjectDesc *obj_desc)
|
||||
int
|
||||
inv_drop(Oid lobjId)
|
||||
{
|
||||
Oid classoid;
|
||||
Oid classoid;
|
||||
|
||||
LargeObjectDrop(lobjId);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.68 2004/08/29 04:12:48 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.69 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -66,7 +66,7 @@ static LOCKMASK LockConflicts[] = {
|
||||
|
||||
};
|
||||
|
||||
static LOCKMETHODID LockTableId = INVALID_LOCKMETHOD;
|
||||
static LOCKMETHODID LockTableId = INVALID_LOCKMETHOD;
|
||||
|
||||
/*
|
||||
* Create the lock table described by LockConflicts
|
||||
@@ -74,7 +74,7 @@ static LOCKMETHODID LockTableId = INVALID_LOCKMETHOD;
|
||||
void
|
||||
InitLockTable(int maxBackends)
|
||||
{
|
||||
LOCKMETHODID LongTermTableId;
|
||||
LOCKMETHODID LongTermTableId;
|
||||
|
||||
/* there's no zero-th table */
|
||||
NumLockMethods = 1;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.138 2004/08/29 04:12:48 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.139 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Outside modules can create a lock table and acquire/release
|
||||
@@ -51,12 +51,12 @@ int max_locks_per_xact; /* set by guc.c */
|
||||
* map from lock method id to the lock table data structures
|
||||
*/
|
||||
static LockMethod LockMethods[MAX_LOCK_METHODS];
|
||||
static HTAB *LockMethodLockHash[MAX_LOCK_METHODS];
|
||||
static HTAB *LockMethodProcLockHash[MAX_LOCK_METHODS];
|
||||
static HTAB *LockMethodLocalHash[MAX_LOCK_METHODS];
|
||||
static HTAB *LockMethodLockHash[MAX_LOCK_METHODS];
|
||||
static HTAB *LockMethodProcLockHash[MAX_LOCK_METHODS];
|
||||
static HTAB *LockMethodLocalHash[MAX_LOCK_METHODS];
|
||||
|
||||
/* exported so lmgr.c can initialize it */
|
||||
int NumLockMethods;
|
||||
int NumLockMethods;
|
||||
|
||||
|
||||
/* private state for GrantAwaitedLock */
|
||||
@@ -64,7 +64,7 @@ static LOCALLOCK *awaitedLock;
|
||||
static ResourceOwner awaitedOwner;
|
||||
|
||||
|
||||
static const char * const lock_mode_names[] =
|
||||
static const char *const lock_mode_names[] =
|
||||
{
|
||||
"INVALID",
|
||||
"AccessShareLock",
|
||||
@@ -146,7 +146,7 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP)
|
||||
|| (Trace_lock_table && (((LOCK *) MAKE_PTR(proclockP->tag.lock))->tag.relId == Trace_lock_table))
|
||||
)
|
||||
elog(LOG,
|
||||
"%s: proclock(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%x)",
|
||||
"%s: proclock(%lx) lock(%lx) tbl(%d) proc(%lx) xid(%u) hold(%x)",
|
||||
where, MAKE_OFFSET(proclockP), proclockP->tag.lock,
|
||||
PROCLOCK_LOCKMETHOD(*(proclockP)),
|
||||
proclockP->tag.proc, proclockP->tag.xid,
|
||||
@@ -157,14 +157,13 @@ PROCLOCK_PRINT(const char *where, const PROCLOCK *proclockP)
|
||||
|
||||
#define LOCK_PRINT(where, lock, type)
|
||||
#define PROCLOCK_PRINT(where, proclockP)
|
||||
|
||||
#endif /* not LOCK_DEBUG */
|
||||
|
||||
|
||||
static void RemoveLocalLock(LOCALLOCK *locallock);
|
||||
static void GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner);
|
||||
static int WaitOnLock(LOCKMETHODID lockmethodid, LOCALLOCK *locallock,
|
||||
ResourceOwner owner);
|
||||
ResourceOwner owner);
|
||||
static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PGPROC *proc,
|
||||
int *myHolding);
|
||||
|
||||
@@ -186,7 +185,7 @@ InitLocks(void)
|
||||
LockMethod
|
||||
GetLocksMethodTable(LOCK *lock)
|
||||
{
|
||||
LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*lock);
|
||||
LOCKMETHODID lockmethodid = LOCK_LOCKMETHOD(*lock);
|
||||
|
||||
Assert(0 < lockmethodid && lockmethodid < NumLockMethods);
|
||||
return LockMethods[lockmethodid];
|
||||
@@ -238,7 +237,7 @@ LockMethodTableInit(const char *tabName,
|
||||
|
||||
if (numModes >= MAX_LOCKMODES)
|
||||
elog(ERROR, "too many lock types %d (limit is %d)",
|
||||
numModes, MAX_LOCKMODES-1);
|
||||
numModes, MAX_LOCKMODES - 1);
|
||||
|
||||
/* Compute init/max size to request for lock hashtables */
|
||||
max_table_size = NLOCKENTS(maxBackends);
|
||||
@@ -285,10 +284,10 @@ LockMethodTableInit(const char *tabName,
|
||||
|
||||
sprintf(shmemName, "%s (lock hash)", tabName);
|
||||
LockMethodLockHash[lockmethodid] = ShmemInitHash(shmemName,
|
||||
init_table_size,
|
||||
max_table_size,
|
||||
&info,
|
||||
hash_flags);
|
||||
init_table_size,
|
||||
max_table_size,
|
||||
&info,
|
||||
hash_flags);
|
||||
|
||||
if (!LockMethodLockHash[lockmethodid])
|
||||
elog(FATAL, "could not initialize lock table \"%s\"", tabName);
|
||||
@@ -304,22 +303,23 @@ LockMethodTableInit(const char *tabName,
|
||||
|
||||
sprintf(shmemName, "%s (proclock hash)", tabName);
|
||||
LockMethodProcLockHash[lockmethodid] = ShmemInitHash(shmemName,
|
||||
init_table_size,
|
||||
max_table_size,
|
||||
&info,
|
||||
hash_flags);
|
||||
init_table_size,
|
||||
max_table_size,
|
||||
&info,
|
||||
hash_flags);
|
||||
|
||||
if (!LockMethodProcLockHash[lockmethodid])
|
||||
elog(FATAL, "could not initialize lock table \"%s\"", tabName);
|
||||
|
||||
/*
|
||||
* allocate a non-shared hash table for LOCALLOCK structs. This is used
|
||||
* to store lock counts and resource owner information.
|
||||
* allocate a non-shared hash table for LOCALLOCK structs. This is
|
||||
* used to store lock counts and resource owner information.
|
||||
*
|
||||
* The non-shared table could already exist in this process (this occurs
|
||||
* when the postmaster is recreating shared memory after a backend crash).
|
||||
* If so, delete and recreate it. (We could simply leave it, since it
|
||||
* ought to be empty in the postmaster, but for safety let's zap it.)
|
||||
* when the postmaster is recreating shared memory after a backend
|
||||
* crash). If so, delete and recreate it. (We could simply leave it,
|
||||
* since it ought to be empty in the postmaster, but for safety let's
|
||||
* zap it.)
|
||||
*/
|
||||
if (LockMethodLocalHash[lockmethodid])
|
||||
hash_destroy(LockMethodLocalHash[lockmethodid]);
|
||||
@@ -359,7 +359,7 @@ LockMethodTableInit(const char *tabName,
|
||||
LOCKMETHODID
|
||||
LockMethodTableRename(LOCKMETHODID lockmethodid)
|
||||
{
|
||||
LOCKMETHODID newLockMethodId;
|
||||
LOCKMETHODID newLockMethodId;
|
||||
|
||||
if (NumLockMethods >= MAX_LOCK_METHODS)
|
||||
return INVALID_LOCKMETHOD;
|
||||
@@ -483,7 +483,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
/*
|
||||
* Find or create a LOCALLOCK entry for this lock and lockmode
|
||||
*/
|
||||
MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
|
||||
MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
|
||||
localtag.lock = *locktag;
|
||||
localtag.xid = xid;
|
||||
localtag.mode = lockmode;
|
||||
@@ -509,14 +509,14 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
locallock->lockOwners = NULL;
|
||||
locallock->lockOwners = (LOCALLOCKOWNER *)
|
||||
MemoryContextAlloc(TopMemoryContext,
|
||||
locallock->maxLockOwners * sizeof(LOCALLOCKOWNER));
|
||||
locallock->maxLockOwners * sizeof(LOCALLOCKOWNER));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure there will be room to remember the lock */
|
||||
if (locallock->numLockOwners >= locallock->maxLockOwners)
|
||||
{
|
||||
int newsize = locallock->maxLockOwners * 2;
|
||||
int newsize = locallock->maxLockOwners * 2;
|
||||
|
||||
locallock->lockOwners = (LOCALLOCKOWNER *)
|
||||
repalloc(locallock->lockOwners,
|
||||
@@ -526,7 +526,8 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
}
|
||||
|
||||
/*
|
||||
* If we already hold the lock, we can just increase the count locally.
|
||||
* If we already hold the lock, we can just increase the count
|
||||
* locally.
|
||||
*/
|
||||
if (locallock->nLocks > 0)
|
||||
{
|
||||
@@ -558,7 +559,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("out of shared memory"),
|
||||
errhint("You may need to increase max_locks_per_transaction.")));
|
||||
errhint("You may need to increase max_locks_per_transaction.")));
|
||||
}
|
||||
locallock->lock = lock;
|
||||
|
||||
@@ -588,7 +589,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
/*
|
||||
* Create the hash key for the proclock table.
|
||||
*/
|
||||
MemSet(&proclocktag, 0, sizeof(PROCLOCKTAG)); /* must clear padding */
|
||||
MemSet(&proclocktag, 0, sizeof(PROCLOCKTAG)); /* must clear padding */
|
||||
proclocktag.lock = MAKE_OFFSET(lock);
|
||||
proclocktag.proc = MAKE_OFFSET(MyProc);
|
||||
TransactionIdStore(xid, &proclocktag.xid);
|
||||
@@ -605,7 +606,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("out of shared memory"),
|
||||
errhint("You may need to increase max_locks_per_transaction.")));
|
||||
errhint("You may need to increase max_locks_per_transaction.")));
|
||||
}
|
||||
locallock->proclock = proclock;
|
||||
|
||||
@@ -668,8 +669,8 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
Assert((lock->nRequested > 0) && (lock->requested[lockmode] > 0));
|
||||
|
||||
/*
|
||||
* If this process (under any XID) is a holder of the lock, just
|
||||
* grant myself another one without blocking.
|
||||
* If this process (under any XID) is a holder of the lock, just grant
|
||||
* myself another one without blocking.
|
||||
*/
|
||||
LockCountMyLocks(proclock->tag.lock, MyProc, myHolding);
|
||||
if (myHolding[lockmode] > 0)
|
||||
@@ -715,7 +716,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
SHMQueueDelete(&proclock->lockLink);
|
||||
SHMQueueDelete(&proclock->procLink);
|
||||
proclock = (PROCLOCK *) hash_search(LockMethodProcLockHash[lockmethodid],
|
||||
(void *) &(proclock->tag),
|
||||
(void *) &(proclock->tag),
|
||||
HASH_REMOVE, NULL);
|
||||
if (!proclock)
|
||||
elog(WARNING, "proclock table corrupted");
|
||||
@@ -737,7 +738,7 @@ LockAcquire(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
* Construct bitmask of locks this process holds on this object.
|
||||
*/
|
||||
{
|
||||
LOCKMASK heldLocks = 0;
|
||||
LOCKMASK heldLocks = 0;
|
||||
|
||||
for (i = 1; i <= lockMethodTable->numLockModes; i++)
|
||||
{
|
||||
@@ -954,7 +955,7 @@ static void
|
||||
GrantLockLocal(LOCALLOCK *locallock, ResourceOwner owner)
|
||||
{
|
||||
LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
Assert(locallock->numLockOwners < locallock->maxLockOwners);
|
||||
/* Count the total */
|
||||
@@ -1153,7 +1154,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
/*
|
||||
* Find the LOCALLOCK entry for this lock and lockmode
|
||||
*/
|
||||
MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
|
||||
MemSet(&localtag, 0, sizeof(localtag)); /* must clear padding */
|
||||
localtag.lock = *locktag;
|
||||
localtag.xid = xid;
|
||||
localtag.mode = lockmode;
|
||||
@@ -1179,7 +1180,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
{
|
||||
LOCALLOCKOWNER *lockOwners = locallock->lockOwners;
|
||||
ResourceOwner owner;
|
||||
int i;
|
||||
int i;
|
||||
|
||||
/* Session locks and user locks are not transactional */
|
||||
if (xid != InvalidTransactionId &&
|
||||
@@ -1213,7 +1214,7 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrease the total local count. If we're still holding the lock,
|
||||
* Decrease the total local count. If we're still holding the lock,
|
||||
* we're done.
|
||||
*/
|
||||
locallock->nLocks--;
|
||||
@@ -1239,8 +1240,8 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
PROCLOCK_PRINT("LockRelease: found", proclock);
|
||||
|
||||
/*
|
||||
* Double-check that we are actually holding a lock of the type we want to
|
||||
* release.
|
||||
* Double-check that we are actually holding a lock of the type we
|
||||
* want to release.
|
||||
*/
|
||||
if (!(proclock->holdMask & LOCKBIT_ON(lockmode)))
|
||||
{
|
||||
@@ -1316,8 +1317,8 @@ LockRelease(LOCKMETHODID lockmethodid, LOCKTAG *locktag,
|
||||
if (lock->nRequested == 0)
|
||||
{
|
||||
/*
|
||||
* We've just released the last lock, so garbage-collect the
|
||||
* lock object.
|
||||
* We've just released the last lock, so garbage-collect the lock
|
||||
* object.
|
||||
*/
|
||||
Assert(SHMQueueEmpty(&(lock->procLocks)));
|
||||
lock = (LOCK *) hash_search(LockMethodLockHash[lockmethodid],
|
||||
@@ -1367,7 +1368,7 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
|
||||
LockMethod lockMethodTable;
|
||||
int i,
|
||||
numLockModes;
|
||||
LOCALLOCK *locallock;
|
||||
LOCALLOCK *locallock;
|
||||
PROCLOCK *proclock;
|
||||
LOCK *lock;
|
||||
|
||||
@@ -1390,9 +1391,9 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
|
||||
/*
|
||||
* First we run through the locallock table and get rid of unwanted
|
||||
* entries, then we scan the process's proclocks and get rid of those.
|
||||
* We do this separately because we may have multiple locallock entries
|
||||
* pointing to the same proclock, and we daren't end up with any
|
||||
* dangling pointers.
|
||||
* We do this separately because we may have multiple locallock
|
||||
* entries pointing to the same proclock, and we daren't end up with
|
||||
* any dangling pointers.
|
||||
*/
|
||||
hash_seq_init(&status, LockMethodLocalHash[lockmethodid]);
|
||||
|
||||
@@ -1413,7 +1414,10 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
|
||||
if (LOCALLOCK_LOCKMETHOD(*locallock) != lockmethodid)
|
||||
continue;
|
||||
|
||||
/* Ignore locks with Xid=0 unless we are asked to release all locks */
|
||||
/*
|
||||
* Ignore locks with Xid=0 unless we are asked to release all
|
||||
* locks
|
||||
*/
|
||||
if (TransactionIdEquals(locallock->tag.xid, InvalidTransactionId)
|
||||
&& !allxids)
|
||||
continue;
|
||||
@@ -1443,7 +1447,10 @@ LockReleaseAll(LOCKMETHODID lockmethodid, bool allxids)
|
||||
if (LOCK_LOCKMETHOD(*lock) != lockmethodid)
|
||||
goto next_item;
|
||||
|
||||
/* Ignore locks with Xid=0 unless we are asked to release all locks */
|
||||
/*
|
||||
* Ignore locks with Xid=0 unless we are asked to release all
|
||||
* locks
|
||||
*/
|
||||
if (TransactionIdEquals(proclock->tag.xid, InvalidTransactionId)
|
||||
&& !allxids)
|
||||
goto next_item;
|
||||
@@ -1552,7 +1559,7 @@ void
|
||||
LockReleaseCurrentOwner(void)
|
||||
{
|
||||
HASH_SEQ_STATUS status;
|
||||
LOCALLOCK *locallock;
|
||||
LOCALLOCK *locallock;
|
||||
LOCALLOCKOWNER *lockOwners;
|
||||
int i;
|
||||
|
||||
@@ -1613,7 +1620,7 @@ LockReassignCurrentOwner(void)
|
||||
{
|
||||
ResourceOwner parent = ResourceOwnerGetParent(CurrentResourceOwner);
|
||||
HASH_SEQ_STATUS status;
|
||||
LOCALLOCK *locallock;
|
||||
LOCALLOCK *locallock;
|
||||
LOCALLOCKOWNER *lockOwners;
|
||||
|
||||
Assert(parent != NULL);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.23 2004/08/29 04:12:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.24 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -533,7 +533,7 @@ LWLockReleaseAll(void)
|
||||
bool
|
||||
LWLockHeldByMe(LWLockId lockid)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_held_lwlocks; i++)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.152 2004/08/29 04:12:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.153 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -122,7 +122,8 @@ ProcGlobalSemas(int maxBackends)
|
||||
void
|
||||
InitProcGlobal(int maxBackends)
|
||||
{
|
||||
bool foundProcGlobal, foundDummy;
|
||||
bool foundProcGlobal,
|
||||
foundDummy;
|
||||
|
||||
/* Create or attach to the ProcGlobal shared structure */
|
||||
ProcGlobal = (PROC_HDR *)
|
||||
@@ -279,7 +280,7 @@ InitProcess(void)
|
||||
void
|
||||
InitDummyProcess(int proctype)
|
||||
{
|
||||
PGPROC *dummyproc;
|
||||
PGPROC *dummyproc;
|
||||
|
||||
/*
|
||||
* ProcGlobal should be set by a previous call to InitProcGlobal (we
|
||||
@@ -365,9 +366,9 @@ LockWaitCancel(void)
|
||||
{
|
||||
/*
|
||||
* Somebody kicked us off the lock queue already. Perhaps they
|
||||
* granted us the lock, or perhaps they detected a deadlock.
|
||||
* If they did grant us the lock, we'd better remember it in
|
||||
* our local lock table.
|
||||
* granted us the lock, or perhaps they detected a deadlock. If
|
||||
* they did grant us the lock, we'd better remember it in our
|
||||
* local lock table.
|
||||
*/
|
||||
if (MyProc->waitStatus == STATUS_OK)
|
||||
GrantAwaitedLock();
|
||||
@@ -480,8 +481,8 @@ ProcKill(int code, Datum arg)
|
||||
static void
|
||||
DummyProcKill(int code, Datum arg)
|
||||
{
|
||||
int proctype = DatumGetInt32(arg);
|
||||
PGPROC *dummyproc;
|
||||
int proctype = DatumGetInt32(arg);
|
||||
PGPROC *dummyproc;
|
||||
|
||||
Assert(proctype >= 0 && proctype < NUM_DUMMY_PROCS);
|
||||
|
||||
@@ -696,8 +697,8 @@ ProcSleep(LockMethod lockMethodTable,
|
||||
/*
|
||||
* Set timer so we can wake up after awhile and check for a deadlock.
|
||||
* If a deadlock is detected, the handler releases the process's
|
||||
* semaphore and sets MyProc->waitStatus = STATUS_ERROR, allowing us to
|
||||
* know that we must report failure rather than success.
|
||||
* semaphore and sets MyProc->waitStatus = STATUS_ERROR, allowing us
|
||||
* to know that we must report failure rather than success.
|
||||
*
|
||||
* By delaying the check until we've waited for a bit, we can avoid
|
||||
* running the rather expensive deadlock-check code in most cases.
|
||||
@@ -914,8 +915,8 @@ CheckDeadLock(void)
|
||||
RemoveFromWaitQueue(MyProc);
|
||||
|
||||
/*
|
||||
* Set MyProc->waitStatus to STATUS_ERROR so that ProcSleep will report
|
||||
* an error after we return from the signal handler.
|
||||
* Set MyProc->waitStatus to STATUS_ERROR so that ProcSleep will
|
||||
* report an error after we return from the signal handler.
|
||||
*/
|
||||
MyProc->waitStatus = STATUS_ERROR;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.29 2004/08/29 04:12:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.30 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -73,8 +73,8 @@ s_lock(volatile slock_t *lock, const char *file, int line)
|
||||
* (and thus the probability of unintended failure) than to fix the
|
||||
* total time spent.
|
||||
*
|
||||
* The pg_usleep() delays are measured in centiseconds (0.01 sec) because 10
|
||||
* msec is a common resolution limit at the OS level.
|
||||
* The pg_usleep() delays are measured in centiseconds (0.01 sec) because
|
||||
* 10 msec is a common resolution limit at the OS level.
|
||||
*/
|
||||
#define SPINS_PER_DELAY 100
|
||||
#define NUM_DELAYS 1000
|
||||
@@ -125,7 +125,7 @@ s_lock(volatile slock_t *lock, const char *file, int line)
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
|
||||
#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
|
||||
|
||||
|
||||
#if defined(__GNUC__)
|
||||
@@ -238,10 +238,8 @@ tas_dummy() /* really means: extern int tas(slock_t
|
||||
}
|
||||
#endif /* __sparc || __sparc__ */
|
||||
|
||||
|
||||
#endif /* not __GNUC__ */
|
||||
|
||||
#endif /* HAVE_SPINLOCKS */
|
||||
#endif /* HAVE_SPINLOCKS */
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/page/bufpage.c,v 1.60 2004/08/29 04:12:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/page/bufpage.c,v 1.61 2004/08/29 05:06:48 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -289,7 +289,7 @@ itemoffcompare(const void *itemidp1, const void *itemidp2)
|
||||
{
|
||||
/* Sort in decreasing itemoff order */
|
||||
return ((itemIdSort) itemidp2)->itemoff -
|
||||
((itemIdSort) itemidp1)->itemoff;
|
||||
((itemIdSort) itemidp1)->itemoff;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -339,7 +339,7 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
|
||||
for (i = 0; i < nline; i++)
|
||||
{
|
||||
lp = PageGetItemId(page, i + 1);
|
||||
if (lp->lp_flags & LP_DELETE) /* marked for deletion */
|
||||
if (lp->lp_flags & LP_DELETE) /* marked for deletion */
|
||||
lp->lp_flags &= ~(LP_USED | LP_DELETE);
|
||||
if (lp->lp_flags & LP_USED)
|
||||
nused++;
|
||||
@@ -353,7 +353,7 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
|
||||
for (i = 0; i < nline; i++)
|
||||
{
|
||||
lp = PageGetItemId(page, i + 1);
|
||||
lp->lp_len = 0; /* indicate unused & deallocated */
|
||||
lp->lp_len = 0; /* indicate unused & deallocated */
|
||||
}
|
||||
((PageHeader) page)->pd_upper = pd_special;
|
||||
}
|
||||
@@ -382,7 +382,7 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
|
||||
}
|
||||
else
|
||||
{
|
||||
lp->lp_len = 0; /* indicate unused & deallocated */
|
||||
lp->lp_len = 0; /* indicate unused & deallocated */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,7 +536,8 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum)
|
||||
nline--; /* there's one less than when we started */
|
||||
for (i = 1; i <= nline; i++)
|
||||
{
|
||||
ItemId ii = PageGetItemId(phdr, i);
|
||||
ItemId ii = PageGetItemId(phdr, i);
|
||||
|
||||
if (ii->lp_off <= offset)
|
||||
ii->lp_off += size;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.109 2004/08/29 04:12:49 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/smgr/md.c,v 1.110 2004/08/29 05:06:49 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -54,9 +54,9 @@
|
||||
|
||||
typedef struct _MdfdVec
|
||||
{
|
||||
File mdfd_vfd; /* fd number in fd.c's pool */
|
||||
BlockNumber mdfd_segno; /* segment number, from 0 */
|
||||
#ifndef LET_OS_MANAGE_FILESIZE /* for large relations */
|
||||
File mdfd_vfd; /* fd number in fd.c's pool */
|
||||
BlockNumber mdfd_segno; /* segment number, from 0 */
|
||||
#ifndef LET_OS_MANAGE_FILESIZE /* for large relations */
|
||||
struct _MdfdVec *mdfd_chain; /* next segment, or NULL */
|
||||
#endif
|
||||
} MdfdVec;
|
||||
@@ -69,7 +69,7 @@ static MemoryContext MdCxt; /* context for all md.c allocations */
|
||||
* we keep track of pending fsync operations: we need to remember all relation
|
||||
* segments that have been written since the last checkpoint, so that we can
|
||||
* fsync them down to disk before completing the next checkpoint. This hash
|
||||
* table remembers the pending operations. We use a hash table not because
|
||||
* table remembers the pending operations. We use a hash table not because
|
||||
* we want to look up individual operations, but simply as a convenient way
|
||||
* of eliminating duplicate requests.
|
||||
*
|
||||
@@ -80,8 +80,8 @@ static MemoryContext MdCxt; /* context for all md.c allocations */
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
RelFileNode rnode; /* the targeted relation */
|
||||
BlockNumber segno; /* which segment */
|
||||
RelFileNode rnode; /* the targeted relation */
|
||||
BlockNumber segno; /* which segment */
|
||||
} PendingOperationEntry;
|
||||
|
||||
static HTAB *pendingOpsTable = NULL;
|
||||
@@ -91,12 +91,13 @@ static HTAB *pendingOpsTable = NULL;
|
||||
static MdfdVec *mdopen(SMgrRelation reln, bool allowNotFound);
|
||||
static bool register_dirty_segment(SMgrRelation reln, MdfdVec *seg);
|
||||
static MdfdVec *_fdvec_alloc(void);
|
||||
|
||||
#ifndef LET_OS_MANAGE_FILESIZE
|
||||
static MdfdVec *_mdfd_openseg(SMgrRelation reln, BlockNumber segno,
|
||||
int oflags);
|
||||
int oflags);
|
||||
#endif
|
||||
static MdfdVec *_mdfd_getseg(SMgrRelation reln, BlockNumber blkno,
|
||||
bool allowNotFound);
|
||||
bool allowNotFound);
|
||||
static BlockNumber _mdnblocks(File file, Size blcksz);
|
||||
|
||||
|
||||
@@ -113,10 +114,10 @@ mdinit(void)
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
|
||||
/*
|
||||
* Create pending-operations hashtable if we need it. Currently,
|
||||
* we need it if we are standalone (not under a postmaster) OR
|
||||
* if we are a bootstrap-mode subprocess of a postmaster (that is,
|
||||
* a startup or bgwriter process).
|
||||
* Create pending-operations hashtable if we need it. Currently, we
|
||||
* need it if we are standalone (not under a postmaster) OR if we are
|
||||
* a bootstrap-mode subprocess of a postmaster (that is, a startup or
|
||||
* bgwriter process).
|
||||
*/
|
||||
if (!IsUnderPostmaster || IsBootstrapProcessingMode())
|
||||
{
|
||||
@@ -130,7 +131,7 @@ mdinit(void)
|
||||
pendingOpsTable = hash_create("Pending Ops Table",
|
||||
100L,
|
||||
&hash_ctl,
|
||||
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
|
||||
HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
|
||||
if (pendingOpsTable == NULL)
|
||||
ereport(FATAL,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
@@ -333,7 +334,7 @@ mdextend(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp)
|
||||
static MdfdVec *
|
||||
mdopen(SMgrRelation reln, bool allowNotFound)
|
||||
{
|
||||
MdfdVec *mdfd;
|
||||
MdfdVec *mdfd;
|
||||
char *path;
|
||||
File fd;
|
||||
|
||||
@@ -613,8 +614,7 @@ mdtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp)
|
||||
FileTruncate(v->mdfd_vfd, 0);
|
||||
FileUnlink(v->mdfd_vfd);
|
||||
v = v->mdfd_chain;
|
||||
Assert(ov != reln->md_fd); /* we never drop the 1st
|
||||
* segment */
|
||||
Assert(ov != reln->md_fd); /* we never drop the 1st segment */
|
||||
pfree(ov);
|
||||
}
|
||||
else if (priorblocks + ((BlockNumber) RELSEG_SIZE) > nblocks)
|
||||
@@ -714,8 +714,8 @@ mdsync(void)
|
||||
/*
|
||||
* If we are in the bgwriter, the sync had better include all fsync
|
||||
* requests that were queued by backends before the checkpoint REDO
|
||||
* point was determined. We go that a little better by accepting
|
||||
* all requests queued up to the point where we start fsync'ing.
|
||||
* point was determined. We go that a little better by accepting all
|
||||
* requests queued up to the point where we start fsync'ing.
|
||||
*/
|
||||
AbsorbFsyncRequests();
|
||||
|
||||
@@ -724,22 +724,22 @@ mdsync(void)
|
||||
{
|
||||
/*
|
||||
* If fsync is off then we don't have to bother opening the file
|
||||
* at all. (We delay checking until this point so that changing
|
||||
* at all. (We delay checking until this point so that changing
|
||||
* fsync on the fly behaves sensibly.)
|
||||
*/
|
||||
if (enableFsync)
|
||||
{
|
||||
SMgrRelation reln;
|
||||
MdfdVec *seg;
|
||||
MdfdVec *seg;
|
||||
|
||||
/*
|
||||
* Find or create an smgr hash entry for this relation.
|
||||
* This may seem a bit unclean -- md calling smgr? But it's
|
||||
* really the best solution. It ensures that the open file
|
||||
* reference isn't permanently leaked if we get an error here.
|
||||
* (You may say "but an unreferenced SMgrRelation is still a
|
||||
* leak!" Not really, because the only case in which a checkpoint
|
||||
* is done by a process that isn't about to shut down is in the
|
||||
* Find or create an smgr hash entry for this relation. This
|
||||
* may seem a bit unclean -- md calling smgr? But it's really
|
||||
* the best solution. It ensures that the open file reference
|
||||
* isn't permanently leaked if we get an error here. (You may
|
||||
* say "but an unreferenced SMgrRelation is still a leak!"
|
||||
* Not really, because the only case in which a checkpoint is
|
||||
* done by a process that isn't about to shut down is in the
|
||||
* bgwriter, and it will periodically do smgrcloseall(). This
|
||||
* fact justifies our not closing the reln in the success path
|
||||
* either, which is a good thing since in non-bgwriter cases
|
||||
@@ -750,11 +750,11 @@ mdsync(void)
|
||||
reln = smgropen(entry->rnode);
|
||||
|
||||
/*
|
||||
* It is possible that the relation has been dropped or truncated
|
||||
* since the fsync request was entered. Therefore, we have to
|
||||
* allow file-not-found errors. This applies both during
|
||||
* _mdfd_getseg() and during FileSync, since fd.c might have
|
||||
* closed the file behind our back.
|
||||
* It is possible that the relation has been dropped or
|
||||
* truncated since the fsync request was entered. Therefore,
|
||||
* we have to allow file-not-found errors. This applies both
|
||||
* during _mdfd_getseg() and during FileSync, since fd.c might
|
||||
* have closed the file behind our back.
|
||||
*/
|
||||
seg = _mdfd_getseg(reln,
|
||||
entry->segno * ((BlockNumber) RELSEG_SIZE),
|
||||
@@ -903,8 +903,7 @@ _mdfd_openseg(SMgrRelation reln, BlockNumber segno, int oflags)
|
||||
/* all done */
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif /* LET_OS_MANAGE_FILESIZE */
|
||||
#endif /* LET_OS_MANAGE_FILESIZE */
|
||||
|
||||
/*
|
||||
* _mdfd_getseg() -- Find the segment of the relation holding the
|
||||
@@ -915,6 +914,7 @@ static MdfdVec *
|
||||
_mdfd_getseg(SMgrRelation reln, BlockNumber blkno, bool allowNotFound)
|
||||
{
|
||||
MdfdVec *v = mdopen(reln, allowNotFound);
|
||||
|
||||
#ifndef LET_OS_MANAGE_FILESIZE
|
||||
BlockNumber segstogo;
|
||||
BlockNumber nextsegno;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.79 2004/08/29 04:12:50 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/smgr/smgr.c,v 1.80 2004/08/29 05:06:49 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -36,36 +36,36 @@
|
||||
*/
|
||||
typedef struct f_smgr
|
||||
{
|
||||
bool (*smgr_init) (void); /* may be NULL */
|
||||
bool (*smgr_init) (void); /* may be NULL */
|
||||
bool (*smgr_shutdown) (void); /* may be NULL */
|
||||
bool (*smgr_close) (SMgrRelation reln);
|
||||
bool (*smgr_create) (SMgrRelation reln, bool isRedo);
|
||||
bool (*smgr_unlink) (RelFileNode rnode, bool isRedo);
|
||||
bool (*smgr_extend) (SMgrRelation reln, BlockNumber blocknum,
|
||||
char *buffer, bool isTemp);
|
||||
char *buffer, bool isTemp);
|
||||
bool (*smgr_read) (SMgrRelation reln, BlockNumber blocknum,
|
||||
char *buffer);
|
||||
char *buffer);
|
||||
bool (*smgr_write) (SMgrRelation reln, BlockNumber blocknum,
|
||||
char *buffer, bool isTemp);
|
||||
char *buffer, bool isTemp);
|
||||
BlockNumber (*smgr_nblocks) (SMgrRelation reln);
|
||||
BlockNumber (*smgr_truncate) (SMgrRelation reln, BlockNumber nblocks,
|
||||
bool isTemp);
|
||||
bool isTemp);
|
||||
bool (*smgr_immedsync) (SMgrRelation reln);
|
||||
bool (*smgr_commit) (void); /* may be NULL */
|
||||
bool (*smgr_abort) (void); /* may be NULL */
|
||||
bool (*smgr_sync) (void); /* may be NULL */
|
||||
bool (*smgr_commit) (void); /* may be NULL */
|
||||
bool (*smgr_abort) (void); /* may be NULL */
|
||||
bool (*smgr_sync) (void); /* may be NULL */
|
||||
} f_smgr;
|
||||
|
||||
|
||||
static const f_smgr smgrsw[] = {
|
||||
/* magnetic disk */
|
||||
{mdinit, NULL, mdclose, mdcreate, mdunlink, mdextend,
|
||||
mdread, mdwrite, mdnblocks, mdtruncate, mdimmedsync,
|
||||
NULL, NULL, mdsync
|
||||
mdread, mdwrite, mdnblocks, mdtruncate, mdimmedsync,
|
||||
NULL, NULL, mdsync
|
||||
}
|
||||
};
|
||||
|
||||
static const int NSmgr = lengthof(smgrsw);
|
||||
static const int NSmgr = lengthof(smgrsw);
|
||||
|
||||
|
||||
/*
|
||||
@@ -119,20 +119,20 @@ static PendingRelDelete *pendingDeletes = NULL; /* head of linked list */
|
||||
|
||||
typedef struct xl_smgr_create
|
||||
{
|
||||
RelFileNode rnode;
|
||||
RelFileNode rnode;
|
||||
} xl_smgr_create;
|
||||
|
||||
typedef struct xl_smgr_truncate
|
||||
{
|
||||
BlockNumber blkno;
|
||||
RelFileNode rnode;
|
||||
BlockNumber blkno;
|
||||
RelFileNode rnode;
|
||||
} xl_smgr_truncate;
|
||||
|
||||
|
||||
/* local function prototypes */
|
||||
static void smgrshutdown(int code, Datum arg);
|
||||
static void smgr_internal_unlink(RelFileNode rnode, int which,
|
||||
bool isTemp, bool isRedo);
|
||||
bool isTemp, bool isRedo);
|
||||
|
||||
|
||||
/*
|
||||
@@ -151,7 +151,7 @@ smgrinit(void)
|
||||
{
|
||||
if (smgrsw[i].smgr_init)
|
||||
{
|
||||
if (! (*(smgrsw[i].smgr_init)) ())
|
||||
if (!(*(smgrsw[i].smgr_init)) ())
|
||||
elog(FATAL, "smgr initialization failed on %s: %m",
|
||||
DatumGetCString(DirectFunctionCall1(smgrout,
|
||||
Int16GetDatum(i))));
|
||||
@@ -171,7 +171,7 @@ smgrshutdown(int code, Datum arg)
|
||||
{
|
||||
if (smgrsw[i].smgr_shutdown)
|
||||
{
|
||||
if (! (*(smgrsw[i].smgr_shutdown)) ())
|
||||
if (!(*(smgrsw[i].smgr_shutdown)) ())
|
||||
elog(FATAL, "smgr shutdown failed on %s: %m",
|
||||
DatumGetCString(DirectFunctionCall1(smgrout,
|
||||
Int16GetDatum(i))));
|
||||
@@ -187,7 +187,7 @@ smgrshutdown(int code, Datum arg)
|
||||
SMgrRelation
|
||||
smgropen(RelFileNode rnode)
|
||||
{
|
||||
SMgrRelation reln;
|
||||
SMgrRelation reln;
|
||||
bool found;
|
||||
|
||||
if (SMgrRelationHash == NULL)
|
||||
@@ -233,7 +233,7 @@ smgropen(RelFileNode rnode)
|
||||
void
|
||||
smgrclose(SMgrRelation reln)
|
||||
{
|
||||
if (! (*(smgrsw[reln->smgr_which].smgr_close)) (reln))
|
||||
if (!(*(smgrsw[reln->smgr_which].smgr_close)) (reln))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not close relation %u/%u/%u: %m",
|
||||
@@ -265,9 +265,7 @@ smgrcloseall(void)
|
||||
hash_seq_init(&status, SMgrRelationHash);
|
||||
|
||||
while ((reln = (SMgrRelation) hash_seq_search(&status)) != NULL)
|
||||
{
|
||||
smgrclose(reln);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -283,7 +281,7 @@ smgrcloseall(void)
|
||||
void
|
||||
smgrclosenode(RelFileNode rnode)
|
||||
{
|
||||
SMgrRelation reln;
|
||||
SMgrRelation reln;
|
||||
|
||||
/* Nothing to do if hashtable not set up */
|
||||
if (SMgrRelationHash == NULL)
|
||||
@@ -310,9 +308,9 @@ smgrclosenode(RelFileNode rnode)
|
||||
void
|
||||
smgrcreate(SMgrRelation reln, bool isTemp, bool isRedo)
|
||||
{
|
||||
XLogRecPtr lsn;
|
||||
XLogRecData rdata;
|
||||
xl_smgr_create xlrec;
|
||||
XLogRecPtr lsn;
|
||||
XLogRecData rdata;
|
||||
xl_smgr_create xlrec;
|
||||
PendingRelDelete *pending;
|
||||
|
||||
/*
|
||||
@@ -320,15 +318,16 @@ smgrcreate(SMgrRelation reln, bool isTemp, bool isRedo)
|
||||
* database, so create a per-database subdirectory if needed.
|
||||
*
|
||||
* XXX this is a fairly ugly violation of module layering, but this seems
|
||||
* to be the best place to put the check. Maybe TablespaceCreateDbspace
|
||||
* should be here and not in commands/tablespace.c? But that would imply
|
||||
* importing a lot of stuff that smgr.c oughtn't know, either.
|
||||
* to be the best place to put the check. Maybe
|
||||
* TablespaceCreateDbspace should be here and not in
|
||||
* commands/tablespace.c? But that would imply importing a lot of
|
||||
* stuff that smgr.c oughtn't know, either.
|
||||
*/
|
||||
TablespaceCreateDbspace(reln->smgr_rnode.spcNode,
|
||||
reln->smgr_rnode.dbNode,
|
||||
isRedo);
|
||||
|
||||
if (! (*(smgrsw[reln->smgr_which].smgr_create)) (reln, isRedo))
|
||||
if (!(*(smgrsw[reln->smgr_which].smgr_create)) (reln, isRedo))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not create relation %u/%u/%u: %m",
|
||||
@@ -340,9 +339,10 @@ smgrcreate(SMgrRelation reln, bool isTemp, bool isRedo)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Make a non-transactional XLOG entry showing the file creation. It's
|
||||
* non-transactional because we should replay it whether the transaction
|
||||
* commits or not; if not, the file will be dropped at abort time.
|
||||
* Make a non-transactional XLOG entry showing the file creation.
|
||||
* It's non-transactional because we should replay it whether the
|
||||
* transaction commits or not; if not, the file will be dropped at
|
||||
* abort time.
|
||||
*/
|
||||
xlrec.rnode = reln->smgr_rnode;
|
||||
|
||||
@@ -417,7 +417,7 @@ smgrscheduleunlink(SMgrRelation reln, bool isTemp)
|
||||
void
|
||||
smgrdounlink(SMgrRelation reln, bool isTemp, bool isRedo)
|
||||
{
|
||||
RelFileNode rnode = reln->smgr_rnode;
|
||||
RelFileNode rnode = reln->smgr_rnode;
|
||||
int which = reln->smgr_which;
|
||||
|
||||
/* Close the file and throw away the hashtable entry */
|
||||
@@ -433,24 +433,25 @@ static void
|
||||
smgr_internal_unlink(RelFileNode rnode, int which, bool isTemp, bool isRedo)
|
||||
{
|
||||
/*
|
||||
* Get rid of any leftover buffers for the rel (shouldn't be any in the
|
||||
* commit case, but there can be in the abort case).
|
||||
* Get rid of any leftover buffers for the rel (shouldn't be any in
|
||||
* the commit case, but there can be in the abort case).
|
||||
*/
|
||||
DropRelFileNodeBuffers(rnode, isTemp, 0);
|
||||
|
||||
/*
|
||||
* Tell the free space map to forget this relation. It won't be accessed
|
||||
* any more anyway, but we may as well recycle the map space quickly.
|
||||
* Tell the free space map to forget this relation. It won't be
|
||||
* accessed any more anyway, but we may as well recycle the map space
|
||||
* quickly.
|
||||
*/
|
||||
FreeSpaceMapForgetRel(&rnode);
|
||||
|
||||
/*
|
||||
* And delete the physical files.
|
||||
*
|
||||
* Note: we treat deletion failure as a WARNING, not an error,
|
||||
* because we've already decided to commit or abort the current xact.
|
||||
* Note: we treat deletion failure as a WARNING, not an error, because
|
||||
* we've already decided to commit or abort the current xact.
|
||||
*/
|
||||
if (! (*(smgrsw[which].smgr_unlink)) (rnode, isRedo))
|
||||
if (!(*(smgrsw[which].smgr_unlink)) (rnode, isRedo))
|
||||
ereport(WARNING,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not unlink relation %u/%u/%u: %m",
|
||||
@@ -470,8 +471,8 @@ smgr_internal_unlink(RelFileNode rnode, int which, bool isTemp, bool isRedo)
|
||||
void
|
||||
smgrextend(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp)
|
||||
{
|
||||
if (! (*(smgrsw[reln->smgr_which].smgr_extend)) (reln, blocknum, buffer,
|
||||
isTemp))
|
||||
if (!(*(smgrsw[reln->smgr_which].smgr_extend)) (reln, blocknum, buffer,
|
||||
isTemp))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not extend relation %u/%u/%u: %m",
|
||||
@@ -492,14 +493,14 @@ smgrextend(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp)
|
||||
void
|
||||
smgrread(SMgrRelation reln, BlockNumber blocknum, char *buffer)
|
||||
{
|
||||
if (! (*(smgrsw[reln->smgr_which].smgr_read)) (reln, blocknum, buffer))
|
||||
if (!(*(smgrsw[reln->smgr_which].smgr_read)) (reln, blocknum, buffer))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not read block %u of relation %u/%u/%u: %m",
|
||||
blocknum,
|
||||
reln->smgr_rnode.spcNode,
|
||||
reln->smgr_rnode.dbNode,
|
||||
reln->smgr_rnode.relNode)));
|
||||
errmsg("could not read block %u of relation %u/%u/%u: %m",
|
||||
blocknum,
|
||||
reln->smgr_rnode.spcNode,
|
||||
reln->smgr_rnode.dbNode,
|
||||
reln->smgr_rnode.relNode)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -516,15 +517,15 @@ smgrread(SMgrRelation reln, BlockNumber blocknum, char *buffer)
|
||||
void
|
||||
smgrwrite(SMgrRelation reln, BlockNumber blocknum, char *buffer, bool isTemp)
|
||||
{
|
||||
if (! (*(smgrsw[reln->smgr_which].smgr_write)) (reln, blocknum, buffer,
|
||||
isTemp))
|
||||
if (!(*(smgrsw[reln->smgr_which].smgr_write)) (reln, blocknum, buffer,
|
||||
isTemp))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not write block %u of relation %u/%u/%u: %m",
|
||||
blocknum,
|
||||
reln->smgr_rnode.spcNode,
|
||||
reln->smgr_rnode.dbNode,
|
||||
reln->smgr_rnode.relNode)));
|
||||
errmsg("could not write block %u of relation %u/%u/%u: %m",
|
||||
blocknum,
|
||||
reln->smgr_rnode.spcNode,
|
||||
reln->smgr_rnode.dbNode,
|
||||
reln->smgr_rnode.relNode)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -571,9 +572,9 @@ smgrtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp)
|
||||
BlockNumber newblks;
|
||||
|
||||
/*
|
||||
* Tell the free space map to forget anything it may have stored
|
||||
* for the about-to-be-deleted blocks. We want to be sure it
|
||||
* won't return bogus block numbers later on.
|
||||
* Tell the free space map to forget anything it may have stored for
|
||||
* the about-to-be-deleted blocks. We want to be sure it won't return
|
||||
* bogus block numbers later on.
|
||||
*/
|
||||
FreeSpaceMapTruncateRel(&reln->smgr_rnode, nblocks);
|
||||
|
||||
@@ -583,22 +584,22 @@ smgrtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp)
|
||||
if (newblks == InvalidBlockNumber)
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not truncate relation %u/%u/%u to %u blocks: %m",
|
||||
reln->smgr_rnode.spcNode,
|
||||
reln->smgr_rnode.dbNode,
|
||||
reln->smgr_rnode.relNode,
|
||||
nblocks)));
|
||||
errmsg("could not truncate relation %u/%u/%u to %u blocks: %m",
|
||||
reln->smgr_rnode.spcNode,
|
||||
reln->smgr_rnode.dbNode,
|
||||
reln->smgr_rnode.relNode,
|
||||
nblocks)));
|
||||
|
||||
if (!isTemp)
|
||||
{
|
||||
/*
|
||||
* Make a non-transactional XLOG entry showing the file truncation.
|
||||
* It's non-transactional because we should replay it whether the
|
||||
* transaction commits or not; the underlying file change is certainly
|
||||
* not reversible.
|
||||
* Make a non-transactional XLOG entry showing the file
|
||||
* truncation. It's non-transactional because we should replay it
|
||||
* whether the transaction commits or not; the underlying file
|
||||
* change is certainly not reversible.
|
||||
*/
|
||||
XLogRecPtr lsn;
|
||||
XLogRecData rdata;
|
||||
XLogRecPtr lsn;
|
||||
XLogRecData rdata;
|
||||
xl_smgr_truncate xlrec;
|
||||
|
||||
xlrec.blkno = newblks;
|
||||
@@ -637,7 +638,7 @@ smgrtruncate(SMgrRelation reln, BlockNumber nblocks, bool isTemp)
|
||||
void
|
||||
smgrimmedsync(SMgrRelation reln)
|
||||
{
|
||||
if (! (*(smgrsw[reln->smgr_which].smgr_immedsync)) (reln))
|
||||
if (!(*(smgrsw[reln->smgr_which].smgr_immedsync)) (reln))
|
||||
ereport(ERROR,
|
||||
(errcode_for_file_access(),
|
||||
errmsg("could not sync relation %u/%u/%u: %m",
|
||||
@@ -774,7 +775,7 @@ smgrcommit(void)
|
||||
{
|
||||
if (smgrsw[i].smgr_commit)
|
||||
{
|
||||
if (! (*(smgrsw[i].smgr_commit)) ())
|
||||
if (!(*(smgrsw[i].smgr_commit)) ())
|
||||
elog(ERROR, "transaction commit failed on %s: %m",
|
||||
DatumGetCString(DirectFunctionCall1(smgrout,
|
||||
Int16GetDatum(i))));
|
||||
@@ -794,7 +795,7 @@ smgrabort(void)
|
||||
{
|
||||
if (smgrsw[i].smgr_abort)
|
||||
{
|
||||
if (! (*(smgrsw[i].smgr_abort)) ())
|
||||
if (!(*(smgrsw[i].smgr_abort)) ())
|
||||
elog(ERROR, "transaction abort failed on %s: %m",
|
||||
DatumGetCString(DirectFunctionCall1(smgrout,
|
||||
Int16GetDatum(i))));
|
||||
@@ -814,7 +815,7 @@ smgrsync(void)
|
||||
{
|
||||
if (smgrsw[i].smgr_sync)
|
||||
{
|
||||
if (! (*(smgrsw[i].smgr_sync)) ())
|
||||
if (!(*(smgrsw[i].smgr_sync)) ())
|
||||
elog(ERROR, "storage sync failed on %s: %m",
|
||||
DatumGetCString(DirectFunctionCall1(smgrout,
|
||||
Int16GetDatum(i))));
|
||||
@@ -846,8 +847,8 @@ smgr_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
|
||||
/*
|
||||
* First, force bufmgr to drop any buffers it has for the to-be-
|
||||
* truncated blocks. We must do this, else subsequent XLogReadBuffer
|
||||
* operations will not re-extend the file properly.
|
||||
* truncated blocks. We must do this, else subsequent
|
||||
* XLogReadBuffer operations will not re-extend the file properly.
|
||||
*/
|
||||
DropRelFileNodeBuffers(xlrec->rnode, false, xlrec->blkno);
|
||||
|
||||
@@ -862,7 +863,7 @@ smgr_redo(XLogRecPtr lsn, XLogRecord *record)
|
||||
|
||||
/* Do the truncation */
|
||||
newblks = (*(smgrsw[reln->smgr_which].smgr_truncate)) (reln,
|
||||
xlrec->blkno,
|
||||
xlrec->blkno,
|
||||
false);
|
||||
if (newblks == InvalidBlockNumber)
|
||||
ereport(WARNING,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/storage/smgr/smgrtype.c,v 1.24 2004/08/29 04:12:50 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/storage/smgr/smgrtype.c,v 1.25 2004/08/29 05:06:49 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
typedef struct smgrid
|
||||
{
|
||||
const char *smgr_name;
|
||||
const char *smgr_name;
|
||||
} smgrid;
|
||||
|
||||
/*
|
||||
@@ -29,7 +29,7 @@ static const smgrid StorageManager[] = {
|
||||
{"magnetic disk"}
|
||||
};
|
||||
|
||||
static const int NStorageManagers = lengthof(StorageManager);
|
||||
static const int NStorageManagers = lengthof(StorageManager);
|
||||
|
||||
|
||||
Datum
|
||||
|
||||
Reference in New Issue
Block a user