diff options
| author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2008-09-30 10:52:14 +0000 |
|---|---|---|
| committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2008-09-30 10:52:14 +0000 |
| commit | 15c121b3ed7eb2f290e19533e41ccca734d23574 (patch) | |
| tree | b60226d720f87b82b5b44647e3d3031081cdfb07 /src/include/storage/freespace.h | |
| parent | 2dbc0ca937f8ba9c76866a99fd04866232acea95 (diff) | |
| download | postgresql-15c121b3ed7eb2f290e19533e41ccca734d23574.tar.gz | |
Rewrite the FSM. Instead of relying on a fixed-size shared memory segment, the
free space information is stored in a dedicated FSM relation fork, with each
relation (except for hash indexes; they don't use FSM).
This eliminates the max_fsm_relations and max_fsm_pages GUC options; remove any
trace of them from the backend, initdb, and documentation.
Rewrite contrib/pg_freespacemap to match the new FSM implementation. Also
introduce a new variant of the get_raw_page(regclass, int4, int4) function in
contrib/pageinspect that let's you to return pages from any relation fork, and
a new fsm_page_contents() function to inspect the new FSM pages.
Diffstat (limited to 'src/include/storage/freespace.h')
| -rw-r--r-- | src/include/storage/freespace.h | 150 |
1 files changed, 15 insertions, 135 deletions
diff --git a/src/include/storage/freespace.h b/src/include/storage/freespace.h index 86dd22647c..d417e8c980 100644 --- a/src/include/storage/freespace.h +++ b/src/include/storage/freespace.h @@ -7,152 +7,32 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/freespace.h,v 1.28 2008/03/10 02:04:10 tgl Exp $ + * $PostgreSQL: pgsql/src/include/storage/freespace.h,v 1.29 2008/09/30 10:52:13 heikki Exp $ * *------------------------------------------------------------------------- */ #ifndef FREESPACE_H_ #define FREESPACE_H_ -#include "storage/relfilenode.h" -#include "storage/itemptr.h" +#include "utils/rel.h" +#include "storage/bufpage.h" +#include "access/xlog.h" - -/* Initial value for average-request moving average */ -#define INITIAL_AVERAGE ((Size) (BLCKSZ / 32)) - -/* - * Number of pages and bytes per allocation chunk. Indexes can squeeze 50% - * more pages into the same space because they don't need to remember how much - * free space on each page. The nominal number of pages, CHUNKPAGES, is for - * regular rels, and INDEXCHUNKPAGES is for indexes. CHUNKPAGES should be - * even so that no space is wasted in the index case. - */ -#define CHUNKPAGES 16 -#define CHUNKBYTES (CHUNKPAGES * sizeof(FSMPageData)) -#define INDEXCHUNKPAGES ((int) (CHUNKBYTES / sizeof(IndexFSMPageData))) - - -/* - * Typedefs and macros for items in the page-storage arena. We use the - * existing ItemPointer and BlockId data structures, which are designed - * to pack well (they should be 6 and 4 bytes apiece regardless of machine - * alignment issues). Unfortunately we can't use the ItemPointer access - * macros, because they include Asserts insisting that ip_posid != 0. - */ -typedef ItemPointerData FSMPageData; -typedef BlockIdData IndexFSMPageData; - -#define FSMPageGetPageNum(ptr) \ - BlockIdGetBlockNumber(&(ptr)->ip_blkid) -#define FSMPageGetSpace(ptr) \ - ((Size) (ptr)->ip_posid) -#define FSMPageSetPageNum(ptr, pg) \ - BlockIdSet(&(ptr)->ip_blkid, pg) -#define FSMPageSetSpace(ptr, sz) \ - ((ptr)->ip_posid = (OffsetNumber) (sz)) -#define IndexFSMPageGetPageNum(ptr) \ - BlockIdGetBlockNumber(ptr) -#define IndexFSMPageSetPageNum(ptr, pg) \ - BlockIdSet(ptr, pg) - -/* - * Shared free-space-map objects - * - * The per-relation objects are indexed by a hash table, and are also members - * of two linked lists: one ordered by recency of usage (most recent first), - * and the other ordered by physical location of the associated storage in - * the page-info arena. - * - * Each relation owns one or more chunks of per-page storage in the "arena". - * The chunks for each relation are always consecutive, so that it can treat - * its page storage as a simple array. We further insist that its page data - * be ordered by block number, so that binary search is possible. - * - * Note: we handle pointers to these items as pointers, not as SHMEM_OFFSETs. - * This assumes that all processes accessing the map will have the shared - * memory segment mapped at the same place in their address space. - */ -typedef struct FSMHeader FSMHeader; -typedef struct FSMRelation FSMRelation; - -/* Header for whole map */ -struct FSMHeader -{ - FSMRelation *usageList; /* FSMRelations in usage-recency order */ - FSMRelation *usageListTail; /* tail of usage-recency list */ - FSMRelation *firstRel; /* FSMRelations in arena storage order */ - FSMRelation *lastRel; /* tail of storage-order list */ - int numRels; /* number of FSMRelations now in use */ - double sumRequests; /* sum of requested chunks over all rels */ - char *arena; /* arena for page-info storage */ - int totalChunks; /* total size of arena, in chunks */ - int usedChunks; /* # of chunks assigned */ - /* NB: there are totalChunks - usedChunks free chunks at end of arena */ -}; - -/* - * Per-relation struct --- this is an entry in the shared hash table. - * The hash key is the RelFileNode value (hence, we look at the physical - * relation ID, not the logical ID, which is appropriate). - */ -struct FSMRelation -{ - RelFileNode key; /* hash key (must be first) */ - FSMRelation *nextUsage; /* next rel in usage-recency order */ - FSMRelation *priorUsage; /* prior rel in usage-recency order */ - FSMRelation *nextPhysical; /* next rel in arena-storage order */ - FSMRelation *priorPhysical; /* prior rel in arena-storage order */ - bool isIndex; /* if true, we store only page numbers */ - Size avgRequest; /* moving average of space requests */ - BlockNumber interestingPages; /* # of pages with useful free space */ - int firstChunk; /* chunk # of my first chunk in arena */ - int storedPages; /* # of pages stored in arena */ - int nextPage; /* index (from 0) to start next search at */ -}; - - - -/* GUC variables */ -extern PGDLLIMPORT int MaxFSMRelations; -extern PGDLLIMPORT int MaxFSMPages; - - -/* - * function prototypes - */ -extern void InitFreeSpaceMap(void); -extern Size FreeSpaceShmemSize(void); -extern FSMHeader *GetFreeSpaceMap(void); - -extern BlockNumber GetPageWithFreeSpace(RelFileNode *rel, Size spaceNeeded); -extern BlockNumber RecordAndGetPageWithFreeSpace(RelFileNode *rel, +/* prototypes for public functions in freespace.c */ +extern Size GetRecordedFreeSpace(Relation rel, BlockNumber heapBlk); +extern BlockNumber GetPageWithFreeSpace(Relation rel, Size spaceNeeded); +extern BlockNumber RecordAndGetPageWithFreeSpace(Relation rel, BlockNumber oldPage, Size oldSpaceAvail, Size spaceNeeded); -extern Size GetAvgFSMRequestSize(RelFileNode *rel); -extern void RecordRelationFreeSpace(RelFileNode *rel, - BlockNumber interestingPages, - int nPages, - FSMPageData *pageSpaces); - -extern BlockNumber GetFreeIndexPage(RelFileNode *rel); -extern void RecordIndexFreeSpace(RelFileNode *rel, - BlockNumber interestingPages, - int nPages, - BlockNumber *pages); - -extern void FreeSpaceMapTruncateRel(RelFileNode *rel, BlockNumber nblocks); -extern void FreeSpaceMapForgetRel(RelFileNode *rel); -extern void FreeSpaceMapForgetDatabase(Oid dbid); - -extern void PrintFreeSpaceMapStatistics(int elevel); +extern void RecordPageWithFreeSpace(Relation rel, BlockNumber heapBlk, + Size spaceAvail); -extern void DumpFreeSpaceMap(int code, Datum arg); -extern void LoadFreeSpaceMap(void); +extern void FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks); +extern void FreeSpaceMapVacuum(Relation rel); -#ifdef FREESPACE_DEBUG -extern void DumpFreeSpace(void); -#endif +/* WAL prototypes */ +extern void fsm_desc(StringInfo buf, uint8 xl_info, char *rec); +extern void fsm_redo(XLogRecPtr lsn, XLogRecord *record); #endif /* FREESPACE_H */ |
