1. WAL needs in zero-ed content of newly initialized page.
2. Log record for PageRepaireFragmentation now keeps array of !LP_USED offnums to redo cleanup properly.
This commit is contained in:
parent
2783bd50da
commit
3e059b3802
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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
|
* INTERFACE ROUTINES
|
||||||
@ -90,7 +90,8 @@
|
|||||||
|
|
||||||
XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from,
|
XLogRecPtr log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from,
|
||||||
Buffer newbuf, HeapTuple newtup);
|
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 */
|
/* comments are in heap_update */
|
||||||
static xl_heaptid _locked_tuple_;
|
static xl_heaptid _locked_tuple_;
|
||||||
@ -2002,11 +2003,11 @@ heap_restrpos(HeapScanDesc scan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
XLogRecPtr
|
XLogRecPtr
|
||||||
log_heap_clean(Relation reln, Buffer buffer)
|
log_heap_clean(Relation reln, Buffer buffer, char *unused, int unlen)
|
||||||
{
|
{
|
||||||
xl_heap_clean xlrec;
|
xl_heap_clean xlrec;
|
||||||
XLogRecPtr recptr;
|
XLogRecPtr recptr;
|
||||||
XLogRecData rdata[2];
|
XLogRecData rdata[3];
|
||||||
|
|
||||||
xlrec.node = reln->rd_node;
|
xlrec.node = reln->rd_node;
|
||||||
xlrec.block = BufferGetBlockNumber(buffer);
|
xlrec.block = BufferGetBlockNumber(buffer);
|
||||||
@ -2015,10 +2016,20 @@ log_heap_clean(Relation reln, Buffer buffer)
|
|||||||
rdata[0].len = SizeOfHeapClean;
|
rdata[0].len = SizeOfHeapClean;
|
||||||
rdata[0].next = &(rdata[1]);
|
rdata[0].next = &(rdata[1]);
|
||||||
|
|
||||||
rdata[1].buffer = buffer;
|
if (unlen > 0)
|
||||||
rdata[1].data = NULL;
|
{
|
||||||
rdata[1].len = 0;
|
rdata[1].buffer = buffer;
|
||||||
rdata[1].next = NULL;
|
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);
|
recptr = XLogInsert(RM_HEAP_ID, XLOG_HEAP_CLEAN, rdata);
|
||||||
|
|
||||||
@ -2102,14 +2113,10 @@ log_heap_move(Relation reln, Buffer oldbuf, ItemPointerData from,
|
|||||||
static void
|
static void
|
||||||
heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
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;
|
Relation reln;
|
||||||
Buffer buffer;
|
Buffer buffer;
|
||||||
Page page;
|
Page page;
|
||||||
OffsetNumber maxoff;
|
|
||||||
OffsetNumber offnum;
|
|
||||||
HeapTupleHeader htup;
|
|
||||||
ItemId lp;
|
|
||||||
|
|
||||||
if (!redo || (record->xl_info & XLR_BKP_BLOCK_1))
|
if (!redo || (record->xl_info & XLR_BKP_BLOCK_1))
|
||||||
return;
|
return;
|
||||||
@ -2133,23 +2140,25 @@ heap_xlog_clean(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
maxoff = PageGetMaxOffsetNumber(page);
|
if (record->xl_len > SizeOfHeapClean)
|
||||||
for (offnum = FirstOffsetNumber;
|
|
||||||
offnum <= maxoff;
|
|
||||||
offnum = OffsetNumberNext(offnum))
|
|
||||||
{
|
{
|
||||||
lp = PageGetItemId(page, offnum);
|
char unbuf[BLCKSZ];
|
||||||
|
OffsetNumber *unused = (OffsetNumber*)unbuf;
|
||||||
|
char *unend;
|
||||||
|
ItemId lp;
|
||||||
|
|
||||||
if (!ItemIdIsUsed(lp))
|
memcpy(unbuf, (char*)xlrec + SizeOfHeapClean, record->xl_len - SizeOfHeapClean);
|
||||||
continue;
|
unend = unbuf + (record->xl_len - SizeOfHeapClean);
|
||||||
|
|
||||||
htup = (HeapTupleHeader) PageGetItem(page, lp);
|
while((char*)unused < unend)
|
||||||
|
{
|
||||||
if (!HeapTupleSatisfiesNow(htup))
|
lp = ((PageHeader) page)->pd_linp + *unused;
|
||||||
lp->lp_flags &= ~LP_USED;
|
lp->lp_flags &= ~LP_USED;
|
||||||
|
unused++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PageRepairFragmentation(page);
|
PageRepairFragmentation(page, NULL);
|
||||||
UnlockAndWriteBuffer(buffer);
|
UnlockAndWriteBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2247,7 +2256,10 @@ heap_xlog_insert(bool redo, XLogRecPtr lsn, XLogRecord *record)
|
|||||||
uint32 newlen;
|
uint32 newlen;
|
||||||
|
|
||||||
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
|
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
|
||||||
|
{
|
||||||
PageInit(page, BufferGetPageSize(buffer), 0);
|
PageInit(page, BufferGetPageSize(buffer), 0);
|
||||||
|
PageZero(page);
|
||||||
|
}
|
||||||
|
|
||||||
if (XLByteLE(lsn, PageGetLSN(page))) /* changes are applied */
|
if (XLByteLE(lsn, PageGetLSN(page))) /* changes are applied */
|
||||||
{
|
{
|
||||||
@ -2401,7 +2413,10 @@ newsame:;
|
|||||||
uint32 newlen;
|
uint32 newlen;
|
||||||
|
|
||||||
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
|
if (record->xl_info & XLOG_HEAP_INIT_PAGE)
|
||||||
|
{
|
||||||
PageInit(page, BufferGetPageSize(buffer), 0);
|
PageInit(page, BufferGetPageSize(buffer), 0);
|
||||||
|
PageZero(page);
|
||||||
|
}
|
||||||
|
|
||||||
if (XLByteLE(lsn, PageGetLSN(page))) /* changes are applied */
|
if (XLByteLE(lsn, PageGetLSN(page))) /* changes are applied */
|
||||||
{
|
{
|
||||||
@ -2583,6 +2598,12 @@ heap_desc(char *buf, uint8 xl_info, char* rec)
|
|||||||
ItemPointerGetBlockNumber(&(xlrec->newtid)),
|
ItemPointerGetBlockNumber(&(xlrec->newtid)),
|
||||||
ItemPointerGetOffsetNumber(&(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
|
else
|
||||||
strcat(buf, "UNKNOWN");
|
strcat(buf, "UNKNOWN");
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -47,7 +47,8 @@
|
|||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "utils/temprel.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,
|
extern XLogRecPtr log_heap_move(Relation reln,
|
||||||
Buffer oldbuf, ItemPointerData from,
|
Buffer oldbuf, ItemPointerData from,
|
||||||
Buffer newbuf, HeapTuple newtup);
|
Buffer newbuf, HeapTuple newtup);
|
||||||
@ -878,7 +879,7 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
|
|||||||
|
|
||||||
if (tempPage != (Page) NULL)
|
if (tempPage != (Page) NULL)
|
||||||
{ /* Some tuples are gone */
|
{ /* Some tuples are gone */
|
||||||
PageRepairFragmentation(tempPage);
|
PageRepairFragmentation(tempPage, NULL);
|
||||||
vacpage->free = ((PageHeader) tempPage)->pd_upper - ((PageHeader) tempPage)->pd_lower;
|
vacpage->free = ((PageHeader) tempPage)->pd_upper - ((PageHeader) tempPage)->pd_lower;
|
||||||
free_size += vacpage->free;
|
free_size += vacpage->free;
|
||||||
reap_page(vacuum_pages, vacpage);
|
reap_page(vacuum_pages, vacpage);
|
||||||
@ -1898,6 +1899,10 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
|
|||||||
if (vacpage->blkno == (BlockNumber) (blkno - 1) &&
|
if (vacpage->blkno == (BlockNumber) (blkno - 1) &&
|
||||||
vacpage->offsets_free > 0)
|
vacpage->offsets_free > 0)
|
||||||
{
|
{
|
||||||
|
char unbuf[BLCKSZ];
|
||||||
|
OffsetNumber *unused = (OffsetNumber*)unbuf;
|
||||||
|
int uncnt;
|
||||||
|
|
||||||
buf = ReadBuffer(onerel, vacpage->blkno);
|
buf = ReadBuffer(onerel, vacpage->blkno);
|
||||||
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
|
LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE);
|
||||||
START_CRIT_CODE;
|
START_CRIT_CODE;
|
||||||
@ -1928,9 +1933,11 @@ failed to add item with len = %lu to page %u (free space %lu, nusd %u, noff %u)"
|
|||||||
|
|
||||||
}
|
}
|
||||||
Assert(vacpage->offsets_free == num_tuples);
|
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);
|
PageSetLSN(page, recptr);
|
||||||
PageSetSUI(page, ThisStartUpID);
|
PageSetSUI(page, ThisStartUpID);
|
||||||
}
|
}
|
||||||
@ -2039,9 +2046,12 @@ vacuum_heap(VRelStats *vacrelstats, Relation onerel, VacPageList vacuum_pages)
|
|||||||
static void
|
static void
|
||||||
vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
|
vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
|
||||||
{
|
{
|
||||||
Page page = BufferGetPage(buffer);
|
char unbuf[BLCKSZ];
|
||||||
ItemId itemid;
|
OffsetNumber *unused = (OffsetNumber*)unbuf;
|
||||||
int i;
|
int uncnt;
|
||||||
|
Page page = BufferGetPage(buffer);
|
||||||
|
ItemId itemid;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* There shouldn't be any tuples moved onto the page yet! */
|
/* There shouldn't be any tuples moved onto the page yet! */
|
||||||
Assert(vacpage->offsets_used == 0);
|
Assert(vacpage->offsets_used == 0);
|
||||||
@ -2052,9 +2062,11 @@ vacuum_page(Relation onerel, Buffer buffer, VacPage vacpage)
|
|||||||
itemid = &(((PageHeader) page)->pd_linp[vacpage->offsets[i] - 1]);
|
itemid = &(((PageHeader) page)->pd_linp[vacpage->offsets[i] - 1]);
|
||||||
itemid->lp_flags &= ~LP_USED;
|
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);
|
PageSetLSN(page, recptr);
|
||||||
PageSetSUI(page, ThisStartUpID);
|
PageSetSUI(page, ThisStartUpID);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -48,6 +48,19 @@ PageInit(Page page, Size pageSize, Size specialSize)
|
|||||||
p->pd_upper = pageSize - specialSize;
|
p->pd_upper = pageSize - specialSize;
|
||||||
p->pd_special = pageSize - specialSize;
|
p->pd_special = pageSize - specialSize;
|
||||||
PageSetPageSize(page, pageSize);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
@ -251,8 +264,8 @@ itemidcompare(const void *itemidp1, const void *itemidp2)
|
|||||||
* This routine is usable for heap pages only.
|
* This routine is usable for heap pages only.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
PageRepairFragmentation(Page page)
|
PageRepairFragmentation(Page page, OffsetNumber *unused)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct itemIdSortData *itemidbase,
|
struct itemIdSortData *itemidbase,
|
||||||
@ -272,6 +285,8 @@ PageRepairFragmentation(Page page)
|
|||||||
(*lp).lp_flags &= ~(LP_USED | LP_DELETE);
|
(*lp).lp_flags &= ~(LP_USED | LP_DELETE);
|
||||||
if ((*lp).lp_flags & LP_USED)
|
if ((*lp).lp_flags & LP_USED)
|
||||||
nused++;
|
nused++;
|
||||||
|
else if (unused)
|
||||||
|
unused[i - nused] = (OffsetNumber)i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nused == 0)
|
if (nused == 0)
|
||||||
@ -328,6 +343,8 @@ PageRepairFragmentation(Page page)
|
|||||||
|
|
||||||
pfree(itemidbase);
|
pfree(itemidbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return(nline - nused);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -131,6 +131,7 @@ typedef struct xl_heap_clean
|
|||||||
{
|
{
|
||||||
RelFileNode node;
|
RelFileNode node;
|
||||||
BlockNumber block;
|
BlockNumber block;
|
||||||
|
/* UNUSED OFFSET NUMBERS FOLLOW AT THE END */
|
||||||
} xl_heap_clean;
|
} xl_heap_clean;
|
||||||
|
|
||||||
#define SizeOfHeapClean (offsetof(xl_heap_clean, block) + sizeof(BlockNumber))
|
#define SizeOfHeapClean (offsetof(xl_heap_clean, block) + sizeof(BlockNumber))
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -314,11 +314,12 @@ typedef enum
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
extern void PageInit(Page page, Size pageSize, Size specialSize);
|
extern void PageInit(Page page, Size pageSize, Size specialSize);
|
||||||
|
extern void PageZero(Page page);
|
||||||
extern OffsetNumber PageAddItem(Page page, Item item, Size size,
|
extern OffsetNumber PageAddItem(Page page, Item item, Size size,
|
||||||
OffsetNumber offsetNumber, ItemIdFlags flags);
|
OffsetNumber offsetNumber, ItemIdFlags flags);
|
||||||
extern Page PageGetTempPage(Page page, Size specialSize);
|
extern Page PageGetTempPage(Page page, Size specialSize);
|
||||||
extern void PageRestoreTempPage(Page tempPage, Page oldPage);
|
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 Size PageGetFreeSpace(Page page);
|
||||||
extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
|
extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
|
||||||
extern void IndexPageCleanup(Buffer buffer);
|
extern void IndexPageCleanup(Buffer buffer);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user