@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $ Header : / cvsroot / pgsql / src / backend / storage / page / bufpage . c , v 1.41 2001 / 11 / 08 04 : 05 : 13 tgl Exp $
* $ Header : / cvsroot / pgsql / src / backend / storage / page / bufpage . c , v 1.42 2002 / 01 / 15 22 : 14 : 17 tgl Exp $
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
@ -20,10 +20,6 @@
# include "storage/bufpage.h"
static void PageIndexTupleDeleteAdjustLinePointers ( PageHeader phdr ,
char * location , Size size ) ;
/* ----------------------------------------------------------------
* Page support functions
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -44,24 +40,15 @@ PageInit(Page page, Size pageSize, Size specialSize)
Assert ( pageSize >
specialSize + sizeof ( PageHeaderData ) - sizeof ( ItemIdData ) ) ;
/* Make sure all fields of page are zero, as well as unused space */
MemSet ( p , 0 , pageSize ) ;
p - > pd_lower = sizeof ( PageHeaderData ) - sizeof ( ItemIdData ) ;
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 ) ;
}
/* ----------------
* PageAddItem
@ -86,10 +73,11 @@ PageAddItem(Page page,
OffsetNumber offsetNumber ,
ItemIdFlags flags )
{
PageHeader phdr = ( PageHeader ) page ;
int i ;
Size alignedSize ;
Offset lower ;
Offset upper ;
int lower ;
int upper ;
ItemId itemId ;
OffsetNumber limit ;
bool needshuffle = false ;
@ -97,6 +85,16 @@ PageAddItem(Page page,
flags & = ~ OverwritePageMode ;
/*
* Be wary about corrupted page pointers
*/
if ( phdr - > pd_lower < ( sizeof ( PageHeaderData ) - sizeof ( ItemIdData ) ) | |
phdr - > pd_lower > phdr - > pd_upper | |
phdr - > pd_upper > phdr - > pd_special | |
phdr - > pd_special > BLCKSZ )
elog ( ERROR , " PageAddItem: corrupted page pointers: lower = %u, upper = %u, special = %u " ,
phdr - > pd_lower , phdr - > pd_upper , phdr - > pd_special ) ;
/*
* Find first unallocated offsetNumber
*/
@ -114,7 +112,7 @@ PageAddItem(Page page,
}
if ( offsetNumber < limit )
{
itemId = & ( ( PageHeader ) page ) - > pd_linp [ offsetNumber - 1 ] ;
itemId = & phdr - > pd_linp [ offsetNumber - 1 ] ;
if ( ( ( * itemId ) . lp_flags & LP_USED ) | |
( ( * itemId ) . lp_len ! = 0 ) )
{
@ -138,7 +136,7 @@ PageAddItem(Page page,
/* look for "recyclable" (unused & deallocated) ItemId */
for ( offsetNumber = 1 ; offsetNumber < limit ; offsetNumber + + )
{
itemId = & ( ( PageHeader ) page ) - > pd_linp [ offsetNumber - 1 ] ;
itemId = & phdr - > pd_linp [ offsetNumber - 1 ] ;
if ( ( ( ( * itemId ) . lp_flags & LP_USED ) = = 0 ) & &
( ( * itemId ) . lp_len = = 0 ) )
break ;
@ -146,18 +144,21 @@ PageAddItem(Page page,
}
/*
* Compute new lower and upper pointers for page , see if it ' ll fit
* Compute new lower and upper pointers for page , see if it ' ll fit .
*
* Note : do arithmetic as signed ints , to avoid mistakes if , say ,
* alignedSize > pd_upper .
*/
if ( offsetNumber > limit )
lower = ( Offset ) ( ( ( char * ) ( & ( ( PageHeader ) page ) - > pd_linp [ offsetNumber ] ) ) - ( ( char * ) page ) ) ;
lower = ( char * ) ( & phdr - > pd_linp [ offsetNumber ] ) - ( char * ) page ;
else if ( offsetNumber = = limit | | needshuffle )
lower = ( ( PageHeader ) page ) - > pd_lower + sizeof ( ItemIdData ) ;
lower = phdr - > pd_lower + sizeof ( ItemIdData ) ;
else
lower = ( ( PageHeader ) page ) - > pd_lower ;
lower = phdr - > pd_lower ;
alignedSize = MAXALIGN ( size ) ;
upper = ( ( PageHeader ) page ) - > pd_upper - alignedSize ;
upper = ( int ) phdr - > pd_upper - ( int ) alignedSize ;
if ( lower > upper )
return InvalidOffsetNumber ;
@ -169,24 +170,26 @@ PageAddItem(Page page,
if ( needshuffle )
{
/* shuffle ItemId's (Do the PageManager Shuffle...) */
for ( i = ( limit - 1 ) ; i > = offsetNumber ; i - - )
for ( i = ( int ) limit - 1 ; i > = ( int ) offsetNumber ; i - - )
{
ItemId fromitemId ,
toitemId ;
fromitemId = & ( ( PageHeader ) page ) - > pd_linp [ i - 1 ] ;
toitemId = & ( ( PageHeader ) page ) - > pd_linp [ i ] ;
fromitemId = & phdr - > pd_linp [ i - 1 ] ;
toitemId = & phdr - > pd_linp [ i ] ;
* toitemId = * fromitemId ;
}
}
itemId = & ( ( PageHeader ) page ) - > pd_linp [ offsetNumber - 1 ] ;
itemId = & phdr - > pd_linp [ offsetNumber - 1 ] ;
( * itemId ) . lp_off = upper ;
( * itemId ) . lp_len = size ;
( * itemId ) . lp_flags = flags ;
memmove ( ( char * ) page + upper , item , size ) ;
( ( PageHeader ) page ) - > pd_lower = lower ;
( ( PageHeader ) page ) - > pd_upper = upper ;
phdr - > pd_lower = ( LocationIndex ) lower ;
phdr - > pd_upper = ( LocationIndex ) upper ;
return offsetNumber ;
}
@ -383,79 +386,76 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
Size
PageGetFreeSpace ( Page page )
{
Size space ;
int space ;
space = ( ( PageHeader ) page ) - > pd_upper - ( ( PageHeader ) page ) - > pd_lower ;
/*
* Use signed arithmetic here so that we behave sensibly if
* pd_lower > pd_upper .
*/
space = ( int ) ( ( PageHeader ) page ) - > pd_upper -
( int ) ( ( PageHeader ) page ) - > pd_lower ;
if ( space < sizeof ( ItemIdData ) )
if ( space < ( int ) sizeof ( ItemIdData ) )
return 0 ;
space - = sizeof ( ItemIdData ) ; /* XXX not always appropriate */
return space ;
return ( Size ) space ;
}
/*
* PageRepairFragmentation un - useful for index page cleanup because
* of it doesn ' t remove line pointers . This routine could be more
* effective but . . . no time - : )
*/
void
IndexPageCleanup ( Buffer buffer )
{
Page page = ( Page ) BufferGetPage ( buffer ) ;
ItemId lp ;
OffsetNumber maxoff ;
OffsetNumber i ;
maxoff = PageGetMaxOffsetNumber ( page ) ;
for ( i = 0 ; i < maxoff ; i + + )
{
lp = ( ( PageHeader ) page ) - > pd_linp + i ;
if ( ( * lp ) . lp_flags & LP_DELETE ) /* marked for deletion */
{
PageIndexTupleDelete ( page , i + 1 ) ;
maxoff - - ;
}
}
}
/*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* PageIndexTupleDelete
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* This routine does the work of removing a tuple from an index page .
*
* Unlike heap pages , we compact out the line pointer for the removed tuple .
*/
void
PageIndexTupleDelete ( Page page , OffsetNumber offnum )
{
PageHeader phdr ;
PageHeader phdr = ( PageHeader ) page ;
char * addr ;
ItemId tup ;
Size size ;
char * locn ;
unsigned offset ;
int nbytes ;
int offidx ;
int nline ,
i ;
phdr = ( PageHeader ) page ;
/*
* As with PageRepairFragmentation , paranoia seems justified .
*/
if ( phdr - > pd_lower < ( sizeof ( PageHeaderData ) - sizeof ( ItemIdData ) ) | |
phdr - > pd_lower > phdr - > pd_upper | |
phdr - > pd_upper > phdr - > pd_special | |
phdr - > pd_special > BLCKSZ )
elog ( ERROR , " PageIndexTupleDelete: corrupted page pointers: lower = %u, upper = %u, special = %u " ,
phdr - > pd_lower , phdr - > pd_upper , phdr - > pd_special ) ;
nline = PageGetMaxOffsetNumber ( page ) ;
if ( ( int ) offnum < = 0 | | ( int ) offnum > nline )
elog ( ERROR , " PageIndexTupleDelete: bad offnum %u " , offnum ) ;
/* change offset number to offset index */
offidx = offnum - 1 ;
tup = PageGetItemId ( page , offnum ) ;
size = ItemIdGetLength ( tup ) ;
size = MAXALIGN ( size ) ;
offset = ItemIdGetOffset ( tup ) ;
/* location of deleted tuple data */
locn = ( char * ) ( page + ItemIdGetOffset ( tup ) ) ;
if ( offset < phdr - > pd_upper | | ( offset + size ) > phdr - > pd_special | |
offset ! = MAXALIGN ( offset ) | | size ! = MAXALIGN ( size ) )
elog ( ERROR , " PageIndexTupleDelete: corrupted item pointer: offset = %u size = %u " ,
offset , size ) ;
/*
* First , we want to get rid of the pd_linp entry for the index tuple .
* We copy all subsequent linp ' s back one slot in the array .
*/
nbytes = phdr - > pd_lower -
( ( char * ) & phdr - > pd_linp [ offidx + 1 ] - ( char * ) phdr ) ;
memmove ( ( char * ) & ( phdr - > pd_linp [ offidx ] ) ,
( char * ) & ( phdr - > pd_linp [ offidx + 1 ] ) ,
nbytes ) ;
@ -470,52 +470,28 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum)
*/
/* beginning of tuple space */
addr = ( char * ) ( page + phdr - > pd_upper ) ;
addr = ( char * ) page + phdr - > pd_upper ;
if ( locn ! = add r)
memmove ( addr + size , addr , ( int ) ( locn - add r) ) ;
if ( offset > phdr - > pd_uppe r)
memmove ( addr + size , addr , ( int ) ( offset - phdr - > pd_uppe r) ) ;
/* adjust free space boundary pointers */
phdr - > pd_upper + = size ;
phdr - > pd_lower - = sizeof ( ItemIdData ) ;
/* finally, we need to adjust the linp entries that remain */
if ( ! PageIsEmpty ( page ) )
PageIndexTupleDeleteAdjustLinePointers ( phdr , locn , size ) ;
}
/*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* PageIndexTupleDeleteAdjustLinePointers
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Once the line pointers and tuple data have been shifted around
* on the page , we need to go down the line pointer vector and
* adjust pointers to reflect new locations . Anything that used
* to be before the deleted tuple ' s data was moved forward by the
* size of the deleted tuple .
*
* This routine does the work of adjusting the line pointers .
* Location is where the tuple data used to lie ; size is how
* much space it occupied . We assume that size has been aligned
* as required by the time we get here .
/*
* Finally , we need to adjust the linp entries that remain .
*
* This routine should never be called on an empty page .
* Anything that used to be before the deleted tuple ' s data was moved
* forward by the size of the deleted tuple .
*/
static void
PageIndexTupleDeleteAdjustLinePointers ( PageHeader phdr ,
char * location ,
Size size )
{
int i ;
unsigned offset ;
/* location is an index into the page... */
offset = ( unsigned ) ( location - ( char * ) phdr ) ;
for ( i = PageGetMaxOffsetNumber ( ( Page ) phdr ) - 1 ; i > = 0 ; i - - )
if ( ! PageIsEmpty ( page ) )
{
nline - - ; /* there's one less than when we started */
for ( i = nline ; - - i > = 0 ; )
{
if ( phdr - > pd_linp [ i ] . lp_off < = offset )
phdr - > pd_linp [ i ] . lp_off + = size ;
}
}
}