~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to src/include/storage/bufpage.h

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * bufpage.h
 
4
 *        Standard POSTGRES buffer page definitions.
 
5
 *
 
6
 *
 
7
 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
 
8
 * Portions Copyright (c) 1994, Regents of the University of California
 
9
 *
 
10
 * $PostgreSQL: pgsql/src/include/storage/bufpage.h,v 1.63 2004-12-31 22:03:42 pgsql Exp $
 
11
 *
 
12
 *-------------------------------------------------------------------------
 
13
 */
 
14
#ifndef BUFPAGE_H
 
15
#define BUFPAGE_H
 
16
 
 
17
#include "storage/buf.h"
 
18
#include "storage/bufmgr.h"
 
19
#include "storage/item.h"
 
20
#include "storage/itemid.h"
 
21
#include "storage/off.h"
 
22
#include "access/xlog.h"
 
23
 
 
24
/*
 
25
 * A postgres disk page is an abstraction layered on top of a postgres
 
26
 * disk block (which is simply a unit of i/o, see block.h).
 
27
 *
 
28
 * specifically, while a disk block can be unformatted, a postgres
 
29
 * disk page is always a slotted page of the form:
 
30
 *
 
31
 * +----------------+---------------------------------+
 
32
 * | PageHeaderData | linp1 linp2 linp3 ...                       |
 
33
 * +-----------+----+---------------------------------+
 
34
 * | ... linpN |                                                                          |
 
35
 * +-----------+--------------------------------------+
 
36
 * |               ^ pd_lower                                                     |
 
37
 * |                                                                                              |
 
38
 * |                     v pd_upper                                                       |
 
39
 * +-------------+------------------------------------+
 
40
 * |                     | tupleN ...                                             |
 
41
 * +-------------+------------------+-----------------+
 
42
 * |       ... tuple3 tuple2 tuple1 | "special space" |
 
43
 * +--------------------------------+-----------------+
 
44
 *                                                                      ^ pd_special
 
45
 *
 
46
 * a page is full when nothing can be added between pd_lower and
 
47
 * pd_upper.
 
48
 *
 
49
 * all blocks written out by an access method must be disk pages.
 
50
 *
 
51
 * EXCEPTIONS:
 
52
 *
 
53
 * obviously, a page is not formatted before it is initialized with by
 
54
 * a call to PageInit.
 
55
 *
 
56
 * NOTES:
 
57
 *
 
58
 * linp1..N form an ItemId array.  ItemPointers point into this array
 
59
 * rather than pointing directly to a tuple.  Note that OffsetNumbers
 
60
 * conventionally start at 1, not 0.
 
61
 *
 
62
 * tuple1..N are added "backwards" on the page.  because a tuple's
 
63
 * ItemPointer points to its ItemId entry rather than its actual
 
64
 * byte-offset position, tuples can be physically shuffled on a page
 
65
 * whenever the need arises.
 
66
 *
 
67
 * AM-generic per-page information is kept in PageHeaderData.
 
68
 *
 
69
 * AM-specific per-page data (if any) is kept in the area marked "special
 
70
 * space"; each AM has an "opaque" structure defined somewhere that is
 
71
 * stored as the page trailer.  an access method should always
 
72
 * initialize its pages with PageInit and then set its own opaque
 
73
 * fields.
 
74
 */
 
75
 
 
76
typedef Pointer Page;
 
77
 
 
78
 
 
79
/*
 
80
 * location (byte offset) within a page.
 
81
 *
 
82
 * note that this is actually limited to 2^15 because we have limited
 
83
 * ItemIdData.lp_off and ItemIdData.lp_len to 15 bits (see itemid.h).
 
84
 */
 
85
typedef uint16 LocationIndex;
 
86
 
 
87
 
 
88
/*
 
89
 * disk page organization
 
90
 *
 
91
 * space management information generic to any page
 
92
 *
 
93
 *              pd_lsn          - identifies xlog record for last change to this page.
 
94
 *              pd_tli          - ditto.
 
95
 *              pd_lower        - offset to start of free space.
 
96
 *              pd_upper        - offset to end of free space.
 
97
 *              pd_special      - offset to start of special space.
 
98
 *              pd_pagesize_version - size in bytes and page layout version number.
 
99
 *
 
100
 * The LSN is used by the buffer manager to enforce the basic rule of WAL:
 
101
 * "thou shalt write xlog before data".  A dirty buffer cannot be dumped
 
102
 * to disk until xlog has been flushed at least as far as the page's LSN.
 
103
 * We also store the TLI for identification purposes (it is not clear that
 
104
 * this is actually necessary, but it seems like a good idea).
 
105
 *
 
106
 * The page version number and page size are packed together into a single
 
107
 * uint16 field.  This is for historical reasons: before PostgreSQL 7.3,
 
108
 * there was no concept of a page version number, and doing it this way
 
109
 * lets us pretend that pre-7.3 databases have page version number zero.
 
110
 * We constrain page sizes to be multiples of 256, leaving the low eight
 
111
 * bits available for a version number.
 
112
 *
 
113
 * Minimum possible page size is perhaps 64B to fit page header, opaque space
 
114
 * and a minimal tuple; of course, in reality you want it much bigger, so
 
115
 * the constraint on pagesize mod 256 is not an important restriction.
 
116
 * On the high end, we can only support pages up to 32KB because lp_off/lp_len
 
117
 * are 15 bits.
 
118
 */
 
