summaryrefslogtreecommitdiff
path: root/src/backend/storage
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage')
-rw-r--r--src/backend/storage/Makefile4
-rw-r--r--src/backend/storage/freespace/Makefile30
-rw-r--r--src/backend/storage/freespace/freespace.c183
-rw-r--r--src/backend/storage/ipc/ipci.c16
-rw-r--r--src/backend/storage/ipc/spin.c27
-rw-r--r--src/backend/storage/lmgr/lock.c14
-rw-r--r--src/backend/storage/smgr/md.c99
-rw-r--r--src/backend/storage/smgr/mm.c10
-rw-r--r--src/backend/storage/smgr/smgr.c43
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,