diff options
Diffstat (limited to 'src/backend/storage')
| -rw-r--r-- | src/backend/storage/Makefile | 4 | ||||
| -rw-r--r-- | src/backend/storage/freespace/Makefile | 30 | ||||
| -rw-r--r-- | src/backend/storage/freespace/freespace.c | 183 | ||||
| -rw-r--r-- | src/backend/storage/ipc/ipci.c | 16 | ||||
| -rw-r--r-- | src/backend/storage/ipc/spin.c | 27 | ||||
| -rw-r--r-- | src/backend/storage/lmgr/lock.c | 14 | ||||
| -rw-r--r-- | src/backend/storage/smgr/md.c | 99 | ||||
| -rw-r--r-- | src/backend/storage/smgr/mm.c | 10 | ||||
| -rw-r--r-- | src/backend/storage/smgr/smgr.c | 43 |
9 files changed, 329 insertions, 97 deletions
diff --git a/src/backend/storage/Makefile b/src/backend/storage/Makefile index d9f6544911..ace37e6ac6 100644 --- a/src/backend/storage/Makefile +++ b/src/backend/storage/Makefile @@ -1,14 +1,14 @@ # # Makefile for the storage manager subsystem # -# $Header: /cvsroot/pgsql/src/backend/storage/Makefile,v 1.8 2000/08/31 16:10:30 petere Exp $ +# $Header: /cvsroot/pgsql/src/backend/storage/Makefile,v 1.9 2001/06/27 23:31:39 tgl Exp $ # subdir = src/backend/storage top_builddir = ../../.. include $(top_builddir)/src/Makefile.global -SUBDIRS := buffer file ipc large_object lmgr page smgr +SUBDIRS := buffer file freespace ipc large_object lmgr page smgr SUBDIROBJS := $(SUBDIRS:%=%/SUBSYS.o) all: SUBSYS.o diff --git a/src/backend/storage/freespace/Makefile b/src/backend/storage/freespace/Makefile new file mode 100644 index 0000000000..9d4c5c5793 --- /dev/null +++ b/src/backend/storage/freespace/Makefile @@ -0,0 +1,30 @@ +#------------------------------------------------------------------------- +# +# Makefile-- +# Makefile for storage/freespace +# +# IDENTIFICATION +# $Header: /cvsroot/pgsql/src/backend/storage/freespace/Makefile,v 1.1 2001/06/27 23:31:39 tgl Exp $ +# +#------------------------------------------------------------------------- + +subdir = src/backend/storage/freespace +top_builddir = ../../../.. +include $(top_builddir)/src/Makefile.global + +OBJS = freespace.o + +all: SUBSYS.o + +SUBSYS.o: $(OBJS) + $(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS) + +depend dep: + $(CC) -MM $(CFLAGS) *.c >depend + +clean: + rm -f SUBSYS.o $(OBJS) + +ifeq (depend,$(wildcard depend)) +include depend +endif diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c new file mode 100644 index 0000000000..84f7066348 --- /dev/null +++ b/src/backend/storage/freespace/freespace.c @@ -0,0 +1,183 @@ +/*------------------------------------------------------------------------- + * + * 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 */ diff --git a/src/backend/storage/ipc/ipci.c b/src/backend/storage/ipc/ipci.c index ed42e51a92..75736c8f24 100644 --- a/src/backend/storage/ipc/ipci.c +++ b/src/backend/storage/ipc/ipci.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.40 2001/03/22 03:59:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/ipci.c,v 1.41 2001/06/27 23:31:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,6 +19,7 @@ #include "miscadmin.h" #include "access/xlog.h" #include "storage/bufmgr.h" +#include "storage/freespace.h" #include "storage/lmgr.h" #include "storage/proc.h" #include "storage/sinval.h" @@ -47,8 +48,12 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int maxBackends) * moderately-accurate estimates for the big hogs, plus 100K for the * stuff that's too small to bother with estimating. */ - size = BufferShmemSize() + LockShmemSize(maxBackends) + - XLOGShmemSize() + SLockShmemSize() + SInvalShmemSize(maxBackends); + size = BufferShmemSize(); + size += LockShmemSize(maxBackends); + size += XLOGShmemSize(); + size += SLockShmemSize(); + size += SInvalShmemSize(maxBackends); + size += FreeSpaceShmemSize(); #ifdef STABLE_MEMORY_STORAGE size += MMShmemSize(); #endif @@ -96,4 +101,9 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int maxBackends) * Set up shared-inval messaging */ CreateSharedInvalidationState(maxBackends); + + /* + * Set up free-space map + */ + InitFreeSpaceMap(); } diff --git a/src/backend/storage/ipc/spin.c b/src/backend/storage/ipc/spin.c index 33308f0cc1..05bf5acbbb 100644 --- a/src/backend/storage/ipc/spin.c +++ b/src/backend/storage/ipc/spin.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.32 2001/03/22 03:59:45 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/ipc/Attic/spin.c,v 1.33 2001/06/27 23:31:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,19 +31,18 @@ /* Probably should move these to an appropriate header file */ -extern SPINLOCK ShmemLock; -extern SPINLOCK ShmemIndexLock; extern SPINLOCK BufMgrLock; -extern SPINLOCK LockMgrLock; -extern SPINLOCK ProcStructLock; -extern SPINLOCK SInvalLock; extern SPINLOCK OidGenLockId; extern SPINLOCK XidGenLockId; extern SPINLOCK ControlFileLockId; - +extern SPINLOCK ShmemLock; +extern SPINLOCK ShmemIndexLock; +extern SPINLOCK LockMgrLock; +extern SPINLOCK SInvalLock; +extern SPINLOCK ProcStructLock; +extern SPINLOCK FreeSpaceLock; #ifdef STABLE_MEMORY_STORAGE extern SPINLOCK MMCacheLock; - #endif @@ -57,16 +56,16 @@ extern SPINLOCK MMCacheLock; static void InitSpinLockIDs(void) { - ShmemLock = (SPINLOCK) SHMEMLOCKID; - ShmemIndexLock = (SPINLOCK) SHMEMINDEXLOCKID; BufMgrLock = (SPINLOCK) BUFMGRLOCKID; - LockMgrLock = (SPINLOCK) LOCKMGRLOCKID; - ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID; - SInvalLock = (SPINLOCK) SINVALLOCKID; OidGenLockId = (SPINLOCK) OIDGENLOCKID; XidGenLockId = (SPINLOCK) XIDGENLOCKID; ControlFileLockId = (SPINLOCK) CNTLFILELOCKID; - + ShmemLock = (SPINLOCK) SHMEMLOCKID; + ShmemIndexLock = (SPINLOCK) SHMEMINDEXLOCKID; + LockMgrLock = (SPINLOCK) LOCKMGRLOCKID; + SInvalLock = (SPINLOCK) SINVALLOCKID; + ProcStructLock = (SPINLOCK) PROCSTRUCTLOCKID; + FreeSpaceLock = (SPINLOCK) FREESPACELOCKID; #ifdef STABLE_MEMORY_STORAGE MMCacheLock = (SPINLOCK) MMCACHELOCKID; #endif diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index 577b420797..3eb0104827 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.89 2001/06/22 00:04:59 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/lock.c,v 1.90 2001/06/27 23:31:39 tgl Exp $ * * NOTES * Outside modules can create a lock table and acquire/release @@ -40,6 +40,13 @@ #include "utils/memutils.h" #include "utils/ps_status.h" + +/* This configuration variable is used to set the lock table size */ +int max_locks_per_xact; /* set by guc.c */ + +#define NLOCKENTS(maxBackends) (max_locks_per_xact * (maxBackends)) + + static int WaitOnLock(LOCKMETHOD lockmethod, LOCKMODE lockmode, LOCK *lock, HOLDER *holder); static void LockCountMyLocks(SHMEM_OFFSET lockOffset, PROC *proc, @@ -1388,6 +1395,7 @@ int LockShmemSize(int maxBackends) { int size = 0; + long max_table_size = NLOCKENTS(maxBackends); size += MAXALIGN(sizeof(PROC_HDR)); /* ProcGlobal */ size += maxBackends * MAXALIGN(sizeof(PROC)); /* each MyProc */ @@ -1395,12 +1403,12 @@ LockShmemSize(int maxBackends) * lockMethodTable->ctl */ /* lockHash table */ - size += hash_estimate_size(NLOCKENTS(maxBackends), + size += hash_estimate_size(max_table_size, SHMEM_LOCKTAB_KEYSIZE, SHMEM_LOCKTAB_DATASIZE); /* holderHash table */ - size += hash_estimate_size(NLOCKENTS(maxBackends), + size += hash_estimate_size(max_table_size, SHMEM_HOLDERTAB_KEYSIZE, SHMEM_HOLDERTAB_DATASIZE); diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 762aceda73..54054ee137 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.85 2001/06/06 17:07:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.86 2001/06/27 23:31:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -72,10 +72,10 @@ static MemoryContext MdCxt; /* context for all my allocations */ /* routines declared here */ static void mdclose_fd(int fd); static int _mdfd_getrelnfd(Relation reln); -static MdfdVec *_mdfd_openseg(Relation reln, int segno, int oflags); -static MdfdVec *_mdfd_getseg(Relation reln, int blkno); +static MdfdVec *_mdfd_openseg(Relation reln, BlockNumber segno, int oflags); +static MdfdVec *_mdfd_getseg(Relation reln, BlockNumber blkno); -static int _mdfd_blind_getseg(RelFileNode rnode, int blkno); +static int _mdfd_blind_getseg(RelFileNode rnode, BlockNumber blkno); static int _fdvec_alloc(void); static void _fdvec_free(int); @@ -93,7 +93,7 @@ static BlockNumber _mdnblocks(File file, Size blcksz); * Returns SM_SUCCESS or SM_FAIL with errno set as appropriate. */ int -mdinit() +mdinit(void) { int i; @@ -194,11 +194,11 @@ mdunlink(RelFileNode rnode) if (status == SM_SUCCESS) { char *segpath = (char *) palloc(strlen(path) + 12); - int segno; + BlockNumber segno; for (segno = 1;; segno++) { - sprintf(segpath, "%s.%d", path, segno); + sprintf(segpath, "%s.%u", path, segno); if (unlink(segpath) < 0) { /* ENOENT is expected after the last segment... */ @@ -246,7 +246,7 @@ mdextend(Relation reln, BlockNumber blocknum, char *buffer) v = _mdfd_getseg(reln, blocknum); #ifndef LET_OS_MANAGE_FILESIZE - seekpos = (long) (BLCKSZ * (blocknum % RELSEG_SIZE)); + seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE))); #ifdef DIAGNOSTIC if (seekpos >= BLCKSZ * RELSEG_SIZE) elog(FATAL, "seekpos too big!"); @@ -283,7 +283,7 @@ mdextend(Relation reln, BlockNumber blocknum, char *buffer) #ifndef LET_OS_MANAGE_FILESIZE #ifdef DIAGNOSTIC - if (_mdnblocks(v->mdfd_vfd, BLCKSZ) > RELSEG_SIZE) + if (_mdnblocks(v->mdfd_vfd, BLCKSZ) > ((BlockNumber) RELSEG_SIZE)) elog(FATAL, "segment too big!"); #endif #endif @@ -338,7 +338,7 @@ mdopen(Relation reln) Md_fdvec[vfd].mdfd_chain = (MdfdVec *) NULL; #ifdef DIAGNOSTIC - if (_mdnblocks(fd, BLCKSZ) > RELSEG_SIZE) + if (_mdnblocks(fd, BLCKSZ) > ((BlockNumber) RELSEG_SIZE)) elog(FATAL, "segment too big on relopen!"); #endif #endif @@ -438,7 +438,7 @@ mdread(Relation reln, BlockNumber blocknum, char *buffer) v = _mdfd_getseg(reln, blocknum); #ifndef LET_OS_MANAGE_FILESIZE - seekpos = (long) (BLCKSZ * (blocknum % RELSEG_SIZE)); + seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE))); #ifdef DIAGNOSTIC if (seekpos >= BLCKSZ * RELSEG_SIZE) @@ -482,7 +482,7 @@ mdwrite(Relation reln, BlockNumber blocknum, char *buffer) v = _mdfd_getseg(reln, blocknum); #ifndef LET_OS_MANAGE_FILESIZE - seekpos = (long) (BLCKSZ * (blocknum % RELSEG_SIZE)); + seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE))); #ifdef DIAGNOSTIC if (seekpos >= BLCKSZ * RELSEG_SIZE) elog(FATAL, "seekpos too big!"); @@ -516,7 +516,7 @@ mdflush(Relation reln, BlockNumber blocknum, char *buffer) v = _mdfd_getseg(reln, blocknum); #ifndef LET_OS_MANAGE_FILESIZE - seekpos = (long) (BLCKSZ * (blocknum % RELSEG_SIZE)); + seekpos = (long) (BLCKSZ * (blocknum % ((BlockNumber) RELSEG_SIZE))); #ifdef DIAGNOSTIC if (seekpos >= BLCKSZ * RELSEG_SIZE) elog(FATAL, "seekpos too big!"); @@ -561,7 +561,7 @@ mdblindwrt(RelFileNode rnode, return SM_FAIL; #ifndef LET_OS_MANAGE_FILESIZE - seekpos = (long) (BLCKSZ * (blkno % RELSEG_SIZE)); + seekpos = (long) (BLCKSZ * (blkno % ((BlockNumber) RELSEG_SIZE))); #ifdef DIAGNOSTIC if (seekpos >= BLCKSZ * RELSEG_SIZE) elog(FATAL, "seekpos too big!"); @@ -659,16 +659,14 @@ mdblindmarkdirty(RelFileNode rnode, * * Returns # of blocks, elog's on error. */ -int +BlockNumber mdnblocks(Relation reln) { int fd; MdfdVec *v; - #ifndef LET_OS_MANAGE_FILESIZE - int nblocks; - int segno; - + BlockNumber nblocks; + BlockNumber segno; #endif fd = _mdfd_getrelnfd(reln); @@ -679,10 +677,10 @@ mdnblocks(Relation reln) for (;;) { nblocks = _mdnblocks(v->mdfd_vfd, BLCKSZ); - if (nblocks > RELSEG_SIZE) + if (nblocks > ((BlockNumber) RELSEG_SIZE)) elog(FATAL, "segment too big in mdnblocks!"); - if (nblocks < RELSEG_SIZE) - return (segno * RELSEG_SIZE) + nblocks; + if (nblocks < ((BlockNumber) RELSEG_SIZE)) + return (segno * ((BlockNumber) RELSEG_SIZE)) + nblocks; /* * If segment is exactly RELSEG_SIZE, advance to next one. */ @@ -713,18 +711,16 @@ mdnblocks(Relation reln) /* * mdtruncate() -- Truncate relation to specified number of blocks. * - * Returns # of blocks or -1 on error. + * Returns # of blocks or InvalidBlockNumber on error. */ -int -mdtruncate(Relation reln, int nblocks) +BlockNumber +mdtruncate(Relation reln, BlockNumber nblocks) { - int curnblk; int fd; MdfdVec *v; - + BlockNumber curnblk; #ifndef LET_OS_MANAGE_FILESIZE - int priorblocks; - + BlockNumber priorblocks; #endif /* @@ -732,8 +728,8 @@ mdtruncate(Relation reln, int nblocks) * that truncate/delete loop will get them all! */ curnblk = mdnblocks(reln); - if (nblocks < 0 || nblocks > curnblk) - return -1; /* bogus request */ + if (nblocks > curnblk) + return InvalidBlockNumber; /* bogus request */ if (nblocks == curnblk) return nblocks; /* no work */ @@ -748,7 +744,6 @@ mdtruncate(Relation reln, int nblocks) if (priorblocks > nblocks) { - /* * This segment is no longer wanted at all (and has already * been unlinked from the mdfd_chain). We truncate the file @@ -763,27 +758,25 @@ mdtruncate(Relation reln, int nblocks) * segment */ pfree(ov); } - else if (priorblocks + RELSEG_SIZE > nblocks) + else if (priorblocks + ((BlockNumber) RELSEG_SIZE) > nblocks) { - /* * This is the last segment we want to keep. Truncate the file * to the right length, and clear chain link that points to * any remaining segments (which we shall zap). NOTE: if * nblocks is exactly a multiple K of RELSEG_SIZE, we will * truncate the K+1st segment to 0 length but keep it. This is - * mainly so that the right thing happens if nblocks=0. + * mainly so that the right thing happens if nblocks==0. */ - int lastsegblocks = nblocks - priorblocks; + BlockNumber lastsegblocks = nblocks - priorblocks; if (FileTruncate(v->mdfd_vfd, lastsegblocks * BLCKSZ) < 0) - return -1; + return InvalidBlockNumber; v = v->mdfd_chain; ov->mdfd_chain = (MdfdVec *) NULL; } else { - /* * We still need this segment and 0 or more blocks beyond it, * so nothing to do here. @@ -794,7 +787,7 @@ mdtruncate(Relation reln, int nblocks) } #else if (FileTruncate(v->mdfd_vfd, nblocks * BLCKSZ) < 0) - return -1; + return InvalidBlockNumber; #endif return nblocks; @@ -940,7 +933,7 @@ _fdvec_free(int fdvec) } static MdfdVec * -_mdfd_openseg(Relation reln, int segno, int oflags) +_mdfd_openseg(Relation reln, BlockNumber segno, int oflags) { MdfdVec *v; int fd; @@ -953,7 +946,7 @@ _mdfd_openseg(Relation reln, int segno, int oflags) if (segno > 0) { fullpath = (char *) palloc(strlen(path) + 12); - sprintf(fullpath, "%s.%d", path, segno); + sprintf(fullpath, "%s.%u", path, segno); pfree(path); } else @@ -977,7 +970,7 @@ _mdfd_openseg(Relation reln, int segno, int oflags) v->mdfd_chain = (MdfdVec *) NULL; #ifdef DIAGNOSTIC - if (_mdnblocks(fd, BLCKSZ) > RELSEG_SIZE) + if (_mdnblocks(fd, BLCKSZ) > ((BlockNumber) RELSEG_SIZE)) elog(FATAL, "segment too big on openseg!"); #endif #endif @@ -1007,17 +1000,19 @@ _mdfd_getrelnfd(Relation reln) /* Find the segment of the relation holding the specified block */ static MdfdVec * -_mdfd_getseg(Relation reln, int blkno) +_mdfd_getseg(Relation reln, BlockNumber blkno) { MdfdVec *v; - int segno; int fd; - int i; +#ifndef LET_OS_MANAGE_FILESIZE + BlockNumber segno; + BlockNumber i; +#endif fd = _mdfd_getrelnfd(reln); #ifndef LET_OS_MANAGE_FILESIZE - for (v = &Md_fdvec[fd], segno = blkno / RELSEG_SIZE, i = 1; + for (v = &Md_fdvec[fd], segno = blkno / ((BlockNumber) RELSEG_SIZE), i = 1; segno > 0; i++, segno--) { @@ -1038,7 +1033,7 @@ _mdfd_getseg(Relation reln, int blkno) v->mdfd_chain = _mdfd_openseg(reln, i, (segno == 1) ? O_CREAT : 0); if (v->mdfd_chain == (MdfdVec *) NULL) - elog(ERROR, "cannot open segment %d of relation %s (target block %d): %m", + elog(ERROR, "cannot open segment %u of relation %s (target block %u): %m", i, RelationGetRelationName(reln), blkno); } v = v->mdfd_chain; @@ -1064,26 +1059,24 @@ _mdfd_getseg(Relation reln, int blkno) */ static int -_mdfd_blind_getseg(RelFileNode rnode, int blkno) +_mdfd_blind_getseg(RelFileNode rnode, BlockNumber blkno) { char *path; int fd; - #ifndef LET_OS_MANAGE_FILESIZE - int segno; - + BlockNumber segno; #endif path = relpath(rnode); #ifndef LET_OS_MANAGE_FILESIZE /* append the '.segno', if needed */ - segno = blkno / RELSEG_SIZE; + segno = blkno / ((BlockNumber) RELSEG_SIZE); if (segno > 0) { char *segpath = (char *) palloc(strlen(path) + 12); - sprintf(segpath, "%s.%d", path, segno); + sprintf(segpath, "%s.%u", path, segno); pfree(path); path = segpath; } diff --git a/src/backend/storage/smgr/mm.c b/src/backend/storage/smgr/mm.c index 547fc8d838..791c375de0 100644 --- a/src/backend/storage/smgr/mm.c +++ b/src/backend/storage/smgr/mm.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.23 2001/05/10 20:38:49 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/smgr/Attic/mm.c,v 1.24 2001/06/27 23:31:39 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -489,15 +489,15 @@ mmblindwrt(char *dbstr, /* * mmnblocks() -- Get the number of blocks stored in a relation. * - * Returns # of blocks or -1 on error. + * Returns # of blocks or InvalidBlockNumber on error. */ -int +BlockNumber mmnblocks(Relation reln) { MMRelTag rtag; MMRelHashEntry *rentry; bool found; - int nblocks; + BlockNumber nblocks; if (reln->rd_rel->relisshared) rtag.mmrt_dbid = (Oid) 0; @@ -520,7 +520,7 @@ mmnblocks(Relation reln) if (found) nblocks = rentry->mmrhe_nblocks; else - nblocks = -1; + nblocks = InvalidBlockNumber; SpinRelease(MMCacheLock); diff --git a/src/backend/storage/smgr/smgr.c b/src/backend/storage/smgr/smgr.c index 25598e3cd5..56edbec60f 100644 --- a/src/backend/storage/smgr/smgr.c +++ b/src/backend/storage/smgr/smgr.c @@ -11,13 +11,14 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.49 2001/05/10 20:38:49 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/storage/smgr/smgr.c,v 1.50 2001/06/27 23:31:39 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "storage/bufmgr.h" +#include "storage/freespace.h" #include "storage/smgr.h" #include "utils/memutils.h" @@ -44,8 +45,8 @@ typedef struct f_smgr char *buffer, bool dofsync); int (*smgr_markdirty) (Relation reln, BlockNumber blkno); int (*smgr_blindmarkdirty) (RelFileNode, BlockNumber blkno); - int (*smgr_nblocks) (Relation reln); - int (*smgr_truncate) (Relation reln, int nblocks); + BlockNumber (*smgr_nblocks) (Relation reln); + BlockNumber (*smgr_truncate) (Relation reln, BlockNumber nblocks); int (*smgr_commit) (void); /* may be NULL */ int (*smgr_abort) (void); /* may be NULL */ int (*smgr_sync) (void); @@ -433,16 +434,10 @@ smgrblindmarkdirty(int16 which, * Returns the number of blocks on success, aborts the current * transaction on failure. */ -int +BlockNumber smgrnblocks(int16 which, Relation reln) { - int nblocks; - - if ((nblocks = (*(smgrsw[which].smgr_nblocks)) (reln)) < 0) - elog(ERROR, "cannot count blocks for %s: %m", - RelationGetRelationName(reln)); - - return nblocks; + return (*(smgrsw[which].smgr_nblocks)) (reln); } /* @@ -452,16 +447,24 @@ smgrnblocks(int16 which, Relation reln) * Returns the number of blocks on success, aborts the current * transaction on failure. */ -int -smgrtruncate(int16 which, Relation reln, int nblocks) +BlockNumber +smgrtruncate(int16 which, Relation reln, BlockNumber nblocks) { - int newblks; + BlockNumber newblks; newblks = nblocks; if (smgrsw[which].smgr_truncate) { - if ((newblks = (*(smgrsw[which].smgr_truncate)) (reln, nblocks)) < 0) - elog(ERROR, "cannot truncate %s to %d blocks: %m", + /* + * Tell the free space map to forget this relation, so that it + * stops caching info about the deleted blocks. XXX perhaps + * tell it to forget only info about blocks beyond nblocks? + */ + FreeSpaceMapForgetRel(&reln->rd_node); + + newblks = (*(smgrsw[which].smgr_truncate)) (reln, nblocks); + if (newblks == InvalidBlockNumber) + elog(ERROR, "cannot truncate %s to %u blocks: %m", RelationGetRelationName(reln), nblocks); } @@ -481,7 +484,6 @@ smgrDoPendingDeletes(bool isCommit) pendingDeletes = pending->next; if (pending->atCommit == isCommit) { - /* * Get rid of any leftover buffers for the rel (shouldn't be * any in the commit case, but there can be in the abort @@ -490,6 +492,13 @@ smgrDoPendingDeletes(bool isCommit) DropRelFileNodeBuffers(pending->relnode); /* + * Tell the free space map to forget this relation. It won't + * be accessed any more anyway, but we may as well recycle the + * map space quickly. + */ + FreeSpaceMapForgetRel(&pending->relnode); + + /* * And delete the physical files. * * Note: we treat deletion failure as a NOTICE, not an error, |
