mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
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.
This commit is contained in:
@@ -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
|
||||
|
||||
30
src/backend/storage/freespace/Makefile
Normal file
30
src/backend/storage/freespace/Makefile
Normal file
@@ -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
|
||||
183
src/backend/storage/freespace/freespace.c
Normal file
183
src/backend/storage/freespace/freespace.c
Normal file
@@ -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 */
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -489,6 +491,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.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user