Change the timestamps recorded in transaction commit/abort xlog records
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 30 Apr 2007 21:01:53 +0000 (21:01 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 30 Apr 2007 21:01:53 +0000 (21:01 +0000)
from time_t to TimestampTz representation.  This provides full gettimeofday()
resolution of the timestamps, which might be useful when attempting to
do point-in-time recovery --- previously it was not possible to specify
the stop point with sub-second resolution.  But mostly this is to get
rid of TimestampTz-to-time_t conversion overhead during commit.  Per my
proposal of a day or two back.

src/backend/access/transam/twophase.c
src/backend/access/transam/xact.c
src/backend/access/transam/xlog.c
src/backend/utils/adt/timestamp.c
src/include/access/xact.h
src/include/access/xlog_internal.h
src/include/utils/timestamp.h

index 62c384936db2e8db598cdf4ea3c3d34ca48db541..a2bc15a18ff9c1c77f9cb6179a82af06587ab4cc 100644 (file)
@@ -1675,7 +1675,7 @@ RecordTransactionCommitPrepared(TransactionId xid,
 
        /* Emit the XLOG commit record */
        xlrec.xid = xid;
-       xlrec.crec.xtime = time(NULL);
+       xlrec.crec.xact_time = GetCurrentTimestamp();
        xlrec.crec.nrels = nrels;
        xlrec.crec.nsubxacts = nchildren;
        rdata[0].data = (char *) (&xlrec);
@@ -1753,7 +1753,7 @@ RecordTransactionAbortPrepared(TransactionId xid,
 
        /* Emit the XLOG abort record */
        xlrec.xid = xid;
-       xlrec.arec.xtime = time(NULL);
+       xlrec.arec.xact_time = GetCurrentTimestamp();
        xlrec.arec.nrels = nrels;
        xlrec.arec.nsubxacts = nchildren;
        rdata[0].data = (char *) (&xlrec);
index 480cd88df35abbf440d3ff5bbf4b3a559781bcc4..e3de365461e1edbab9a56850f80039126b899181 100644 (file)
@@ -773,7 +773,7 @@ RecordTransactionCommit(void)
                        MyProc->inCommit = true;
 
                        SetCurrentTransactionStopTimestamp();
-                       xlrec.xtime = timestamptz_to_time_t(xactStopTimestamp);
+                       xlrec.xact_time = xactStopTimestamp;
                        xlrec.nrels = nrels;
                        xlrec.nsubxacts = nchildren;
                        rdata[0].data = (char *) (&xlrec);
@@ -1069,7 +1069,7 @@ RecordTransactionAbort(void)
                        XLogRecPtr      recptr;
 
                        SetCurrentTransactionStopTimestamp();
-                       xlrec.xtime = timestamptz_to_time_t(xactStopTimestamp);
+                       xlrec.xact_time = xactStopTimestamp;
                        xlrec.nrels = nrels;
                        xlrec.nsubxacts = nchildren;
                        rdata[0].data = (char *) (&xlrec);
@@ -1247,7 +1247,7 @@ RecordSubTransactionAbort(void)
                        xl_xact_abort xlrec;
                        XLogRecPtr      recptr;
 
-                       xlrec.xtime = time(NULL);
+                       xlrec.xact_time = GetCurrentTimestamp();
                        xlrec.nrels = nrels;
                        xlrec.nsubxacts = nchildren;
                        rdata[0].data = (char *) (&xlrec);
@@ -4282,12 +4282,9 @@ xact_redo(XLogRecPtr lsn, XLogRecord *record)
 static void
 xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
 {
-       struct tm  *tm = localtime(&xlrec->xtime);
        int                     i;
 
-       appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
-                                        tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
-                                        tm->tm_hour, tm->tm_min, tm->tm_sec);
+       appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
        if (xlrec->nrels > 0)
        {
                appendStringInfo(buf, "; rels:");
@@ -4313,12 +4310,9 @@ xact_desc_commit(StringInfo buf, xl_xact_commit *xlrec)
 static void
 xact_desc_abort(StringInfo buf, xl_xact_abort *xlrec)
 {
-       struct tm  *tm = localtime(&xlrec->xtime);
        int                     i;
 
-       appendStringInfo(buf, "%04u-%02u-%02u %02u:%02u:%02u",
-                                        tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
-                                        tm->tm_hour, tm->tm_min, tm->tm_sec);
+       appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
        if (xlrec->nrels > 0)
        {
                appendStringInfo(buf, "; rels:");
index 4aa2e75ecc7eb8f12fe3b84dbd1efebf95d60be0..9a82abfef6b32dcd784e2df032ded9bc43798dc1 100644 (file)
@@ -47,7 +47,6 @@
 #include "storage/procarray.h"
 #include "storage/spin.h"
 #include "utils/builtins.h"
-#include "utils/nabstime.h"
 #include "utils/pg_locale.h"
 
 
@@ -114,11 +113,11 @@ static bool recoveryTarget = false;
 static bool recoveryTargetExact = false;
 static bool recoveryTargetInclusive = true;
 static TransactionId recoveryTargetXid;
-static time_t recoveryTargetTime;
+static TimestampTz recoveryTargetTime;
 
 /* if recoveryStopsHere returns true, it saves actual stop xid/time here */
 static TransactionId recoveryStopXid;
-static time_t recoveryStopTime;
+static TimestampTz recoveryStopTime;
 static bool recoveryStopAfter;
 
 /*
@@ -3536,7 +3535,7 @@ writeTimeLineHistory(TimeLineID newTLI, TimeLineID parentTLI,
                         xlogfname,
                         recoveryStopAfter ? "after" : "before",
                         recoveryStopXid,
-                        str_time(recoveryStopTime));
+                        timestamptz_to_str(recoveryStopTime));
 
        nbytes = strlen(buffer);
        errno = 0;
@@ -4276,17 +4275,16 @@ readRecoveryCommandFile(void)
                        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 TimestampTz form.
                         */
-                       recoveryTargetTime = (time_t)
-                               DatumGetAbsoluteTime(DirectFunctionCall1(abstimein,
-                                                                                                        CStringGetDatum(tok2)));
+                       recoveryTargetTime =
+                               DatumGetTimestampTz(DirectFunctionCall3(timestamptz_in,
+                                                                                                  CStringGetDatum(tok2),
+                                                                                               ObjectIdGetDatum(InvalidOid),
+                                                                                                               Int32GetDatum(-1)));
                        ereport(LOG,
                                        (errmsg("recovery_target_time = %s",
-                                                       DatumGetCString(DirectFunctionCall1(abstimeout,
-                               AbsoluteTimeGetDatum((AbsoluteTime) recoveryTargetTime))))));
+                                                       timestamptz_to_str(recoveryTargetTime))));
                }
                else if (strcmp(tok1, "recovery_target_inclusive") == 0)
                {
@@ -4464,7 +4462,7 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
 {
        bool            stopsHere;
        uint8           record_info;
-       time_t          recordXtime;
+       TimestampTz     recordXtime;
 
        /* Do we have a PITR target at all? */
        if (!recoveryTarget)
@@ -4479,14 +4477,14 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
                xl_xact_commit *recordXactCommitData;
 
                recordXactCommitData = (xl_xact_commit *) XLogRecGetData(record);
-               recordXtime = recordXactCommitData->xtime;
+               recordXtime = recordXactCommitData->xact_time;
        }
        else if (record_info == XLOG_XACT_ABORT)
        {
                xl_xact_abort *recordXactAbortData;
 
                recordXactAbortData = (xl_xact_abort *) XLogRecGetData(record);
-               recordXtime = recordXactAbortData->xtime;
+               recordXtime = recordXactAbortData->xact_time;
        }
        else
                return false;
@@ -4532,22 +4530,26 @@ recoveryStopsHere(XLogRecord *record, bool *includeThis)
                        if (recoveryStopAfter)
                                ereport(LOG,
                                                (errmsg("recovery stopping after commit of transaction %u, time %s",
-                                                         recoveryStopXid, str_time(recoveryStopTime))));
+                                                               recoveryStopXid,
+                                                               timestamptz_to_str(recoveryStopTime))));
                        else
                                ereport(LOG,
                                                (errmsg("recovery stopping before commit of transaction %u, time %s",
-                                                         recoveryStopXid, str_time(recoveryStopTime))));
+                                                               recoveryStopXid,
+                                                               timestamptz_to_str(recoveryStopTime))));
                }
                else
                {
                        if (recoveryStopAfter)
                                ereport(LOG,
                                                (errmsg("recovery stopping after abort of transaction %u, time %s",
-                                                         recoveryStopXid, str_time(recoveryStopTime))));
+                                                               recoveryStopXid,
+                                                               timestamptz_to_str(recoveryStopTime))));
                        else
                                ereport(LOG,
                                                (errmsg("recovery stopping before abort of transaction %u, time %s",
-                                                         recoveryStopXid, str_time(recoveryStopTime))));
+                                                               recoveryStopXid,
+                                                               timestamptz_to_str(recoveryStopTime))));
                }
        }
 
