On Mon, Aug 15, 2011 at 16:20, Tom Lane <t...@sss.pgh.pa.us> wrote:
> Magnus Hagander <mag...@hagander.net> writes:
>> I'm trying to make my streaming log receiver work properly with 9.1,
>> and have come across a couple of things. The first one that's causing
>> trouble is that the definition of the protocol is currently in
>> walprotocol.h, which is not include:able in a frontend application.
>> AFAICT, this is because it includes utils/timestamp.h, which doesn't
>> work. AFAICT, this means that anybody other than our own backend who
>> wants to talk our replication protocol has to copy the specific struct
>> defines they want in their own code. This seems like a really bad
>> idea. (In my case, it's the StandbyReplyMessage that I need, so I can
>> make my client not get killed by the default settings for timeout)
>
>> The basic reason for this is that we're putting TimestampTz fields in
>> the protocol. This also means that the protocol actually changes
>> definition depending on if the server is compiled with integer or
>> float timestamps. While the replication itself breaks if these are
>> different, this seems like a bad thing to expose in the protocol. It
>> also makes life a lot harder on third party tools.
>
> I don't really see why it matters, given that the data to be shipped is
> also dependent on the timestamp format?

As an example, the stream receiver program needs to be able to
construct the status message and send back - thus needs to be able to
construct a TimestampTz. It never needs to look into the actual WAL
data - it just writes it to a file considering it to be a stream of
pure binary data.


> However, for a narrow fix, I could see moving the data type definition
> to someplace with fewer dependencies.  Perhaps split it into a separate
> file timestamp_type.h, or something like that.

Yes, that seems to fix the problem of timestamptz. See the attached
patch - seems ok?


I also ran into a similar problem with some WAL macro definitions that
are in xlog_internal.h. I've moved them to xlogdefs.h in the attached
xlog.diff file. Does that seem ok as well, or should I move them
somewhere else? (I don't need all those macros, but I moved the
complete block of macros wherever I needed one of them, because
otherwise it would be completely impossible to track). This is just a
simple move of the definitions, zero new logic added and zero removed.


-- 
 Magnus Hagander
 Me: http://www.hagander.net/
 Work: http://www.redpill-linpro.com/
diff --git a/src/include/replication/walprotocol.h b/src/include/replication/walprotocol.h
index 9414667..cdba21b 100644
--- a/src/include/replication/walprotocol.h
+++ b/src/include/replication/walprotocol.h
@@ -13,7 +13,7 @@
 #define _WALPROTOCOL_H
 
 #include "access/xlogdefs.h"