119
typedef struct PageHeaderData
 
120
{
 
121
        /* XXX LSN is member of *any* block, not only page-organized ones */
 
122
        XLogRecPtr      pd_lsn;                 /* LSN: next byte after last byte of xlog
 
123
                                                                 * record for last change to this page */
 
124
        TimeLineID      pd_tli;                 /* TLI of last change */
 
125
        LocationIndex pd_lower;         /* offset to start of free space */
 
126
        LocationIndex pd_upper;         /* offset to end of free space */
 
127
        LocationIndex pd_special;       /* offset to start of special space */
 
128
        uint16          pd_pagesize_version;
 
129
        ItemIdData      pd_linp[1];             /* beginning of line pointer array */
 
130
} PageHeaderData;
 
131
 
 
132
typedef PageHeaderData *PageHeader;
 
133
 
 
134
/*
 
135
 * Page layout version number 0 is for pre-7.3 Postgres releases.
 
136
 * Releases 7.3 and 7.4 use 1, denoting a new HeapTupleHeader layout.
 
137
 * Release 8.0 changed the HeapTupleHeader layout again.
 
138
 */
 
139
#define PG_PAGE_LAYOUT_VERSION          2
 
140
 
 
141
 
 
142
/* ----------------------------------------------------------------
 
143
 *                                              page support macros
 
144
 * ----------------------------------------------------------------
 
145
 */
 
146
 
 
147
/*
 
148
 * PageIsValid
 
149
 *              True iff page is valid.
 
150
 */
 
151
#define PageIsValid(page) PointerIsValid(page)
 
152
 
 
153
/*
 
154
 * line pointer does not count as part of header
 
155
 */
 
156
#define SizeOfPageHeaderData (offsetof(PageHeaderData, pd_linp[0]))
 
157
 
 
158
/*
 
159
 * PageIsEmpty
 
160
 *              returns true iff no itemid has been allocated on the page
 
161
 */
 
162
#define PageIsEmpty(page) \
 
163
        (((PageHeader) (page))->pd_lower <= SizeOfPageHeaderData)
 
164
 
 
165
/*
 
166
 * PageIsNew
 
167
 *              returns true iff page has not been initialized (by PageInit)
 
168
 */
 
169
#define PageIsNew(page) (((PageHeader) (page))->pd_upper == 0)
 
170
 
 
171
/*
 
172
 * PageGetItemId
 
173
 *              Returns an item identifier of a page.
 
174
 */
 
175
#define PageGetItemId(page, offsetNumber) \
 
176
        ((ItemId) (&((PageHeader) (page))->pd_linp[(offsetNumber) - 1]))
 
177
 
 
178
/*
 
179
 * PageGetContents
 
180
 *              To be used in case the page does not contain item pointers.
 
181
 */
 
182
#define PageGetContents(page) \
 
183
        ((char *) (&((PageHeader) (page))->pd_linp[0]))
 
184
 
 
185
/* ----------------
 
186
 *              macros to access page size info
 
187
 * ----------------
 
188
 */
 
189
 
 
190
/*
 
191
 * PageSizeIsValid
 
192
 *              True iff the page size is valid.
 
193
 */
 
194
#define PageSizeIsValid(pageSize) ((pageSize) == BLCKSZ)
 
195
 
 
196
/*
 
197
 * PageGetPageSize
 
198
 *              Returns the page size of a page.
 
199
 *
 
200
 * this can only be called on a formatted page (unlike
 
201
 * BufferGetPageSize, which can be called on an unformatted page).
 
202
 * however, it can be called on a page that is not stored in a buffer.
 
203
 */
 
204
#define PageGetPageSize(page) \
 
205
        ((Size) (((PageHeader) (page))->pd_pagesize_version & (uint16) 0xFF00))
 
206
 
 
207
/*
 
208
 * PageGetPageLayoutVersion
 
209
 *              Returns the page layout version of a page.
 
210
 */
 
211
#define PageGetPageLayoutVersion(page) \
 
212
        (((PageHeader) (page))->pd_pagesize_version & 0x00FF)
 
213
 
 
214
/*
 
215
 * PageSetPageSizeAndVersion
 
216
 *              Sets the page size and page layout version number of a page.
 
217
 *
 
218
 * We could support setting these two values separately, but there's
 
219
 * no real need for it at the moment.
 
220
 */
 