index 420249736f7493c4754e734fb02f366bcd6d6396..a878caead5af95b4c443340bcb5558c905d8be15 100644 (file)
@@ -1301,6 +1301,33 @@ timestamptz_to_time_t(TimestampTz t)
        return result;
 }
 
+/*
+ * Produce a C-string representation of a TimestampTz.
+ *
+ * This is mostly for use in emitting messages.  The primary difference
+ * from timestamptz_out is that we force the output format to ISO.  Note
+ * also that the result is in a static buffer, not pstrdup'd.
+ */
+const char *
+timestamptz_to_str(TimestampTz t)
+{
+       static char     buf[MAXDATELEN + 1];
+       int                     tz;
+       struct pg_tm tt,
+                          *tm = &tt;
+       fsec_t          fsec;
+       char       *tzn;
+
+       if (TIMESTAMP_NOT_FINITE(t))
+               EncodeSpecialTimestamp(t, buf);
+       else if (timestamp2tm(t, &tz, tm, &fsec, &tzn, NULL) == 0)
+               EncodeDateTime(tm, fsec, &tz, &tzn, USE_ISO_DATES, buf);
+       else
+               strlcpy(buf, "(timestamp out of range)", sizeof(buf));
+
+       return buf;
+}
+
 
 void
 dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
