*
*
* 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
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);
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();
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
uint16 curridx;
bool updrqst = false;
+ Assert(!(info & XLR_INFO_MASK));
if (len == 0 || len > MAXLOGRECSZ)
elog(STOP, "XLogInsert: invalid record len %u", len);
}
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 =
MyProc->logRec = RecPtr;
SpinRelease(SInvalLock);
}
- MyLastRecPtr = RecPtr;
- RecPtr.xrecoff += record->xl_len;
+ MyLastRecPtr = RecPtr; /* begin of record */
Insert->currpos += SizeOfXLogRecord;
if (freespace > 0)
{
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;
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;
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.
*/
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);
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",
}
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);
* 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 $
*
*-------------------------------------------------------------------------
*/
uint8 t_hoff; /* sizeof tuple header */
+ /* ^ - 31 bytes - ^ */
+
bits8 t_bits[MinHeapTupleBitmapSize / 8];
/* bit map of domains */
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)))
#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
#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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
*/
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 */