]> granicus.if.org Git - postgresql/blob - src/include/storage/freespace.h
Clean up code associated with updating pg_class statistics columns
[postgresql] / src / include / storage / freespace.h
1 /*-------------------------------------------------------------------------
2  *
3  * freespace.h
4  *        POSTGRES free space map for quickly finding free space in relations
5  *
6  *
7  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  * $PostgreSQL: pgsql/src/include/storage/freespace.h,v 1.20 2006/03/05 15:58:59 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #ifndef FREESPACE_H_
15 #define FREESPACE_H_
16
17 #include "storage/block.h"
18 #include "storage/relfilenode.h"
19 #include "storage/itemptr.h"
20
21
22 /*
23  * exported types
24  */
25 typedef struct PageFreeSpaceInfo
26 {
27         BlockNumber blkno;                      /* which page in relation */
28         Size            avail;                  /* space available on this page */
29 } PageFreeSpaceInfo;
30
31
32 /* Initial value for average-request moving average */
33 #define INITIAL_AVERAGE ((Size) (BLCKSZ / 32))
34
35 /*
36  * Number of pages and bytes per allocation chunk.      Indexes can squeeze 50%
37  * more pages into the same space because they don't need to remember how much
38  * free space on each page.  The nominal number of pages, CHUNKPAGES, is for
39  * regular rels, and INDEXCHUNKPAGES is for indexes.  CHUNKPAGES should be
40  * even so that no space is wasted in the index case.
41  */
42 #define CHUNKPAGES      16
43 #define CHUNKBYTES      (CHUNKPAGES * sizeof(FSMPageData))
44 #define INDEXCHUNKPAGES ((int) (CHUNKBYTES / sizeof(IndexFSMPageData)))
45
46
47 /*
48  * Typedefs and macros for items in the page-storage arena.  We use the
49  * existing ItemPointer and BlockId data structures, which are designed
50  * to pack well (they should be 6 and 4 bytes apiece regardless of machine
51  * alignment issues).  Unfortunately we can't use the ItemPointer access
52  * macros, because they include Asserts insisting that ip_posid != 0.
53  */
54 typedef ItemPointerData FSMPageData;
55 typedef BlockIdData IndexFSMPageData;
56
57 #define FSMPageGetPageNum(ptr)  \
58         BlockIdGetBlockNumber(&(ptr)->ip_blkid)
59 #define FSMPageGetSpace(ptr)    \
60         ((Size) (ptr)->ip_posid)
61 #define FSMPageSetPageNum(ptr, pg)      \
62         BlockIdSet(&(ptr)->ip_blkid, pg)
63 #define FSMPageSetSpace(ptr, sz)        \
64         ((ptr)->ip_posid = (OffsetNumber) (sz))
65 #define IndexFSMPageGetPageNum(ptr) \
66         BlockIdGetBlockNumber(ptr)
67 #define IndexFSMPageSetPageNum(ptr, pg) \
68         BlockIdSet(ptr, pg)
69
70 /*
71  * Shared free-space-map objects
72  *
73  * The per-relation objects are indexed by a hash table, and are also members
74  * of two linked lists: one ordered by recency of usage (most recent first),
75  * and the other ordered by physical location of the associated storage in
76  * the page-info arena.
77  *
78  * Each relation owns one or more chunks of per-page storage in the "arena".
79  * The chunks for each relation are always consecutive, so that it can treat
80  * its page storage as a simple array.  We further insist that its page data
81  * be ordered by block number, so that binary search is possible.
82  *
83  * Note: we handle pointers to these items as pointers, not as SHMEM_OFFSETs.
84  * This assumes that all processes accessing the map will have the shared
85  * memory segment mapped at the same place in their address space.
86  */
87 typedef struct FSMHeader FSMHeader;
88 typedef struct FSMRelation FSMRelation;
89
90 /* Header for whole map */
91 struct FSMHeader
92 {
93         FSMRelation *usageList;         /* FSMRelations in usage-recency order */
94         FSMRelation *usageListTail; /* tail of usage-recency list */
95         FSMRelation *firstRel;          /* FSMRelations in arena storage order */
96         FSMRelation *lastRel;           /* tail of storage-order list */
97         int                     numRels;                /* number of FSMRelations now in use */
98         double          sumRequests;    /* sum of requested chunks over all rels */
99         char       *arena;                      /* arena for page-info storage */
100         int                     totalChunks;    /* total size of arena, in chunks */
101         int                     usedChunks;             /* # of chunks assigned */
102         /* NB: there are totalChunks - usedChunks free chunks at end of arena */
103 };
104
105 /*
106  * Per-relation struct --- this is an entry in the shared hash table.
107  * The hash key is the RelFileNode value (hence, we look at the physical
108  * relation ID, not the logical ID, which is appropriate).
109  */
110 struct FSMRelation
111 {
112         RelFileNode key;                        /* hash key (must be first) */
113         FSMRelation *nextUsage;         /* next rel in usage-recency order */
114         FSMRelation *priorUsage;        /* prior rel in usage-recency order */
115         FSMRelation *nextPhysical;      /* next rel in arena-storage order */
116         FSMRelation *priorPhysical; /* prior rel in arena-storage order */
117         bool            isIndex;                /* if true, we store only page numbers */
118         Size            avgRequest;             /* moving average of space requests */
119         int                     lastPageCount;  /* pages passed to RecordRelationFreeSpace */
120         int                     firstChunk;             /* chunk # of my first chunk in arena */
121         int                     storedPages;    /* # of pages stored in arena */
122         int                     nextPage;               /* index (from 0) to start next search at */
123 };
124
125
126
127 /* GUC variables */
128 extern int      MaxFSMRelations;
129 extern int      MaxFSMPages;
130
131
132 /*
133  * function prototypes
134  */
135 extern void InitFreeSpaceMap(void);
136 extern Size FreeSpaceShmemSize(void);
137
138 extern BlockNumber GetPageWithFreeSpace(RelFileNode *rel, Size spaceNeeded);
139 extern BlockNumber RecordAndGetPageWithFreeSpace(RelFileNode *rel,
140                                                           BlockNumber oldPage,
141                                                           Size oldSpaceAvail,
142                                                           Size spaceNeeded);
143 extern Size GetAvgFSMRequestSize(RelFileNode *rel);
144 extern void RecordRelationFreeSpace(RelFileNode *rel,
145                                                 int nPages,
146                                                 PageFreeSpaceInfo *pageSpaces);
147
148 extern BlockNumber GetFreeIndexPage(RelFileNode *rel);
149 extern void RecordIndexFreeSpace(RelFileNode *rel,
150                                          int nPages,
151                                          BlockNumber *pages);
152
153 extern void FreeSpaceMapTruncateRel(RelFileNode *rel, BlockNumber nblocks);
154 extern void FreeSpaceMapForgetRel(RelFileNode *rel);
155 extern void FreeSpaceMapForgetDatabase(Oid dbid);
156
157 extern void PrintFreeSpaceMapStatistics(int elevel);
158
159 extern void DumpFreeSpaceMap(int code, Datum arg);
160 extern void LoadFreeSpaceMap(void);
161 extern FSMHeader *GetFreeSpaceMap(void);
162
163 #ifdef FREESPACE_DEBUG
164 extern void DumpFreeSpace(void);
165 #endif
166
167 #endif   /* FREESPACE_H */