1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-24 10:47:04 +03:00
Tom Lane e0c9301c87 Install infrastructure for shared-memory free space map. Doesn't actually
do anything yet, but it has the necessary connections to initialization
and so forth.  Make some gestures towards allowing number of blocks in
a relation to be BlockNumber, ie, unsigned int, rather than signed int.
(I doubt I got all the places that are sloppy about it, yet.)  On the
way, replace the hardwired NLOCKS_PER_XACT fudge factor with a GUC
variable.
2001-06-27 23:31:40 +00:00

184 lines
5.0 KiB
C

/*-------------------------------------------------------------------------
*
* freespace.c
* POSTGRES free space map for quickly finding free space in relations
*
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/storage/freespace/freespace.c,v 1.1 2001/06/27 23:31:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "storage/freespace.h"
#include "storage/itemid.h"
#include "storage/shmem.h"
/*
* Shared free-space-map objects
*
* 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;
typedef struct FSMChunk FSMChunk;
/* Header for whole map */
struct FSMHeader
{
HTAB *relationHash; /* hashtable of FSMRelation entries */
FSMRelation *relationList; /* FSMRelations in order by recency of use */
int numRelations; /* number of FSMRelations now in use */
FSMChunk *freeChunks; /* linked list of currently-free chunks */
};
/*
* 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 *nextRel; /* next rel in order by recency of use */
FSMRelation *priorRel; /* prior rel in order by recency of use */
FSMChunk *relChunks; /* linked list of page info chunks */
};
#define SHMEM_FSMHASH_KEYSIZE sizeof(RelFileNode)
#define SHMEM_FSMHASH_DATASIZE (sizeof(FSMRelation) - SHMEM_FSMHASH_KEYSIZE)
#define CHUNKPAGES 32 /* each chunk can store this many pages */
struct FSMChunk
{
FSMChunk *next; /* linked-list link */
int numPages; /* number of pages described here */
BlockNumber pages[CHUNKPAGES]; /* page numbers within relation */
ItemLength bytes[CHUNKPAGES]; /* free space available on each page */
};
SPINLOCK FreeSpaceLock; /* in Shmem or created in
* CreateSpinlocks() */
int MaxFSMRelations; /* these are set by guc.c */
int MaxFSMPages;
static FSMHeader *FreeSpaceMap; /* points to FSMHeader in shared memory */
/*
* InitFreeSpaceMap -- Initialize the freespace module.
*
* This must be called once during shared memory initialization.
* It builds the empty free space map table. FreeSpaceLock must also be
* initialized at some point, but is not touched here --- we assume there is
* no need for locking, since only the calling process can be accessing shared
* memory as yet. FreeSpaceShmemSize() was called previously while computing
* the space needed for shared memory.
*/
void
InitFreeSpaceMap(void)
{
HASHCTL info;
FSMChunk *chunks,
*prevchunk;
int nchunks;
/* Create table header */
FreeSpaceMap = (FSMHeader *) ShmemAlloc(sizeof(FSMHeader));
if (FreeSpaceMap == NULL)
elog(FATAL, "Insufficient shared memory for free space map");
MemSet(FreeSpaceMap, 0, sizeof(FSMHeader));
/* Create hashtable for FSMRelations */
info.keysize = SHMEM_FSMHASH_KEYSIZE;
info.datasize = SHMEM_FSMHASH_DATASIZE;
info.hash = tag_hash;
FreeSpaceMap->relationHash = ShmemInitHash("Free Space Map Hash",
MaxFSMRelations / 10,
MaxFSMRelations,
&info,
(HASH_ELEM | HASH_FUNCTION));
if (!FreeSpaceMap->relationHash)
elog(FATAL, "Insufficient shared memory for free space map");
/* Allocate FSMChunks and fill up the free-chunks list */
nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1;
chunks = (FSMChunk *) ShmemAlloc(nchunks * sizeof(FSMChunk));
if (chunks == NULL)
elog(FATAL, "Insufficient shared memory for free space map");
prevchunk = NULL;
while (nchunks-- > 0)
{
chunks->next = prevchunk;
prevchunk = chunks;
chunks++;
}
FreeSpaceMap->freeChunks = prevchunk;
}
int
FreeSpaceShmemSize(void)
{
int size;
int nchunks;
/*
* There is no point in allowing less than one "chunk" per relation,
* so force MaxFSMPages to be at least CHUNKPAGES * MaxFSMRelations.
*/
Assert(MaxFSMRelations > 0);
if (MaxFSMPages < CHUNKPAGES * MaxFSMRelations)
MaxFSMPages = CHUNKPAGES * MaxFSMRelations;
/* table header */
size = MAXALIGN(sizeof(FSMHeader));
/* hash table, including the FSMRelation objects */
size += hash_estimate_size(MaxFSMRelations,
SHMEM_FSMHASH_KEYSIZE,
SHMEM_FSMHASH_DATASIZE);
/* FSMChunk objects */
nchunks = (MaxFSMPages - 1) / CHUNKPAGES + 1;
size += MAXALIGN(nchunks * sizeof(FSMChunk));
return size;
}
void
FreeSpaceMapForgetRel(RelFileNode *rel)
{
}
#ifdef FREESPACE_DEBUG
/*
* Dump contents of freespace map for debugging.
*
* We assume caller holds the FreeSpaceLock, or is otherwise unconcerned
* about other processes.
*/
void
DumpFreeSpace(void)
{
}
#endif /* FREESPACE_DEBUG */