-#include "utils/timestamp.h"
+#include "utils/timestamp_defs.h"
 
 
 /*
diff --git a/src/include/utils/timestamp.h b/src/include/utils/timestamp.h
index 9e51b58..1a5ea0d 100644
--- a/src/include/utils/timestamp.h
+++ b/src/include/utils/timestamp.h
@@ -19,86 +19,7 @@
 
 #include "fmgr.h"
 #include "pgtime.h"
-#ifdef HAVE_INT64_TIMESTAMP
-#include "utils/int8.h"
-#endif
-
-/*
- * Timestamp represents absolute time.
- *
- * Interval represents delta time. Keep track of months (and years), days,
- * and hours/minutes/seconds separately since the elapsed time spanned is
- * unknown until instantiated relative to an absolute time.
- *
- * Note that Postgres uses "time interval" to mean a bounded interval,
- * consisting of a beginning and ending time, not a time span - thomas 97/03/20
- *
- * We have two implementations, one that uses int64 values with units of
- * microseconds, and one that uses double values with units of seconds.
- *
- * TimeOffset and fsec_t are convenience typedefs for temporary variables
- * that are of different types in the two cases.  Do not use fsec_t in values
- * stored on-disk, since it is not the same size in both implementations.
- * Also, fsec_t is only meant for *fractional* seconds; beware of overflow
- * if the value you need to store could be many seconds.
- */
-
-#ifdef HAVE_INT64_TIMESTAMP
-
-typedef int64 Timestamp;
-typedef int64 TimestampTz;
-typedef int64 TimeOffset;
-typedef int32 fsec_t;			/* fractional seconds (in microseconds) */
-#else
-
-typedef double Timestamp;
-typedef double TimestampTz;
-typedef double TimeOffset;
-typedef double fsec_t;			/* fractional seconds (in seconds) */
-#endif
-
-typedef struct
-{
-	TimeOffset	time;			/* all time units other than days, months and
-								 * years */
-	int32		day;			/* days, after time for alignment */
-	int32		month;			/* months and years, after time for alignment */
-} Interval;
-
-
-#define MAX_TIMESTAMP_PRECISION 6
-#define MAX_INTERVAL_PRECISION 6
-
-/* in both timestamp.h and ecpg/dt.h */
-#define DAYS_PER_YEAR	365.25	/* assumes leap year every four years */
-#define MONTHS_PER_YEAR 12
-/*
- *	DAYS_PER_MONTH is very imprecise.  The more accurate value is
- *	365.2425/12 = 30.436875, or '30 days 10:29:06'.  Right now we only
- *	return an integral number of days, but someday perhaps we should
- *	also return a 'time' value to be used as well.	ISO 8601 suggests
- *	30 days.
- */
-#define DAYS_PER_MONTH	30		/* assumes exactly 30 days per month */
-#define HOURS_PER_DAY	24		/* assume no daylight savings time changes */
-
-/*
- *	This doesn't adjust for uneven daylight savings time intervals or leap
- *	seconds, and it crudely estimates leap years.  A more accurate value
- *	for days per years is 365.2422.
- */
-#define SECS_PER_YEAR	(36525 * 864)	/* avoid floating-point computation */
-#define SECS_PER_DAY	86400
-#define SECS_PER_HOUR	3600
-#define SECS_PER_MINUTE 60
-#define MINS_PER_HOUR	60
-
-#ifdef HAVE_INT64_TIMESTAMP
-#define USECS_PER_DAY	INT64CONST(86400000000)
-#define USECS_PER_HOUR	INT64CONST(3600000000)
-#define USECS_PER_MINUTE INT64CONST(60000000)
-#define USECS_PER_SEC	INT64CONST(1000000)
-#endif
+#include "timestamp_type.h"
 
 /*
  * Macros for fmgr-callable functions.
diff --git a/src/include/utils/timestamp_type.h b/src/include/utils/timestamp_type.h
new file mode 100644
index 0000000..377b7f2
--- /dev/null
+++ b/src/include/utils/timestamp_type.h
@@ -0,0 +1,94 @@
+/*-------------------------------------------------------------------------
+ *
+ * timestamp_type.h
+ *	  Definitions for the timestamp datatype (separate from timestamp.h so
+ *    they can be used from frontends)
+ *
+ * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/utils/timestamp_type.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TIMESTAMP_TYPE_H
+#define TIMESTAMP_TYPE_H
+
+/*
+ * Timestamp represents absolute time.
+ *
+ * Interval represents delta time. Keep track of months (and years), days,
+ * and hours/minutes/seconds separately since the elapsed time spanned is
+ * unknown until instantiated relative to an absolute time.
+ *
+ * Note that Postgres uses "time interval" to mean a bounded interval,
+ * consisting of a beginning and ending time, not a time span - thomas 97/03/20
+ *
+ * We have two implementations, one that uses int64 values with units of
+ * microseconds, and one that uses double values with units of seconds.
+ *
+ * TimeOffset and fsec_t are convenience typedefs for temporary variables
+ * that are of different types in the two cases.  Do not use fsec_t in values
+ * stored on-disk, since it is not the same size in both implementations.
+ * Also, fsec_t is only meant for *fractional* seconds; beware of overflow
+ * if the value you need to store could be many seconds.
+ */
+
+#ifdef HAVE_INT64_TIMESTAMP
+
+typedef int64 Timestamp;
+typedef int64 TimestampTz;
+typedef int64 TimeOffset;
+typedef int32 fsec_t;			/* fractional seconds (in microseconds) */
+#else
+
+typedef double Timestamp;
+typedef double TimestampTz;
+typedef double TimeOffset;
+typedef double fsec_t;			/* fractional seconds (in seconds) */
+#endif
+
+typedef struct
+{
+	TimeOffset	time;			/* all time units other than days, months and
+								 * years */
+	int32		day;			/* days, after time for alignment */
+	int32		month;			/* months and years, after time for alignment */
+} Interval;
+
+
+#define MAX_TIMESTAMP_PRECISION 6
+#define MAX_INTERVAL_PRECISION 6
+
+/* in both timestamp.h and ecpg/dt.h */
+#define DAYS_PER_YEAR	365.25	/* assumes leap year every four years */
+#define MONTHS_PER_YEAR 12
+/*
+ *	DAYS_PER_MONTH is very imprecise.  The more accurate value is
+ *	365.2425/12 = 30.436875, or '30 days 10:29:06'.  Right now we only
+ *	return an integral number of days, but someday perhaps we should
+ *	also return a 'time' value to be used as well.	ISO 8601 suggests
+ *	30 days.
+ */
+#define DAYS_PER_MONTH	30		/* assumes exactly 30 days per month */
+#define HOURS_PER_DAY	24		/* assume no daylight savings time changes */
+
+/*
+ *	This doesn't adjust for uneven daylight savings time intervals or leap
+ *	seconds, and it crudely estimates leap years.  A more accurate value
+ *	for days per years is 365.2422.
+ */
+#define SECS_PER_YEAR	(36525 * 864)	/* avoid floating-point computation */
+#define SECS_PER_DAY	86400
+#define SECS_PER_HOUR	3600
+#define SECS_PER_MINUTE 60
+#define MINS_PER_HOUR	60
+
+#ifdef HAVE_INT64_TIMESTAMP
+#define USECS_PER_DAY	INT64CONST(86400000000)
+#define USECS_PER_HOUR	INT64CONST(3600000000)
+#define USECS_PER_MINUTE INT64CONST(60000000)
+#define USECS_PER_SEC	INT64CONST(1000000)
+#endif
+
+#endif /* TIMESTAMP_TYPE */
diff --git a/src/include/access/xlog_internal.h b/src/include/access/xlog_internal.h
index 4eaa243..28848f4 100644
--- a/src/include/access/xlog_internal.h
+++ b/src/include/access/xlog_internal.h
@@ -112,57 +112,6 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
 #define XLogPageHeaderSize(hdr)		\
 	(((hdr)->xlp_info & XLP_LONG_HEADER) ? SizeOfXLogLongPHD : SizeOfXLogShortPHD)
 