221
#define PageSetPageSizeAndVersion(page, size, version) \
 
222
( \
 
223
        AssertMacro(((size) & 0xFF00) == (size)), \
 
224
        AssertMacro(((version) & 0x00FF) == (version)), \
 
225
        ((PageHeader) (page))->pd_pagesize_version = (size) | (version) \
 
226
)
 
227
 
 
228
/* ----------------
 
229
 *              page special data macros
 
230
 * ----------------
 
231
 */
 
232
/*
 
233
 * PageGetSpecialSize
 
234
 *              Returns size of special space on a page.
 
235
 */
 
236
#define PageGetSpecialSize(page) \
 
237
        ((uint16) (PageGetPageSize(page) - ((PageHeader)(page))->pd_special))
 
238
 
 
239
/*
 
240
 * PageGetSpecialPointer
 
241
 *              Returns pointer to special space on a page.
 
242
 */
 
243
#define PageGetSpecialPointer(page) \
 
244
( \
 
245
        AssertMacro(PageIsValid(page)), \
 
246
        (char *) ((char *) (page) + ((PageHeader) (page))->pd_special) \
 
247
)
 
248
 
 
249
/*
 
250
 * PageGetItem
 
251
 *              Retrieves an item on the given page.
 
252
 *
 
253
 * Note:
 
254
 *              This does not change the status of any of the resources passed.
 
255
 *              The semantics may change in the future.
 
256
 */
 
257
#define PageGetItem(page, itemId) \
 
258
( \
 
259
        AssertMacro(PageIsValid(page)), \
 
260
        AssertMacro((itemId)->lp_flags & LP_USED), \
 
261
        (Item)(((char *)(page)) + (itemId)->lp_off) \
 
262
)
 
263
 
 
264
/*
 
265
 * BufferGetPageSize
 
266
 *              Returns the page size within a buffer.
 
267
 *
 
268
 * Notes:
 
269
 *              Assumes buffer is valid.
 
270
 *
 
271
 *              The buffer can be a raw disk block and need not contain a valid
 
272
 *              (formatted) disk page.
 
273
 */
 
274
/* XXX should dig out of buffer descriptor */
 
275
#define BufferGetPageSize(buffer) \
 
276
( \
 
277
        AssertMacro(BufferIsValid(buffer)), \
 
278
        (Size)BLCKSZ \
 
279
)
 
280
 
 
281
/*
 
282
 * BufferGetPage
 
283
 *              Returns the page associated with a buffer.
 
284
 */
 
285
#define BufferGetPage(buffer) ((Page)BufferGetBlock(buffer))
 
286
 
 
287
/*
 
288
 * PageGetMaxOffsetNumber
 
289
 *              Returns the maximum offset number used by the given page.
 
290
 *              Since offset numbers are 1-based, this is also the number
 
291
 *              of items on the page.
 
292
 *
 
293
 *              NOTE: if the page is not initialized (pd_lower == 0), we must
 
294
 *              return zero to ensure sane behavior.  Accept double evaluation
 
295
 *              of the argument so that we can ensure this.
 
296
 */
 
297
#define PageGetMaxOffsetNumber(page) \
 
298
        (((PageHeader) (page))->pd_lower <= SizeOfPageHeaderData ? 0 : \
 
299
         ((((PageHeader) (page))->pd_lower - SizeOfPageHeaderData) \
 
300
          / sizeof(ItemIdData)))
 
301
 
 
302
#define PageGetLSN(page) \
 
303
        (((PageHeader) (page))->pd_lsn)
 
304
#define PageSetLSN(page, lsn) \
 
305
        (((PageHeader) (page))->pd_lsn = (lsn))
 
306
 
 
307
#define PageGetTLI(page) \
 
308
        (((PageHeader) (page))->pd_tli)
 
309
#define PageSetTLI(page, tli) \
 
310
        (((PageHeader) (page))->pd_tli = (tli))
 
311
 
 
312
/* ----------------------------------------------------------------
 
313
 *              extern declarations
 
314
 * ----------------------------------------------------------------
 
315
 */
 
316
 
 
317
extern void PageInit(Page page, Size pageSize, Size specialSize);
 
318
extern bool PageHeaderIsValid(PageHeader page);
 
319
extern OffsetNumber PageAddItem(Page page, Item item, Size size,
 
320
                        OffsetNumber offsetNumber, ItemIdFlags flags);
 
321
extern Page PageGetTempPage(Page page, Size specialSize);
 
322
extern void PageRestoreTempPage(Page tempPage, Page oldPage);
 
323
extern int      PageRepairFragmentation(Page page, OffsetNumber *unused);
 
324
extern Size PageGetFreeSpace(Page page);
 
325
extern void PageIndexTupleDelete(Page page, OffsetNumber offset);
 
326
 
 
327
#endif   /* BUFPAGE_H */