/*-------------------------------------------------------------------------
 *
 * bufpage.h--
 *    Standard POSTGRES buffer page definitions.
 *
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 * bufpage.h,v 1.5 1995/04/09 20:27:30 andrew Exp
 *
 *-------------------------------------------------------------------------
 */
#ifndef	BUFPAGE_H
#define BUFPAGE_H

#include "c.h"
#include "machine.h"		/* for BLCKSZ */

#include "storage/buf.h"
#include "storage/item.h"
#include "storage/itemid.h"
#include "storage/itemptr.h"
#include "storage/page.h"


/*
 * location (byte offset) within a page.
 */
typedef uint16	LocationIndex;

/*
 * space management information generic to any page
 *	od_pagesize	- size in bytes, 2^(pageSize+1) (i.e., 2B-64KB).
 *			  (in reality, we need at least 64B to fit the 
 *			  page header, opaque space and a minimal tuple;
 *			  on the high end, we can only support pages up
 *			  to 32KB because BlockSize is 16 bits.)
 */
typedef struct OpaqueData {
    unsigned int od_pagesize:4;
} OpaqueData;
    
typedef OpaqueData	*Opaque;

typedef Size		PageSize;
typedef uint16		SpecialSize;	/* size of special space on a page */
typedef uint16		PageFreeSpace;	/* size of free space on a page ??? */

typedef struct PageHeaderData {	/* disk page organization */
    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 */
    OpaqueData       	pd_opaque;	/* AM-generic information */
    ItemIdData		pd_linp[1];	/* line pointers */
} PageHeaderData;

typedef PageHeaderData	*PageHeader;

typedef enum {
    ShufflePageManagerMode,
    OverwritePageManagerMode
} PageManagerMode;

/* ----------------
 *	misc support macros
 * ----------------
 */

/*
 * XXX this is wrong -- ignores padding/alignment, variable page size,
 * AM-specific opaque space at the end of the page (as in btrees), ...
 * however, it at least serves as an upper bound for heap pages.
 */
#define MAXTUPLEN	(BLCKSZ - sizeof (PageHeaderData))

/* ----------------------------------------------------------------
 *			page support macros
 * ----------------------------------------------------------------
 */
/*
 * PageIsValid -- This is defined in page.h.
 */

/*
 * PageSizeIsValid --
 *	True iff the page size is valid.
 *
 * XXX currently all page sizes are "valid" but we only actually
 *     use BLCKSZ.
 */
#define PageSizeIsValid(pageSize) 1

/*
 * PageIsUsed --
 *	True iff the page size is used.
 *
 * Note:
 *	Assumes page is valid.
 */
#define PageIsUsed(page) \
    (AssertMacro(PageIsValid(page)) ? \
     ((bool) (((PageHeader) (page))->pd_lower != 0)) : false)

/*
 * PageIsEmpty --
 *	returns true iff no itemid has been allocated on the page
 */
#define PageIsEmpty(page) \
    (((PageHeader) (page))->pd_lower == \
     (sizeof(PageHeaderData) - sizeof(ItemIdData)) ? true : false)

/*
 * PageGetItemId --
 *	Returns an item identifier of a page.
 */
#define PageGetItemId(page, offsetIndex) \
    ((ItemId) (&((PageHeader) (page))->pd_linp[ offsetIndex ]))

/*
 * PageGetFirstItemId --
 *	Returns the first item identifier on a page.
 */
#define PageGetFirstItemId(page) \
    PageGetItemId(page, (OffsetIndex)0)

/* ----------------
 *	macros to access opaque space
 * ----------------
 */
#define OpaqueGetPageSize(opaque) \
    ((PageSize) (1 << (1 + (opaque)->od_pagesize)))

/*
 * PageGetPageSize --
 *	Returns the page size of a page.
 */
#define PageGetPageSize(page) \
    ((PageSize) \
     (OpaqueGetPageSize((Opaque) &((PageHeader) (page))->pd_opaque)))

/* ----------------
 *	page special data macros
 * ----------------
 */
/*
 * PageGetSpecialSize --
 *	Returns size of special space on a page.
 *
 * Note:
 *	Assumes page is locked.
 */
#define PageGetSpecialSize(page) \
    ((uint16) (PageGetPageSize(page) - ((PageHeader)page)->pd_special))

/*
 * PageGetSpecialPointer --
 *	Returns pointer to special space on a page.
 *
 * Note:
 *	Assumes page is locked.
 */
#define PageGetSpecialPointer(page) \
    (AssertMacro(PageIsValid(page)) ? \
     (char *) ((char *) (page) + ((PageHeader) (page))->pd_special) \
     : (char *) 0)

/* ----------------------------------------------------------------
 *		      buffer page support macros
 * ----------------------------------------------------------------
 */
/*
 * BufferInitPage --
 *	Initializes the logical pages associated with a buffer.
 *
 * XXX does nothing at present
 */
#define BufferInitPage(buffer, pageSize) \
    Assert(BufferIsValid(buffer)); \
    Assert(PageSizeIsValid(pageSize)); \
    (void) BufferGetBlockSize(buffer)

/*
 * BufferSimpleInitPage --
 *	Initialize the "simple" physical page associated with a buffer
 */
#define BufferSimpleInitPage(buffer) \
    PageInit((Page)BufferGetBlock(buffer), BufferGetBlockSize(buffer), 0)

/* ----------------------------------------------------------------
 *	extern declarations
 * ----------------------------------------------------------------
 */

extern PageSize BufferGetPageSize(Buffer buffer);
extern Page BufferGetPage(Buffer buffer);
extern void PageInit(Page page, PageSize pageSize, SpecialSize specialSize);
extern Item PageGetItem(Page page, ItemId itemId);
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 OffsetIndex PageGetMaxOffsetIndex(Page page);
extern void PageRepairFragmentation(Page page);
extern PageFreeSpace PageGetFreeSpace(Page page);
extern void PageManagerModeSet(PageManagerMode mode);
extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
extern void PageIndexTupleDeleteAdjustLinePointers(PageHeader phdr,
				       char *location, Size size);


#endif	/* BUFPAGE_H */
