From bf1c8f2b3b067c29f1abdf6fe866fb485ade96e9 Mon Sep 17 00:00:00 2001
From: "Vadim B. Mikheev" <vadim4o@yahoo.com>
Date: Fri, 2 Jun 2000 10:20:27 +0000
Subject: [PATCH] heap' xlog records

---
 src/backend/access/heap/heapam.c  | 37 ++++++++++++++++-
 src/backend/access/transam/xlog.c | 52 ++++++++++++++---------
 src/include/access/htup.h         | 69 ++++++++++++++++++++++++++++++-
 src/include/access/xlog.h         | 10 ++++-
 src/include/storage/bufpage.h     |  6 ++-
 5 files changed, 150 insertions(+), 24 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 01553e422b0..c99687e2699 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.69 2000/05/30 00:49:39 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.70 2000/06/02 10:20:24 vadim Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1246,6 +1246,27 @@ heap_insert(Relation relation, HeapTuple tup)
 
 	RelationPutHeapTupleAtEnd(relation, tup);
 
+#ifdef XLOG
+	/* XLOG stuff */
+	{
+		xl_heap_insert	xlrec;
+		xlrec.itid.dbId = relation->rd_lockInfo.lockRelId.dbId;
+		xlrec.itid.relId = relation->rd_lockInfo.lockRelId.relId;
+XXX		xlrec.itid.tid = tp.t_self;
+		xlrec.t_natts = tup->t_data->t_natts;
+		xlrec.t_oid = tup->t_data->t_oid;
+		xlrec.t_hoff = tup->t_data->t_hoff;
+		xlrec.mask = tup->t_data->t_infomask;
+		
+		XLogRecPtr recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_INSERT,
+			(char*) xlrec, sizeof(xlrec), 
+			(char*) tup->t_data + offsetof(HeapTupleHeaderData, tbits), 
+			tup->t_len - offsetof(HeapTupleHeaderData, tbits));
+
+		dp->pd_lsn = recptr;
+	}
+#endif
+
 	if (IsSystemRelationName(RelationGetRelationName(relation)))
 		RelationMark4RollbackHeapTuple(relation, tup);
 
@@ -1333,6 +1354,20 @@ l1:
 		return result;
 	}
 
+#ifdef XLOG
+	/* XLOG stuff */
+	{
+		xl_heap_delete	xlrec;
+		xlrec.dtid.dbId = relation->rd_lockInfo.lockRelId.dbId;
+		xlrec.dtid.relId = relation->rd_lockInfo.lockRelId.relId;
+		xlrec.dtid.tid = tp.t_self;
+		XLogRecPtr recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_DELETE,
+			(char*) xlrec, sizeof(xlrec), NULL, 0);
+
+		dp->pd_lsn = recptr;
+	}
+#endif
+
 	/* store transaction information of xact deleting the tuple */
 	TransactionIdStore(GetCurrentTransactionId(), &(tp.t_data->t_xmax));
 	tp.t_data->t_cmax = GetCurrentCommandId();
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 07a8392c4e4..ca75cfefb18 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.14 2000/06/02 03:58:34 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.15 2000/06/02 10:20:25 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -219,7 +219,7 @@ static char readBuf[BLCKSZ];
 static XLogRecord *nextRecord = NULL;
 
 XLogRecPtr
-XLogInsert(RmgrId rmid, char *hdr, uint32 hdrlen, char *buf, uint32 buflen)
+XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32 buflen)
 {
 	XLogCtlInsert *Insert = &XLogCtl->Insert;
 	XLogRecord *record;
@@ -231,6 +231,7 @@ XLogInsert(RmgrId rmid, char *hdr, uint32 hdrlen, char *buf, uint32 buflen)
 	uint16		curridx;
 	bool		updrqst = false;
 
+	Assert(!(info & XLR_INFO_MASK));
 	if (len == 0 || len > MAXLOGRECSZ)
 		elog(STOP, "XLogInsert: invalid record len %u", len);
 
@@ -306,7 +307,8 @@ XLogInsert(RmgrId rmid, char *hdr, uint32 hdrlen, char *buf, uint32 buflen)
 	}
 	record->xl_xid = GetCurrentTransactionId();
 	record->xl_len = (len > freespace) ? freespace : len;
