diff options
Diffstat (limited to 'src/backend/storage')
-rw-r--r-- | src/backend/storage/buffer/buf_init.c | 4 | ||||
-rw-r--r-- | src/backend/storage/buffer/bufmgr.c | 292 | ||||
-rw-r--r-- | src/backend/storage/buffer/localbuf.c | 129 | ||||
-rw-r--r-- | src/backend/storage/file/fd.c | 140 | ||||
-rw-r--r-- | src/backend/storage/smgr/md.c | 166 | ||||
-rw-r--r-- | src/backend/storage/smgr/mm.c | 35 | ||||
-rw-r--r-- | src/backend/storage/smgr/smgr.c | 119 |
7 files changed, 201 insertions, 684 deletions
diff --git a/src/backend/storage/buffer/buf_init.c b/src/backend/storage/buffer/buf_init.c index 6132b732f86..a8c56562f2d 100644 --- a/src/backend/storage/buffer/buf_init.c +++ b/src/backend/storage/buffer/buf_init.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.49 2002/06/20 20:29:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/buf_init.c,v 1.50 2002/08/06 02:36:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -258,7 +258,7 @@ ShutdownBufferPoolAccess(void) /* Release any buffer context locks we are holding */ UnlockBuffers(); /* Release any buffer reference counts we are holding */ - ResetBufferPool(false); + AtEOXact_Buffers(false); } /* ----------------------------------------------------- diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index b2c19e99f47..1ca7af3b775 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.127 2002/07/02 05:47:37 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/bufmgr.c,v 1.128 2002/08/06 02:36:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,16 +57,9 @@ #include "pgstat.h" #define BufferGetLSN(bufHdr) \ - (*((XLogRecPtr*)MAKE_PTR((bufHdr)->data))) + (*((XLogRecPtr*) MAKE_PTR((bufHdr)->data))) -extern long int ReadBufferCount; -extern long int ReadLocalBufferCount; -extern long int BufferHitCount; -extern long int LocalBufferHitCount; -extern long int BufferFlushCount; -extern long int LocalBufferFlushCount; - static void WaitIO(BufferDesc *buf); static void StartBufferIO(BufferDesc *buf, bool forInput); static void TerminateBufferIO(BufferDesc *buf); @@ -82,16 +75,12 @@ static Buffer ReadBufferInternal(Relation reln, BlockNumber blockNum, bool bufferLockHeld); static BufferDesc *BufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr); -static int ReleaseBufferWithBufferLock(Buffer buffer); static int BufferReplace(BufferDesc *bufHdr); #ifdef NOT_USED void PrintBufferDescs(void); #endif static void write_buffer(Buffer buffer, bool unpin); -static void drop_relfilenode_buffers(RelFileNode rnode, - bool do_local, bool do_both); -static int release_buffer(Buffer buffer, bool havelock); /* * ReadBuffer -- returns a buffer containing the requested @@ -140,7 +129,7 @@ ReadBufferInternal(Relation reln, BlockNumber blockNum, bool isLocalBuf; isExtend = (blockNum == P_NEW); - isLocalBuf = reln->rd_myxactonly; + isLocalBuf = reln->rd_istemp; if (isLocalBuf) { @@ -684,10 +673,10 @@ ReleaseAndReadBuffer(Buffer buffer, /* * BufferSync -- Write all dirty buffers in the pool. * - * This is called at checkpoint time and write out all dirty buffers. + * This is called at checkpoint time and writes out all dirty shared buffers. */ void -BufferSync() +BufferSync(void) { int i; BufferDesc *bufHdr; @@ -780,8 +769,7 @@ BufferSync() status = smgrblindwrt(DEFAULT_SMGR, bufHdr->tag.rnode, bufHdr->tag.blockNum, - (char *) MAKE_PTR(bufHdr->data), - true); /* must fsync */ + (char *) MAKE_PTR(bufHdr->data)); } else { @@ -908,19 +896,16 @@ ResetBufferUsage(void) NDirectFileWrite = 0; } -/* ---------------------------------------------- - * ResetBufferPool - * - * This routine is supposed to be called when a transaction aborts. - * It will release all the buffer pins held by the transaction. - * Currently, we also call it during commit if BufferPoolCheckLeak - * detected a problem --- in that case, isCommit is TRUE, and we - * only clean up buffer pin counts. +/* + * AtEOXact_Buffers - clean up at end of transaction. * - * ---------------------------------------------- + * During abort, we need to release any buffer pins we're holding + * (this cleans up in case elog interrupted a routine that pins a + * buffer). During commit, we shouldn't need to do that, but check + * anyway to see if anyone leaked a buffer reference count. */ void -ResetBufferPool(bool isCommit) +AtEOXact_Buffers(bool isCommit) { int i; @@ -928,7 +913,16 @@ ResetBufferPool(bool isCommit) { if (PrivateRefCount[i] != 0) { - BufferDesc *buf = &BufferDescriptors[i]; + BufferDesc *buf = &(BufferDescriptors[i]); + + if (isCommit) + elog(WARNING, + "Buffer Leak: [%03d] (freeNext=%d, freePrev=%d, " + "rel=%u/%u, blockNum=%u, flags=0x%x, refcount=%d %ld)", + i, buf->freeNext, buf->freePrev, + buf->tag.rnode.tblNode, buf->tag.rnode.relNode, + buf->tag.blockNum, buf->flags, + buf->refcount, PrivateRefCount[i]); PrivateRefCount[i] = 1; /* make sure we release shared pin */ LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); @@ -938,48 +932,15 @@ ResetBufferPool(bool isCommit) } } - ResetLocalBufferPool(); - - if (!isCommit) - smgrabort(); + AtEOXact_LocalBuffers(isCommit); } /* - * BufferPoolCheckLeak - * - * check if there is buffer leak - */ -bool -BufferPoolCheckLeak(void) -{ - int i; - bool result = false; - - for (i = 0; i < NBuffers; i++) - { - if (PrivateRefCount[i] != 0) - { - BufferDesc *buf = &(BufferDescriptors[i]); - - elog(WARNING, - "Buffer Leak: [%03d] (freeNext=%d, freePrev=%d, \ -rel=%u/%u, blockNum=%u, flags=0x%x, refcount=%d %ld)", - i, buf->freeNext, buf->freePrev, - buf->tag.rnode.tblNode, buf->tag.rnode.relNode, - buf->tag.blockNum, buf->flags, - buf->refcount, PrivateRefCount[i]); - result = true; - } - } - return result; -} - -/* ------------------------------------------------ * FlushBufferPool * - * Flush all dirty blocks in buffer pool to disk - * at the checkpoint time - * ------------------------------------------------ + * Flush all dirty blocks in buffer pool to disk at the checkpoint time. + * Local relations do not participate in checkpoints, so they don't need to be + * flushed. */ void FlushBufferPool(void) @@ -989,16 +950,13 @@ FlushBufferPool(void) } /* - * At the commit time we have to flush local buffer pool only + * Do whatever is needed to prepare for commit at the bufmgr and smgr levels */ void BufmgrCommit(void) { - LocalBufferSync(); + /* Nothing to do in bufmgr anymore... */ - /* - * All files created in current transaction will be fsync-ed - */ smgrcommit(); } @@ -1051,15 +1009,15 @@ BufferReplace(BufferDesc *bufHdr) if (reln != (Relation) NULL) { - status = smgrwrite(DEFAULT_SMGR, reln, bufHdr->tag.blockNum, + status = smgrwrite(DEFAULT_SMGR, reln, + bufHdr->tag.blockNum, (char *) MAKE_PTR(bufHdr->data)); } else { status = smgrblindwrt(DEFAULT_SMGR, bufHdr->tag.rnode, bufHdr->tag.blockNum, - (char *) MAKE_PTR(bufHdr->data), - false); /* no fsync */ + (char *) MAKE_PTR(bufHdr->data)); } /* drop relcache refcnt incremented by RelationNodeCacheGetRelation */ @@ -1091,31 +1049,55 @@ RelationGetNumberOfBlocks(Relation relation) { /* * relation->rd_nblocks should be accurate already if the relation is - * myxactonly. (XXX how safe is that really?) Don't call smgr on a - * view, either. + * new or temp, because no one else should be modifying it. Otherwise + * we need to ask the smgr for the current physical file length. + * + * Don't call smgr on a view, either. */ if (relation->rd_rel->relkind == RELKIND_VIEW) relation->rd_nblocks = 0; - else if (!relation->rd_myxactonly) + else if (!relation->rd_isnew && !relation->rd_istemp) relation->rd_nblocks = smgrnblocks(DEFAULT_SMGR, relation); return relation->rd_nblocks; } -/* - * drop_relfilenode_buffers -- common functionality for - * DropRelationBuffers and - * DropRelFileNodeBuffers +/* --------------------------------------------------------------------- + * DropRelationBuffers * - * XXX currently it sequentially searches the buffer pool, should be - * changed to more clever ways of searching. + * This function removes all the buffered pages for a relation + * from the buffer pool. Dirty pages are simply dropped, without + * bothering to write them out first. This is NOT rollback-able, + * and so should be used only with extreme caution! + * + * We assume that the caller holds an exclusive lock on the relation, + * which should assure that no new buffers will be acquired for the rel + * meanwhile. + * -------------------------------------------------------------------- */ -static void -drop_relfilenode_buffers(RelFileNode rnode, bool do_local, bool do_both) +void +DropRelationBuffers(Relation rel) +{ + DropRelFileNodeBuffers(rel->rd_node, rel->rd_istemp); +} + +/* --------------------------------------------------------------------- + * DropRelFileNodeBuffers + * + * This is the same as DropRelationBuffers, except that the target + * relation is specified by RelFileNode and temp status. + * + * This is NOT rollback-able. One legitimate use is to clear the + * buffer cache of buffers for a relation that is being deleted + * during transaction abort. + * -------------------------------------------------------------------- + */ +void +DropRelFileNodeBuffers(RelFileNode rnode, bool istemp) { int i; BufferDesc *bufHdr; - if (do_local) + if (istemp) { for (i = 0; i < NLocBuffer; i++) { @@ -1128,8 +1110,7 @@ drop_relfilenode_buffers(RelFileNode rnode, bool do_local, bool do_both) bufHdr->tag.rnode.relNode = InvalidOid; } } - if (!do_both) - return; + return; } LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); @@ -1160,18 +1141,19 @@ recheck: bufHdr->cntxDirty = false; /* - * Release any refcount we may have. - * - * This is very probably dead code, and if it isn't then it's - * probably wrong. I added the Assert to find out --- tgl - * 11/99. + * Release any refcount we may have. If someone else has a + * pin on the buffer, we got trouble. */ if (!(bufHdr->flags & BM_FREE)) { - /* Assert checks that buffer will actually get freed! */ - Assert(PrivateRefCount[i - 1] == 1 && - bufHdr->refcount == 1); - ReleaseBufferWithBufferLock(i); + /* the sole pin should be ours */ + if (bufHdr->refcount != 1 || PrivateRefCount[i - 1] == 0) + elog(FATAL, "DropRelFileNodeBuffers: block %u is referenced (private %ld, global %d)", + bufHdr->tag.blockNum, + PrivateRefCount[i - 1], bufHdr->refcount); + /* Make sure it will be released */ + PrivateRefCount[i - 1] = 1; + UnpinBuffer(bufHdr); } /* @@ -1185,43 +1167,6 @@ recheck: } /* --------------------------------------------------------------------- - * DropRelationBuffers - * - * This function removes all the buffered pages for a relation - * from the buffer pool. Dirty pages are simply dropped, without - * bothering to write them out first. This is NOT rollback-able, - * and so should be used only with extreme caution! - * - * We assume that the caller holds an exclusive lock on the relation, - * which should assure that no new buffers will be acquired for the rel - * meanwhile. - * -------------------------------------------------------------------- - */ -void -DropRelationBuffers(Relation rel) -{ - drop_relfilenode_buffers(rel->rd_node, rel->rd_myxactonly, false); -} - -/* --------------------------------------------------------------------- - * DropRelFileNodeBuffers - * - * This is the same as DropRelationBuffers, except that the target - * relation is specified by RelFileNode. - * - * This is NOT rollback-able. One legitimate use is to clear the - * buffer cache of buffers for a relation that is being deleted - * during transaction abort. - * -------------------------------------------------------------------- - */ -void -DropRelFileNodeBuffers(RelFileNode rnode) -{ - /* We have to search both local and shared buffers... */ - drop_relfilenode_buffers(rnode, true, true); -} - -/* --------------------------------------------------------------------- * DropBuffers * * This function removes all the buffers in the buffer cache for a @@ -1296,7 +1241,7 @@ recheck: */ #ifdef NOT_USED void -PrintBufferDescs() +PrintBufferDescs(void) { int i; BufferDesc *buf = BufferDescriptors; @@ -1331,7 +1276,7 @@ blockNum=%u, flags=0x%x, refcount=%d %ld)", #ifdef NOT_USED void -PrintPinnedBufs() +PrintPinnedBufs(void) { int i; BufferDesc *buf = BufferDescriptors; @@ -1351,33 +1296,6 @@ blockNum=%u, flags=0x%x, refcount=%d %ld)", } #endif -/* - * BufferPoolBlowaway - * - * this routine is solely for the purpose of experiments -- sometimes - * you may want to blowaway whatever is left from the past in buffer - * pool and start measuring some performance with a clean empty buffer - * pool. - */ -#ifdef NOT_USED -void -BufferPoolBlowaway() -{ - int i; - - BufferSync(); - for (i = 1; i <= NBuffers; i++) - { - if (BufferIsValid(i)) - { - while (BufferIsValid(i)) - ReleaseBuffer(i); - } - BufTableDelete(&BufferDescriptors[i - 1]); - } -} -#endif - /* --------------------------------------------------------------------- * FlushRelationBuffers * @@ -1428,7 +1346,7 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock) XLogRecPtr recptr; int status; - if (rel->rd_myxactonly) + if (rel->rd_istemp) { for (i = 0; i < NLocBuffer; i++) { @@ -1544,12 +1462,14 @@ FlushRelationBuffers(Relation rel, BlockNumber firstDelBlock) return 0; } +#undef ReleaseBuffer + /* - * release_buffer -- common functionality for - * ReleaseBuffer and ReleaseBufferWithBufferLock + * ReleaseBuffer -- remove the pin on a buffer without + * marking it dirty. */ -static int -release_buffer(Buffer buffer, bool havelock) +int +ReleaseBuffer(Buffer buffer) { BufferDesc *bufHdr; @@ -1570,41 +1490,14 @@ release_buffer(Buffer buffer, bool havelock) PrivateRefCount[buffer - 1]--; else { - if (!havelock) - LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); - + LWLockAcquire(BufMgrLock, LW_EXCLUSIVE); UnpinBuffer(bufHdr); - - if (!havelock) - LWLockRelease(BufMgrLock); + LWLockRelease(BufMgrLock); } return STATUS_OK; } -#undef ReleaseBuffer - -/* - * ReleaseBuffer -- remove the pin on a buffer without - * marking it dirty. - */ -int -ReleaseBuffer(Buffer buffer) -{ - return release_buffer(buffer, false); -} - -/* - * ReleaseBufferWithBufferLock - * Same as ReleaseBuffer except we hold the bufmgr lock - */ -static int -ReleaseBufferWithBufferLock(Buffer buffer) -{ - return release_buffer(buffer, true); -} - - #ifdef NOT_USED void IncrBufferRefCount_Debug(char *file, int line, Buffer buffer) @@ -1847,10 +1740,13 @@ SetBufferCommitInfoNeedsSave(Buffer buffer) BufferDesc *bufHdr; if (BufferIsLocal(buffer)) + { + WriteLocalBuffer(buffer, false); return; + } if (BAD_BUFFER_ID(buffer)) - return; + elog(ERROR, "SetBufferCommitInfoNeedsSave: bad buffer %d", buffer); bufHdr = &BufferDescriptors[buffer - 1]; diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index d5edc570b6e..50168c8b306 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -1,48 +1,37 @@ /*------------------------------------------------------------------------- * * localbuf.c - * local buffer manager. Fast buffer manager for temporary tables - * or special cases when the operation is not visible to other backends. - * - * When a relation is being created, the descriptor will have rd_islocal - * set to indicate that the local buffer manager should be used. During - * the same transaction the relation is being created, any inserts or - * selects from the newly created relation will use the local buffer - * pool. rd_islocal is reset at the end of a transaction (commit/abort). - * This is useful for queries like SELECT INTO TABLE and create index. + * local buffer manager. Fast buffer manager for temporary tables, + * which never need to be WAL-logged or checkpointed, etc. * * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994-5, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.44 2002/06/20 20:29:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/buffer/localbuf.c,v 1.45 2002/08/06 02:36:34 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" -#include <sys/types.h> -#include <sys/file.h> -#include <math.h> -#include <signal.h> - -#include "executor/execdebug.h" #include "storage/buf_internals.h" #include "storage/bufmgr.h" #include "storage/smgr.h" #include "utils/relcache.h" -extern long int LocalBufferFlushCount; +/*#define LBDEBUG*/ + +/* should be a GUC parameter some day */ int NLocBuffer = 64; + BufferDesc *LocalBufferDescriptors = NULL; Block *LocalBufferBlockPointers = NULL; long *LocalRefCount = NULL; static int nextFreeLocalBuf = 0; -/*#define LBDEBUG*/ /* * LocalBufferAlloc - @@ -61,11 +50,11 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) reln->rd_node.relNode && LocalBufferDescriptors[i].tag.blockNum == blockNum) { - #ifdef LBDEBUG fprintf(stderr, "LB ALLOC (%u,%d) %d\n", RelationGetRelid(reln), blockNum, -i - 1); #endif + LocalRefCount[i]++; *foundPtr = TRUE; return &LocalBufferDescriptors[i]; @@ -94,14 +83,17 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) elog(ERROR, "no empty local buffer."); /* - * this buffer is not referenced but it might still be dirty (the last - * transaction to touch it doesn't need its contents but has not - * flushed it). if that's the case, write it out before reusing it! + * this buffer is not referenced but it might still be dirty. + * if that's the case, write it out before reusing it! */ if (bufHdr->flags & BM_DIRTY || bufHdr->cntxDirty) { Relation bufrel = RelationNodeCacheGetRelation(bufHdr->tag.rnode); + /* + * The relcache is not supposed to throw away temp rels, so this + * should always succeed. + */ Assert(bufrel != NULL); /* flush this page */ @@ -114,25 +106,18 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) } /* - * it's all ours now. - * - * We need not in tblNode currently but will in future I think, when - * we'll give up rel->rd_fd to fmgr cache. - */ - bufHdr->tag.rnode = reln->rd_node; - bufHdr->tag.blockNum = blockNum; - bufHdr->flags &= ~BM_DIRTY; - bufHdr->cntxDirty = false; - - /* * lazy memory allocation: allocate space on first use of a buffer. + * + * Note this path cannot be taken for a buffer that was previously + * in use, so it's okay to do it (and possibly error out) before + * marking the buffer as valid. */ if (bufHdr->data == (SHMEM_OFFSET) 0) { char *data = (char *) malloc(BLCKSZ); if (data == NULL) - elog(FATAL, "Out of memory in LocalBufferAlloc"); + elog(ERROR, "Out of memory in LocalBufferAlloc"); /* * This is a bit of a hack: bufHdr->data needs to be a shmem @@ -147,13 +132,24 @@ LocalBufferAlloc(Relation reln, BlockNumber blockNum, bool *foundPtr) LocalBufferBlockPointers[-(bufHdr->buf_id + 2)] = (Block) data; } + /* + * it's all ours now. + * + * We need not in tblNode currently but will in future I think, when + * we'll give up rel->rd_fd to fmgr cache. + */ + bufHdr->tag.rnode = reln->rd_node; + bufHdr->tag.blockNum = blockNum; + bufHdr->flags &= ~BM_DIRTY; + bufHdr->cntxDirty = false; + *foundPtr = FALSE; return bufHdr; } /* * WriteLocalBuffer - - * writes out a local buffer + * writes out a local buffer (actually, just marks it dirty) */ void WriteLocalBuffer(Buffer buffer, bool release) @@ -180,7 +176,7 @@ WriteLocalBuffer(Buffer buffer, bool release) * InitLocalBuffer - * init the local buffer cache. Since most queries (esp. multi-user ones) * don't involve local buffers, we delay allocating actual memory for the - * buffer until we need it. + * buffers until we need them; just make the buffer headers here. */ void InitLocalBuffer(void) @@ -211,65 +207,30 @@ InitLocalBuffer(void) } /* - * LocalBufferSync - * - * Flush all dirty buffers in the local buffer cache at commit time. - * Since the buffer cache is only used for keeping relations visible - * during a transaction, we will not need these buffers again. + * AtEOXact_LocalBuffers - clean up at end of transaction. * - * Note that we have to *flush* local buffers because of them are not - * visible to checkpoint makers. But we can skip XLOG flush check. + * This is just like AtEOXact_Buffers, but for local buffers. */ void -LocalBufferSync(void) +AtEOXact_LocalBuffers(bool isCommit) { int i; for (i = 0; i < NLocBuffer; i++) { - BufferDesc *buf = &LocalBufferDescriptors[i]; - Relation bufrel; - - if (buf->flags & BM_DIRTY || buf->cntxDirty) + if (LocalRefCount[i] != 0) { -#ifdef LBDEBUG - fprintf(stderr, "LB SYNC %d\n", -i - 1); -#endif - bufrel = RelationNodeCacheGetRelation(buf->tag.rnode); - - Assert(bufrel != NULL); + BufferDesc *buf = &(LocalBufferDescriptors[i]); - smgrwrite(DEFAULT_SMGR, bufrel, buf->tag.blockNum, - (char *) MAKE_PTR(buf->data)); - smgrmarkdirty(DEFAULT_SMGR, bufrel, buf->tag.blockNum); - LocalBufferFlushCount++; + if (isCommit) + elog(WARNING, + "Local Buffer Leak: [%03d] (rel=%u/%u, blockNum=%u, flags=0x%x, refcount=%d %ld)", + i, + buf->tag.rnode.tblNode, buf->tag.rnode.relNode, + buf->tag.blockNum, buf->flags, + buf->refcount, LocalRefCount[i]); - /* drop relcache refcount from RelationNodeCacheGetRelation */ - RelationDecrementReferenceCount(bufrel); - - buf->flags &= ~BM_DIRTY; - buf->cntxDirty = false; + LocalRefCount[i] = 0; } } - - MemSet(LocalRefCount, 0, sizeof(long) * NLocBuffer); - nextFreeLocalBuf = 0; -} - -void -ResetLocalBufferPool(void) -{ - int i; - - for (i = 0; i < NLocBuffer; i++) - { - BufferDesc *buf = &LocalBufferDescriptors[i]; - - buf->tag.rnode.relNode = InvalidOid; - buf->flags &= ~BM_DIRTY; - buf->cntxDirty = false; - } - - MemSet(LocalRefCount, 0, sizeof(long) * NLocBuffer); - nextFreeLocalBuf = 0; } diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 391a078e602..8be2ed219b9 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.92 2002/06/20 20:29:34 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.93 2002/08/06 02:36:34 tgl Exp $ * * NOTES: * @@ -119,8 +119,7 @@ typedef struct vfd unsigned short fdstate; /* bitflags for VFD's state */ /* these are the assigned bits in fdstate: */ -#define FD_DIRTY (1 << 0) /* written to, but not yet fsync'd */ -#define FD_TEMPORARY (1 << 1) /* should be unlinked when closed */ +#define FD_TEMPORARY (1 << 0) /* should be unlinked when closed */ File nextFree; /* link to next free VFD, if in freelist */ File lruMoreRecently; /* doubly linked recency-of-use list */ @@ -396,15 +395,6 @@ LruDelete(File file) vfdP->seekPos = (long) lseek(vfdP->fd, 0L, SEEK_CUR); Assert(vfdP->seekPos != -1L); - /* if we have written to the file, sync it before closing */ - if (vfdP->fdstate & FD_DIRTY) - { - if (pg_fsync(vfdP->fd)) - elog(LOG, "LruDelete: failed to fsync %s: %m", - vfdP->fileName); - vfdP->fdstate &= ~FD_DIRTY; - } - /* close the file */ if (close(vfdP->fd)) elog(LOG, "LruDelete: failed to close %s: %m", @@ -725,17 +715,8 @@ fileNameOpenFile(FileName fileName, /* Saved flags are adjusted to be OK for re-opening file */ vfdP->fileFlags = fileFlags & ~(O_CREAT | O_TRUNC | O_EXCL); vfdP->fileMode = fileMode; - vfdP->seekPos = 0; - - /* - * Have to fsync file on commit. Alternative way - log file creation - * and fsync log before actual file creation. - */ - if (fileFlags & O_CREAT) - vfdP->fdstate = FD_DIRTY; - else - vfdP->fdstate = 0x0; + vfdP->fdstate = 0x0; return file; } @@ -841,15 +822,6 @@ FileClose(File file) /* remove the file from the lru ring */ Delete(file); - /* if we did any writes, sync the file before closing */ - if (vfdP->fdstate & FD_DIRTY) - { - if (pg_fsync(vfdP->fd)) - elog(LOG, "FileClose: failed to fsync %s: %m", - vfdP->fileName); - vfdP->fdstate &= ~FD_DIRTY; - } - /* close the file */ if (close(vfdP->fd)) elog(LOG, "FileClose: failed to close %s: %m", @@ -1022,108 +994,11 @@ FileTruncate(File file, long offset) DO_DB(elog(LOG, "FileTruncate %d (%s)", file, VfdCache[file].fileName)); - FileSync(file); FileAccess(file); returnCode = ftruncate(VfdCache[file].fd, (size_t) offset); return returnCode; } -/* - * FileSync --- if a file is marked as dirty, fsync it. - * - * The FD_DIRTY bit is slightly misnamed: it doesn't mean that we need to - * write the file, but that we *have* written it and need to execute an - * fsync() to ensure the changes are down on disk before we mark the current - * transaction committed. - * - * FD_DIRTY is set by FileWrite or by an explicit FileMarkDirty() call. - * It is cleared after successfully fsync'ing the file. FileClose() will - * fsync a dirty File that is about to be closed, since there will be no - * other place to remember the need to fsync after the VFD is gone. - * - * Note that the DIRTY bit is logically associated with the actual disk file, - * not with any particular kernel FD we might have open for it. We assume - * that fsync will force out any dirty buffers for that file, whether or not - * they were written through the FD being used for the fsync call --- they - * might even have been written by some other backend! - * - * Note also that LruDelete currently fsyncs a dirty file that it is about - * to close the kernel file descriptor for. The idea there is to avoid - * having to re-open the kernel descriptor later. But it's not real clear - * that this is a performance win; we could end up fsyncing the same file - * multiple times in a transaction, which would probably cost more time - * than is saved by avoiding an open() call. This should be studied. - * - * This routine used to think it could skip the fsync if the file is - * physically closed, but that is now WRONG; see comments for FileMarkDirty. - */ -int -FileSync(File file) -{ - int returnCode; - - Assert(FileIsValid(file)); - - if (!(VfdCache[file].fdstate & FD_DIRTY)) - { - /* Need not sync if file is not dirty. */ - returnCode = 0; - } - else if (!enableFsync) - { - /* Don't force the file open if pg_fsync isn't gonna sync it. */ - returnCode = 0; - VfdCache[file].fdstate &= ~FD_DIRTY; - } - else - { - /* - * We don't use FileAccess() because we don't want to force the - * file to the front of the LRU ring; we aren't expecting to - * access it again soon. - */ - if (FileIsNotOpen(file)) - { - returnCode = LruInsert(file); - if (returnCode != 0) - return returnCode; - } - returnCode = pg_fsync(VfdCache[file].fd); - if (returnCode == 0) - VfdCache[file].fdstate &= ~FD_DIRTY; - } - - return returnCode; -} - -/* - * FileMarkDirty --- mark a file as needing fsync at transaction commit. - * - * Since FileWrite marks the file dirty, this routine is not needed in - * normal use. It is called when the buffer manager detects that some other - * backend has written out a shared buffer that this backend dirtied (but - * didn't write) in the current xact. In that scenario, we need to fsync - * the file before we can commit. We cannot assume that the other backend - * has fsync'd the file yet; we need to do our own fsync to ensure that - * (a) the disk page is written and (b) this backend's commit is delayed - * until the write is complete. - * - * Note we are assuming that an fsync issued by this backend will write - * kernel disk buffers that were dirtied by another backend. Furthermore, - * it doesn't matter whether we currently have the file physically open; - * we must fsync even if we have to re-open the file to do it. - */ -void -FileMarkDirty(File file) -{ - Assert(FileIsValid(file)); - - DO_DB(elog(LOG, "FileMarkDirty: %d (%s)", - file, VfdCache[file].fileName)); - - VfdCache[file].fdstate |= FD_DIRTY; -} - /* * Routines that want to use stdio (ie, FILE*) should use AllocateFile @@ -1142,7 +1017,6 @@ FileMarkDirty(File file) * * Ideally this should be the *only* direct call of fopen() in the backend. */ - FILE * AllocateFile(char *name, char *mode) { @@ -1229,12 +1103,6 @@ closeAllVfds(void) * exit (it doesn't particularly care which). All still-open temporary-file * VFDs are closed, which also causes the underlying files to be deleted. * Furthermore, all "allocated" stdio files are closed. - * - * This routine is not involved in fsync'ing non-temporary files at xact - * commit; that is done by FileSync under control of the buffer manager. - * During a commit, that is done *before* control gets here. If we still - * have any needs-fsync bits set when we get here, we assume this is abort - * and clear them. */ void AtEOXact_Files(void) @@ -1249,8 +1117,6 @@ AtEOXact_Files(void) if ((VfdCache[i].fdstate & FD_TEMPORARY) && VfdCache[i].fileName != NULL) FileClose(i); - else - VfdCache[i].fdstate &= ~FD_DIRTY; } } diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 978d85d4868..25051a9799c 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.91 2002/06/20 20:29:35 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.92 2002/08/06 02:36:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -381,16 +381,7 @@ mdclose_fd(int fd) /* if not closed already */ if (v->mdfd_vfd >= 0) - { - /* - * We sync the file descriptor so that we don't need to reopen - * it at transaction commit to force changes to disk. (This - * is not really optional, because we are about to forget that - * the file even exists...) - */ - FileSync(v->mdfd_vfd); FileClose(v->mdfd_vfd); - } /* Now free vector */ v = v->mdfd_chain; if (ov != &Md_fdvec[fd]) @@ -403,16 +394,7 @@ mdclose_fd(int fd) if (v != (MdfdVec *) NULL) { if (v->mdfd_vfd >= 0) - { - /* - * We sync the file descriptor so that we don't need to reopen - * it at transaction commit to force changes to disk. (This - * is not really optional, because we are about to forget that - * the file even exists...) - */ - FileSync(v->mdfd_vfd); FileClose(v->mdfd_vfd); - } } #endif @@ -498,55 +480,15 @@ mdwrite(Relation reln, BlockNumber blocknum, char *buffer) } /* - * mdflush() -- Synchronously write a block to disk. - * - * This is exactly like mdwrite(), but doesn't return until the file - * system buffer cache has been flushed. - */ -int -mdflush(Relation reln, BlockNumber blocknum, char *buffer) -{ - int status; - long seekpos; - MdfdVec *v; - - v = _mdfd_getseg(reln, blocknum); - -#ifndef LET_OS_MANAGE_FILESIZE - seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE))); -#ifdef DIAGNOSTIC - if (seekpos >= BLCKSZ * RELSEG_SIZE) - elog(FATAL, "seekpos too big!"); -#endif -#else - seekpos = (long) (BLCKSZ * (blocknum)); -#endif - - if (FileSeek(v->mdfd_vfd, seekpos, SEEK_SET) != seekpos) - return SM_FAIL; - - /* write and sync the block */ - status = SM_SUCCESS; - if (FileWrite(v->mdfd_vfd, buffer, BLCKSZ) != BLCKSZ - || FileSync(v->mdfd_vfd) < 0) - status = SM_FAIL; - - return status; -} - -/* * mdblindwrt() -- Write a block to disk blind. * - * We have to be able to do this using only the name and OID of - * the database and relation in which the block belongs. Otherwise - * this is much like mdwrite(). If dofsync is TRUE, then we fsync - * the file, making it more like mdflush(). + * We have to be able to do this using only the rnode of the relation + * in which the block belongs. Otherwise this is much like mdwrite(). */ int mdblindwrt(RelFileNode rnode, BlockNumber blkno, - char *buffer, - bool dofsync) + char *buffer) { int status; long seekpos; @@ -568,7 +510,6 @@ mdblindwrt(RelFileNode rnode, #endif errno = 0; - if (lseek(fd, seekpos, SEEK_SET) != seekpos) { elog(LOG, "mdblindwrt: lseek(%ld) failed: %m", seekpos); @@ -578,7 +519,7 @@ mdblindwrt(RelFileNode rnode, status = SM_SUCCESS; - /* write and optionally sync the block */ + /* write the block */ errno = 0; if (write(fd, buffer, BLCKSZ) != BLCKSZ) { @@ -599,54 +540,6 @@ mdblindwrt(RelFileNode rnode, } /* - * mdmarkdirty() -- Mark the specified block "dirty" (ie, needs fsync). - * - * Returns SM_SUCCESS or SM_FAIL. - */ -int -mdmarkdirty(Relation reln, BlockNumber blkno) -{ - MdfdVec *v; - - v = _mdfd_getseg(reln, blkno); - - FileMarkDirty(v->mdfd_vfd); - - return SM_SUCCESS; -} - -/* - * mdblindmarkdirty() -- Mark the specified block "dirty" (ie, needs fsync). - * - * We have to be able to do this using only the name and OID of - * the database and relation in which the block belongs. Otherwise - * this is much like mdmarkdirty(). However, we do the fsync immediately - * rather than building md/fd datastructures to postpone it till later. - */ -int -mdblindmarkdirty(RelFileNode rnode, - BlockNumber blkno) -{ - int status; - int fd; - - fd = _mdfd_blind_getseg(rnode, blkno); - - if (fd < 0) - return SM_FAIL; - - status = SM_SUCCESS; - - if (pg_fsync(fd) < 0) - status = SM_FAIL; - - if (close(fd) < 0) - status = SM_FAIL; - - return status; -} - -/* * mdnblocks() -- Get the number of blocks stored in a relation. * * Important side effect: all segments of the relation are opened @@ -796,61 +689,36 @@ mdtruncate(Relation reln, BlockNumber nblocks) /* * mdcommit() -- Commit a transaction. * - * All changes to magnetic disk relations must be forced to stable - * storage. This routine makes a pass over the private table of - * file descriptors. Any descriptors to which we have done writes, - * but not synced, are synced here. - * * Returns SM_SUCCESS or SM_FAIL with errno set as appropriate. */ int -mdcommit() +mdcommit(void) { - int i; - MdfdVec *v; - - for (i = 0; i < CurFd; i++) - { - v = &Md_fdvec[i]; - if (v->mdfd_flags & MDFD_FREE) - continue; - /* Sync the file entry */ -#ifndef LET_OS_MANAGE_FILESIZE - for (; v != (MdfdVec *) NULL; v = v->mdfd_chain) -#else - if (v != (MdfdVec *) NULL) -#endif - { - if (FileSync(v->mdfd_vfd) < 0) - return SM_FAIL; - } - } - + /* + * We don't actually have to do anything here... + */ return SM_SUCCESS; } /* * mdabort() -- Abort a transaction. * - * Changes need not be forced to disk at transaction abort. We mark - * all file descriptors as clean here. Always returns SM_SUCCESS. + * Changes need not be forced to disk at transaction abort. */ int -mdabort() +mdabort(void) { /* - * We don't actually have to do anything here. fd.c will discard - * fsync-needed bits in its AtEOXact_Files() routine. + * We don't actually have to do anything here... */ return SM_SUCCESS; } /* - * mdsync() -- Sync storage. - * + * mdsync() -- Sync previous writes to stable storage. */ int -mdsync() +mdsync(void) { sync(); if (IsUnderPostmaster) @@ -861,11 +729,9 @@ mdsync() /* * _fdvec_alloc () -- grab a free (or new) md file descriptor vector. - * */ -static -int -_fdvec_alloc() +static int +_fdvec_alloc(void) { MdfdVec *nvec; int fdvec, diff --git a/src/backend/storage/smgr/mm.c b/src/backend/storage/smgr/mm.c index 89396d173c9..739e938fe28 100644 --- a/src/backend/storage/smgr/mm.c +++ b/src/backend/storage/smgr/mm.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.31 2002/06/20 20:29:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.32 2002/08/06 02:36:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -81,7 +81,7 @@ static HTAB *MMCacheHT; static HTAB *MMRelCacheHT; int -mminit() +mminit(void) { char *mmcacheblk; int mmsize = 0; @@ -151,7 +151,7 @@ mminit() } int -mmshutdown() +mmshutdown(void) { return SM_SUCCESS; } @@ -443,30 +443,15 @@ mmwrite(Relation reln, BlockNumber blocknum, char *buffer) } /* - * mmflush() -- Synchronously write a block to stable storage. - * - * For main-memory relations, this is exactly equivalent to mmwrite(). - */ -int -mmflush(Relation reln, BlockNumber blocknum, char *buffer) -{ - return mmwrite(reln, blocknum, buffer); -} - -/* * mmblindwrt() -- Write a block to stable storage blind. * - * We have to be able to do this using only the name and OID of - * the database and relation in which the block belongs. + * We have to be able to do this using only the rnode of the relation + * in which the block belongs. Otherwise this is much like mmwrite(). */ int -mmblindwrt(char *dbstr, - char *relstr, - Oid dbid, - Oid relid, +mmblindwrt(RelFileNode rnode, BlockNumber blkno, - char *buffer, - bool dofsync) + char *buffer) { return SM_FAIL; } @@ -512,7 +497,7 @@ mmnblocks(Relation reln) * Returns SM_SUCCESS or SM_FAIL with errno set as appropriate. */ int -mmcommit() +mmcommit(void) { return SM_SUCCESS; } @@ -522,7 +507,7 @@ mmcommit() */ int -mmabort() +mmabort(void) { return SM_SUCCESS; } @@ -536,7 +521,7 @@ mmabort() * manager will use. */ int -MMShmemSize() +MMShmemSize(void) { int size = 0; diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index a7fb23b4427..252781d9c3f 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.57 2002/06/20 20:29:36 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.58 2002/08/06 02:36:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -40,12 +40,8 @@ typedef struct f_smgr char *buffer); int (*smgr_write) (Relation reln, BlockNumber blocknum, char *buffer); - int (*smgr_flush) (Relation reln, BlockNumber blocknum, - char *buffer); int (*smgr_blindwrt) (RelFileNode rnode, BlockNumber blkno, - char *buffer, bool dofsync); - int (*smgr_markdirty) (Relation reln, BlockNumber blkno); - int (*smgr_blindmarkdirty) (RelFileNode, BlockNumber blkno); + char *buffer); BlockNumber (*smgr_nblocks) (Relation reln); BlockNumber (*smgr_truncate) (Relation reln, BlockNumber nblocks); int (*smgr_commit) (void); /* may be NULL */ @@ -62,15 +58,15 @@ static f_smgr smgrsw[] = { /* magnetic disk */ {mdinit, NULL, mdcreate, mdunlink, mdextend, mdopen, mdclose, - mdread, mdwrite, mdflush, mdblindwrt, mdmarkdirty, mdblindmarkdirty, + mdread, mdwrite, mdblindwrt, mdnblocks, mdtruncate, mdcommit, mdabort, mdsync }, #ifdef STABLE_MEMORY_STORAGE /* main memory */ {mminit, mmshutdown, mmcreate, mmunlink, mmextend, mmopen, mmclose, - mmread, mmwrite, mmflush, mmblindwrt, mmmarkdirty, mmblindmarkdirty, - mmnblocks, NULL, mmcommit, mmabort}, + mmread, mmwrite, mmblindwrt, + mmnblocks, NULL, mmcommit, mmabort, NULL}, #endif }; @@ -110,6 +106,7 @@ typedef struct PendingRelDelete { RelFileNode relnode; /* relation that may need to be deleted */ int16 which; /* which storage manager? */ + bool isTemp; /* is it a temporary relation? */ bool atCommit; /* T=delete at commit; F=delete at abort */ struct PendingRelDelete *next; /* linked-list link */ } PendingRelDelete; @@ -123,7 +120,7 @@ static PendingRelDelete *pendingDeletes = NULL; /* head of linked list */ * */ int -smgrinit() +smgrinit(void) { int i; @@ -181,6 +178,7 @@ smgrcreate(int16 which, Relation reln) MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete)); pending->relnode = reln->rd_node; pending->which = which; + pending->isTemp = reln->rd_istemp; pending->atCommit = false; /* delete if abort */ pending->next = pendingDeletes; pendingDeletes = pending; @@ -208,6 +206,7 @@ smgrunlink(int16 which, Relation reln) MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete)); pending->relnode = reln->rd_node; pending->which = which; + pending->isTemp = reln->rd_istemp; pending->atCommit = true; /* delete if commit */ pending->next = pendingDeletes; pendingDeletes = pending; @@ -312,8 +311,10 @@ smgrread(int16 which, Relation reln, BlockNumber blocknum, char *buffer) /* * smgrwrite() -- Write the supplied buffer out. * - * This is not a synchronous write -- the interface for that is - * smgrflush(). The buffer is written out via the appropriate + * This is not a synchronous write -- the block is not necessarily + * on disk at return, only dumped out to the kernel. + * + * The buffer is written out via the appropriate * storage manager. This routine returns SM_SUCCESS or aborts * the current transaction. */ @@ -332,23 +333,6 @@ smgrwrite(int16 which, Relation reln, BlockNumber blocknum, char *buffer) } /* - * smgrflush() -- A synchronous smgrwrite(). - */ -int -smgrflush(int16 which, Relation reln, BlockNumber blocknum, char *buffer) -{ - int status; - - status = (*(smgrsw[which].smgr_flush)) (reln, blocknum, buffer); - - if (status == SM_FAIL) - elog(ERROR, "cannot flush block %d of %s to stable store: %m", - blocknum, RelationGetRelationName(reln)); - - return status; -} - -/* * smgrblindwrt() -- Write a page out blind. * * In some cases, we may find a page in the buffer cache that we @@ -357,20 +341,18 @@ smgrflush(int16 which, Relation reln, BlockNumber blocknum, char *buffer) * that has not yet committed, which created a new relation. In * this case, the buffer manager will call smgrblindwrt() with * the name and OID of the database and the relation to which the - * buffer belongs. Every storage manager must be able to force - * this page down to stable storage in this circumstance. The - * write should be synchronous if dofsync is true. + * buffer belongs. Every storage manager must be able to write + * this page out to stable storage in this circumstance. */ int smgrblindwrt(int16 which, RelFileNode rnode, BlockNumber blkno, - char *buffer, - bool dofsync) + char *buffer) { int status; - status = (*(smgrsw[which].smgr_blindwrt)) (rnode, blkno, buffer, dofsync); + status = (*(smgrsw[which].smgr_blindwrt)) (rnode, blkno, buffer); if (status == SM_FAIL) elog(ERROR, "cannot write block %d of %u/%u blind: %m", @@ -380,53 +362,6 @@ smgrblindwrt(int16 which, } /* - * smgrmarkdirty() -- Mark a page dirty (needs fsync). - * - * Mark the specified page as needing to be fsync'd before commit. - * Ordinarily, the storage manager will do this implicitly during - * smgrwrite(). However, the buffer manager may discover that some - * other backend has written a buffer that we dirtied in the current - * transaction. In that case, we still need to fsync the file to be - * sure the page is down to disk before we commit. - */ -int -smgrmarkdirty(int16 which, - Relation reln, - BlockNumber blkno) -{ - int status; - - status = (*(smgrsw[which].smgr_markdirty)) (reln, blkno); - - if (status == SM_FAIL) - elog(ERROR, "cannot mark block %d of %s: %m", - blkno, RelationGetRelationName(reln)); - - return status; -} - -/* - * smgrblindmarkdirty() -- Mark a page dirty, "blind". - * - * Just like smgrmarkdirty, except we don't have a reldesc. - */ -int -smgrblindmarkdirty(int16 which, - RelFileNode rnode, - BlockNumber blkno) -{ - int status; - - status = (*(smgrsw[which].smgr_blindmarkdirty)) (rnode, blkno); - - if (status == SM_FAIL) - elog(ERROR, "cannot mark block %d of %u/%u blind: %m", - blkno, rnode.tblNode, rnode.relNode); - - return status; -} - -/* * smgrnblocks() -- Calculate the number of POSTGRES blocks in the * supplied relation. * @@ -504,7 +439,7 @@ smgrDoPendingDeletes(bool isCommit) * any in the commit case, but there can be in the abort * case). */ - DropRelFileNodeBuffers(pending->relnode); + DropRelFileNodeBuffers(pending->relnode, pending->isTemp); /* * Tell the free space map to forget this relation. It won't @@ -531,11 +466,13 @@ smgrDoPendingDeletes(bool isCommit) } /* - * smgrcommit(), smgrabort() -- Commit or abort changes made during the - * current transaction. + * smgrcommit() -- Prepare to commit changes made during the current + * transaction. + * + * This is called before we actually commit. */ int -smgrcommit() +smgrcommit(void) { int i; @@ -553,8 +490,11 @@ smgrcommit() return SM_SUCCESS; } +/* + * smgrabort() -- Abort changes made during the current transaction. + */ int -smgrabort() +smgrabort(void) { int i; @@ -572,8 +512,11 @@ smgrabort() return SM_SUCCESS; } +/* + * Sync files to disk at checkpoint time. + */ int -smgrsync() +smgrsync(void) { int i; |