-/*
- * We break each logical log file (xlogid value) into segment files of the
- * size indicated by XLOG_SEG_SIZE.  One possible segment at the end of each
- * log file is wasted, to ensure that we don't have problems representing
- * last-byte-position-plus-1.
- */
-#define XLogSegSize		((uint32) XLOG_SEG_SIZE)
-#define XLogSegsPerFile (((uint32) 0xffffffff) / XLogSegSize)
-#define XLogFileSize	(XLogSegsPerFile * XLogSegSize)
-
-
-/*
- * Macros for manipulating XLOG pointers
- */
-
-/* Increment an xlogid/segment pair */
-#define NextLogSeg(logId, logSeg)	\
-	do { \
-		if ((logSeg) >= XLogSegsPerFile-1) \
-		{ \
-			(logId)++; \
-			(logSeg) = 0; \
-		} \
-		else \
-			(logSeg)++; \
-	} while (0)
-
-/* Decrement an xlogid/segment pair (assume it's not 0,0) */
-#define PrevLogSeg(logId, logSeg)	\
-	do { \
-		if (logSeg) \
-			(logSeg)--; \
-		else \
-		{ \
-			(logId)--; \
-			(logSeg) = XLogSegsPerFile-1; \
-		} \
-	} while (0)
-
-/* Align a record pointer to next page */
-#define NextLogPage(recptr) \
-	do {	\
-		if ((recptr).xrecoff % XLOG_BLCKSZ != 0)	\
-			(recptr).xrecoff +=	\
-				(XLOG_BLCKSZ - (recptr).xrecoff % XLOG_BLCKSZ);	\
-		if ((recptr).xrecoff >= XLogFileSize) \
-		{	\
-			((recptr).xlogid)++;	\
-			(recptr).xrecoff = 0; \
-		}	\
-	} while (0)
 
 /*
  * Compute ID and segment from an XLogRecPtr.
@@ -207,36 +156,6 @@ typedef XLogLongPageHeaderData *XLogLongPageHeader;
 #define XLOGDIR				"pg_xlog"
 #define XLOG_CONTROL_FILE	"global/pg_control"
 
-/*
- * These macros encapsulate knowledge about the exact layout of XLog file
- * names, timeline history file names, and archive-status file names.
- */
-#define MAXFNAMELEN		64
-
-#define XLogFileName(fname, tli, log, seg)	\
-	snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg)
-
-#define XLogFromFileName(fname, tli, log, seg)	\
-	sscanf(fname, "%08X%08X%08X", tli, log, seg)
-
-#define XLogFilePath(path, tli, log, seg)	\
-	snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli, log, seg)
-
-#define TLHistoryFileName(fname, tli)	\
-	snprintf(fname, MAXFNAMELEN, "%08X.history", tli)
-
-#define TLHistoryFilePath(path, tli)	\
-	snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli)
-
-#define StatusFilePath(path, xlog, suffix)	\
-	snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix)
-
-#define BackupHistoryFileName(fname, tli, log, seg, offset) \
-	snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli, log, seg, offset)
-
-#define BackupHistoryFilePath(path, tli, log, seg, offset)	\
-	snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli, log, seg, offset)
-
 
 /*
  * Method table for resource managers.
diff --git a/src/include/access/xlogdefs.h b/src/include/access/xlogdefs.h
index 6530df0..6c0394d 100644
--- a/src/include/access/xlogdefs.h
+++ b/src/include/access/xlogdefs.h
@@ -71,6 +71,90 @@ typedef struct XLogRecPtr
 			recptr.xrecoff += nbytes;						\
 	} while (0)
 
+/*
+ * We break each logical log file (xlogid value) into segment files of the
+ * size indicated by XLOG_SEG_SIZE.  One possible segment at the end of each
+ * log file is wasted, to ensure that we don't have problems representing
+ * last-byte-position-plus-1.
+ */
+#define XLogSegSize		((uint32) XLOG_SEG_SIZE)
+#define XLogSegsPerFile (((uint32) 0xffffffff) / XLogSegSize)
+#define XLogFileSize	(XLogSegsPerFile * XLogSegSize)
+
+/*
+ * Macros for manipulating XLOG pointers
+ */
+
+/* Increment an xlogid/segment pair */
+#define NextLogSeg(logId, logSeg)	\
+	do { \
+		if ((logSeg) >= XLogSegsPerFile-1) \
+		{ \
+			(logId)++; \
+			(logSeg) = 0; \
+		} \
+		else \
+			(logSeg)++; \
+	} while (0)
+
+/* Decrement an xlogid/segment pair (assume it's not 0,0) */
+#define PrevLogSeg(logId, logSeg)	\
+	do { \
+		if (logSeg) \
+			(logSeg)--; \
+		else \
+		{ \
+			(logId)--; \
+			(logSeg) = XLogSegsPerFile-1; \
+		} \
+	} while (0)
+
+/* Align a record pointer to next page */
+#define NextLogPage(recptr) \
+	do {	\
+		if ((recptr).xrecoff % XLOG_BLCKSZ != 0)	\
+			(recptr).xrecoff +=	\
+				(XLOG_BLCKSZ - (recptr).xrecoff % XLOG_BLCKSZ);	\
+		if ((recptr).xrecoff >= XLogFileSize) \
+		{	\
+			((recptr).xlogid)++;	\
+			(recptr).xrecoff = 0; \
+		}	\
+	} while (0)
+
+
+
+/*
+ * These macros encapsulate knowledge about the exact layout of XLog file
+ * names, timeline history file names, and archive-status file names.
+ */
+#define MAXFNAMELEN		64
+
+#define XLogFileName(fname, tli, log, seg)	\
+	snprintf(fname, MAXFNAMELEN, "%08X%08X%08X", tli, log, seg)
+
+#define XLogFromFileName(fname, tli, log, seg)	\
+	sscanf(fname, "%08X%08X%08X", tli, log, seg)
+
+#define XLogFilePath(path, tli, log, seg)	\
+	snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X", tli, log, seg)
+
+#define TLHistoryFileName(fname, tli)	\
+	snprintf(fname, MAXFNAMELEN, "%08X.history", tli)
+
+#define TLHistoryFilePath(path, tli)	\
+	snprintf(path, MAXPGPATH, XLOGDIR "/%08X.history", tli)
+
+#define StatusFilePath(path, xlog, suffix)	\
+	snprintf(path, MAXPGPATH, XLOGDIR "/archive_status/%s%s", xlog, suffix)
+
+#define BackupHistoryFileName(fname, tli, log, seg, offset) \
+	snprintf(fname, MAXFNAMELEN, "%08X%08X%08X.%08X.backup", tli, log, seg, offset)
+
+#define BackupHistoryFilePath(path, tli, log, seg, offset)	\
+	snprintf(path, MAXPGPATH, XLOGDIR "/%08X%08X%08X.%08X.backup", tli, log, seg, offset)
+
+
 
 /*
  * TimeLineID (TLI) - identifies different database histories to prevent
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to