Vacuum/mdtruncate() (was: RE: [HACKERS] Current TODO list)

Ole Gjerde <gjerde@icebox.org>

From: Ole Gjerde <gjerde@icebox.org>
To: Hiroshi Inoue <Inoue@tpf.co.jp>
Cc: Bruce Momjian <maillist@candle.pha.pa.us>, PostgreSQL-development <pgsql-hackers@postgreSQL.org>
Date: 1999-05-24T06:42:10Z
Lists: pgsql-hackers
On Mon, 24 May 1999, Hiroshi Inoue wrote:
> Backends would continue to access the file descritors already hold
> if vacuum does nothing about the invalidation of Relation Cache.

Yes, and I don't believe that is a problem.  I may be wrong however...

First, please reverse my patch to mdtruncate() in md.c as soon as
possible.  It does not work properly in some cases.

Second, I do have a better patch in the works.  It is included below, but
DO NOT APPLY THIS!!!  I would like someone to look it over quick.  I have
checked the logic by hand for a few cases and done a bunch of tests.  I
would like to test more first.

While doing a bunch of vacuums, I have seen some strange things(so my
patch probably isn't 100%).
I started with 58 segments, and did a bunch of delete/vacuums and got it
down to about 5-6.  Then I got the error below while running a vacuum
analyze.  This appeared after the index clean, but before any tuples were
moved.
ERROR:  HEAP_MOVED_IN was not expected

Also, I was seeing some more errors about INDEX' TUPLES being higher than
HEAP TUPLES.  Didn't this just get fixed, or did I break something with my
patch.  I was seeing these after doing delete/vacuums with my patch.

Thanks,
Ole Gjerde

Index: src/backend/storage/smgr/md.c
===================================================================
RCS file: /usr/local/cvsroot/pgsql/src/backend/storage/smgr/md.c,v
retrieving revision 1.43
diff -u -r1.43 md.c
--- src/backend/storage/smgr/md.c	1999/05/17 06:38:41	1.43
+++ src/backend/storage/smgr/md.c	1999/05/24 06:30:25
@@ -712,32 +712,62 @@
 
 #ifndef LET_OS_MANAGE_FILESIZE
 	int			curnblk,
-					i,
 					oldsegno,
-					newsegno;
-	char		fname[NAMEDATALEN];
-	char		tname[NAMEDATALEN + 10];
+					newsegno,
+					lastsegblocks,
+					segcount = 0;
+	MdfdVec		*ov,
+				*lastv;
+	MemoryContext	oldcxt;
 
+	fd = RelationGetFile(reln);
 	curnblk = mdnblocks(reln);
-	oldsegno = curnblk / RELSEG_SIZE;
-	newsegno = nblocks / RELSEG_SIZE;
 
-	StrNCpy(fname, RelationGetRelationName(reln)->data, NAMEDATALEN);
+	oldsegno = (curnblk / RELSEG_SIZE) + 1;
+	newsegno = (nblocks / RELSEG_SIZE) + 1;
+	oldcxt = MemoryContextSwitchTo(MdCxt);
 
-	if (newsegno < oldsegno) {
-		for (i = (newsegno + 1);; i++) {
-			sprintf(tname, "%s.%d", fname, i);
-			if (FileNameUnlink(tname) < 0)
-				break;
+	if (newsegno < oldsegno && newsegno > 1)
+	{
+		lastv = v = &Md_fdvec[fd];
+		for (segcount = 1; v != (MdfdVec *) NULL;segcount++, v = v->mdfd_chain)
+		{
+			if(segcount == newsegno) /* Save pointer to last file
+						    in the chain */
+				lastv = v;
+                        if(segcount > newsegno)
+			{
+				FileUnlink(v->mdfd_vfd);
+				ov = v;
+				if (ov != &Md_fdvec[fd])
+					pfree(ov);
+			}
 		}
+		lastv->mdfd_chain = (MdfdVec *) NULL;
         }
-#endif
 
+	/* Find the last file in the md chain */
+	for (v = &Md_fdvec[fd]; v->mdfd_chain != (MdfdVec *) NULL;)
+		v = v->mdfd_chain;
+
+	/* Calculate the # of blocks in the last segment */
+	lastsegblocks = nblocks - ((newsegno - 1) * RELSEG_SIZE);
+
+	MemoryContextSwitchTo(oldcxt);
+
+	if (FileTruncate(v->mdfd_vfd, lastsegblocks * BLCKSZ) < 0)
+		return -1;
+
+#else
+
 	fd = RelationGetFile(reln);
+
 	v = &Md_fdvec[fd];
 
 	if (FileTruncate(v->mdfd_vfd, nblocks * BLCKSZ) < 0)
 		return -1;
+
+#endif
 
 	return nblocks;