-	record->xl_info = (len > freespace) ? XLR_TO_BE_CONTINUED : 0;
+	record->xl_info = (len > freespace) ? 
+		(info | XLR_TO_BE_CONTINUED) : info;
 	record->xl_rmid = rmid;
 	RecPtr.xlogid = XLogCtl->xlblocks[curridx].xlogid;
 	RecPtr.xrecoff =
@@ -318,8 +320,7 @@ XLogInsert(RmgrId rmid, char *hdr, uint32 hdrlen, char *buf, uint32 buflen)
 		MyProc->logRec = RecPtr;
 		SpinRelease(SInvalLock);
 	}
-	MyLastRecPtr = RecPtr;
-	RecPtr.xrecoff += record->xl_len;
+	MyLastRecPtr = RecPtr;	/* begin of record */
 	Insert->currpos += SizeOfXLogRecord;
 	if (freespace > 0)
 	{
@@ -364,6 +365,7 @@ nbuf:
 		if (hdrlen > freespace)
 		{
 			subrecord->xl_len = freespace;
+			/* we don't store info in subrecord' xl_info */
 			subrecord->xl_info = XLR_TO_BE_CONTINUED;
 			memcpy(Insert->currpos, hdr, freespace);
 			hdrlen -= freespace;
@@ -383,6 +385,7 @@ nbuf:
 		if (buflen > freespace)
 		{
 			subrecord->xl_len += freespace;
+			/* we don't store info in subrecord' xl_info */
 			subrecord->xl_info = XLR_TO_BE_CONTINUED;
 			memcpy(Insert->currpos, buf, freespace);
 			buflen -= freespace;
@@ -395,15 +398,22 @@ nbuf:
 			memcpy(Insert->currpos, buf, buflen);
 			Insert->currpos += buflen;
 		}
+		/* we don't store info in subrecord' xl_info */
 		subrecord->xl_info = 0;
-		RecPtr.xlogid = XLogCtl->xlblocks[curridx].xlogid;
-		RecPtr.xrecoff = XLogCtl->xlblocks[curridx].xrecoff -
-			BLCKSZ + SizeOfXLogPHD + subrecord->xl_len;
 		Insert->currpos = ((char *) Insert->currpage) +
 			DOUBLEALIGN(Insert->currpos - ((char *) Insert->currpage));
 	}
 	freespace = ((char *) Insert->currpage) + BLCKSZ - Insert->currpos;
 
+	/*
+	 * Begin of the next record will be stored as LSN for
+	 * changed data page...
+	 */
+	RecPtr.xlogid = XLogCtl->xlblocks[curridx].xlogid;
+	RecPtr.xrecoff =
+		XLogCtl->xlblocks[curridx].xrecoff - BLCKSZ +
+		Insert->currpos - ((char *) Insert->currpage);
+
 	/*
 	 * All done! Update global LgwrRqst if some block was filled up.
 	 */
@@ -884,7 +894,8 @@ got_record:;
 		XLogSubRecord *subrecord;
 		uint32		len = record->xl_len;
 
-		if (record->xl_len + RecPtr->xrecoff % BLCKSZ + SizeOfXLogRecord != BLCKSZ)
+		if (DOUBLEALIGN(record->xl_len) + RecPtr->xrecoff % BLCKSZ + 
+			SizeOfXLogRecord != BLCKSZ)
 		{
 			elog(emode, "ReadRecord: invalid fragmented record len %u in (%u, %u)",
 				 record->xl_len, RecPtr->xlogid, RecPtr->xrecoff);
@@ -945,7 +956,7 @@ got_record:;
 			buffer += subrecord->xl_len;
 			if (subrecord->xl_info & XLR_TO_BE_CONTINUED)
 			{
-				if (subrecord->xl_len +
+				if (DOUBLEALIGN(subrecord->xl_len) +
 					SizeOfXLogPHD + SizeOfXLogSubRecord != BLCKSZ)
 				{
 					elog(emode, "ReadRecord: invalid fragmented subrecord len %u in logfile %u seg %u off %u",
@@ -956,23 +967,26 @@ got_record:;
 			}
 			break;
 		}
-		if (BLCKSZ - SizeOfXLogRecord >=
-			subrecord->xl_len + SizeOfXLogPHD + SizeOfXLogSubRecord)
+		if (BLCKSZ - SizeOfXLogRecord >= DOUBLEALIGN(subrecord->xl_len) + 
+			SizeOfXLogPHD + SizeOfXLogSubRecord)
 		{
-			nextRecord = (XLogRecord *)
-				((char *) subrecord + subrecord->xl_len + SizeOfXLogSubRecord);
+			nextRecord = (XLogRecord *) ((char *) subrecord + 
+				DOUBLEALIGN(subrecord->xl_len) + SizeOfXLogSubRecord);
 		}
 		EndRecPtr.xlogid = readId;
 		EndRecPtr.xrecoff = readSeg * XLogSegSize + readOff * BLCKSZ +
-			SizeOfXLogPHD + SizeOfXLogSubRecord + subrecord->xl_len;
+			SizeOfXLogPHD + SizeOfXLogSubRecord + 
+			DOUBLEALIGN(subrecord->xl_len);
 		ReadRecPtr = *RecPtr;
 		return (record);
 	}
-	if (BLCKSZ - SizeOfXLogRecord >=
-		record->xl_len + RecPtr->xrecoff % BLCKSZ + SizeOfXLogRecord)
-		nextRecord = (XLogRecord *) ((char *) record + record->xl_len + SizeOfXLogRecord);
+	if (BLCKSZ - SizeOfXLogRecord >= DOUBLEALIGN(record->xl_len) + 
+		RecPtr->xrecoff % BLCKSZ + SizeOfXLogRecord)
+		nextRecord = (XLogRecord *) ((char *) record + 
+			DOUBLEALIGN(record->xl_len) + SizeOfXLogRecord);
 	EndRecPtr.xlogid = RecPtr->xlogid;
-	EndRecPtr.xrecoff = RecPtr->xrecoff + record->xl_len + SizeOfXLogRecord;
+	EndRecPtr.xrecoff = RecPtr->xrecoff + 
+		DOUBLEALIGN(record->xl_len) + SizeOfXLogRecord;
 	ReadRecPtr = *RecPtr;
 
 	return (record);
diff --git a/src/include/access/htup.h b/src/include/access/htup.h
index 784c5051a93..ff514092160 100644
--- a/src/include/access/htup.h
+++ b/src/include/access/htup.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: htup.h,v 1.29 2000/04/12 17:16:26 momjian Exp $
+ * $Id: htup.h,v 1.30 2000/06/02 10:20:26 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,6 +44,8 @@ typedef struct HeapTupleHeaderData
 
 	uint8		t_hoff;			/* sizeof tuple header */
 
+								/* ^ - 31 bytes - ^ */
+
 	bits8		t_bits[MinHeapTupleBitmapSize / 8];
 	/* bit map of domains */
 
@@ -52,6 +54,71 @@ typedef struct HeapTupleHeaderData
 
 typedef HeapTupleHeaderData *HeapTupleHeader;
 
+
+#ifdef XLOG
+
+/* XLOG stuff */
+
+/*
+ * XLOG allows to store some information in high 4 bits of log
+ * record xl_info field
+ */
+#define	XLOG_HEAP_INSERT	0x00
+#define	XLOG_HEAP_DELETE	0x10
+#define	XLOG_HEAP_UPDATE	0x20
+#define	XLOG_HEAP_MOVE		0x30
+
+/*
+ * All what we need to find changed tuple (14 bytes)
+ */
+typedef struct xl_heaptid
+{
+	Oid					dbId;		/* database */
+	Oid					relId;		/* relation */
+	ItemPointerData		tid;		/* changed tuple id */
+} xl_heaptid;
+
+/* This is what we need to know about delete - ALIGN(14) = 16 bytes */
+typedef struct xl_heap_delete
+{
+	xl_heaptid			dtid;		/* deleted tuple id */
+} xl_heap_delete;
+
+/* This is what we need to know about insert - 22 + data */
+typedef struct xl_heap_insert
+{
+	xl_heaptid			itid;		/* inserted tuple id */
+	/* something from tuple header */
+	int16				t_natts;
+	Oid					t_oid;
+	uint8				t_hoff;
+	uint8				mask;		/* low 8 bits of t_infomask */
+	/* TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_heap_insert;
+
+/* This is what we need to know about update - 28 + data */
+typedef struct xl_heap_update
+{
+	xl_heaptid			dtid;		/* deleted tuple id */
+	ItemPointerData		itid;		/* new inserted tuple id */
+	/* something from header of new tuple version */
+	int16				t_natts;
+	uint8				t_hoff;
+	uint8				mask;		/* low 8 bits of t_infomask */
+	/* NEW TUPLE DATA FOLLOWS AT END OF STRUCT */
+} xl_heap_update;
+
+/* This is what we need to know about tuple move - ALIGN(20) = 24 bytes */
+typedef struct xl_heap_move
+{
+	xl_heaptid			ftid;		/* moved from */
+	ItemPointerData		ttid;		/* moved to */
+} xl_heap_move;
+
+/* end of XLOG stuff */
+
+#endif	/* XLOG */
+
 #define MinTupleSize	(MAXALIGN(sizeof (PageHeaderData)) + \
 						 MAXALIGN(sizeof(HeapTupleHeaderData)) + \
 						 MAXALIGN(sizeof(char)))
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index e2ab6e4f417..b5fda0b58ad 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -47,7 +47,12 @@ typedef struct XLogSubRecord
 
 #define SizeOfXLogSubRecord DOUBLEALIGN(sizeof(XLogSubRecord))
 
+/*
+ * XLOG uses only low 4 bits of xl_info. High 4 bits may be used
+ * by rmgr...
+ */
 #define XLR_TO_BE_CONTINUED		0x01
+#define	XLR_INFO_MASK			0x0F
 
 #define XLOG_PAGE_MAGIC 0x17345168
 
@@ -63,8 +68,9 @@ typedef XLogPageHeaderData *XLogPageHeader;
 
 #define XLP_FIRST_IS_SUBRECORD	0x0001
 
-extern XLogRecPtr XLogInsert(RmgrId rmid, char *hdr, uint32 hdrlen,
-		   char *buf, uint32 buflen);
+extern XLogRecPtr XLogInsert(RmgrId rmid, uint8 info, 
+			char *hdr, uint32 hdrlen,
+			char *buf, uint32 buflen);
 extern void XLogFlush(XLogRecPtr RecPtr);
 
 #endif	 /* XLOG_H */
diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h
index f1c25963951..15d1106f26c 100644
--- a/src/include/storage/bufpage.h
+++ b/src/include/storage/bufpage.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: bufpage.h,v 1.28 2000/01/26 05:58:32 momjian Exp $
+ * $Id: bufpage.h,v 1.29 2000/06/02 10:20:27 vadim Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -117,6 +117,10 @@ typedef OpaqueData *Opaque;
  */
 typedef struct PageHeaderData
 {
+#ifdef XLOG
+	XLogRecPtr	pd_lsn;			/* XLOG: next byte after last byte of xlog */
+								/* record for last change of this page */
+#endif
 	LocationIndex pd_lower;		/* offset to start of free space */
 	LocationIndex pd_upper;		/* offset to end of free space */
 	LocationIndex pd_special;	/* offset to start of special space */
-- 
GitLab