index cb9188de577e87f7938e98db5fe0887f2884f5ca..c06d2628346574c8dac7881121bb86a3c1aab5ee 100644 (file)
@@ -81,7 +81,7 @@ typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid,
 
 typedef struct xl_xact_commit
 {
-       time_t          xtime;
+       TimestampTz     xact_time;              /* time of commit */
        int                     nrels;                  /* number of RelFileNodes */
        int                     nsubxacts;              /* number of subtransaction XIDs */
        /* Array of RelFileNode(s) to drop at commit */
@@ -93,7 +93,7 @@ typedef struct xl_xact_commit
 
 typedef struct xl_xact_abort
 {
-       time_t          xtime;
+       TimestampTz     xact_time;              /* time of abort */
        int                     nrels;                  /* number of RelFileNodes */
        int                     nsubxacts;              /* number of subtransaction XIDs */
        /* Array of RelFileNode(s) to drop at abort */
index 70fb077245e0f17b1c95b16229fbd7640cd0f742..6a7618937734178b91c0519bab64a3eede36bd56 100644 (file)
@@ -71,7 +71,7 @@ typedef struct XLogContRecord
 /*
  * Each page of XLOG file has a header like this:
  */
-#define XLOG_PAGE_MAGIC 0xD05F /* can be used as WAL version indicator */
+#define XLOG_PAGE_MAGIC 0xD061 /* can be used as WAL version indicator */
 
 typedef struct XLogPageHeaderData
 {
index a019a309edf3ee7584cc82d19ba21391fe71748c..c6487bdf332e0d8c5f68deed7845ceebe96f0cfe 100644 (file)
@@ -318,6 +318,8 @@ extern bool TimestampDifferenceExceeds(TimestampTz start_time,
 extern TimestampTz time_t_to_timestamptz(time_t tm);
 extern time_t timestamptz_to_time_t(TimestampTz t);
 
+extern const char *timestamptz_to_str(TimestampTz t);
+
 extern int     tm2timestamp(struct pg_tm * tm, fsec_t fsec, int *tzp, Timestamp *dt);
 extern int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm * tm,
                         fsec_t *fsec, char **tzn, pg_tz *attimezone);