diff options
Diffstat (limited to 'src/backend/access/transam')
-rw-r--r-- | src/backend/access/transam/clog.c | 3 | ||||
-rw-r--r-- | src/backend/access/transam/slru.c | 68 | ||||
-rw-r--r-- | src/backend/access/transam/subtrans.c | 26 | ||||
-rw-r--r-- | src/backend/access/transam/transam.c | 20 | ||||
-rw-r--r-- | src/backend/access/transam/varsup.c | 41 | ||||
-rw-r--r-- | src/backend/access/transam/xact.c | 478 | ||||
-rw-r--r-- | src/backend/access/transam/xlog.c | 656 | ||||
-rw-r--r-- | src/backend/access/transam/xlogutils.c | 19 |
8 files changed, 695 insertions, 616 deletions
diff --git a/src/backend/access/transam/clog.c b/src/backend/access/transam/clog.c index b26807f9afb..fb490e4137a 100644 --- a/src/backend/access/transam/clog.c +++ b/src/backend/access/transam/clog.c @@ -24,7 +24,7 @@ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.24 2004/08/29 04:12:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.25 2004/08/29 05:06:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -62,6 +62,7 @@ * Link to shared-memory data structures for CLOG control */ static SlruCtlData ClogCtlData; + #define ClogCtl (&ClogCtlData) diff --git a/src/backend/access/transam/slru.c b/src/backend/access/transam/slru.c index c695013ed17..c87b38a7922 100644 --- a/src/backend/access/transam/slru.c +++ b/src/backend/access/transam/slru.c @@ -48,7 +48,7 @@ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.20 2004/08/29 04:12:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/slru.c,v 1.21 2004/08/29 05:06:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -79,7 +79,7 @@ * segment and page numbers in SimpleLruTruncate (see PagePrecedes()). * * Note: this file currently assumes that segment file names will be four - * hex digits. This sets a lower bound on the segment size (64K transactions + * hex digits. This sets a lower bound on the segment size (64K transactions * for 32-bit TransactionIds). */ #define SLRU_PAGES_PER_SEGMENT 32 @@ -96,9 +96,9 @@ */ typedef struct SlruFlushData { - int num_files; /* # files actually open */ - int fd[NUM_SLRU_BUFFERS]; /* their FD's */ - int segno[NUM_SLRU_BUFFERS]; /* their log seg#s */ + int num_files; /* # files actually open */ + int fd[NUM_SLRU_BUFFERS]; /* their FD's */ + int segno[NUM_SLRU_BUFFERS]; /* their log seg#s */ } SlruFlushData; /* @@ -132,7 +132,7 @@ static int slru_errno; static bool SlruPhysicalReadPage(SlruCtl ctl, int pageno, int slotno); static bool SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, - SlruFlush fdata); + SlruFlush fdata); static void SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid); static int SlruSelectLRUPage(SlruCtl ctl, int pageno); @@ -385,7 +385,7 @@ SimpleLruWritePage(SlruCtl ctl, int slotno, SlruFlush fdata) /* If we failed, and we're in a flush, better close the files */ if (!ok && fdata) { - int i; + int i; for (i = 0; i < fdata->num_files; i++) close(fdata->fd[i]); @@ -511,7 +511,7 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata) */ if (fdata) { - int i; + int i; for (i = 0; i < fdata->num_files; i++) { @@ -527,16 +527,17 @@ SlruPhysicalWritePage(SlruCtl ctl, int pageno, int slotno, SlruFlush fdata) { /* * If the file doesn't already exist, we should create it. It is - * possible for this to need to happen when writing a page that's not - * first in its segment; we assume the OS can cope with that. - * (Note: it might seem that it'd be okay to create files only when - * SimpleLruZeroPage is called for the first page of a segment. - * However, if after a crash and restart the REDO logic elects to - * replay the log from a checkpoint before the latest one, then it's - * possible that we will get commands to set transaction status of - * transactions that have already been truncated from the commit log. - * Easiest way to deal with that is to accept references to - * nonexistent files here and in SlruPhysicalReadPage.) + * possible for this to need to happen when writing a page that's + * not first in its segment; we assume the OS can cope with that. + * (Note: it might seem that it'd be okay to create files only + * when SimpleLruZeroPage is called for the first page of a + * segment. However, if after a crash and restart the REDO logic + * elects to replay the log from a checkpoint before the latest + * one, then it's possible that we will get commands to set + * transaction status of transactions that have already been + * truncated from the commit log. Easiest way to deal with that is + * to accept references to nonexistent files here and in + * SlruPhysicalReadPage.) */ SlruFileName(ctl, path, segno); fd = BasicOpenFile(path, O_RDWR | PG_BINARY, S_IRUSR | S_IWUSR); @@ -648,36 +649,36 @@ SlruReportIOError(SlruCtl ctl, int pageno, TransactionId xid) ereport(ERROR, (errcode_for_file_access(), errmsg("could not access status of transaction %u", xid), - errdetail("could not seek in file \"%s\" to offset %u: %m", - path, offset))); + errdetail("could not seek in file \"%s\" to offset %u: %m", + path, offset))); break; case SLRU_READ_FAILED: ereport(ERROR, (errcode_for_file_access(), errmsg("could not access status of transaction %u", xid), - errdetail("could not read from file \"%s\" at offset %u: %m", - path, offset))); + errdetail("could not read from file \"%s\" at offset %u: %m", + path, offset))); break; case SLRU_WRITE_FAILED: ereport(ERROR, (errcode_for_file_access(), errmsg("could not access status of transaction %u", xid), - errdetail("could not write to file \"%s\" at offset %u: %m", - path, offset))); + errdetail("could not write to file \"%s\" at offset %u: %m", + path, offset))); break; case SLRU_FSYNC_FAILED: ereport(ERROR, (errcode_for_file_access(), errmsg("could not access status of transaction %u", xid), - errdetail("could not fsync file \"%s\": %m", - path))); + errdetail("could not fsync file \"%s\": %m", + path))); break; case SLRU_CLOSE_FAILED: ereport(ERROR, (errcode_for_file_access(), errmsg("could not access status of transaction %u", xid), - errdetail("could not close file \"%s\": %m", - path))); + errdetail("could not close file \"%s\": %m", + path))); break; default: /* can't get here, we trust */ @@ -841,8 +842,8 @@ SimpleLruTruncate(SlruCtl ctl, int cutoffPage) /* * Scan shared memory and remove any pages preceding the cutoff page, * to ensure we won't rewrite them later. (Since this is normally - * called in or just after a checkpoint, any dirty pages should - * have been flushed already ... we're just being extra careful here.) + * called in or just after a checkpoint, any dirty pages should have + * been flushed already ... we're just being extra careful here.) */ LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE); @@ -952,8 +953,11 @@ SlruScanDirectory(SlruCtl ctl, int cutoffPage, bool doDeletions) errno = 0; } #ifdef WIN32 - /* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but - not in released version */ + + /* + * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but + * not in released version + */ if (GetLastError() == ERROR_NO_MORE_FILES) errno = 0; #endif diff --git a/src/backend/access/transam/subtrans.c b/src/backend/access/transam/subtrans.c index 7976de2300c..93a586148be 100644 --- a/src/backend/access/transam/subtrans.c +++ b/src/backend/access/transam/subtrans.c @@ -5,7 +5,7 @@ * * The pg_subtrans manager is a pg_clog-like manager that stores the parent * transaction Id for each transaction. It is a fundamental part of the - * nested transactions implementation. A main transaction has a parent + * nested transactions implementation. A main transaction has a parent * of InvalidTransactionId, and each subtransaction has its immediate parent. * The tree can easily be walked from child to parent, but not in the * opposite direction. @@ -22,7 +22,7 @@ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.4 2004/08/29 04:12:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/subtrans.c,v 1.5 2004/08/29 05:06:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -57,6 +57,7 @@ * Link to shared-memory data structures for SUBTRANS control */ static SlruCtlData SubTransCtlData; + #define SubTransCtl (&SubTransCtlData) @@ -101,7 +102,7 @@ SubTransGetParent(TransactionId xid) int entryno = TransactionIdToEntry(xid); int slotno; TransactionId *ptr; - TransactionId parent; + TransactionId parent; /* Can't ask about stuff that might not be around anymore */ Assert(TransactionIdFollowsOrEquals(xid, RecentXmin)); @@ -139,7 +140,7 @@ TransactionId SubTransGetTopmostTransaction(TransactionId xid) { TransactionId parentXid = xid, - previousXid = xid; + previousXid = xid; /* Can't ask about stuff that might not be around anymore */ Assert(TransactionIdFollowsOrEquals(xid, RecentXmin)); @@ -185,7 +186,7 @@ SUBTRANSShmemInit(void) * must have been called already.) * * Note: it's not really necessary to create the initial segment now, - * since slru.c would create it on first write anyway. But we may as well + * since slru.c would create it on first write anyway. But we may as well * do it to be sure the directory is set up correctly. */ void @@ -229,10 +230,11 @@ StartupSUBTRANS(void) int startPage; /* - * Since we don't expect pg_subtrans to be valid across crashes, - * we initialize the currently-active page to zeroes during startup. + * Since we don't expect pg_subtrans to be valid across crashes, we + * initialize the currently-active page to zeroes during startup. * Whenever we advance into a new page, ExtendSUBTRANS will likewise - * zero the new page without regard to whatever was previously on disk. + * zero the new page without regard to whatever was previously on + * disk. */ LWLockAcquire(SubtransControlLock, LW_EXCLUSIVE); @@ -251,8 +253,8 @@ ShutdownSUBTRANS(void) /* * Flush dirty SUBTRANS pages to disk * - * This is not actually necessary from a correctness point of view. - * We do it merely as a debugging aid. + * This is not actually necessary from a correctness point of view. We do + * it merely as a debugging aid. */ SimpleLruFlush(SubTransCtl, false); } @@ -266,8 +268,8 @@ CheckPointSUBTRANS(void) /* * Flush dirty SUBTRANS pages to disk * - * This is not actually necessary from a correctness point of view. - * We do it merely to improve the odds that writing of dirty pages is done + * This is not actually necessary from a correctness point of view. We do + * it merely to improve the odds that writing of dirty pages is done * by the checkpoint process and not by backends. */ SimpleLruFlush(SubTransCtl, true); diff --git a/src/backend/access/transam/transam.c b/src/backend/access/transam/transam.c index fd5a1619a77..f82168be5b7 100644 --- a/src/backend/access/transam/transam.c +++ b/src/backend/access/transam/transam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.60 2004/08/29 04:12:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/transam.c,v 1.61 2004/08/29 05:06:40 momjian Exp $ * * NOTES * This file contains the high level access-method interface to the @@ -126,7 +126,7 @@ TransactionLogUpdate(TransactionId transactionId, /* trans id to update */ static void TransactionLogMultiUpdate(int nxids, TransactionId *xids, XidStatus status) { - int i; + int i; Assert(nxids != 0); @@ -199,9 +199,10 @@ TransactionIdDidCommit(TransactionId transactionId) return true; /* - * If it's marked subcommitted, we have to check the parent recursively. - * However, if it's older than RecentXmin, we can't look at pg_subtrans; - * instead assume that the parent crashed without cleaning up its children. + * If it's marked subcommitted, we have to check the parent + * recursively. However, if it's older than RecentXmin, we can't look + * at pg_subtrans; instead assume that the parent crashed without + * cleaning up its children. */ if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED) { @@ -214,7 +215,7 @@ TransactionIdDidCommit(TransactionId transactionId) return TransactionIdDidCommit(parentXid); } - /* + /* * It's not committed. */ return false; @@ -247,9 +248,10 @@ TransactionIdDidAbort(TransactionId transactionId) return true; /* - * If it's marked subcommitted, we have to check the parent recursively. - * However, if it's older than RecentXmin, we can't look at pg_subtrans; - * instead assume that the parent crashed without cleaning up its children. + * If it's marked subcommitted, we have to check the parent + * recursively. However, if it's older than RecentXmin, we can't look + * at pg_subtrans; instead assume that the parent crashed without + * cleaning up its children. */ if (xidstatus == TRANSACTION_STATUS_SUB_COMMITTED) { diff --git a/src/backend/access/transam/varsup.c b/src/backend/access/transam/varsup.c index cfd78937428..84926ac415a 100644 --- a/src/backend/access/transam/varsup.c +++ b/src/backend/access/transam/varsup.c @@ -6,7 +6,7 @@ * Copyright (c) 2000-2004, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.58 2004/08/29 04:12:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/varsup.c,v 1.59 2004/08/29 05:06:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -47,9 +47,9 @@ GetNewTransactionId(bool isSubXact) xid = ShmemVariableCache->nextXid; /* - * If we are allocating the first XID of a new page of the commit - * log, zero out that commit-log page before returning. We must do - * this while holding XidGenLock, else another xact could acquire and + * If we are allocating the first XID of a new page of the commit log, + * zero out that commit-log page before returning. We must do this + * while holding XidGenLock, else another xact could acquire and * commit a later XID before we zero the page. Fortunately, a page of * the commit log holds 32K or more transactions, so we don't have to * do this very often. @@ -61,17 +61,18 @@ GetNewTransactionId(bool isSubXact) /* * Now advance the nextXid counter. This must not happen until after - * we have successfully completed ExtendCLOG() --- if that routine fails, - * we want the next incoming transaction to try it again. We cannot - * assign more XIDs until there is CLOG space for them. + * we have successfully completed ExtendCLOG() --- if that routine + * fails, we want the next incoming transaction to try it again. We + * cannot assign more XIDs until there is CLOG space for them. */ TransactionIdAdvance(ShmemVariableCache->nextXid); /* - * We must store the new XID into the shared PGPROC array before releasing - * XidGenLock. This ensures that when GetSnapshotData calls + * We must store the new XID into the shared PGPROC array before + * releasing XidGenLock. This ensures that when GetSnapshotData calls * ReadNewTransactionId, all active XIDs before the returned value of - * nextXid are already present in PGPROC. Else we have a race condition. + * nextXid are already present in PGPROC. Else we have a race + * condition. * * XXX by storing xid into MyProc without acquiring SInvalLock, we are * relying on fetch/store of an xid to be atomic, else other backends @@ -86,19 +87,19 @@ GetNewTransactionId(bool isSubXact) * * A solution to the atomic-store problem would be to give each PGPROC * its own spinlock used only for fetching/storing that PGPROC's xid - * and related fields. (SInvalLock would then mean primarily that + * and related fields. (SInvalLock would then mean primarily that * PGPROCs couldn't be added/removed while holding the lock.) * * If there's no room to fit a subtransaction XID into PGPROC, set the * cache-overflowed flag instead. This forces readers to look in - * pg_subtrans to map subtransaction XIDs up to top-level XIDs. - * There is a race-condition window, in that the new XID will not - * appear as running until its parent link has been placed into - * pg_subtrans. However, that will happen before anyone could possibly - * have a reason to inquire about the status of the XID, so it seems - * OK. (Snapshots taken during this window *will* include the parent - * XID, so they will deliver the correct answer later on when someone - * does have a reason to inquire.) + * pg_subtrans to map subtransaction XIDs up to top-level XIDs. There + * is a race-condition window, in that the new XID will not appear as + * running until its parent link has been placed into pg_subtrans. + * However, that will happen before anyone could possibly have a + * reason to inquire about the status of the XID, so it seems OK. + * (Snapshots taken during this window *will* include the parent XID, + * so they will deliver the correct answer later on when someone does + * have a reason to inquire.) */ if (MyProc != NULL) { @@ -112,9 +113,7 @@ GetNewTransactionId(bool isSubXact) MyProc->subxids.nxids++; } else - { MyProc->subxids.overflowed = true; - } } } diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index fd5d6b51682..3bb38e4227f 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.182 2004/08/29 04:12:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.183 2004/08/29 05:06:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -89,19 +89,20 @@ typedef enum TBlockState */ typedef struct TransactionStateData { - TransactionId transactionIdData; /* my XID */ - char *name; /* savepoint name, if any */ - int savepointLevel; /* savepoint level */ - CommandId commandId; /* current CID */ - TransState state; /* low-level state */ - TBlockState blockState; /* high-level state */ - int nestingLevel; /* nest depth */ - MemoryContext curTransactionContext; /* my xact-lifetime context */ - ResourceOwner curTransactionOwner; /* my query resources */ - List *childXids; /* subcommitted child XIDs */ - AclId currentUser; /* subxact start current_user */ - bool prevXactReadOnly; /* entry-time xact r/o state */ - struct TransactionStateData *parent; /* back link to parent */ + TransactionId transactionIdData; /* my XID */ + char *name; /* savepoint name, if any */ + int savepointLevel; /* savepoint level */ + CommandId commandId; /* current CID */ + TransState state; /* low-level state */ + TBlockState blockState; /* high-level state */ + int nestingLevel; /* nest depth */ + MemoryContext curTransactionContext; /* my xact-lifetime + * context */ + ResourceOwner curTransactionOwner; /* my query resources */ + List *childXids; /* subcommitted child XIDs */ + AclId currentUser; /* subxact start current_user */ + bool prevXactReadOnly; /* entry-time xact r/o state */ + struct TransactionStateData *parent; /* back link to parent */ } TransactionStateData; typedef TransactionStateData *TransactionState; @@ -180,8 +181,8 @@ static TransactionState CurrentTransactionState = &TopTransactionStateData; * This does not change as we enter and exit subtransactions, so we don't * keep it inside the TransactionState stack. */ -static AbsoluteTime xactStartTime; /* integer part */ -static int xactStartTimeUsec; /* microsecond part */ +static AbsoluteTime xactStartTime; /* integer part */ +static int xactStartTimeUsec; /* microsecond part */ /* @@ -261,7 +262,7 @@ IsAbortedTransactionBlockState(void) { TransactionState s = CurrentTransactionState; - if (s->blockState == TBLOCK_ABORT || + if (s->blockState == TBLOCK_ABORT || s->blockState == TBLOCK_SUBABORT) return true; @@ -362,15 +363,15 @@ TransactionIdIsCurrentTransactionId(TransactionId xid) } /* - * We will return true for the Xid of the current subtransaction, - * any of its subcommitted children, any of its parents, or any of - * their previously subcommitted children. However, a transaction - * being aborted is no longer "current", even though it may still - * have an entry on the state stack. + * We will return true for the Xid of the current subtransaction, any + * of its subcommitted children, any of its parents, or any of their + * previously subcommitted children. However, a transaction being + * aborted is no longer "current", even though it may still have an + * entry on the state stack. */ for (s = CurrentTransactionState; s != NULL; s = s->parent) { - ListCell *cell; + ListCell *cell; if (s->state == TRANS_ABORT) continue; @@ -502,15 +503,16 @@ AtSubStart_Memory(void) Assert(CurTransactionContext != NULL); /* - * Create a CurTransactionContext, which will be used to hold data that - * survives subtransaction commit but disappears on subtransaction abort. - * We make it a child of the immediate parent's CurTransactionContext. + * Create a CurTransactionContext, which will be used to hold data + * that survives subtransaction commit but disappears on + * subtransaction abort. We make it a child of the immediate parent's + * CurTransactionContext. */ CurTransactionContext = AllocSetContextCreate(CurTransactionContext, "CurTransactionContext", - ALLOCSET_DEFAULT_MINSIZE, - ALLOCSET_DEFAULT_INITSIZE, - ALLOCSET_DEFAULT_MAXSIZE); + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); s->curTransactionContext = CurTransactionContext; /* Make the CurTransactionContext active. */ @@ -528,8 +530,8 @@ AtSubStart_ResourceOwner(void) Assert(s->parent != NULL); /* - * Create a resource owner for the subtransaction. We make it a - * child of the immediate parent's resource owner. + * Create a resource owner for the subtransaction. We make it a child + * of the immediate parent's resource owner. */ s->curTransactionOwner = ResourceOwnerCreate(s->parent->curTransactionOwner, @@ -560,10 +562,11 @@ RecordTransactionCommit(void) nchildren = xactGetCommittedChildren(&children); /* - * If we made neither any XLOG entries nor any temp-rel updates, - * and have no files to be deleted, we can omit recording the transaction + * If we made neither any XLOG entries nor any temp-rel updates, and + * have no files to be deleted, we can omit recording the transaction * commit at all. (This test includes the effects of subtransactions, - * so the presence of committed subxacts need not alone force a write.) + * so the presence of committed subxacts need not alone force a + * write.) */ if (MyXactMadeXLogEntry || MyXactMadeTempRelUpdate || nrels > 0) { @@ -577,17 +580,18 @@ RecordTransactionCommit(void) START_CRIT_SECTION(); /* - * If our transaction made any transaction-controlled XLOG entries, - * we need to lock out checkpoint start between writing our XLOG - * record and updating pg_clog. Otherwise it is possible for the - * checkpoint to set REDO after the XLOG record but fail to flush the - * pg_clog update to disk, leading to loss of the transaction commit - * if we crash a little later. Slightly klugy fix for problem - * discovered 2004-08-10. + * If our transaction made any transaction-controlled XLOG + * entries, we need to lock out checkpoint start between writing + * our XLOG record and updating pg_clog. Otherwise it is possible + * for the checkpoint to set REDO after the XLOG record but fail + * to flush the pg_clog update to disk, leading to loss of the + * transaction commit if we crash a little later. Slightly klugy + * fix for problem discovered 2004-08-10. * * (If it made no transaction-controlled XLOG entries, its XID - * appears nowhere in permanent storage, so no one else will ever care - * if it committed; so it doesn't matter if we lose the commit flag.) + * appears nowhere in permanent storage, so no one else will ever + * care if it committed; so it doesn't matter if we lose the + * commit flag.) * * Note we only need a shared lock. */ @@ -798,21 +802,21 @@ static void RecordSubTransactionCommit(void) { /* - * We do not log the subcommit in XLOG; it doesn't matter until - * the top-level transaction commits. + * We do not log the subcommit in XLOG; it doesn't matter until the + * top-level transaction commits. * * We must mark the subtransaction subcommitted in clog if its XID * appears either in permanent rels or in local temporary rels. We - * test this by seeing if we made transaction-controlled entries - * *OR* local-rel tuple updates. (The test here actually covers the - * entire transaction tree so far, so it may mark subtransactions that - * don't really need it, but it's probably not worth being tenser. - * Note that if a prior subtransaction dirtied these variables, then + * test this by seeing if we made transaction-controlled entries *OR* + * local-rel tuple updates. (The test here actually covers the entire + * transaction tree so far, so it may mark subtransactions that don't + * really need it, but it's probably not worth being tenser. Note that + * if a prior subtransaction dirtied these variables, then * RecordTransactionCommit will have to do the full pushup anyway...) */ if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate) { - TransactionId xid = GetCurrentTransactionId(); + TransactionId xid = GetCurrentTransactionId(); /* XXX does this really need to be a critical section? */ START_CRIT_SECTION(); @@ -837,8 +841,8 @@ RecordTransactionAbort(void) { int nrels; RelFileNode *rptr; - int nchildren; - TransactionId *children; + int nchildren; + TransactionId *children; /* Get data needed for abort record */ nrels = smgrGetPendingDeletes(false, &rptr); @@ -846,13 +850,13 @@ RecordTransactionAbort(void) /* * If we made neither any transaction-controlled XLOG entries nor any - * temp-rel updates, and are not going to delete any files, we can omit - * recording the transaction abort at all. No one will ever care that - * it aborted. (These tests cover our whole transaction tree.) + * temp-rel updates, and are not going to delete any files, we can + * omit recording the transaction abort at all. No one will ever care + * that it aborted. (These tests cover our whole transaction tree.) */ if (MyLastRecPtr.xrecoff != 0 || MyXactMadeTempRelUpdate || nrels > 0) { - TransactionId xid = GetCurrentTransactionId(); + TransactionId xid = GetCurrentTransactionId(); /* * Catch the scenario where we aborted partway through @@ -867,13 +871,13 @@ RecordTransactionAbort(void) * We only need to log the abort in XLOG if the transaction made * any transaction-controlled XLOG entries or will delete files. * (If it made no transaction-controlled XLOG entries, its XID - * appears nowhere in permanent storage, so no one else will ever care - * if it committed.) + * appears nowhere in permanent storage, so no one else will ever + * care if it committed.) * * We do not flush XLOG to disk unless deleting files, since the - * default assumption after a crash would be that we aborted, anyway. - * For the same reason, we don't need to worry about interlocking - * against checkpoint start. + * default assumption after a crash would be that we aborted, + * anyway. For the same reason, we don't need to worry about + * interlocking against checkpoint start. */ if (MyLastRecPtr.xrecoff != 0 || nrels > 0) { @@ -990,9 +994,9 @@ RecordSubTransactionAbort(void) { int nrels; RelFileNode *rptr; - TransactionId xid = GetCurrentTransactionId(); - int nchildren; - TransactionId *children; + TransactionId xid = GetCurrentTransactionId(); + int nchildren; + TransactionId *children; /* Get data needed for abort record */ nrels = smgrGetPendingDeletes(false, &rptr); @@ -1000,10 +1004,10 @@ RecordSubTransactionAbort(void) /* * If we made neither any transaction-controlled XLOG entries nor any - * temp-rel updates, and are not going to delete any files, we can omit - * recording the transaction abort at all. No one will ever care that - * it aborted. (These tests cover our whole transaction tree, and - * therefore may mark subxacts that don't really need it, but it's + * temp-rel updates, and are not going to delete any files, we can + * omit recording the transaction abort at all. No one will ever care + * that it aborted. (These tests cover our whole transaction tree, + * and therefore may mark subxacts that don't really need it, but it's * probably not worth being tenser.) * * In this case we needn't worry about marking subcommitted children as @@ -1021,9 +1025,9 @@ RecordSubTransactionAbort(void) if (MyLastRecPtr.xrecoff != 0 || nrels > 0) { XLogRecData rdata[3]; - int lastrdata = 0; + int lastrdata = 0; xl_xact_abort xlrec; - XLogRecPtr recptr; + XLogRecPtr recptr; xlrec.xtime = time(NULL); xlrec.nrels = nrels; @@ -1071,8 +1075,8 @@ RecordSubTransactionAbort(void) /* * We can immediately remove failed XIDs from PGPROC's cache of * running child XIDs. It's easiest to do it here while we have the - * child XID array at hand, even though in the main-transaction - * case the equivalent work happens just after return from + * child XID array at hand, even though in the main-transaction case + * the equivalent work happens just after return from * RecordTransactionAbort. */ XidCacheRemoveRunningXids(xid, nchildren, children); @@ -1169,7 +1173,8 @@ StartTransaction(void) s->state = TRANS_START; /* - * Make sure we've freed any old snapshot, and reset xact state variables + * Make sure we've freed any old snapshot, and reset xact state + * variables */ FreeXactSnapshot(); XactIsoLevel = DefaultXactIsoLevel; @@ -1323,9 +1328,9 @@ CommitTransaction(void) * want to release locks at the point where any backend waiting for us * will see our transaction as being fully cleaned up. * - * Resources that can be associated with individual queries are - * handled by the ResourceOwner mechanism. The other calls here - * are for backend-wide state. + * Resources that can be associated with individual queries are handled + * by the ResourceOwner mechanism. The other calls here are for + * backend-wide state. */ smgrDoPendingDeletes(true); @@ -1342,7 +1347,8 @@ CommitTransaction(void) * after relcache references are dropped (see comments for * AtEOXact_RelationCache), but before locks are released (if anyone * is waiting for lock on a relation we've modified, we want them to - * know about the catalog change before they start using the relation). + * know about the catalog change before they start using the + * relation). */ AtEOXact_Inval(true); @@ -1428,11 +1434,12 @@ AbortTransaction(void) /* * Reset user id which might have been changed transiently. We cannot - * use s->currentUser, but must get the session userid from miscinit.c. + * use s->currentUser, but must get the session userid from + * miscinit.c. * * (Note: it is not necessary to restore session authorization here * because that can only be changed via GUC, and GUC will take care of - * rolling it back if need be. However, an error within a SECURITY + * rolling it back if need be. However, an error within a SECURITY * DEFINER function could send control here with the wrong current * userid.) */ @@ -1443,7 +1450,7 @@ AbortTransaction(void) */ DeferredTriggerAbortXact(); AtAbort_Portals(); - AtEOXact_LargeObject(false); /* 'false' means it's abort */ + AtEOXact_LargeObject(false); /* 'false' means it's abort */ AtAbort_Notify(); AtEOXact_UpdatePasswordFile(false); @@ -1523,7 +1530,7 @@ CleanupTransaction(void) */ AtCleanup_Portals(); /* now safe to release portal memory */ - CurrentResourceOwner = NULL; /* and resource owner */ + CurrentResourceOwner = NULL; /* and resource owner */ ResourceOwnerDelete(TopTransactionResourceOwner); s->curTransactionOwner = NULL; CurTransactionResourceOwner = NULL; @@ -1561,9 +1568,10 @@ StartTransactionCommand(void) break; /* - * This is the case when we are somewhere in a transaction block - * and about to start a new command. For now we do nothing - * but someday we may do command-local resource initialization. + * This is the case when we are somewhere in a transaction + * block and about to start a new command. For now we do + * nothing but someday we may do command-local resource + * initialization. */ case TBLOCK_INPROGRESS: case TBLOCK_SUBINPROGRESS: @@ -1616,8 +1624,8 @@ CommitTransactionCommand(void) /* * This shouldn't happen, because it means the previous * StartTransactionCommand didn't set the STARTED state - * appropriately, or we didn't manage previous pending - * abort states. + * appropriately, or we didn't manage previous pending abort + * states. */ case TBLOCK_DEFAULT: case TBLOCK_SUBABORT_PENDING: @@ -1689,19 +1697,21 @@ CommitTransactionCommand(void) break; /* - * Ditto, but in a subtransaction. AbortOutOfAnyTransaction + * Ditto, but in a subtransaction. AbortOutOfAnyTransaction * will do the dirty work. */ case TBLOCK_SUBENDABORT_ALL: AbortOutOfAnyTransaction(); - s = CurrentTransactionState; /* changed by AbortOutOfAnyTransaction */ + s = CurrentTransactionState; /* changed by + * AbortOutOfAnyTransaction + * */ /* AbortOutOfAnyTransaction sets the blockState */ break; /* * We were just issued a SAVEPOINT inside a transaction block. - * Start a subtransaction. (DefineSavepoint already - * did PushTransaction, so as to have someplace to put the + * Start a subtransaction. (DefineSavepoint already did + * PushTransaction, so as to have someplace to put the * SUBBEGIN state.) */ case TBLOCK_SUBBEGIN: @@ -1720,14 +1730,15 @@ CommitTransactionCommand(void) * We were issued a RELEASE command, so we end the current * subtransaction and return to the parent transaction. * - * Since RELEASE can exit multiple levels of subtransaction, - * we must loop here until we get out of all SUBEND'ed levels. + * Since RELEASE can exit multiple levels of subtransaction, we + * must loop here until we get out of all SUBEND'ed levels. */ case TBLOCK_SUBEND: - do { + do + { CommitSubTransaction(); PopTransaction(); - s = CurrentTransactionState; /* changed by pop */ + s = CurrentTransactionState; /* changed by pop */ } while (s->blockState == TBLOCK_SUBEND); break; @@ -1738,25 +1749,26 @@ CommitTransactionCommand(void) break; /* - * The current subtransaction is ending. Do the equivalent - * of a ROLLBACK TO followed by a RELEASE command. + * The current subtransaction is ending. Do the equivalent of + * a ROLLBACK TO followed by a RELEASE command. */ case TBLOCK_SUBENDABORT_RELEASE: CleanupAbortedSubTransactions(false); break; /* - * The current subtransaction is ending due to a ROLLBACK - * TO command, so close all savepoints up to the target - * level. When finished, recreate the savepoint. + * The current subtransaction is ending due to a ROLLBACK TO + * command, so close all savepoints up to the target level. + * When finished, recreate the savepoint. */ case TBLOCK_SUBENDABORT: { - char *name = CleanupAbortedSubTransactions(true); + char *name = CleanupAbortedSubTransactions(true); Assert(PointerIsValid(name)); DefineSavepoint(name); - s = CurrentTransactionState; /* changed by DefineSavepoint */ + s = CurrentTransactionState; /* changed by + * DefineSavepoint */ pfree(name); /* This is the same as TBLOCK_SUBBEGIN case */ @@ -1780,8 +1792,8 @@ static char * CleanupAbortedSubTransactions(bool returnName) { TransactionState s = CurrentTransactionState; - char *name = NULL; - + char *name = NULL; + AssertState(PointerIsValid(s->parent)); Assert(s->parent->blockState == TBLOCK_SUBINPROGRESS || s->parent->blockState == TBLOCK_INPROGRESS || @@ -1798,7 +1810,7 @@ CleanupAbortedSubTransactions(bool returnName) CleanupSubTransaction(); PopTransaction(); - s = CurrentTransactionState; /* changed by pop */ + s = CurrentTransactionState; /* changed by pop */ while (s->blockState == TBLOCK_SUBABORT_PENDING) { @@ -1827,9 +1839,9 @@ AbortCurrentTransaction(void) switch (s->blockState) { - /* - * we aren't in a transaction, so we do nothing. - */ + /* + * we aren't in a transaction, so we do nothing. + */ case TBLOCK_DEFAULT: break; @@ -1856,10 +1868,10 @@ AbortCurrentTransaction(void) break; /* - * This is the case when we are somewhere in a transaction block - * and we've gotten a failure, so we abort the transaction and - * set up the persistent ABORT state. We will stay in ABORT - * until we get an "END TRANSACTION". + * This is the case when we are somewhere in a transaction + * block and we've gotten a failure, so we abort the + * transaction and set up the persistent ABORT state. We will + * stay in ABORT until we get an "END TRANSACTION". */ case TBLOCK_INPROGRESS: AbortTransaction(); @@ -1900,8 +1912,8 @@ AbortCurrentTransaction(void) break; /* - * If we are just starting a subtransaction, put it - * in aborted state. + * If we are just starting a subtransaction, put it in aborted + * state. */ case TBLOCK_SUBBEGIN: StartAbortedSubTransaction(); @@ -1914,8 +1926,8 @@ AbortCurrentTransaction(void) break; /* - * If we are aborting an ending transaction, - * we have to abort the parent transaction too. + * If we are aborting an ending transaction, we have to abort + * the parent transaction too. */ case TBLOCK_SUBEND: case TBLOCK_SUBABORT_PENDING: @@ -1924,7 +1936,7 @@ AbortCurrentTransaction(void) PopTransaction(); s = CurrentTransactionState; /* changed by pop */ Assert(s->blockState != TBLOCK_SUBEND && - s->blockState != TBLOCK_SUBENDABORT); + s->blockState != TBLOCK_SUBENDABORT); AbortCurrentTransaction(); break; @@ -1937,13 +1949,13 @@ AbortCurrentTransaction(void) PopTransaction(); s = CurrentTransactionState; /* changed by pop */ Assert(s->blockState != TBLOCK_SUBEND && - s->blockState != TBLOCK_SUBENDABORT); + s->blockState != TBLOCK_SUBENDABORT); AbortCurrentTransaction(); break; /* - * We are already aborting the whole transaction tree. - * Do nothing, CommitTransactionCommand will call + * We are already aborting the whole transaction tree. Do + * nothing, CommitTransactionCommand will call * AbortOutOfAnyTransaction and set things straight. */ case TBLOCK_SUBENDABORT_ALL: @@ -2068,8 +2080,8 @@ bool IsInTransactionChain(void *stmtNode) { /* - * Return true on same conditions that would make PreventTransactionChain - * error out + * Return true on same conditions that would make + * PreventTransactionChain error out */ if (IsTransactionBlock()) return true; @@ -2097,8 +2109,8 @@ IsInTransactionChain(void *stmtNode) * (mainly because it's easier to control the order that way, where needed). * * At transaction end, the callback occurs post-commit or post-abort, so the - * callback functions can only do noncritical cleanup. At subtransaction - * start, the callback is called when the subtransaction has finished + * callback functions can only do noncritical cleanup. At subtransaction + * start, the callback is called when the subtransaction has finished * initializing. */ void @@ -2141,9 +2153,7 @@ CallXactCallbacks(XactEvent event, TransactionId parentXid) XactCallbackItem *item; for (item = Xact_callbacks; item; item = item->next) - { (*item->callback) (event, parentXid, item->arg); - } } @@ -2164,8 +2174,8 @@ BeginTransactionBlock(void) switch (s->blockState) { /* - * We are not inside a transaction block, so allow one - * to begin. + * We are not inside a transaction block, so allow one to + * begin. */ case TBLOCK_STARTED: s->blockState = TBLOCK_BEGIN; @@ -2180,7 +2190,7 @@ BeginTransactionBlock(void) case TBLOCK_SUBABORT: ereport(WARNING, (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION), - errmsg("there is already a transaction in progress"))); + errmsg("there is already a transaction in progress"))); break; /* These cases are invalid. Reject them altogether. */ @@ -2215,12 +2225,13 @@ EndTransactionBlock(void) switch (s->blockState) { - /* - * We are in a transaction block which should commit when we - * get to the upcoming CommitTransactionCommand() so we set the - * state to "END". CommitTransactionCommand() will recognize this - * and commit the transaction and return us to the default state. - */ + /* + * We are in a transaction block which should commit when we + * get to the upcoming CommitTransactionCommand() so we set + * the state to "END". CommitTransactionCommand() will + * recognize this and commit the transaction and return us to + * the default state. + */ case TBLOCK_INPROGRESS: case TBLOCK_SUBINPROGRESS: s->blockState = TBLOCK_END; @@ -2229,30 +2240,31 @@ EndTransactionBlock(void) /* * We are in a transaction block which aborted. Since the - * AbortTransaction() was already done, we need only - * change to the special "END ABORT" state. The upcoming - * CommitTransactionCommand() will recognise this and then put us - * back in the default state. + * AbortTransaction() was already done, we need only change to + * the special "END ABORT" state. The upcoming + * CommitTransactionCommand() will recognise this and then put + * us back in the default state. */ case TBLOCK_ABORT: s->blockState = TBLOCK_ENDABORT; break; /* - * Here we are inside an aborted subtransaction. Go to the "abort - * the whole tree" state so that CommitTransactionCommand() calls - * AbortOutOfAnyTransaction. + * Here we are inside an aborted subtransaction. Go to the + * "abort the whole tree" state so that + * CommitTransactionCommand() calls AbortOutOfAnyTransaction. */ case TBLOCK_SUBABORT: s->blockState = TBLOCK_SUBENDABORT_ALL; break; case TBLOCK_STARTED: + /* - * here, the user issued COMMIT when not inside a - * transaction. Issue a WARNING and go to abort state. The - * upcoming call to CommitTransactionCommand() will then put us - * back into the default state. + * here, the user issued COMMIT when not inside a transaction. + * Issue a WARNING and go to abort state. The upcoming call + * to CommitTransactionCommand() will then put us back into + * the default state. */ ereport(WARNING, (errcode(ERRCODE_NO_ACTIVE_SQL_TRANSACTION), @@ -2303,11 +2315,10 @@ UserAbortTransactionBlock(void) break; /* - * We are inside a failed subtransaction and we got an - * abort command from the user. Abort processing is already - * done, so go to the "abort all" state and - * CommitTransactionCommand will call AbortOutOfAnyTransaction - * to set things straight. + * We are inside a failed subtransaction and we got an abort + * command from the user. Abort processing is already done, + * so go to the "abort all" state and CommitTransactionCommand + * will call AbortOutOfAnyTransaction to set things straight. */ case TBLOCK_SUBABORT: s->blockState = TBLOCK_SUBENDABORT_ALL; @@ -2325,7 +2336,7 @@ UserAbortTransactionBlock(void) break; /* - * We are inside a subtransaction. Abort the current + * We are inside a subtransaction. Abort the current * subtransaction and go to the "abort all" state, so * CommitTransactionCommand will call AbortOutOfAnyTransaction * to set things straight. @@ -2373,7 +2384,7 @@ UserAbortTransactionBlock(void) void DefineSavepoint(char *name) { - TransactionState s = CurrentTransactionState; + TransactionState s = CurrentTransactionState; switch (s->blockState) { @@ -2381,11 +2392,12 @@ DefineSavepoint(char *name) case TBLOCK_SUBINPROGRESS: /* Normal subtransaction start */ PushTransaction(); - s = CurrentTransactionState; /* changed by push */ + s = CurrentTransactionState; /* changed by push */ + /* * Note that we are allocating the savepoint name in the - * parent transaction's CurTransactionContext, since we - * don't yet have a transaction context for the new guy. + * parent transaction's CurTransactionContext, since we don't + * yet have a transaction context for the new guy. */ s->name = MemoryContextStrdup(CurTransactionContext, name); s->blockState = TBLOCK_SUBBEGIN; @@ -2413,16 +2425,16 @@ DefineSavepoint(char *name) /* * ReleaseSavepoint - * This executes a RELEASE command. + * This executes a RELEASE command. */ void ReleaseSavepoint(List *options) { - TransactionState s = CurrentTransactionState; + TransactionState s = CurrentTransactionState; TransactionState target, - xact; - ListCell *cell; - char *name = NULL; + xact; + ListCell *cell; + char *name = NULL; /* * Check valid block state transaction status. @@ -2437,8 +2449,8 @@ ReleaseSavepoint(List *options) break; /* - * We are in a non-aborted subtransaction. This is - * the only valid case. + * We are in a non-aborted subtransaction. This is the only + * valid case. */ case TBLOCK_SUBINPROGRESS: break; @@ -2461,9 +2473,9 @@ ReleaseSavepoint(List *options) break; } - foreach (cell, options) + foreach(cell, options) { - DefElem *elem = lfirst(cell); + DefElem *elem = lfirst(cell); if (strcmp(elem->defname, "savepoint_name") == 0) name = strVal(elem->arg); @@ -2490,8 +2502,8 @@ ReleaseSavepoint(List *options) /* * Mark "commit pending" all subtransactions up to the target - * subtransaction. The actual commits will happen when control - * gets to CommitTransactionCommand. + * subtransaction. The actual commits will happen when control gets + * to CommitTransactionCommand. */ xact = CurrentTransactionState; for (;;) @@ -2507,23 +2519,23 @@ ReleaseSavepoint(List *options) /* * RollbackToSavepoint - * This executes a ROLLBACK TO <savepoint> command. + * This executes a ROLLBACK TO <savepoint> command. */ void RollbackToSavepoint(List *options) { TransactionState s = CurrentTransactionState; TransactionState target, - xact; - ListCell *cell; - char *name = NULL; + xact; + ListCell *cell; + char *name = NULL; switch (s->blockState) { - /* - * We can't rollback to a savepoint if there is no saveopint - * defined. - */ + /* + * We can't rollback to a savepoint if there is no saveopint + * defined. + */ case TBLOCK_ABORT: case TBLOCK_INPROGRESS: ereport(ERROR, @@ -2536,9 +2548,10 @@ RollbackToSavepoint(List *options) */ case TBLOCK_SUBABORT: case TBLOCK_SUBINPROGRESS: + /* - * Have to do AbortSubTransaction, but first check - * if this is the right subtransaction + * Have to do AbortSubTransaction, but first check if this is + * the right subtransaction */ break; @@ -2559,9 +2572,9 @@ RollbackToSavepoint(List *options) break; } - foreach (cell, options) + foreach(cell, options) { - DefElem *elem = lfirst(cell); + DefElem *elem = lfirst(cell); if (strcmp(elem->defname, "savepoint_name") == 0) name = strVal(elem->arg); @@ -2597,7 +2610,7 @@ RollbackToSavepoint(List *options) /* * Mark "abort pending" all subtransactions up to the target - * subtransaction. (Except the current subtransaction!) + * subtransaction. (Except the current subtransaction!) */ xact = CurrentTransactionState; @@ -2623,7 +2636,7 @@ RollbackToSavepoint(List *options) void BeginInternalSubTransaction(char *name) { - TransactionState s = CurrentTransactionState; + TransactionState s = CurrentTransactionState; switch (s->blockState) { @@ -2632,11 +2645,12 @@ BeginInternalSubTransaction(char *name) case TBLOCK_SUBINPROGRESS: /* Normal subtransaction start */ PushTransaction(); - s = CurrentTransactionState; /* changed by push */ + s = CurrentTransactionState; /* changed by push */ + /* * Note that we are allocating the savepoint name in the - * parent transaction's CurTransactionContext, since we - * don't yet have a transaction context for the new guy. + * parent transaction's CurTransactionContext, since we don't + * yet have a transaction context for the new guy. */ if (name) s->name = MemoryContextStrdup(CurTransactionContext, name); @@ -2698,7 +2712,7 @@ RollbackAndReleaseCurrentSubTransaction(void) switch (s->blockState) { - /* Must be in a subtransaction */ + /* Must be in a subtransaction */ case TBLOCK_SUBABORT: case TBLOCK_SUBINPROGRESS: break; @@ -2748,7 +2762,8 @@ AbortOutOfAnyTransaction(void) /* * Get out of any transaction or nested transaction */ - do { + do + { switch (s->blockState) { case TBLOCK_DEFAULT: @@ -2770,21 +2785,26 @@ AbortOutOfAnyTransaction(void) s->blockState = TBLOCK_DEFAULT; break; case TBLOCK_SUBBEGIN: + /* - * We didn't get as far as starting the subxact, so there's - * nothing to abort. Just pop back to parent. + * We didn't get as far as starting the subxact, so + * there's nothing to abort. Just pop back to parent. */ PopTransaction(); - s = CurrentTransactionState; /* changed by pop */ + s = CurrentTransactionState; /* changed by pop */ break; case TBLOCK_SUBINPROGRESS: case TBLOCK_SUBEND: case TBLOCK_SUBABORT_PENDING: - /* In a subtransaction, so clean it up and abort parent too */ + + /* + * In a subtransaction, so clean it up and abort parent + * too + */ AbortSubTransaction(); CleanupSubTransaction(); PopTransaction(); - s = CurrentTransactionState; /* changed by pop */ + s = CurrentTransactionState; /* changed by pop */ break; case TBLOCK_SUBABORT: case TBLOCK_SUBENDABORT_ALL: @@ -2793,7 +2813,7 @@ AbortOutOfAnyTransaction(void) /* As above, but AbortSubTransaction already done */ CleanupSubTransaction(); PopTransaction(); - s = CurrentTransactionState; /* changed by pop */ + s = CurrentTransactionState; /* changed by pop */ break; } } while (s->blockState != TBLOCK_DEFAULT); @@ -2819,7 +2839,7 @@ CommitTransactionToLevel(int level) { CommitSubTransaction(); PopTransaction(); - s = CurrentTransactionState; /* changed by pop */ + s = CurrentTransactionState; /* changed by pop */ Assert(s->state == TRANS_INPROGRESS); } } @@ -2840,7 +2860,7 @@ IsTransactionBlock(void) /* * IsTransactionOrTransactionBlock --- are we within either a transaction - * or a transaction block? (The backend is only really "idle" when this + * or a transaction block? (The backend is only really "idle" when this * returns false.) * * This should match up with IsTransactionBlock and IsTransactionState. @@ -2928,9 +2948,10 @@ StartSubTransaction(void) /* * Generate a new Xid and record it in pg_subtrans. NB: we must make - * the subtrans entry BEFORE the Xid appears anywhere in shared storage, - * such as in the lock table; because until it's made the Xid may not - * appear to be "running" to other backends. See GetNewTransactionId. + * the subtrans entry BEFORE the Xid appears anywhere in shared + * storage, such as in the lock table; because until it's made the Xid + * may not appear to be "running" to other backends. See + * GetNewTransactionId. */ s->transactionIdData = GetNewTransactionId(true); @@ -2943,7 +2964,7 @@ StartSubTransaction(void) */ s->currentUser = GetUserId(); s->prevXactReadOnly = XactReadOnly; - + /* * Initialize other subsystems for new subtransaction */ @@ -2954,7 +2975,7 @@ StartSubTransaction(void) s->state = TRANS_INPROGRESS; /* - * Call start-of-subxact callbacks + * Call start-of-subxact callbacks */ CallXactCallbacks(XACT_EVENT_START_SUB, s->parent->transactionIdData); @@ -3020,9 +3041,9 @@ CommitSubTransaction(void) s->parent->transactionIdData); /* - * We need to restore the upper transaction's read-only state, - * in case the upper is read-write while the child is read-only; - * GUC will incorrectly think it should leave the child state in place. + * We need to restore the upper transaction's read-only state, in case + * the upper is read-write while the child is read-only; GUC will + * incorrectly think it should leave the child state in place. */ XactReadOnly = s->prevXactReadOnly; @@ -3117,14 +3138,16 @@ AbortSubTransaction(void) /* * Reset user id which might have been changed transiently. Here we * want to restore to the userid that was current at subxact entry. - * (As in AbortTransaction, we need not worry about the session userid.) + * (As in AbortTransaction, we need not worry about the session + * userid.) * * Must do this after AtEOXact_GUC to handle the case where we entered * the subxact inside a SECURITY DEFINER function (hence current and * session userids were different) and then session auth was changed - * inside the subxact. GUC will reset both current and session userids - * to the entry-time session userid. This is right in every other - * scenario so it seems simplest to let GUC do that and fix it here. + * inside the subxact. GUC will reset both current and session + * userids to the entry-time session userid. This is right in every + * other scenario so it seems simplest to let GUC do that and fix it + * here. */ SetUserId(s->currentUser); @@ -3168,11 +3191,11 @@ CleanupSubTransaction(void) * StartAbortedSubTransaction * * This function is used to start a subtransaction and put it immediately - * into aborted state. The end result should be equivalent to + * into aborted state. The end result should be equivalent to * StartSubTransaction immediately followed by AbortSubTransaction. * The reason we don't implement it just that way is that many of the backend * modules aren't designed to handle starting a subtransaction when not - * inside a valid transaction. Rather than making them all capable of + * inside a valid transaction. Rather than making them all capable of * doing that, we just omit the paired start and abort calls in this path. */ static void @@ -3195,9 +3218,10 @@ StartAbortedSubTransaction(void) /* Make sure currentUser is reasonably valid */ Assert(s->parent != NULL); s->currentUser = s->parent->currentUser; - + /* - * Initialize only what has to be there for CleanupSubTransaction to work. + * Initialize only what has to be there for CleanupSubTransaction to + * work. */ AtSubStart_Memory(); AtSubStart_ResourceOwner(); @@ -3219,8 +3243,8 @@ StartAbortedSubTransaction(void) static void PushTransaction(void) { - TransactionState p = CurrentTransactionState; - TransactionState s; + TransactionState p = CurrentTransactionState; + TransactionState s; /* * We keep subtransaction state nodes in TopTransactionContext. @@ -3315,7 +3339,7 @@ ShowTransactionStateRec(TransactionState s) /* use ereport to suppress computation if msg will not be printed */ ereport(DEBUG2, (errmsg_internal("name: %s; blockState: %13s; state: %7s, xid/cid: %u/%02u, nestlvl: %d, children: %s", - PointerIsValid(s->name) ? s->name : "unnamed", + PointerIsValid(s->name) ? s->name : "unnamed", BlockStateAsString(s->blockState), TransStateAsString(s->state), (unsigned int) s->transactionIdData, @@ -3393,7 +3417,7 @@ TransStateAsString(TransState state) /* * xactGetCommittedChildren * - * Gets the list of committed children of the current transaction. The return + * Gets the list of committed children of the current transaction. The return * value is the number of child transactions. *children is set to point to a * palloc'd array of TransactionIds. If there are no subxacts, *children is * set to NULL. @@ -3401,10 +3425,10 @@ TransStateAsString(TransState state) int xactGetCommittedChildren(TransactionId **ptr) { - TransactionState s = CurrentTransactionState; - int nchildren; - TransactionId *children; - ListCell *p; + TransactionState s = CurrentTransactionState; + int nchildren; + TransactionId *children; + ListCell *p; nchildren = list_length(s->childXids); if (nchildren == 0) @@ -3438,12 +3462,12 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record) if (info == XLOG_XACT_COMMIT) { xl_xact_commit *xlrec = (xl_xact_commit *) XLogRecGetData(record); - int i; + int i; TransactionIdCommit(record->xl_xid); /* Mark committed subtransactions as committed */ TransactionIdCommitTree(xlrec->nsubxacts, - (TransactionId *) &(xlrec->xnodes[xlrec->nrels])); + (TransactionId *) &(xlrec->xnodes[xlrec->nrels])); /* Make sure files supposed to be dropped are dropped */ for (i = 0; i < xlrec->nrels; i++) { @@ -3454,12 +3478,12 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record) else if (info == XLOG_XACT_ABORT) { xl_xact_abort *xlrec = (xl_xact_abort *) XLogRecGetData(record); - int i; + int i; TransactionIdAbort(record->xl_xid); /* mark subtransactions as aborted */ TransactionIdAbortTree(xlrec->nsubxacts, - (TransactionId *) &(xlrec->xnodes[xlrec->nrels])); + (TransactionId *) &(xlrec->xnodes[xlrec->nrels])); /* Make sure files supposed to be dropped are dropped */ for (i = 0; i < xlrec->nrels; i++) { @@ -3486,7 +3510,7 @@ void xact_desc(char *buf, uint8 xl_info, char *rec) { uint8 info = xl_info & ~XLR_INFO_MASK; - int i; + int i; if (info == XLOG_XACT_COMMIT) { @@ -3502,6 +3526,7 @@ xact_desc(char *buf, uint8 xl_info, char *rec) for (i = 0; i < xlrec->nrels; i++) { RelFileNode rnode = xlrec->xnodes[i]; + sprintf(buf + strlen(buf), " %u/%u/%u", rnode.spcNode, rnode.dbNode, rnode.relNode); } @@ -3509,7 +3534,7 @@ xact_desc(char *buf, uint8 xl_info, char *rec) if (xlrec->nsubxacts > 0) { TransactionId *xacts = (TransactionId *) - &xlrec->xnodes[xlrec->nrels]; + &xlrec->xnodes[xlrec->nrels]; sprintf(buf + strlen(buf), "; subxacts:"); for (i = 0; i < xlrec->nsubxacts; i++) @@ -3530,6 +3555,7 @@ xact_desc(char *buf, uint8 xl_info, char *rec) for (i = 0; i < xlrec->nrels; i++) { RelFileNode rnode = xlrec->xnodes[i]; + sprintf(buf + strlen(buf), " %u/%u/%u", rnode.spcNode, rnode.dbNode, rnode.relNode); } @@ -3537,7 +3563,7 @@ xact_desc(char *buf, uint8 xl_info, char *rec) if (xlrec->nsubxacts > 0) { TransactionId *xacts = (TransactionId *) - &xlrec->xnodes[xlrec->nrels]; + &xlrec->xnodes[xlrec->nrels]; sprintf(buf + strlen(buf), "; subxacts:"); for (i = 0; i < xlrec->nsubxacts; i++) @@ -3549,7 +3575,7 @@ xact_desc(char *buf, uint8 xl_info, char *rec) } void -XactPushRollback(void (*func) (void *), void *data) + XactPushRollback(void (*func) (void *), void *data) { #ifdef XLOG_II if (_RollbackFunc != NULL) diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 309f17a83fc..e65c109f665 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.165 2004/08/29 04:12:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.166 2004/08/29 05:06:40 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -128,26 +128,28 @@ TimeLineID ThisTimeLineID = 0; /* Are we doing recovery from XLOG? */ bool InRecovery = false; + /* Are we recovering using offline XLOG archives? */ -static bool InArchiveRecovery = false; +static bool InArchiveRecovery = false; + /* Was the last xlog file restored from archive, or local? */ -static bool restoredFromArchive = false; +static bool restoredFromArchive = false; /* options taken from recovery.conf */ static char *recoveryRestoreCommand = NULL; static bool recoveryTarget = false; static bool recoveryTargetExact = false; static bool recoveryTargetInclusive = true; -static TransactionId recoveryTargetXid; -static time_t recoveryTargetTime; +static TransactionId recoveryTargetXid; +static time_t recoveryTargetTime; /* if recoveryStopsHere returns true, it saves actual stop xid/time here */ -static TransactionId recoveryStopXid; -static time_t recoveryStopTime; -static bool recoveryStopAfter; +static TransactionId recoveryStopXid; +static time_t recoveryStopTime; +static bool recoveryStopAfter; /* constraint set by read_backup_label */ -static XLogRecPtr recoveryMinXlogOffset = { 0, 0 }; +static XLogRecPtr recoveryMinXlogOffset = {0, 0}; /* * During normal operation, the only timeline we care about is ThisTimeLineID. @@ -161,7 +163,7 @@ static XLogRecPtr recoveryMinXlogOffset = { 0, 0 }; * * expectedTLIs: an integer list of recoveryTargetTLI and the TLIs of * its known parents, newest first (so recoveryTargetTLI is always the - * first list member). Only these TLIs are expected to be seen in the WAL + * first list member). Only these TLIs are expected to be seen in the WAL * segments we read, and indeed only these TLIs will be considered as * candidate WAL files to open at all. * @@ -171,9 +173,9 @@ static XLogRecPtr recoveryMinXlogOffset = { 0, 0 }; * file was created.) During a sequential scan we do not allow this value * to decrease. */ -static TimeLineID recoveryTargetTLI; -static List *expectedTLIs; -static TimeLineID curFileTLI; +static TimeLineID recoveryTargetTLI; +static List *expectedTLIs; +static TimeLineID curFileTLI; /* * MyLastRecPtr points to the start of the last XLOG record inserted by the @@ -373,7 +375,7 @@ static ControlFileData *ControlFile = NULL; /* File path names */ -char XLogDir[MAXPGPATH]; +char XLogDir[MAXPGPATH]; static char ControlFilePath[MAXPGPATH]; /* @@ -422,7 +424,7 @@ static bool XLogArchiveIsDone(const char *xlog); static void XLogArchiveCleanup(const char *xlog); static void readRecoveryCommandFile(void); static void exitArchiveRecovery(TimeLineID endTLI, - uint32 endLogId, uint32 endLogSeg); + uint32 endLogId, uint32 endLogSeg); static bool recoveryStopsHere(XLogRecord *record, bool *includeThis); static bool AdvanceXLInsertBuffer(void); @@ -435,7 +437,7 @@ static bool InstallXLogFileSegment(uint32 log, uint32 seg, char *tmppath, static int XLogFileOpen(uint32 log, uint32 seg); static int XLogFileRead(uint32 log, uint32 seg, int emode); static bool RestoreArchivedFile(char *path, const char *xlogfname, - const char *recovername, off_t expectedSize); + const char *recovername, off_t expectedSize); static void PreallocXlogFiles(XLogRecPtr endptr); static void MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr); static XLogRecord *ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer); @@ -447,12 +449,13 @@ static List *readTimeLineHistory(TimeLineID targetTLI); static bool existsTimeLineHistory(TimeLineID probeTLI); static TimeLineID findNewestTimeLine(TimeLineID startTLI); static void writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, - TimeLineID endTLI, - uint32 endLogId, uint32 endLogSeg); + TimeLineID endTLI, + uint32 endLogId, uint32 endLogSeg); static void WriteControlFile(void); static void ReadControlFile(void); static char *str_time(time_t tnow); static void issue_xlog_fsync(void); + #ifdef WAL_DEBUG static void xlog_outrec(char *buf, XLogRecord *record); #endif @@ -514,7 +517,8 @@ XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata) if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID) { RecPtr.xlogid = 0; - RecPtr.xrecoff = SizeOfXLogLongPHD; /* start of 1st chkpt record */ + RecPtr.xrecoff = SizeOfXLogLongPHD; /* start of 1st chkpt + * record */ return (RecPtr); } @@ -724,7 +728,8 @@ begin:; /* * If there isn't enough space on the current XLOG page for a record - * header, advance to the next page (leaving the unused space as zeroes). + * header, advance to the next page (leaving the unused space as + * zeroes). */ updrqst = false; freespace = INSERT_FREESPACE(Insert); @@ -895,19 +900,21 @@ static void XLogArchiveNotify(const char *xlog) { char archiveStatusPath[MAXPGPATH]; - FILE *fd; + FILE *fd; /* insert an otherwise empty file called <XLOG>.ready */ StatusFilePath(archiveStatusPath, xlog, ".ready"); fd = AllocateFile(archiveStatusPath, "w"); - if (fd == NULL) { + if (fd == NULL) + { ereport(LOG, (errcode_for_file_access(), errmsg("could not create archive status file \"%s\": %m", archiveStatusPath))); return; } - if (FreeFile(fd)) { + if (FreeFile(fd)) + { ereport(LOG, (errcode_for_file_access(), errmsg("could not write archive status file \"%s\": %m", @@ -935,7 +942,7 @@ XLogArchiveNotifySeg(uint32 log, uint32 seg) /* * XLogArchiveIsDone * - * Checks for a ".done" archive notification file. This is called when we + * Checks for a ".done" archive notification file. This is called when we * are ready to delete or recycle an old XLOG segment file. If it is okay * to delete it then return true. * @@ -958,7 +965,7 @@ XLogArchiveIsDone(const char *xlog) /* check for .ready --- this means archiver is still busy with it */ StatusFilePath(archiveStatusPath, xlog, ".ready"); if (stat(archiveStatusPath, &stat_buf) == 0) - return false; + return false; /* Race condition --- maybe archiver just finished, so recheck */ StatusFilePath(archiveStatusPath, xlog, ".done"); @@ -978,7 +985,7 @@ XLogArchiveIsDone(const char *xlog) static void XLogArchiveCleanup(const char *xlog) { - char archiveStatusPath[MAXPGPATH]; + char archiveStatusPath[MAXPGPATH]; /* Remove the .done file */ StatusFilePath(archiveStatusPath, xlog, ".done"); @@ -1267,8 +1274,8 @@ XLogWrite(XLogwrtRqst WriteRqst) issue_xlog_fsync(); LogwrtResult.Flush = LogwrtResult.Write; /* end of current page */ - if (XLogArchivingActive()) - XLogArchiveNotifySeg(openLogId, openLogSeg); + if (XLogArchivingActive()) + XLogArchiveNotifySeg(openLogId, openLogSeg); } if (ispartialpage) @@ -1552,7 +1559,7 @@ XLogFileInit(uint32 log, uint32 seg, ereport(PANIC, (errcode_for_file_access(), - errmsg("could not write to file \"%s\": %m", tmppath))); + errmsg("could not write to file \"%s\": %m", tmppath))); } } @@ -1591,8 +1598,8 @@ XLogFileInit(uint32 log, uint32 seg, if (fd < 0) ereport(PANIC, (errcode_for_file_access(), - errmsg("could not open file \"%s\" (log file %u, segment %u): %m", - path, log, seg))); + errmsg("could not open file \"%s\" (log file %u, segment %u): %m", + path, log, seg))); return (fd); } @@ -1606,7 +1613,7 @@ XLogFileInit(uint32 log, uint32 seg, * a different timeline) * * Currently this is only used during recovery, and so there are no locking - * considerations. But we should be just as tense as XLogFileInit to avoid + * considerations. But we should be just as tense as XLogFileInit to avoid * emplacing a bogus file. */ static void @@ -1660,7 +1667,7 @@ XLogFileCopy(uint32 log, uint32 seg, errmsg("could not read file \"%s\": %m", path))); else ereport(PANIC, - (errmsg("insufficient data in file \"%s\"", path))); + (errmsg("insufficient data in file \"%s\"", path))); } errno = 0; if ((int) write(fd, buffer, sizeof(buffer)) != (int) sizeof(buffer)) @@ -1677,7 +1684,7 @@ XLogFileCopy(uint32 log, uint32 seg, ereport(PANIC, (errcode_for_file_access(), - errmsg("could not write to file \"%s\": %m", tmppath))); + errmsg("could not write to file \"%s\": %m", tmppath))); } } @@ -1805,8 +1812,8 @@ XLogFileOpen(uint32 log, uint32 seg) if (fd < 0) ereport(PANIC, (errcode_for_file_access(), - errmsg("could not open file \"%s\" (log file %u, segment %u): %m", - path, log, seg))); + errmsg("could not open file \"%s\" (log file %u, segment %u): %m", + path, log, seg))); return fd; } @@ -1823,11 +1830,11 @@ XLogFileRead(uint32 log, uint32 seg, int emode) int fd; /* - * Loop looking for a suitable timeline ID: we might need to - * read any of the timelines listed in expectedTLIs. + * Loop looking for a suitable timeline ID: we might need to read any + * of the timelines listed in expectedTLIs. * - * We expect curFileTLI on entry to be the TLI of the preceding file - * in sequence, or 0 if there was no predecessor. We do not allow + * We expect curFileTLI on entry to be the TLI of the preceding file in + * sequence, or 0 if there was no predecessor. We do not allow * curFileTLI to go backwards; this prevents us from picking up the * wrong file when a parent timeline extends to higher segment numbers * than the child we want to read. @@ -1868,8 +1875,8 @@ XLogFileRead(uint32 log, uint32 seg, int emode) errno = ENOENT; ereport(emode, (errcode_for_file_access(), - errmsg("could not open file \"%s\" (log file %u, segment %u): %m", - path, log, seg))); + errmsg("could not open file \"%s\" (log file %u, segment %u): %m", + path, log, seg))); return -1; } @@ -1891,36 +1898,37 @@ static bool RestoreArchivedFile(char *path, const char *xlogfname, const char *recovername, off_t expectedSize) { - char xlogpath[MAXPGPATH]; - char xlogRestoreCmd[MAXPGPATH]; - char *dp; - char *endp; + char xlogpath[MAXPGPATH]; + char xlogRestoreCmd[MAXPGPATH]; + char *dp; + char *endp; const char *sp; - int rc; + int rc; struct stat stat_buf; /* * When doing archive recovery, we always prefer an archived log file * even if a file of the same name exists in XLogDir. The reason is - * that the file in XLogDir could be an old, un-filled or partly-filled - * version that was copied and restored as part of backing up $PGDATA. + * that the file in XLogDir could be an old, un-filled or + * partly-filled version that was copied and restored as part of + * backing up $PGDATA. * - * We could try to optimize this slightly by checking the local - * copy lastchange timestamp against the archived copy, - * but we have no API to do this, nor can we guarantee that the - * lastchange timestamp was preserved correctly when we copied - * to archive. Our aim is robustness, so we elect not to do this. + * We could try to optimize this slightly by checking the local copy + * lastchange timestamp against the archived copy, but we have no API + * to do this, nor can we guarantee that the lastchange timestamp was + * preserved correctly when we copied to archive. Our aim is + * robustness, so we elect not to do this. * - * If we cannot obtain the log file from the archive, however, we - * will try to use the XLogDir file if it exists. This is so that - * we can make use of log segments that weren't yet transferred to - * the archive. + * If we cannot obtain the log file from the archive, however, we will + * try to use the XLogDir file if it exists. This is so that we can + * make use of log segments that weren't yet transferred to the + * archive. * * Notice that we don't actually overwrite any files when we copy back * from archive because the recoveryRestoreCommand may inadvertently - * restore inappropriate xlogs, or they may be corrupt, so we may - * wish to fallback to the segments remaining in current XLogDir later. - * The copy-from-archive filename is always the same, ensuring that we + * restore inappropriate xlogs, or they may be corrupt, so we may wish + * to fallback to the segments remaining in current XLogDir later. The + * copy-from-archive filename is always the same, ensuring that we * don't run out of disk space on long recoveries. */ snprintf(xlogpath, MAXPGPATH, "%s/%s", XLogDir, recovername); @@ -1961,14 +1969,14 @@ RestoreArchivedFile(char *path, const char *xlogfname, case 'p': /* %p: full path of target file */ sp++; - StrNCpy(dp, xlogpath, endp-dp); + StrNCpy(dp, xlogpath, endp - dp); make_native_path(dp); dp += strlen(dp); break; case 'f': /* %f: filename of desired file */ sp++; - StrNCpy(dp, xlogfname, endp-dp); + StrNCpy(dp, xlogfname, endp - dp); dp += strlen(dp); break; case '%': @@ -1993,7 +2001,7 @@ RestoreArchivedFile(char *path, const char *xlogfname, *dp = '\0'; ereport(DEBUG3, - (errmsg_internal("executing restore command \"%s\"", + (errmsg_internal("executing restore command \"%s\"", xlogRestoreCmd))); /* @@ -2006,9 +2014,9 @@ RestoreArchivedFile(char *path, const char *xlogfname, * command apparently succeeded, but let's make sure the file is * really there now and has the correct size. * - * XXX I made wrong-size a fatal error to ensure the DBA would - * notice it, but is that too strong? We could try to plow ahead - * with a local copy of the file ... but the problem is that there + * XXX I made wrong-size a fatal error to ensure the DBA would notice + * it, but is that too strong? We could try to plow ahead with a + * local copy of the file ... but the problem is that there * probably isn't one, and we'd incorrectly conclude we've reached * the end of WAL and we're done recovering ... */ @@ -2041,23 +2049,23 @@ RestoreArchivedFile(char *path, const char *xlogfname, } /* - * remember, we rollforward UNTIL the restore fails - * so failure here is just part of the process... - * that makes it difficult to determine whether the restore - * failed because there isn't an archive to restore, or - * because the administrator has specified the restore + * remember, we rollforward UNTIL the restore fails so failure here is + * just part of the process... that makes it difficult to determine + * whether the restore failed because there isn't an archive to + * restore, or because the administrator has specified the restore * program incorrectly. We have to assume the former. */ ereport(DEBUG1, - (errmsg("could not restore \"%s\" from archive: return code %d", - xlogfname, rc))); + (errmsg("could not restore \"%s\" from archive: return code %d", + xlogfname, rc))); /* - * if an archived file is not available, there might still be a version - * of this file in XLogDir, so return that as the filename to open. + * if an archived file is not available, there might still be a + * version of this file in XLogDir, so return that as the filename to + * open. * - * In many recovery scenarios we expect this to fail also, but - * if so that just means we've reached the end of WAL. + * In many recovery scenarios we expect this to fail also, but if so that + * just means we've reached the end of WAL. */ snprintf(path, MAXPGPATH, "%s/%s", XLogDir, xlogfname); return false; @@ -2118,24 +2126,24 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr) { /* * We ignore the timeline part of the XLOG segment identifiers in - * deciding whether a segment is still needed. This ensures that + * deciding whether a segment is still needed. This ensures that * we won't prematurely remove a segment from a parent timeline. * We could probably be a little more proactive about removing * segments of non-parent timelines, but that would be a whole lot * more complicated. * - * We use the alphanumeric sorting property of the filenames to decide - * which ones are earlier than the lastoff segment. + * We use the alphanumeric sorting property of the filenames to + * decide which ones are earlier than the lastoff segment. */ if (strlen(xlde->d_name) == 24 && strspn(xlde->d_name, "0123456789ABCDEF") == 24 && strcmp(xlde->d_name + 8, lastoff + 8) <= 0) { - bool recycle; + bool recycle; if (XLogArchivingActive()) recycle = XLogArchiveIsDone(xlde->d_name); - else + else recycle = true; if (recycle) @@ -2160,8 +2168,8 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr) { /* No need for any more future segments... */ ereport(LOG, - (errmsg("removing transaction log file \"%s\"", - xlde->d_name))); + (errmsg("removing transaction log file \"%s\"", + xlde->d_name))); unlink(path); } @@ -2171,8 +2179,11 @@ MoveOfflineLogs(uint32 log, uint32 seg, XLogRecPtr endptr) errno = 0; } #ifdef WIN32 - /* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but - not in released version */ + + /* + * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but + * not in released version + */ if (GetLastError() == ERROR_NO_MORE_FILES) errno = 0; #endif @@ -2263,8 +2274,8 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode) if (!EQ_CRC64(record->xl_crc, crc)) { ereport(emode, - (errmsg("incorrect resource manager data checksum in record at %X/%X", - recptr.xlogid, recptr.xrecoff))); + (errmsg("incorrect resource manager data checksum in record at %X/%X", + recptr.xlogid, recptr.xrecoff))); return (false); } @@ -2286,8 +2297,8 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode) if (!EQ_CRC64(cbuf, crc)) { ereport(emode, - (errmsg("incorrect checksum of backup block %d in record at %X/%X", - i + 1, recptr.xlogid, recptr.xrecoff))); + (errmsg("incorrect checksum of backup block %d in record at %X/%X", + i + 1, recptr.xlogid, recptr.xrecoff))); return (false); } blk += sizeof(BkpBlock) + BLCKSZ; @@ -2361,12 +2372,13 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer) ereport(PANIC, (errmsg("invalid record offset at %X/%X", RecPtr->xlogid, RecPtr->xrecoff))); + /* * Since we are going to a random position in WAL, forget any - * prior state about what timeline we were in, and allow it - * to be any timeline in expectedTLIs. We also set a flag to - * allow curFileTLI to go backwards (but we can't reset that - * variable right here, since we might not change files at all). + * prior state about what timeline we were in, and allow it to be + * any timeline in expectedTLIs. We also set a flag to allow + * curFileTLI to go backwards (but we can't reset that variable + * right here, since we might not change files at all). */ lastPageTLI = 0; /* see comment in ValidXLOGHeader */ randAccess = true; /* allow curFileTLI to go backwards too */ @@ -2418,9 +2430,9 @@ ReadRecord(XLogRecPtr *RecPtr, int emode, char *buffer) if (targetRecOff == 0) { /* - * Can only get here in the continuing-from-prev-page case, because - * XRecOffIsValid eliminated the zero-page-offset case otherwise. - * Need to skip over the new page's header. + * Can only get here in the continuing-from-prev-page case, + * because XRecOffIsValid eliminated the zero-page-offset case + * otherwise. Need to skip over the new page's header. */ tmpRecPtr.xrecoff += pageHeaderSize; targetRecOff = pageHeaderSize; @@ -2631,15 +2643,15 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode) ControlFile->system_identifier); ereport(emode, (errmsg("WAL file is from different system"), - errdetail("WAL file SYSID is %s, pg_control SYSID is %s", - fhdrident_str, sysident_str))); + errdetail("WAL file SYSID is %s, pg_control SYSID is %s", + fhdrident_str, sysident_str))); return false; } if (longhdr->xlp_seg_size != XLogSegSize) { ereport(emode, (errmsg("WAL file is from different system"), - errdetail("Incorrect XLOG_SEG_SIZE in page header."))); + errdetail("Incorrect XLOG_SEG_SIZE in page header."))); return false; } } @@ -2671,9 +2683,9 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode) * immediate parent's TLI, we should never see TLI go backwards across * successive pages of a consistent WAL sequence. * - * Of course this check should only be applied when advancing sequentially - * across pages; therefore ReadRecord resets lastPageTLI to zero when - * going to a random page. + * Of course this check should only be applied when advancing + * sequentially across pages; therefore ReadRecord resets lastPageTLI + * to zero when going to a random page. */ if (hdr->xlp_tli < lastPageTLI) { @@ -2691,7 +2703,7 @@ ValidXLOGHeader(XLogPageHeader hdr, int emode) * Try to read a timeline's history file. * * If successful, return the list of component TLIs (the given TLI followed by - * its ancestor TLIs). If we can't find the history file, assume that the + * its ancestor TLIs). If we can't find the history file, assume that the * timeline has no parents, and return a list of just the specified timeline * ID. */ @@ -2702,7 +2714,7 @@ readTimeLineHistory(TimeLineID targetTLI) char path[MAXPGPATH]; char histfname[MAXFNAMELEN]; char fline[MAXPGPATH]; - FILE *fd; + FILE *fd; if (InArchiveRecovery) { @@ -2712,7 +2724,7 @@ readTimeLineHistory(TimeLineID targetTLI) else TLHistoryFilePath(path, targetTLI); - fd = AllocateFile(path, "r"); + fd = AllocateFile(path, "r"); if (fd == NULL) { if (errno != ENOENT) @@ -2725,15 +2737,15 @@ readTimeLineHistory(TimeLineID targetTLI) result = NIL; - /* - * Parse the file... - */ - while (fgets(fline, MAXPGPATH, fd) != NULL) + /* + * Parse the file... + */ + while (fgets(fline, MAXPGPATH, fd) != NULL) { /* skip leading whitespace and check for # comment */ - char *ptr; - char *endptr; - TimeLineID tli; + char *ptr; + char *endptr; + TimeLineID tli; for (ptr = fline; *ptr; ptr++) { @@ -2754,7 +2766,7 @@ readTimeLineHistory(TimeLineID targetTLI) tli <= (TimeLineID) linitial_int(result)) ereport(FATAL, (errmsg("invalid data in history file: %s", fline), - errhint("Timeline IDs must be in increasing sequence."))); + errhint("Timeline IDs must be in increasing sequence."))); /* Build list with newest item first */ result = lcons_int((int) tli, result); @@ -2768,7 +2780,7 @@ readTimeLineHistory(TimeLineID targetTLI) targetTLI <= (TimeLineID) linitial_int(result)) ereport(FATAL, (errmsg("invalid data in history file \"%s\"", path), - errhint("Timeline IDs must be less than child timeline's ID."))); + errhint("Timeline IDs must be less than child timeline's ID."))); result = lcons_int((int) targetTLI, result); @@ -2787,7 +2799,7 @@ existsTimeLineHistory(TimeLineID probeTLI) { char path[MAXPGPATH]; char histfname[MAXFNAMELEN]; - FILE *fd; + FILE *fd; if (InArchiveRecovery) { @@ -2827,12 +2839,12 @@ findNewestTimeLine(TimeLineID startTLI) TimeLineID probeTLI; /* - * The algorithm is just to probe for the existence of timeline history - * files. XXX is it useful to allow gaps in the sequence? + * The algorithm is just to probe for the existence of timeline + * history files. XXX is it useful to allow gaps in the sequence? */ newestTLI = startTLI; - for (probeTLI = startTLI + 1; ; probeTLI++) + for (probeTLI = startTLI + 1;; probeTLI++) { if (existsTimeLineHistory(probeTLI)) { @@ -2856,7 +2868,7 @@ findNewestTimeLine(TimeLineID startTLI) * endTLI et al: ID of the last used WAL file, for annotation purposes * * Currently this is only used during recovery, and so there are no locking - * considerations. But we should be just as tense as XLogFileInit to avoid + * considerations. But we should be just as tense as XLogFileInit to avoid * emplacing a bogus file. */ static void @@ -2872,7 +2884,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, int fd; int nbytes; - Assert(newTLI > parentTLI); /* else bad selection of newTLI */ + Assert(newTLI > parentTLI); /* else bad selection of newTLI */ /* * Write into a temp file name. @@ -2932,12 +2944,16 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, * space */ unlink(tmppath); - /* if write didn't set errno, assume problem is no disk space */ + + /* + * if write didn't set errno, assume problem is no disk + * space + */ errno = save_errno ? save_errno : ENOSPC; ereport(PANIC, (errcode_for_file_access(), - errmsg("could not write to file \"%s\": %m", tmppath))); + errmsg("could not write to file \"%s\": %m", tmppath))); } } close(srcfd); @@ -2946,8 +2962,8 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, /* * Append one line with the details of this timeline split. * - * If we did have a parent file, insert an extra newline just in case - * the parent file failed to end with one. + * If we did have a parent file, insert an extra newline just in case the + * parent file failed to end with one. */ XLogFileName(xlogfname, endTLI, endLogId, endLogSeg); @@ -2967,8 +2983,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI, int save_errno = errno; /* - * If we fail to make the file, delete it to release disk - * space + * If we fail to make the file, delete it to release disk space */ unlink(tmppath); /* if write didn't set errno, assume problem is no disk space */ @@ -3215,7 +3230,7 @@ ReadControlFile(void) ereport(FATAL, (errmsg("database files are incompatible with server"), errdetail("The database cluster was initialized with XLOG_SEG_SIZE %d," - " but the server was compiled with XLOG_SEG_SIZE %d.", + " but the server was compiled with XLOG_SEG_SIZE %d.", ControlFile->xlog_seg_size, XLOG_SEG_SIZE), errhint("It looks like you need to recompile or initdb."))); if (ControlFile->nameDataLen != NAMEDATALEN) @@ -3336,7 +3351,8 @@ XLOGShmemSize(void) void XLOGShmemInit(void) { - bool foundXLog, foundCFile; + bool foundXLog, + foundCFile; /* this must agree with space requested by XLOGShmemSize() */ if (XLOGbuffers < MinXLOGbuffers) @@ -3414,16 +3430,17 @@ BootStrapXLOG(void) crc64 crc; /* - * Select a hopefully-unique system identifier code for this installation. - * We use the result of gettimeofday(), including the fractional seconds - * field, as being about as unique as we can easily get. (Think not to - * use random(), since it hasn't been seeded and there's no portable way - * to seed it other than the system clock value...) The upper half of the - * uint64 value is just the tv_sec part, while the lower half is the XOR - * of tv_sec and tv_usec. This is to ensure that we don't lose uniqueness - * unnecessarily if "uint64" is really only 32 bits wide. A person - * knowing this encoding can determine the initialization time of the - * installation, which could perhaps be useful sometimes. + * Select a hopefully-unique system identifier code for this + * installation. We use the result of gettimeofday(), including the + * fractional seconds field, as being about as unique as we can easily + * get. (Think not to use random(), since it hasn't been seeded and + * there's no portable way to seed it other than the system clock + * value...) The upper half of the uint64 value is just the tv_sec + * part, while the lower half is the XOR of tv_sec and tv_usec. This + * is to ensure that we don't lose uniqueness unnecessarily if + * "uint64" is really only 32 bits wide. A person knowing this + * encoding can determine the initialization time of the installation, + * which could perhaps be useful sometimes. */ gettimeofday(&tv, NULL); sysidentifier = ((uint64) tv.tv_sec) << 32; @@ -3492,18 +3509,18 @@ BootStrapXLOG(void) errno = ENOSPC; ereport(PANIC, (errcode_for_file_access(), - errmsg("could not write bootstrap transaction log file: %m"))); + errmsg("could not write bootstrap transaction log file: %m"))); } if (pg_fsync(openLogFile) != 0) ereport(PANIC, (errcode_for_file_access(), - errmsg("could not fsync bootstrap transaction log file: %m"))); + errmsg("could not fsync bootstrap transaction log file: %m"))); if (close(openLogFile)) ereport(PANIC, (errcode_for_file_access(), - errmsg("could not close bootstrap transaction log file: %m"))); + errmsg("could not close bootstrap transaction log file: %m"))); openLogFile = -1; @@ -3550,37 +3567,37 @@ str_time(time_t tnow) static void readRecoveryCommandFile(void) { - char recoveryCommandFile[MAXPGPATH]; - FILE *fd; - char cmdline[MAXPGPATH]; - TimeLineID rtli = 0; - bool rtliGiven = false; - bool syntaxError = false; - - snprintf(recoveryCommandFile, MAXPGPATH, "%s/recovery.conf", DataDir); - fd = AllocateFile(recoveryCommandFile, "r"); + char recoveryCommandFile[MAXPGPATH]; + FILE *fd; + char cmdline[MAXPGPATH]; + TimeLineID rtli = 0; + bool rtliGiven = false; + bool syntaxError = false; + + snprintf(recoveryCommandFile, MAXPGPATH, "%s/recovery.conf", DataDir); + fd = AllocateFile(recoveryCommandFile, "r"); if (fd == NULL) { if (errno == ENOENT) return; /* not there, so no archive recovery */ ereport(FATAL, - (errcode_for_file_access(), + (errcode_for_file_access(), errmsg("could not open recovery command file \"%s\": %m", recoveryCommandFile))); } ereport(LOG, - (errmsg("starting archive recovery"))); + (errmsg("starting archive recovery"))); - /* - * Parse the file... - */ - while (fgets(cmdline, MAXPGPATH, fd) != NULL) + /* + * Parse the file... + */ + while (fgets(cmdline, MAXPGPATH, fd) != NULL) { /* skip leading whitespace and check for # comment */ - char *ptr; - char *tok1; - char *tok2; + char *ptr; + char *tok1; + char *tok2; for (ptr = cmdline; *ptr; ptr++) { @@ -3591,13 +3608,13 @@ readRecoveryCommandFile(void) continue; /* identify the quoted parameter value */ - tok1 = strtok(ptr, "'"); + tok1 = strtok(ptr, "'"); if (!tok1) { syntaxError = true; break; } - tok2 = strtok(NULL, "'"); + tok2 = strtok(NULL, "'"); if (!tok2) { syntaxError = true; @@ -3611,13 +3628,15 @@ readRecoveryCommandFile(void) break; } - if (strcmp(tok1,"restore_command") == 0) { + if (strcmp(tok1, "restore_command") == 0) + { recoveryRestoreCommand = pstrdup(tok2); ereport(LOG, (errmsg("restore_command = \"%s\"", recoveryRestoreCommand))); } - else if (strcmp(tok1,"recovery_target_timeline") == 0) { + else if (strcmp(tok1, "recovery_target_timeline") == 0) + { rtliGiven = true; if (strcmp(tok2, "latest") == 0) rtli = 0; @@ -3637,7 +3656,8 @@ readRecoveryCommandFile(void) ereport(LOG, (errmsg("recovery_target_timeline = latest"))); } - else if (strcmp(tok1,"recovery_target_xid") == 0) { + else if (strcmp(tok1, "recovery_target_xid") == 0) + { errno = 0; recoveryTargetXid = (TransactionId) strtoul(tok2, NULL, 0); if (errno == EINVAL || errno == ERANGE) @@ -3650,7 +3670,8 @@ readRecoveryCommandFile(void) recoveryTarget = true; recoveryTargetExact = true; } - else if (strcmp(tok1,"recovery_target_time") == 0) { + else if (strcmp(tok1, "recovery_target_time") == 0) + { /* * if recovery_target_xid specified, then this overrides * recovery_target_time @@ -3659,20 +3680,22 @@ readRecoveryCommandFile(void) continue; recoveryTarget = true; recoveryTargetExact = false; + /* - * Convert the time string given by the user to the time_t format. - * We use type abstime's input converter because we know abstime - * has the same representation as time_t. + * Convert the time string given by the user to the time_t + * format. We use type abstime's input converter because we + * know abstime has the same representation as time_t. */ recoveryTargetTime = (time_t) DatumGetAbsoluteTime(DirectFunctionCall1(abstimein, - CStringGetDatum(tok2))); + CStringGetDatum(tok2))); ereport(LOG, (errmsg("recovery_target_time = %s", - DatumGetCString(DirectFunctionCall1(abstimeout, - AbsoluteTimeGetDatum((AbsoluteTime) recoveryTargetTime)))))); + DatumGetCString(DirectFunctionCall1(abstimeout, + AbsoluteTimeGetDatum((AbsoluteTime) recoveryTargetTime)))))); } - else if (strcmp(tok1,"recovery_target_inclusive") == 0) { + else if (strcmp(tok1, "recovery_target_inclusive") == 0) + { /* * does nothing if a recovery_target is not also set */ @@ -3694,11 +3717,11 @@ readRecoveryCommandFile(void) FreeFile(fd); - if (syntaxError) - ereport(FATAL, + if (syntaxError) + ereport(FATAL, (errmsg("syntax error in recovery command file: %s", cmdline), - errhint("Lines should have the format parameter = 'value'."))); + errhint("Lines should have the format parameter = 'value'."))); /* Check that required parameters were supplied */ if (recoveryRestoreCommand == NULL) @@ -3710,10 +3733,10 @@ readRecoveryCommandFile(void) InArchiveRecovery = true; /* - * If user specified recovery_target_timeline, validate it or compute the - * "latest" value. We can't do this until after we've gotten the restore - * command and set InArchiveRecovery, because we need to fetch timeline - * history files from the archive. + * If user specified recovery_target_timeline, validate it or compute + * the "latest" value. We can't do this until after we've gotten the + * restore command and set InArchiveRecovery, because we need to fetch + * timeline history files from the archive. */ if (rtliGiven) { @@ -3722,8 +3745,8 @@ readRecoveryCommandFile(void) /* Timeline 1 does not have a history file, all else should */ if (rtli != 1 && !existsTimeLineHistory(rtli)) ereport(FATAL, - (errmsg("recovery_target_timeline %u does not exist", - rtli))); + (errmsg("recovery_target_timeline %u does not exist", + rtli))); recoveryTargetTLI = rtli; } else @@ -3740,10 +3763,10 @@ readRecoveryCommandFile(void) static void exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg) { - char recoveryPath[MAXPGPATH]; - char xlogpath[MAXPGPATH]; - char recoveryCommandFile[MAXPGPATH]; - char recoveryCommandDone[MAXPGPATH]; + char recoveryPath[MAXPGPATH]; + char xlogpath[MAXPGPATH]; + char recoveryCommandFile[MAXPGPATH]; + char recoveryCommandDone[MAXPGPATH]; /* * We are no longer in archive recovery state. @@ -3751,9 +3774,9 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg) InArchiveRecovery = false; /* - * We should have the ending log segment currently open. Verify, - * and then close it (to avoid problems on Windows with trying to - * rename or delete an open file). + * We should have the ending log segment currently open. Verify, and + * then close it (to avoid problems on Windows with trying to rename + * or delete an open file). */ Assert(readFile >= 0); Assert(readId == endLogId); @@ -3763,17 +3786,17 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg) readFile = -1; /* - * If the segment was fetched from archival storage, we want to replace - * the existing xlog segment (if any) with the archival version. This - * is because whatever is in XLogDir is very possibly older than what - * we have from the archives, since it could have come from restoring - * a PGDATA backup. In any case, the archival version certainly is - * more descriptive of what our current database state is, because that - * is what we replayed from. + * If the segment was fetched from archival storage, we want to + * replace the existing xlog segment (if any) with the archival + * version. This is because whatever is in XLogDir is very possibly + * older than what we have from the archives, since it could have come + * from restoring a PGDATA backup. In any case, the archival version + * certainly is more descriptive of what our current database state + * is, because that is what we replayed from. * * Note that if we are establishing a new timeline, ThisTimeLineID is - * already set to the new value, and so we will create a new file instead - * of overwriting any existing file. + * already set to the new value, and so we will create a new file + * instead of overwriting any existing file. */ snprintf(recoveryPath, MAXPGPATH, "%s/RECOVERYXLOG", XLogDir); XLogFilePath(xlogpath, ThisTimeLineID, endLogId, endLogSeg); @@ -3798,6 +3821,7 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg) * RECOVERYXLOG laying about, get rid of it. */ unlink(recoveryPath); /* ignore any error */ + /* * If we are establishing a new timeline, we have to copy data * from the last WAL segment of the old timeline to create a @@ -3809,22 +3833,22 @@ exitArchiveRecovery(TimeLineID endTLI, uint32 endLogId, uint32 endLogSeg) } /* - * Let's just make real sure there are not .ready or .done flags posted - * for the new segment. + * Let's just make real sure there are not .ready or .done flags + * posted for the new segment. */ XLogFileName(xlogpath, ThisTimeLineID, endLogId, endLogSeg); XLogArchiveCleanup(xlogpath); /* Get rid of any remaining recovered timeline-history file, too */ snprintf(recoveryPath, MAXPGPATH, "%s/RECOVERYHISTORY", XLogDir); - unlink(recoveryPath); /* ignore any error */ + unlink(recoveryPath); /* ignore any error */ /* - * Rename the config file out of the way, so that we don't accidentally - * re-enter archive recovery mode in a subsequent crash. + * Rename the config file out of the way, so that we don't + * accidentally re-enter archive recovery mode in a subsequent crash. */ - snprintf(recoveryCommandFile, MAXPGPATH, "%s/recovery.conf", DataDir); - snprintf(recoveryCommandDone, MAXPGPATH, "%s/recovery.done", DataDir); + snprintf(recoveryCommandFile, MAXPGPATH, "%s/recovery.conf", DataDir); + snprintf(recoveryCommandDone, MAXPGPATH, "%s/recovery.done", DataDir); unlink(recoveryCommandDone); if (rename(recoveryCommandFile, recoveryCommandDone) != 0) ereport(FATAL, @@ -3849,8 +3873,8 @@ static bool recoveryStopsHere(XLogRecord *record, bool *includeThis) { bool stopsHere; - uint8 record_info; - time_t recordXtime; + uint8 record_info; + time_t recordXtime; /* Do we have a PITR target at all? */ if (!recoveryTarget) @@ -3862,14 +3886,14 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) record_info = record->xl_info & ~XLR_INFO_MASK; if (record_info == XLOG_XACT_COMMIT) { - xl_xact_commit *recordXactCommitData; + xl_xact_commit *recordXactCommitData; recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record); recordXtime = recordXactCommitData->xtime; } else if (record_info == XLOG_XACT_ABORT) { - xl_xact_abort *recordXactAbortData; + xl_xact_abort *recordXactAbortData; recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record); recordXtime = recordXactAbortData->xtime; @@ -3880,14 +3904,13 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) if (recoveryTargetExact) { /* - * there can be only one transaction end record - * with this exact transactionid + * there can be only one transaction end record with this exact + * transactionid * - * when testing for an xid, we MUST test for - * equality only, since transactions are numbered - * in the order they start, not the order they - * complete. A higher numbered xid will complete - * before you about 50% of the time... + * when testing for an xid, we MUST test for equality only, since + * transactions are numbered in the order they start, not the + * order they complete. A higher numbered xid will complete before + * you about 50% of the time... */ stopsHere = (record->xl_xid == recoveryTargetXid); if (stopsHere) @@ -3896,11 +3919,9 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) else { /* - * there can be many transactions that - * share the same commit time, so - * we stop after the last one, if we are - * inclusive, or stop at the first one - * if we are exclusive + * there can be many transactions that share the same commit time, + * so we stop after the last one, if we are inclusive, or stop at + * the first one if we are exclusive */ if (recoveryTargetInclusive) stopsHere = (recordXtime > recoveryTargetTime); @@ -3921,22 +3942,22 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis) if (recoveryStopAfter) ereport(LOG, (errmsg("recovery stopping after commit of transaction %u, time %s", - recoveryStopXid, str_time(recoveryStopTime)))); + recoveryStopXid, str_time(recoveryStopTime)))); else ereport(LOG, (errmsg("recovery stopping before commit of transaction %u, time %s", - recoveryStopXid, str_time(recoveryStopTime)))); + recoveryStopXid, str_time(recoveryStopTime)))); } else { if (recoveryStopAfter) ereport(LOG, (errmsg("recovery stopping after abort of transaction %u, time %s", - recoveryStopXid, str_time(recoveryStopTime)))); + recoveryStopXid, str_time(recoveryStopTime)))); else ereport(LOG, (errmsg("recovery stopping before abort of transaction %u, time %s", - recoveryStopXid, str_time(recoveryStopTime)))); + recoveryStopXid, str_time(recoveryStopTime)))); } } @@ -4009,14 +4030,14 @@ StartupXLOG(void) #endif /* - * Initialize on the assumption we want to recover to the same timeline - * that's active according to pg_control. + * Initialize on the assumption we want to recover to the same + * timeline that's active according to pg_control. */ recoveryTargetTLI = ControlFile->checkPointCopy.ThisTimeLineID; /* - * Check for recovery control file, and if so set up state for - * offline recovery + * Check for recovery control file, and if so set up state for offline + * recovery */ readRecoveryCommandFile(); @@ -4029,7 +4050,7 @@ StartupXLOG(void) * timeline. */ if (!list_member_int(expectedTLIs, - (int) ControlFile->checkPointCopy.ThisTimeLineID)) + (int) ControlFile->checkPointCopy.ThisTimeLineID)) ereport(FATAL, (errmsg("requested timeline %u is not a child of database system timeline %u", recoveryTargetTLI, @@ -4038,29 +4059,30 @@ StartupXLOG(void) if (read_backup_label(&checkPointLoc)) { /* - * When a backup_label file is present, we want to roll forward from - * the checkpoint it identifies, rather than using pg_control. + * When a backup_label file is present, we want to roll forward + * from the checkpoint it identifies, rather than using + * pg_control. */ record = ReadCheckpointRecord(checkPointLoc, 0, buffer); if (record != NULL) { ereport(LOG, (errmsg("checkpoint record is at %X/%X", - checkPointLoc.xlogid, checkPointLoc.xrecoff))); + checkPointLoc.xlogid, checkPointLoc.xrecoff))); InRecovery = true; /* force recovery even if SHUTDOWNED */ } else { ereport(PANIC, - (errmsg("could not locate required checkpoint record"), - errhint("If you are not restoring from a backup, try removing $PGDATA/backup_label."))); + (errmsg("could not locate required checkpoint record"), + errhint("If you are not restoring from a backup, try removing $PGDATA/backup_label."))); } } else { /* - * Get the last valid checkpoint record. If the latest one according - * to pg_control is broken, try the next-to-last one. + * Get the last valid checkpoint record. If the latest one + * according to pg_control is broken, try the next-to-last one. */ checkPointLoc = ControlFile->checkPoint; record = ReadCheckpointRecord(checkPointLoc, 1, buffer); @@ -4068,7 +4090,7 @@ StartupXLOG(void) { ereport(LOG, (errmsg("checkpoint record is at %X/%X", - checkPointLoc.xlogid, checkPointLoc.xrecoff))); + checkPointLoc.xlogid, checkPointLoc.xrecoff))); } else { @@ -4077,13 +4099,14 @@ StartupXLOG(void) if (record != NULL) { ereport(LOG, - (errmsg("using previous checkpoint record at %X/%X", - checkPointLoc.xlogid, checkPointLoc.xrecoff))); - InRecovery = true; /* force recovery even if SHUTDOWNED */ + (errmsg("using previous checkpoint record at %X/%X", + checkPointLoc.xlogid, checkPointLoc.xrecoff))); + InRecovery = true; /* force recovery even if + * SHUTDOWNED */ } else ereport(PANIC, - (errmsg("could not locate a valid checkpoint record"))); + (errmsg("could not locate a valid checkpoint record"))); } } @@ -4108,9 +4131,9 @@ StartupXLOG(void) ShmemVariableCache->oidCount = 0; /* - * We must replay WAL entries using the same TimeLineID they were created - * under, so temporarily adopt the TLI indicated by the checkpoint (see - * also xlog_redo()). + * We must replay WAL entries using the same TimeLineID they were + * created under, so temporarily adopt the TLI indicated by the + * checkpoint (see also xlog_redo()). */ ThisTimeLineID = checkPoint.ThisTimeLineID; @@ -4123,8 +4146,8 @@ StartupXLOG(void) checkPoint.undo = RecPtr; /* - * Check whether we need to force recovery from WAL. If it appears - * to have been a clean shutdown and we did not have a recovery.conf + * Check whether we need to force recovery from WAL. If it appears to + * have been a clean shutdown and we did not have a recovery.conf * file, then assume no recovery needed. */ if (XLByteLT(checkPoint.undo, RecPtr) || @@ -4219,7 +4242,7 @@ StartupXLOG(void) */ if (recoveryStopsHere(record, &recoveryApply)) { - needNewTimeLine = true; /* see below */ + needNewTimeLine = true; /* see below */ recoveryContinue = false; if (!recoveryApply) break; @@ -4242,6 +4265,7 @@ StartupXLOG(void) record = ReadRecord(NULL, LOG, buffer); } while (record != NULL && recoveryContinue); + /* * end of main redo apply loop */ @@ -4276,7 +4300,8 @@ StartupXLOG(void) if (needNewTimeLine) /* stopped because of stop request */ ereport(FATAL, (errmsg("requested recovery stop point is before end time of backup dump"))); - else /* ran off end of WAL */ + else +/* ran off end of WAL */ ereport(FATAL, (errmsg("WAL ends before end time of backup dump"))); } @@ -4284,10 +4309,10 @@ StartupXLOG(void) /* * Consider whether we need to assign a new timeline ID. * - * If we stopped short of the end of WAL during recovery, then we - * are generating a new timeline and must assign it a unique new ID. - * Otherwise, we can just extend the timeline we were in when we - * ran out of WAL. + * If we stopped short of the end of WAL during recovery, then we are + * generating a new timeline and must assign it a unique new ID. + * Otherwise, we can just extend the timeline we were in when we ran + * out of WAL. */ if (needNewTimeLine) { @@ -4302,8 +4327,8 @@ StartupXLOG(void) XLogCtl->ThisTimeLineID = ThisTimeLineID; /* - * We are now done reading the old WAL. Turn off archive fetching - * if it was active, and make a writable copy of the last WAL segment. + * We are now done reading the old WAL. Turn off archive fetching if + * it was active, and make a writable copy of the last WAL segment. * (Note that we also have a copy of the last block of the old WAL in * readBuf; we will use that below.) */ @@ -4361,7 +4386,7 @@ StartupXLOG(void) * XLogWrite()). * * Note: it might seem we should do AdvanceXLInsertBuffer() here, but - * this is sufficient. The first actual attempt to insert a log + * this is sufficient. The first actual attempt to insert a log * record will advance the insert state. */ XLogCtl->Write.curridx = NextBufIdx(0); @@ -4434,8 +4459,8 @@ StartupXLOG(void) XLogCloseRelationCache(); /* - * Now that we've checkpointed the recovery, it's safe to - * flush old backup_label, if present. + * Now that we've checkpointed the recovery, it's safe to flush + * old backup_label, if present. */ remove_backup_label(); } @@ -4504,7 +4529,7 @@ ReadCheckpointRecord(XLogRecPtr RecPtr, break; default: ereport(LOG, - (errmsg("invalid checkpoint link in backup_label file"))); + (errmsg("invalid checkpoint link in backup_label file"))); break; } return NULL; @@ -4557,7 +4582,7 @@ ReadCheckpointRecord(XLogRecPtr RecPtr, { case 1: ereport(LOG, - (errmsg("invalid xl_info in primary checkpoint record"))); + (errmsg("invalid xl_info in primary checkpoint record"))); break; case 2: ereport(LOG, @@ -4576,7 +4601,7 @@ ReadCheckpointRecord(XLogRecPtr RecPtr, { case 1: ereport(LOG, - (errmsg("invalid length of primary checkpoint record"))); + (errmsg("invalid length of primary checkpoint record"))); break; case 2: ereport(LOG, @@ -4791,8 +4816,8 @@ CreateCheckPoint(bool shutdown, bool force) * so there's a risk of deadlock. Need to find a better solution. See * pgsql-hackers discussion of 17-Dec-01. * - * XXX actually, the whole UNDO code is dead code and unlikely to ever - * be revived, so the lack of a good solution here is not troubling. + * XXX actually, the whole UNDO code is dead code and unlikely to ever be + * revived, so the lack of a good solution here is not troubling. */ #ifdef NOT_USED checkPoint.undo = GetUndoRecPtr(); @@ -4919,11 +4944,11 @@ CreateCheckPoint(bool shutdown, bool force) PreallocXlogFiles(recptr); /* - * Truncate pg_subtrans if possible. We can throw away all data before - * the oldest XMIN of any running transaction. No future transaction will - * attempt to reference any pg_subtrans entry older than that (see Asserts - * in subtrans.c). During recovery, though, we mustn't do this because - * StartupSUBTRANS hasn't been called yet. + * Truncate pg_subtrans if possible. We can throw away all data + * before the oldest XMIN of any running transaction. No future + * transaction will attempt to reference any pg_subtrans entry older + * than that (see Asserts in subtrans.c). During recovery, though, we + * mustn't do this because StartupSUBTRANS hasn't been called yet. */ if (!InRecovery) TruncateSUBTRANS(GetOldestXmin(true)); @@ -4974,8 +4999,10 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record) ShmemVariableCache->nextXid = checkPoint.nextXid; ShmemVariableCache->nextOid = checkPoint.nextOid; ShmemVariableCache->oidCount = 0; + /* - * TLI may change in a shutdown checkpoint, but it shouldn't decrease + * TLI may change in a shutdown checkpoint, but it shouldn't + * decrease */ if (checkPoint.ThisTimeLineID != ThisTimeLineID) { @@ -4984,7 +5011,7 @@ xlog_redo(XLogRecPtr lsn, XLogRecord *record) (int) checkPoint.ThisTimeLineID)) ereport(PANIC, (errmsg("unexpected timeline ID %u (after %u) in checkpoint record", - checkPoint.ThisTimeLineID, ThisTimeLineID))); + checkPoint.ThisTimeLineID, ThisTimeLineID))); /* Following WAL records should be run with new TLI */ ThisTimeLineID = checkPoint.ThisTimeLineID; } @@ -5071,8 +5098,7 @@ xlog_outrec(char *buf, XLogRecord *record) sprintf(buf + strlen(buf), ": %s", RmgrTable[record->xl_rmid].rm_name); } - -#endif /* WAL_DEBUG */ +#endif /* WAL_DEBUG */ /* @@ -5200,7 +5226,7 @@ pg_start_backup(PG_FUNCTION_ARGS) char *backupidstr; XLogRecPtr checkpointloc; XLogRecPtr startpoint; - time_t stamp_time; + time_t stamp_time; char strfbuf[128]; char labelfilepath[MAXPGPATH]; char xlogfilename[MAXFNAMELEN]; @@ -5209,24 +5235,26 @@ pg_start_backup(PG_FUNCTION_ARGS) struct stat stat_buf; FILE *fp; - if (!superuser()) + if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to run a backup")))); backupidstr = DatumGetCString(DirectFunctionCall1(textout, - PointerGetDatum(backupid))); + PointerGetDatum(backupid))); + /* - * Force a CHECKPOINT. This is not strictly necessary, but it seems - * like a good idea to minimize the amount of past WAL needed to use the - * backup. Also, this guarantees that two successive backup runs - * will have different checkpoint positions and hence different history - * file names, even if nothing happened in between. + * Force a CHECKPOINT. This is not strictly necessary, but it seems + * like a good idea to minimize the amount of past WAL needed to use + * the backup. Also, this guarantees that two successive backup runs + * will have different checkpoint positions and hence different + * history file names, even if nothing happened in between. */ RequestCheckpoint(true); + /* * Now we need to fetch the checkpoint record location, and also its - * REDO pointer. The oldest point in WAL that would be needed to restore - * starting from the checkpoint is precisely the REDO pointer. + * REDO pointer. The oldest point in WAL that would be needed to + * restore starting from the checkpoint is precisely the REDO pointer. */ LWLockAcquire(ControlFileLock, LW_EXCLUSIVE); checkpointloc = ControlFile->checkPoint; @@ -5235,18 +5263,21 @@ pg_start_backup(PG_FUNCTION_ARGS) XLByteToSeg(startpoint, _logId, _logSeg); XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg); + /* - * We deliberately use strftime/localtime not the src/timezone functions, - * so that backup labels will consistently be recorded in the same - * timezone regardless of TimeZone setting. This matches elog.c's - * practice. + * We deliberately use strftime/localtime not the src/timezone + * functions, so that backup labels will consistently be recorded in + * the same timezone regardless of TimeZone setting. This matches + * elog.c's practice. */ stamp_time = time(NULL); strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S %Z", localtime(&stamp_time)); + /* - * Check for existing backup label --- implies a backup is already running + * Check for existing backup label --- implies a backup is already + * running */ snprintf(labelfilepath, MAXPGPATH, "%s/backup_label", DataDir); if (stat(labelfilepath, &stat_buf) != 0) @@ -5263,6 +5294,7 @@ pg_start_backup(PG_FUNCTION_ARGS) errmsg("a backup is already in progress"), errhint("If you're sure there is no backup in progress, remove file \"%s\" and try again.", labelfilepath))); + /* * Okay, write the file */ @@ -5283,13 +5315,14 @@ pg_start_backup(PG_FUNCTION_ARGS) (errcode_for_file_access(), errmsg("could not write file \"%s\": %m", labelfilepath))); + /* * We're done. As a convenience, return the starting WAL offset. */ snprintf(xlogfilename, sizeof(xlogfilename), "%X/%X", startpoint.xlogid, startpoint.xrecoff); result = DatumGetTextP(DirectFunctionCall1(textin, - CStringGetDatum(xlogfilename))); + CStringGetDatum(xlogfilename))); PG_RETURN_TEXT_P(result); } @@ -5308,7 +5341,7 @@ pg_stop_backup(PG_FUNCTION_ARGS) XLogCtlInsert *Insert = &XLogCtl->Insert; XLogRecPtr startpoint; XLogRecPtr stoppoint; - time_t stamp_time; + time_t stamp_time; char strfbuf[128]; char labelfilepath[MAXPGPATH]; char histfilepath[MAXPGPATH]; @@ -5321,10 +5354,11 @@ pg_stop_backup(PG_FUNCTION_ARGS) char ch; int ich; - if (!superuser()) + if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), (errmsg("must be superuser to run a backup")))); + /* * Get the current end-of-WAL position; it will be unsafe to use this * dump to restore to a point in advance of this time. @@ -5335,16 +5369,18 @@ pg_stop_backup(PG_FUNCTION_ARGS) XLByteToSeg(stoppoint, _logId, _logSeg); XLogFileName(stopxlogfilename, ThisTimeLineID, _logId, _logSeg); + /* - * We deliberately use strftime/localtime not the src/timezone functions, - * so that backup labels will consistently be recorded in the same - * timezone regardless of TimeZone setting. This matches elog.c's - * practice. + * We deliberately use strftime/localtime not the src/timezone + * functions, so that backup labels will consistently be recorded in + * the same timezone regardless of TimeZone setting. This matches + * elog.c's practice. */ stamp_time = time(NULL); strftime(strfbuf, sizeof(strfbuf), "%Y-%m-%d %H:%M:%S %Z", localtime(&stamp_time)); + /* * Open the existing label file */ @@ -5361,9 +5397,11 @@ pg_stop_backup(PG_FUNCTION_ARGS) (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("a backup is not in progress"))); } + /* * Read and parse the START WAL LOCATION line (this code is pretty - * crude, but we are not expecting any variability in the file format). + * crude, but we are not expecting any variability in the file + * format). */ if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %24s)%c", &startpoint.xlogid, &startpoint.xrecoff, startxlogfilename, @@ -5371,6 +5409,7 @@ pg_stop_backup(PG_FUNCTION_ARGS) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("invalid data in file \"%s\"", labelfilepath))); + /* * Write the backup history file */ @@ -5396,6 +5435,7 @@ pg_stop_backup(PG_FUNCTION_ARGS) (errcode_for_file_access(), errmsg("could not write file \"%s\": %m", histfilepath))); + /* * Close and remove the backup label file */ @@ -5409,6 +5449,7 @@ pg_stop_backup(PG_FUNCTION_ARGS) (errcode_for_file_access(), errmsg("could not remove file \"%s\": %m", labelfilepath))); + /* * Notify archiver that history file may be archived immediately */ @@ -5418,13 +5459,14 @@ pg_stop_backup(PG_FUNCTION_ARGS) startpoint.xrecoff % XLogSegSize); XLogArchiveNotify(histfilepath); } + /* * We're done. As a convenience, return the ending WAL offset. */ snprintf(stopxlogfilename, sizeof(stopxlogfilename), "%X/%X", stoppoint.xlogid, stoppoint.xrecoff); result = DatumGetTextP(DirectFunctionCall1(textin, - CStringGetDatum(stopxlogfilename))); + CStringGetDatum(stopxlogfilename))); PG_RETURN_TEXT_P(result); } @@ -5433,7 +5475,7 @@ pg_stop_backup(PG_FUNCTION_ARGS) * * If we see a backup_label during recovery, we assume that we are recovering * from a backup dump file, and we therefore roll forward from the checkpoint - * identified by the label file, NOT what pg_control says. This avoids the + * identified by the label file, NOT what pg_control says. This avoids the * problem that pg_control might have been archived one or more checkpoints * later than the start of the dump, and so if we rely on it as the start * point, we will fail to restore a consistent database state. @@ -5476,10 +5518,11 @@ read_backup_label(XLogRecPtr *checkPointLoc) labelfilepath))); return false; /* it's not there, all is fine */ } + /* - * Read and parse the START WAL LOCATION and CHECKPOINT lines (this code - * is pretty crude, but we are not expecting any variability in the file - * format). + * Read and parse the START WAL LOCATION and CHECKPOINT lines (this + * code is pretty crude, but we are not expecting any variability in + * the file format). */ if (fscanf(lfp, "START WAL LOCATION: %X/%X (file %08X%16s)%c", &startpoint.xlogid, &startpoint.xrecoff, &tli, @@ -5498,6 +5541,7 @@ read_backup_label(XLogRecPtr *checkPointLoc) (errcode_for_file_access(), errmsg("could not read file \"%s\": %m", labelfilepath))); + /* * Try to retrieve the backup history file (no error if we can't) */ @@ -5511,24 +5555,24 @@ read_backup_label(XLogRecPtr *checkPointLoc) BackupHistoryFilePath(histfilepath, tli, _logId, _logSeg, startpoint.xrecoff % XLogSegSize); - fp = AllocateFile(histfilepath, "r"); + fp = AllocateFile(histfilepath, "r"); if (fp) { /* * Parse history file to identify stop point. */ if (fscanf(fp, "START WAL LOCATION: %X/%X (file %24s)%c", - &startpoint.xlogid, &startpoint.xrecoff, startxlogfilename, + &startpoint.xlogid, &startpoint.xrecoff, startxlogfilename, &ch) != 4 || ch != '\n') ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("invalid data in file \"%s\"", histfilename))); + errmsg("invalid data in file \"%s\"", histfilename))); if (fscanf(fp, "STOP WAL LOCATION: %X/%X (file %24s)%c", - &stoppoint.xlogid, &stoppoint.xrecoff, stopxlogfilename, + &stoppoint.xlogid, &stoppoint.xrecoff, stopxlogfilename, &ch) != 4 || ch != '\n') ereport(FATAL, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), - errmsg("invalid data in file \"%s\"", histfilename))); + errmsg("invalid data in file \"%s\"", histfilename))); recoveryMinXlogOffset = stoppoint; if (ferror(fp) || FreeFile(fp)) ereport(FATAL, diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index 1791068d7a5..4f1ac8dde58 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.33 2004/08/29 04:12:23 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlogutils.c,v 1.34 2004/08/29 05:06:41 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -212,11 +212,11 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode) res->reldata.rd_node = rnode; /* - * We set up the lockRelId in case anything tries to lock the dummy - * relation. Note that this is fairly bogus since relNode may be - * different from the relation's OID. It shouldn't really matter - * though, since we are presumably running by ourselves and can't - * have any lock conflicts ... + * We set up the lockRelId in case anything tries to lock the + * dummy relation. Note that this is fairly bogus since relNode + * may be different from the relation's OID. It shouldn't really + * matter though, since we are presumably running by ourselves and + * can't have any lock conflicts ... */ res->reldata.rd_lockInfo.lockRelId.dbId = rnode.dbNode; res->reldata.rd_lockInfo.lockRelId.relId = rnode.relNode; @@ -234,14 +234,15 @@ XLogOpenRelation(bool redo, RmgrId rmid, RelFileNode rnode) res->reldata.rd_targblock = InvalidBlockNumber; res->reldata.rd_smgr = smgropen(res->reldata.rd_node); + /* * Create the target file if it doesn't already exist. This lets * us cope if the replay sequence contains writes to a relation * that is later deleted. (The original coding of this routine * would instead return NULL, causing the writes to be suppressed. - * But that seems like it risks losing valuable data if the filesystem - * loses an inode during a crash. Better to write the data until we - * are actually told to delete the file.) + * But that seems like it risks losing valuable data if the + * filesystem loses an inode during a crash. Better to write the + * data until we are actually told to delete the file.) */ smgrcreate(res->reldata.rd_smgr, res->reldata.rd_istemp, true); } |