Thread

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

    Ole Gjerde <gjerde@icebox.org> — 1999-05-24T06:42:10Z

    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;