aboutsummaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
Diffstat (limited to 'src/include')
-rw-r--r--src/include/access/transam.h18
-rw-r--r--src/include/access/xlog.h171
-rw-r--r--src/include/access/xlogdefs.h41
-rw-r--r--src/include/access/xlogutils.h10
-rw-r--r--src/include/catalog/pg_control.h115
-rw-r--r--src/include/miscadmin.h4
-rw-r--r--src/include/storage/ipc.h4
-rw-r--r--src/include/tcop/tcopprot.h3
-rw-r--r--src/include/utils/pg_crc.h115
9 files changed, 406 insertions, 75 deletions
diff --git a/src/include/access/transam.h b/src/include/access/transam.h
index 620f6e59105..460de699886 100644
--- a/src/include/access/transam.h
+++ b/src/include/access/transam.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: transam.h,v 1.29 2001/01/24 19:43:19 momjian Exp $
+ * $Id: transam.h,v 1.30 2001/03/13 01:17:06 tgl Exp $
*
* NOTES
* Transaction System Version 101 now support proper oid
@@ -79,7 +79,7 @@ typedef unsigned char XidStatus;/* (2 bits) */
* their numbering at 512.
*
* The first 4 bytes of this relation store the version
- * number of the transction system.
+ * number of the transaction system.
* ----------------
*/
typedef struct LogRelationContentsData
@@ -100,13 +100,16 @@ typedef LogRelationContentsData *LogRelationContents;
* is updated in place whenever the variables change.
*
* The first 4 bytes of this relation store the version
- * number of the transction system.
+ * number of the transaction system.
*
* Currently, the relation has only one page and the next
* available xid, the last committed xid and the next
* available oid are stored there.
+ *
+ * XXX As of 7.1, pg_variable isn't used anymore; this is dead code.
* ----------------
*/
+#ifdef NOT_USED
typedef struct VariableRelationContentsData
{
XLogRecPtr LSN;
@@ -117,6 +120,7 @@ typedef struct VariableRelationContentsData
} VariableRelationContentsData;
typedef VariableRelationContentsData *VariableRelationContents;
+#endif /* NOT_USED */
/*
* VariableCache is placed in shmem and used by
@@ -124,8 +128,9 @@ typedef VariableRelationContentsData *VariableRelationContents;
*/
typedef struct VariableCacheData
{
- TransactionId nextXid;
- Oid nextOid;
+ TransactionId nextXid; /* next XID to assign */
+ uint32 xidCount; /* XIDs available before must do XLOG work */
+ Oid nextOid; /* and similarly for OIDs */
uint32 oidCount;
} VariableCacheData;
@@ -184,7 +189,8 @@ extern int RecoveryCheckingEnableState;
extern bool AMI_OVERRIDE;
/* in varsup.c */
-extern int OidGenLockId;
+extern SPINLOCK OidGenLockId;
+extern SPINLOCK XidGenLockId;
extern VariableCache ShmemVariableCache;
#endif /* TRAMSAM_H */
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index c17bf32cc55..dd079496ed6 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -3,7 +3,10 @@
*
* PostgreSQL transaction log manager
*
- * $Header: /cvsroot/pgsql/src/include/access/xlog.h,v 1.18 2001/02/26 00:50:07 tgl Exp $
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: xlog.h,v 1.19 2001/03/13 01:17:06 tgl Exp $
*/
#ifndef XLOG_H
#define XLOG_H
@@ -11,97 +14,126 @@
#include "access/rmgr.h"
#include "access/transam.h"
#include "access/xlogdefs.h"
-#include "access/xlogutils.h"
+#include "utils/pg_crc.h"
-typedef struct crc64
-{
- uint32 crc1;
- uint32 crc2;
-} crc64;
+/*
+ * Header for each record in XLOG
+ *
+ * NOTE: xl_len counts only the rmgr data, not the XLogRecord header,
+ * and also not any backup blocks appended to the record (which are signaled
+ * by xl_info flag bits). The total space needed for an XLOG record is
+ * really:
+ *
+ * SizeOfXLogRecord + xl_len + n_backup_blocks * (sizeof(BkpBlock) + BLCKSZ)
+ */
typedef struct XLogRecord
{
- crc64 xl_crc;
+ crc64 xl_crc; /* CRC for this record */
XLogRecPtr xl_prev; /* ptr to previous record in log */
XLogRecPtr xl_xact_prev; /* ptr to previous record of this xact */
TransactionId xl_xid; /* xact id */
- uint16 xl_len; /* total len of record *data* */
- uint8 xl_info;
- RmgrId xl_rmid; /* resource manager inserted this record */
+ uint16 xl_len; /* total len of rmgr data */
+ uint8 xl_info; /* flag bits, see below */
+ RmgrId xl_rmid; /* resource manager for this record */
/* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */
} XLogRecord;
-#define SizeOfXLogRecord DOUBLEALIGN(sizeof(XLogRecord))
-#define MAXLOGRECSZ (2 * BLCKSZ)
+#define SizeOfXLogRecord MAXALIGN(sizeof(XLogRecord))
+#define MAXLOGRECSZ 65535 /* the most that'll fit in xl_len */
-#define XLogRecGetData(record) \
- ((char*)record + SizeOfXLogRecord)
+#define XLogRecGetData(record) ((char*) (record) + SizeOfXLogRecord)
/*
- * When there is no space on current page we continue
- * on the next page with subrecord.
+ * XLOG uses only low 4 bits of xl_info. High 4 bits may be used by rmgr.
*/
-typedef struct XLogSubRecord
-{
- uint16 xl_len; /* len of data left */
-
- /* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */
-
-} XLogSubRecord;
-
-#define SizeOfXLogSubRecord DOUBLEALIGN(sizeof(XLogSubRecord))
+#define XLR_INFO_MASK 0x0F
/*
- * XLOG uses only low 4 bits of xl_info.
- * High 4 bits may be used by rmgr...
- *
- * We support backup of 2 blocks per record only.
- * If we backed up some of these blocks then we use
- * flags below to signal rmgr about this on recovery.
+ * We support backup of up to 2 disk blocks per XLOG record (could support
+ * more if we cared to dedicate more xl_info bits for this purpose; currently
+ * do not need more than 2 anyway). If we backed up any disk blocks then we
+ * use flag bits in xl_info to signal it.
*/
-#define XLR_SET_BKP_BLOCK(iblk) (0x08 >> iblk)
+#define XLR_BKP_BLOCK_MASK 0x0C /* all info bits used for bkp blocks */
+#define XLR_MAX_BKP_BLOCKS 2
+#define XLR_SET_BKP_BLOCK(iblk) (0x08 >> (iblk))
#define XLR_BKP_BLOCK_1 XLR_SET_BKP_BLOCK(0) /* 0x08 */
#define XLR_BKP_BLOCK_2 XLR_SET_BKP_BLOCK(1) /* 0x04 */
-#define XLR_INFO_MASK 0x0F
/*
* Sometimes we log records which are out of transaction control.
- * Rmgr may use flag below for this purpose.
+ * Rmgr may "or" XLOG_NO_TRAN into info passed to XLogInsert to indicate this.
*/
#define XLOG_NO_TRAN XLR_INFO_MASK
-#define XLOG_PAGE_MAGIC 0x17345168
+/*
+ * Header info for a backup block appended to an XLOG record.
+ *
+ * Note that the backup block has its own CRC, and is not covered by
+ * the CRC of the XLOG record proper. Also note that we don't attempt
+ * to align either the BkpBlock struct or the block's data.
+ */
+typedef struct BkpBlock
+{
+ crc64 crc;
+ RelFileNode node;
+ BlockNumber block;
+} BkpBlock;
-typedef struct XLogPageHeaderData
+/*
+ * When there is not enough space on current page for whole record, we
+ * continue on the next page with continuation record. (However, the
+ * XLogRecord header will never be split across pages; if there's less than
+ * SizeOfXLogRecord space left at the end of a page, we just waste it.)
+ *
+ * Note that xl_rem_len includes backup-block data, unlike xl_len in the
+ * initial header.
+ */
+typedef struct XLogContRecord
{
- uint32 xlp_magic;
- uint16 xlp_info;
-} XLogPageHeaderData;
+ uint32 xl_rem_len; /* total len of remaining data for record */
-#define SizeOfXLogPHD DOUBLEALIGN(sizeof(XLogPageHeaderData))
+ /* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */
-typedef XLogPageHeaderData *XLogPageHeader;
+} XLogContRecord;
-/* When record crosses page boundary */
-#define XLP_FIRST_IS_SUBRECORD 0x0001
+#define SizeOfXLogContRecord MAXALIGN(sizeof(XLogContRecord))
-#define XLByteLT(left, right) \
- (right.xlogid > left.xlogid || \
- (right.xlogid == left.xlogid && right.xrecoff > left.xrecoff))
+/*
+ * Each page of XLOG file has a header like this:
+ */
+#define XLOG_PAGE_MAGIC 0x17345169 /* can be used as WAL version indicator */
-#define XLByteLE(left, right) \
- (right.xlogid > left.xlogid || \
- (right.xlogid == left.xlogid && right.xrecoff >= left.xrecoff))
+typedef struct XLogPageHeaderData
+{
+ uint32 xlp_magic; /* magic value for correctness checks */
+ uint16 xlp_info; /* flag bits, see below */
+} XLogPageHeaderData;
-#define XLByteEQ(left, right) \
- (right.xlogid == left.xlogid && right.xrecoff == left.xrecoff)
+#define SizeOfXLogPHD MAXALIGN(sizeof(XLogPageHeaderData))
-extern StartUpID ThisStartUpID; /* current SUI */
-extern bool InRecovery;
-extern XLogRecPtr MyLastRecPtr;
+typedef XLogPageHeaderData *XLogPageHeader;
+
+/* When record crosses page boundary, set this flag in new page's header */
+#define XLP_FIRST_IS_CONTRECORD 0x0001
+
+/*
+ * We break each logical log file (xlogid value) into 16Mb segments.
+ * 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) (16*1024*1024))
+#define XLogSegsPerFile (((uint32) 0xffffffff) / XLogSegSize)
+#define XLogFileSize (XLogSegsPerFile * XLogSegSize)
+/*
+ * Method table for resource managers.
+ *
+ * RmgrTable[] is indexed by RmgrId values (see rmgr.h).
+ */
typedef struct RmgrData
{
char *rm_name;
@@ -112,12 +144,19 @@ typedef struct RmgrData
extern RmgrData RmgrTable[];
-/*
- * List of these structs is used to pass data to XLOG.
- * If buffer is valid then XLOG will check if buffer must
- * be backup-ed. For backup-ed buffer data will not be
- * inserted into record (and XLOG sets
- * XLR_BKP_BLOCK_X bit in xl_info).
+/*--------------------
+ * List of these structs is used to pass data to XLogInsert().
+ *
+ * If buffer is valid then XLOG will check if buffer must be backed up
+ * (ie, whether this is first change of that page since last checkpoint).
+ * If so, the whole page contents are attached to the XLOG record, and XLOG
+ * sets XLR_BKP_BLOCK_X bit in xl_info. Note that the buffer must be pinned
+ * and locked while this is going on, so that it won't change under us.
+ * NB: when this happens, we do not bother to insert the associated data into
+ * the XLOG record, since we assume it's present in the buffer. Therefore,
+ * rmgr redo routines MUST pay attention to XLR_BKP_BLOCK_X to know what
+ * is actually stored in the XLOG record.
+ *--------------------
*/
typedef struct XLogRecData
{
@@ -127,11 +166,13 @@ typedef struct XLogRecData
struct XLogRecData *next;
} XLogRecData;
+extern StartUpID ThisStartUpID; /* current SUI */
+extern bool InRecovery;
+extern XLogRecPtr MyLastRecPtr;
+
extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info, XLogRecData *rdata);
extern void XLogFlush(XLogRecPtr RecPtr);
-extern void CreateCheckPoint(bool shutdown);
-
extern void xlog_redo(XLogRecPtr lsn, XLogRecord *record);
extern void xlog_undo(XLogRecPtr lsn, XLogRecord *record);
extern void xlog_desc(char *buf, uint8 xl_info, char* rec);
@@ -145,6 +186,10 @@ extern void StartupXLOG(void);
extern void ShutdownXLOG(void);
extern void CreateCheckPoint(bool shutdown);
extern void SetThisStartUpID(void);
+extern void XLogPutNextXid(TransactionId nextXid);
+extern void XLogPutNextOid(Oid nextOid);
+extern void SetRedoRecPtr(void);
+extern void GetRedoRecPtr(void);
/* in storage/ipc/sinval.c, but don't want to declare in sinval.h because
* we'd have to include xlog.h into that ...
diff --git a/src/include/access/xlogdefs.h b/src/include/access/xlogdefs.h
index ce1b3ef8cf6..bc7f9e1a36d 100644
--- a/src/include/access/xlogdefs.h
+++ b/src/include/access/xlogdefs.h
@@ -1,21 +1,56 @@
/*
- *
* xlogdefs.h
*
* Postgres transaction log manager record pointer and
- * system stratup number definitions
+ * system startup number definitions
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
*
+ * $Id: xlogdefs.h,v 1.2 2001/03/13 01:17:06 tgl Exp $
*/
#ifndef XLOG_DEFS_H
#define XLOG_DEFS_H
+/*
+ * Pointer to a location in the XLOG. These pointers are 64 bits wide,
+ * because we don't want them ever to overflow.
+ *
+ * NOTE: xrecoff == 0 is used to indicate an invalid pointer. This is OK
+ * because we use page headers in the XLOG, so no XLOG record can start
+ * right at the beginning of a file.
+ *
+ * NOTE: the "log file number" is somewhat misnamed, since the actual files
+ * making up the XLOG are much smaller than 4Gb. Each actual file is an
+ * XLogSegSize-byte "segment" of a logical log file having the indicated
+ * xlogid. The log file number and segment number together identify a
+ * physical XLOG file. Segment number and offset within the physical file
+ * are computed from xrecoff div and mod XLogSegSize.
+ */
typedef struct XLogRecPtr
{
uint32 xlogid; /* log file #, 0 based */
- uint32 xrecoff; /* offset of record in log file */
+ uint32 xrecoff; /* byte offset of location in log file */
} XLogRecPtr;
/*
+ * Macros for comparing XLogRecPtrs
+ *
+ * Beware of passing expressions with side-effects to these macros,
+ * since the arguments may be evaluated multiple times.
+ */
+#define XLByteLT(a, b) \
+ ((a).xlogid < (b).xlogid || \
+ ((a).xlogid == (b).xlogid && (a).xrecoff < (b).xrecoff))
+
+#define XLByteLE(a, b) \
+ ((a).xlogid < (b).xlogid || \
+ ((a).xlogid == (b).xlogid && (a).xrecoff <= (b).xrecoff))
+
+#define XLByteEQ(a, b) \
+ ((a).xlogid == (b).xlogid && (a).xrecoff == (b).xrecoff)
+
+/*
* StartUpID (SUI) - system startups counter. It's to allow removing
* pg_log after shutdown, in future.
*/
diff --git a/src/include/access/xlogutils.h b/src/include/access/xlogutils.h
index 016381f0d2b..1f1fff7c07f 100644
--- a/src/include/access/xlogutils.h
+++ b/src/include/access/xlogutils.h
@@ -1,3 +1,13 @@
+/*
+ * xlogutils.h
+ *
+ * PostgreSQL transaction log manager utility routines
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: xlogutils.h,v 1.6 2001/03/13 01:17:06 tgl Exp $
+ */
#ifndef XLOG_UTILS_H
#define XLOG_UTILS_H
diff --git a/src/include/catalog/pg_control.h b/src/include/catalog/pg_control.h
new file mode 100644
index 00000000000..97d0e13e783
--- /dev/null
+++ b/src/include/catalog/pg_control.h
@@ -0,0 +1,115 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_control.h
+ * The system control file "pg_control" is not a heap relation.
+ * However, we define it here so that the format is documented.
+ *
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: pg_control.h,v 1.1 2001/03/13 01:17:06 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_CONTROL_H
+#define PG_CONTROL_H
+
+#include <time.h>
+
+#include "access/xlogdefs.h"
+#include "utils/pg_crc.h"
+
+
+/* Version identifier for this pg_control format */
+#define PG_CONTROL_VERSION 71
+
+/*
+ * Body of CheckPoint XLOG records. This is declared here because we keep
+ * a copy of the latest one in pg_control for possible disaster recovery.
+ */
+typedef struct CheckPoint
+{
+ XLogRecPtr redo; /* next RecPtr available when we */
+ /* began to create CheckPoint */
+ /* (i.e. REDO start point) */
+ XLogRecPtr undo; /* first record of oldest in-progress */
+ /* transaction when we started */
+ /* (i.e. UNDO end point) */
+ StartUpID ThisStartUpID; /* current SUI */
+ TransactionId nextXid; /* next free XID */
+ Oid nextOid; /* next free OID */
+ time_t time; /* time stamp of checkpoint */
+} CheckPoint;
+
+/* XLOG info values for XLOG rmgr */
+#define XLOG_CHECKPOINT_SHUTDOWN 0x00
+#define XLOG_CHECKPOINT_ONLINE 0x10
+#define XLOG_NEXTXID 0x20
+#define XLOG_NEXTOID 0x30
+
+
+/* System status indicator */
+typedef enum DBState
+{
+ DB_STARTUP = 0,
+ DB_SHUTDOWNED,
+ DB_SHUTDOWNING,
+ DB_IN_RECOVERY,
+ DB_IN_PRODUCTION
+} DBState;
+
+#define LOCALE_NAME_BUFLEN 128
+
+/*
+ * Contents of pg_control.
+ *
+ * NOTE: try to keep this under 512 bytes so that it will fit on one physical
+ * sector of typical disk drives. This reduces the odds of corruption due to
+ * power failure midway through a write. Currently it fits comfortably,
+ * but we could probably reduce LOCALE_NAME_BUFLEN if things get tight.
+ */
+
+typedef struct ControlFileData
+{
+ crc64 crc; /* CRC for remainder of struct */
+
+ /*
+ * Version identifier information. Keep these fields at the front,
+ * especially pg_control_version; they won't be real useful if they
+ * move around.
+ *
+ * pg_control_version identifies the format of pg_control itself.
+ * catalog_version_no identifies the format of the system catalogs.
+ *
+ * There are additional version identifiers in individual files;
+ * for example, WAL logs contain per-page magic numbers that can serve
+ * as version cues for the WAL log.
+ */
+ uint32 pg_control_version; /* PG_CONTROL_VERSION */
+ uint32 catalog_version_no; /* see catversion.h */
+
+ /*
+ * System status data
+ */
+ DBState state; /* see enum above */
+ time_t time; /* time stamp of last pg_control update */
+ uint32 logId; /* current log file id */
+ uint32 logSeg; /* current log file segment, + 1 */
+ XLogRecPtr checkPoint; /* last check point record ptr */
+ XLogRecPtr prevCheckPoint; /* previous check point record ptr */
+
+ CheckPoint checkPointCopy; /* copy of last check point record */
+
+ /*
+ * This data is used to make sure that configuration of this database
+ * is compatible with the backend executable.
+ */
+ uint32 blcksz; /* block size for this DB */
+ uint32 relseg_size; /* blocks per segment of large relation */
+ /* active locales --- "C" if compiled without USE_LOCALE: */
+ char lc_collate[LOCALE_NAME_BUFLEN];
+ char lc_ctype[LOCALE_NAME_BUFLEN];
+} ControlFileData;
+
+#endif /* PG_CONTROL_H */
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 46d7ab534ea..851174f3966 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -12,7 +12,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: miscadmin.h,v 1.81 2001/02/10 02:31:28 tgl Exp $
+ * $Id: miscadmin.h,v 1.82 2001/03/13 01:17:06 tgl Exp $
*
* NOTES
* some of the information in this file should be moved to
@@ -283,6 +283,8 @@ extern ProcessingMode Mode;
extern bool CreateDataDirLockFile(const char *datadir, bool amPostmaster);
extern bool CreateSocketLockFile(const char *socketfile, bool amPostmaster);
extern void TouchSocketLockFile(void);
+extern void RecordSharedMemoryInLockFile(IpcMemoryKey shmKey,
+ IpcMemoryId shmId);
extern void ValidatePgVersion(const char *path);
diff --git a/src/include/storage/ipc.h b/src/include/storage/ipc.h
index 3173121850d..f1e1e6096cd 100644
--- a/src/include/storage/ipc.h
+++ b/src/include/storage/ipc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: ipc.h,v 1.47 2001/02/10 02:31:28 tgl Exp $
+ * $Id: ipc.h,v 1.48 2001/03/13 01:17:06 tgl Exp $
*
* Some files that would normally need to include only sys/ipc.h must
* instead include this file because on Ultrix, sys/ipc.h is not designed
@@ -105,6 +105,8 @@ extern int IpcSemaphoreGetValue(IpcSemaphoreId semId, int sem);
extern PGShmemHeader *IpcMemoryCreate(uint32 size, bool makePrivate,
int permission);
+extern bool SharedMemoryIsInUse(IpcMemoryKey shmKey, IpcMemoryId shmId);
+
/* ipci.c */
extern void CreateSharedMemoryAndSemaphores(bool makePrivate,
int maxBackends);
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index 52d719c6c5f..94af6e71133 100644
--- a/src/include/tcop/tcopprot.h
+++ b/src/include/tcop/tcopprot.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: tcopprot.h,v 1.38 2001/01/24 19:43:28 momjian Exp $
+ * $Id: tcopprot.h,v 1.39 2001/03/13 01:17:06 tgl Exp $
*
* OLD COMMENTS
* This file was created so that other c files could get the two
@@ -41,6 +41,7 @@ extern void pg_exec_query_string(char *query_string,
#endif /* BOOTSTRAP_INCLUDE */
extern void die(SIGNAL_ARGS);
+extern void quickdie(SIGNAL_ARGS);
extern int PostgresMain(int argc, char *argv[],
int real_argc, char *real_argv[], const char *username);
extern void ResetUsage(void);
diff --git a/src/include/utils/pg_crc.h b/src/include/utils/pg_crc.h
new file mode 100644
index 00000000000..18e012bbcd0
--- /dev/null
+++ b/src/include/utils/pg_crc.h
@@ -0,0 +1,115 @@
+/*
+ * pg_crc.h
+ *
+ * PostgreSQL 64-bit CRC support
+ *
+ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $Id: pg_crc.h,v 1.1 2001/03/13 01:17:06 tgl Exp $
+ */
+#ifndef PG_CRC_H
+#define PG_CRC_H
+
+/*
+ * If we have a 64-bit integer type, then a 64-bit CRC looks just like the
+ * usual sort of implementation. (See Ross Williams' excellent introduction
+ * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
+ * ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
+ * If we have no working 64-bit type, then fake it with two 32-bit registers.
+ *
+ * The present implementation is a normal (not "reflected", in Williams'
+ * terms) 64-bit CRC, using initial all-ones register contents and a final
+ * bit inversion. The chosen polynomial is borrowed from the DLT1 spec
+ * (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
+ *
+ * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
+ * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
+ * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
+ * x^7 + x^4 + x + 1
+ */
+
+#ifdef INT64_IS_BUSTED
+
+/*
+ * crc0 represents the LSBs of the 64-bit value, crc1 the MSBs. Note that
+ * with crc0 placed first, the output of 32-bit and 64-bit implementations
+ * will be bit-compatible only on little-endian architectures. If it were
+ * important to make the two possible implementations bit-compatible on
+ * all machines, we could do a configure test to decide how to order the
+ * two fields, but it seems not worth the trouble.
+ */
+typedef struct crc64
+{
+ uint32 crc0;
+ uint32 crc1;
+} crc64;
+
+/* Initialize a CRC accumulator */
+#define INIT_CRC64(crc) ((crc).crc0 = 0xffffffff, (crc).crc1 = 0xffffffff)
+
+/* Finish a CRC calculation */
+#define FIN_CRC64(crc) ((crc).crc0 ^= 0xffffffff, (crc).crc1 ^= 0xffffffff)
+
+/* Accumulate some (more) bytes into a CRC */
+#define COMP_CRC64(crc, data, len) \
+do { \
+ uint32 __crc0 = (crc).crc0; \
+ uint32 __crc1 = (crc).crc1; \
+ unsigned char *__data = (unsigned char *) (data); \
+ uint32 __len = (len); \
+\
+ while (__len-- > 0) \
+ { \
+ int __tab_index = ((int) (__crc1 >> 24) ^ *__data++) & 0xFF; \
+ __crc1 = crc_table1[__tab_index] ^ ((__crc1 << 8) | (__crc0 >> 24)); \
+ __crc0 = crc_table0[__tab_index] ^ (__crc0 << 8); \
+ } \
+ (crc).crc0 = __crc0; \
+ (crc).crc1 = __crc1; \
+} while (0)
+
+/* Check for equality of two CRCs */
+#define EQ_CRC64(c1,c2) ((c1).crc0 == (c2).crc0 && (c1).crc1 == (c2).crc1)
+
+/* Constant table for CRC calculation */
+extern const uint32 crc_table0[];
+extern const uint32 crc_table1[];
+
+#else /* int64 works */
+
+typedef struct crc64
+{
+ uint64 crc0;
+} crc64;
+
+/* Initialize a CRC accumulator */
+#define INIT_CRC64(crc) ((crc).crc0 = (uint64) 0xffffffffffffffff)
+
+/* Finish a CRC calculation */
+#define FIN_CRC64(crc) ((crc).crc0 ^= (uint64) 0xffffffffffffffff)
+
+/* Accumulate some (more) bytes into a CRC */
+#define COMP_CRC64(crc, data, len) \
+do { \
+ uint64 __crc0 = (crc).crc0; \
+ unsigned char *__data = (unsigned char *) (data); \
+ uint32 __len = (len); \
+\
+ while (__len-- > 0) \
+ { \
+ int __tab_index = ((int) (__crc0 >> 56) ^ *__data++) & 0xFF; \
+ __crc0 = crc_table[__tab_index] ^ (__crc0 << 8); \
+ } \
+ (crc).crc0 = __crc0; \
+} while (0)
+
+/* Check for equality of two CRCs */
+#define EQ_CRC64(c1,c2) ((c1).crc0 == (c2).crc0)
+
+/* Constant table for CRC calculation */
+extern const uint64 crc_table[];
+
+#endif /* INT64_IS_BUSTED */
+
+#endif /* PG_CRC_H */