*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.104 2000/12/30 06:52:33 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/heap/heapam.c,v 1.105 2000/12/30 15:19:54 vadim Exp $
*
*
* INTERFACE ROUTINES
XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from,
Buffer newbuf, HeapTuple newtup);
-XLogRecPtr log_heap_clean(Relation reln, Buffer buffer);
+XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
+ char *unused, int unlen);
/* comments are in heap_update */
static xl_heaptid _locked_tuple_;
}
XLogRecPtr
-log_heap_clean(Relation reln, Buffer buffer)
+log_heap_clean(Relation reln, Buffer buffer, char *unused, int unlen)
{
xl_heap_clean xlrec;
XLogRecPtr recptr;
- XLogRecData rdata[2];
+ XLogRecData rdata[3];
xlrec.node = reln->rd_node;
xlrec.block = BufferGetBlockNumber(buffer);
rdata[0].len = SizeOfHeapClean;
rdata[0].next = &(rdata[1]);
- rdata[1].buffer = buffer;
- rdata[1].data = NULL;
- rdata[1].len = 0;
- rdata[1].next = NULL;
+ if (unlen > 0)
+ {
+ rdata[1].buffer = buffer;
+ rdata[1].data = unused;
+ rdata[1].len = unlen;
+ rdata[1].next = &(rdata[2]);
+ }
+ else
+ rdata[0].next = &(rdata[2]);
+
+ rdata[2].buffer = buffer;
+ rdata[2].data = NULL;
+ rdata[2].len = 0;
+ rdata[2].next = NULL;
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_CLEAN, rdata);
static void
heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record)
{
- xl_heap_clean *xlrec = (xl_heap_clean*) XLogRecGetData(record);
+ xl_heap_clean *xlrec = (xl_heap_clean*) XLogRecGetData(record);
Relation reln;
Buffer buffer;
Page page;
- OffsetNumber maxoff;
- OffsetNumber offnum;
- HeapTupleHeader htup;
- ItemId lp;
if (!redo || (record->xl_info & XLR_BKP_BLOCK_1))
return;
return;
}
- maxoff = PageGetMaxOffsetNumber(page);
- for (offnum = FirstOffsetNumber;
- offnum <= maxoff;
- offnum = OffsetNumberNext(offnum))
+ if (record->xl_len > SizeOfHeapClean)
{
- lp = PageGetItemId(page, offnum);
-
- if (!ItemIdIsUsed(lp))
- continue;
+ char unbuf[BLCKSZ];
+ OffsetNumber *unused = (OffsetNumber*)unbuf;
+ char *unend;
+ ItemId lp;
- htup = (HeapTupleHeader) PageGetItem(page, lp);
+ memcpy(unbuf, (char*)xlrec + SizeOfHeapClean, record->xl_len - SizeOfHeapClean);
+ unend = unbuf + (record->xl_len - SizeOfHeapClean);
- if (!HeapTupleSatisfiesNow(htup))
+ while((char*)unused < unend)
+ {
+ lp = ((PageHeader) page)->pd_linp + *unused;
lp->lp_flags &= ~LP_USED;
+ unused++;
+ }
}
- PageRepairFragmentation(page);
+ PageRepairFragmentation(page, NULL);
UnlockAndWriteBuffer(buffer);
}
uint32 newlen;
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
+ {
PageInit(page, BufferGetPageSize(buffer), 0);
+ PageZero(page);
+ }
if (XLByteLE(lsn, PageGetLSN(page))) /* changes are applied */
{
uint32 newlen;
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
+ {
PageInit(page, BufferGetPageSize(buffer), 0);
+ PageZero(page);
+ }
if (XLByteLE(lsn, PageGetLSN(page))) /* changes are applied */
{
ItemPointerGetBlockNumber(&(xlrec->newtid)),
ItemPointerGetOffsetNumber(&(xlrec->newtid)));
}
+ else if (info == XLOG_HEAP_CLEAN)
+ {
+ xl_heap_clean *xlrec = (xl_heap_clean*) rec;
+ sprintf(buf + strlen(buf), "clean: node %u/%u; blk %u",
+ xlrec->node.tblNode, xlrec->node.relNode, xlrec->block);
+ }
else
strcat(buf, "UNKNOWN");
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.180 2000/12/28 13:00:18 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.181 2000/12/30 15:19:55 vadim Exp $
*
*-------------------------------------------------------------------------
*/
#include "utils/syscache.h"
#include "utils/temprel.h"
-extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer);
+extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
+ char *unused, int unlen);
extern XLogRecPtr log_heap_move(Relation reln,
Buffer oldbuf, ItemPointerData from,
Buffer newbuf, HeapTuple newtup);
if (tempPage != (Page) NULL)
{ /* Some tuples are gone */
- PageRepairFragmentation(tempPage);
+ PageRepairFragmentation(tempPage, NULL);
vacpage->free = ((PageHeader) tempPage)->pd_upper - ((PageHeader) tempPage)->pd_lower;
free_size += vacpage->free;
reap_page(vacuum_pages, vacpage);
if (vacpage->blkno == (BlockNumber) (blkno - 1) &&
vacpage->offsets_free > 0)
{
+ char unbuf[BLCKSZ];
+ OffsetNumber *unused = (OffsetNumber*)unbuf;
+ int uncnt;
+
buf = ReadBuffer(onerel, vacpage->blkno);
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
START_CRIT_CODE;
}
Assert(vacpage->offsets_free == num_tuples);
- PageRepairFragmentation(page);
+ uncnt = PageRepairFragmentation(page, unused);
{
- XLogRecPtr recptr = log_heap_clean(onerel, buf);
+ XLogRecPtr recptr;
+ recptr = log_heap_clean(onerel, buf, (char*)unused,
+ (char*)(&(unused[uncnt])) - (char*)unused);
PageSetLSN(page, recptr);
PageSetSUI(page, ThisStartUpID);
}
static void
vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
{
- Page page = BufferGetPage(buffer);
- ItemId itemid;
- int i;
+ char unbuf[BLCKSZ];
+ OffsetNumber *unused = (OffsetNumber*)unbuf;
+ int uncnt;
+ Page page = BufferGetPage(buffer);
+ ItemId itemid;
+ int i;
/* There shouldn't be any tuples moved onto the page yet! */
Assert(vacpage->offsets_used == 0);
itemid = &(((PageHeader) page)->pd_linp[vacpage->offsets[i] - 1]);
itemid->lp_flags &= ~LP_USED;
}
- PageRepairFragmentation(page);
+ uncnt = PageRepairFragmentation(page, unused);
{
- XLogRecPtr recptr = log_heap_clean(onerel, buffer);
+ XLogRecPtr recptr;
+ recptr = log_heap_clean(onerel, buffer, (char*)unused,
+ (char*)(&(unused[uncnt])) - (char*)unused);
PageSetLSN(page, recptr);
PageSetSUI(page, ThisStartUpID);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.33 2000/10/21 15:43:29 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.34 2000/12/30 15:19:55 vadim Exp $
*
*-------------------------------------------------------------------------
*/
p->pd_upper = pageSize - specialSize;
p->pd_special = pageSize - specialSize;
PageSetPageSize(page, pageSize);
+
+ p->pd_lsn.xlogid = p->pd_lsn.xrecoff = 0;
+ p->pd_sui = 0;
+}
+
+/*
+ * WAL needs in zero-ed page data content
+ */
+void
+PageZero(Page page)
+{
+ MemSet((char*)page + ((PageHeader)page)->pd_lower, 0,
+ ((PageHeader)page)->pd_special - ((PageHeader)page)->pd_lower);
}
/* ----------------
* This routine is usable for heap pages only.
*
*/
-void
-PageRepairFragmentation(Page page)
+int
+PageRepairFragmentation(Page page, OffsetNumber *unused)
{
int i;
struct itemIdSortData *itemidbase,
(*lp).lp_flags &= ~(LP_USED | LP_DELETE);
if ((*lp).lp_flags & LP_USED)
nused++;
+ else if (unused)
+ unused[i - nused] = (OffsetNumber)i;
}
if (nused == 0)
pfree(itemidbase);
}
+
+ return(nline - nused);
}
/*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: htup.h,v 1.43 2000/12/28 13:00:25 vadim Exp $
+ * $Id: htup.h,v 1.44 2000/12/30 15:19:56 vadim Exp $
*
*-------------------------------------------------------------------------
*/
{
RelFileNode node;
BlockNumber block;
+ /* UNUSED OFFSET NUMBERS FOLLOW AT THE END */
} xl_heap_clean;
#define SizeOfHeapClean (offsetof(xl_heap_clean, block) + sizeof(BlockNumber))
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: bufpage.h,v 1.37 2000/11/30 08:46:26 vadim Exp $
+ * $Id: bufpage.h,v 1.38 2000/12/30 15:19:57 vadim Exp $
*
*-------------------------------------------------------------------------
*/
*/
extern void PageInit(Page page, Size pageSize, Size specialSize);
+extern void PageZero(Page page);
extern OffsetNumber PageAddItem(Page page, Item item, Size size,
OffsetNumber offsetNumber, ItemIdFlags flags);
extern Page PageGetTempPage(Page page, Size specialSize);
extern void PageRestoreTempPage(Page tempPage, Page oldPage);
-extern void PageRepairFragmentation(Page page);
+extern int PageRepairFragmentation(Page page, OffsetNumber *unused);
extern Size PageGetFreeSpace(Page page);
extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
extern void IndexPageCleanup(Buffer buffer);