*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.55 1997/12/19 02:05:33 scrappy Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.68 1998/07/26 04:30:25 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#include <fcntl.h>
#include <unistd.h>
-#include <postgres.h>
-
-#include <fmgr.h>
-#include <utils/portal.h>
-#include <access/genam.h>
-#include <access/heapam.h>
-#include <access/xact.h>
-#include <storage/bufmgr.h>
-#include <access/transam.h>
-#include <catalog/pg_index.h>
-#include <catalog/index.h>
-#include <catalog/catname.h>
-#include <catalog/catalog.h>
-#include <catalog/pg_class.h>
-#include <catalog/pg_proc.h>
-#include <catalog/pg_statistic.h>
-#include <catalog/pg_type.h>
-#include <catalog/pg_operator.h>
-#include <parser/parse_oper.h>
-#include <storage/smgr.h>
-#include <storage/lmgr.h>
-#include <utils/inval.h>
-#include <utils/mcxt.h>
-#include <utils/inval.h>
-#include <utils/syscache.h>
-#include <utils/builtins.h>
-#include <commands/vacuum.h>
-#include <storage/bufpage.h>
+#include "postgres.h"
+
+#include "access/genam.h"
+#include "access/heapam.h"
+#include "access/transam.h"
+#include "access/xact.h"
+#include "catalog/catalog.h"
+#include "catalog/catname.h"
+#include "catalog/index.h"
+#ifdef MULTIBYTE
+#include "catalog/pg_class_mb.h"
+#else
+#include "catalog/pg_class.h"
+#endif
+#include "catalog/pg_index.h"
+#include "catalog/pg_operator.h"
+#include "catalog/pg_statistic.h"
+#include "catalog/pg_type.h"
+#include "commands/vacuum.h"
+#include "fmgr.h"
+#include "parser/parse_oper.h"
+#include "storage/bufmgr.h"
+#include "storage/bufpage.h"
#include "storage/shmem.h"
+#include "storage/smgr.h"
+#include "storage/lmgr.h"
+#include "utils/builtins.h"
+#include "utils/inval.h"
+#include "utils/mcxt.h"
+#include "utils/portal.h"
+#include "utils/syscache.h"
+
#ifndef HAVE_GETRUSAGE
#include <rusagestub.h>
#else
#include <sys/resource.h>
#endif
-/* #include <port-protos.h> */ /* Why? */
+ /* #include <port-protos.h> *//* Why? */
-extern int BlowawayRelationBuffers(Relation rdesc, BlockNumber block);
+extern int BlowawayRelationBuffers(Relation rdesc, BlockNumber block);
bool VacuumRunning = false;
#define swapLong(a,b) {long tmp; tmp=a; a=b; b=tmp;}
#define swapInt(a,b) {int tmp; tmp=a; a=b; b=tmp;}
#define swapDatum(a,b) {Datum tmp; tmp=a; a=b; b=tmp;}
-#define VacAttrStatsEqValid(stats) ( stats->f_cmpeq != NULL )
-#define VacAttrStatsLtGtValid(stats) ( stats->f_cmplt != NULL && \
- stats->f_cmpgt != NULL && \
+#define VacAttrStatsEqValid(stats) ( stats->f_cmpeq.fn_addr != NULL )
+#define VacAttrStatsLtGtValid(stats) ( stats->f_cmplt.fn_addr != NULL && \
+ stats->f_cmpgt.fn_addr != NULL && \
RegProcedureIsValid(stats->outfunc) )
pmem = PortalGetVariableMemory(vc_portal);
old = MemoryContextSwitchTo((MemoryContext) pmem);
- Assert(va_spec == NIL || analyze);
+ if (va_spec != NIL && !analyze)
+ elog(ERROR, "Can't vacuum columns, only tables. You can 'vacuum analyze' columns.");
+
foreach(le, va_spec)
{
char *col = (char *) lfirst(le);
int fd;
if ((fd = open("pg_vlock", O_CREAT | O_EXCL, 0600)) < 0)
- elog(WARN, "can't create lock file -- another vacuum cleaner running?");
+ elog(ERROR, "can't create lock file -- another vacuum cleaner running?");
close(fd);
{
/* on entry, not in a transaction */
if (unlink("pg_vlock") < 0)
- elog(WARN, "vacuum: can't destroy lock file!");
+ elog(ERROR, "vacuum: can't destroy lock file!");
/* okay, we're done */
VacuumRunning = false;
if (VacRelP->data)
{
ScanKeyEntryInitialize(&pgckey, 0x0, Anum_pg_class_relname,
- NameEqualRegProcedure,
+ F_NAMEEQ,
PointerGetDatum(VacRelP->data));
}
else
{
ScanKeyEntryInitialize(&pgckey, 0x0, Anum_pg_class_relkind,
- CharacterEqualRegProcedure, CharGetDatum('r'));
+ F_CHAREQ, CharGetDatum('r'));
}
portalmem = PortalGetVariableMemory(vc_portal);
found = true;
- d = heap_getattr(pgctup, buf, Anum_pg_class_relname, pgcdesc, &n);
+ d = heap_getattr(pgctup, Anum_pg_class_relname, pgcdesc, &n);
rname = (char *) d;
/*
continue;
}
- d = heap_getattr(pgctup, buf, Anum_pg_class_relkind, pgcdesc, &n);
+ d = heap_getattr(pgctup, Anum_pg_class_relkind, pgcdesc, &n);
rkind = DatumGetChar(d);
/* get a relation list entry for this guy */
old = MemoryContextSwitchTo((MemoryContext) portalmem);
if (vrl == (VRelList) NULL)
- {
vrl = cur = (VRelList) palloc(sizeof(VRelListData));
- }
else
{
cur->vrl_next = (VRelList) palloc(sizeof(VRelListData));
StartTransactionCommand();
ScanKeyEntryInitialize(&pgckey, 0x0, ObjectIdAttributeNumber,
- ObjectIdEqualRegProcedure,
+ F_OIDEQ,
ObjectIdGetDatum(relid));
pgclass = heap_openr(RelationRelationName);
List *le;
if (length(va_cols) > attr_cnt)
- elog(WARN, "vacuum: too many attributes specified for relation %s",
+ elog(ERROR, "vacuum: too many attributes specified for relation %s",
(RelationGetRelationName(onerel))->data);
attnums = (int *) palloc(attr_cnt * sizeof(int));
foreach(le, va_cols)
attnums[tcnt++] = i;
else
{
- elog(WARN, "vacuum: there is no attribute %s in %s",
+ elog(ERROR, "vacuum: there is no attribute %s in %s",
col, (RelationGetRelationName(onerel))->data);
}
}
func_operator = oper("=", stats->attr->atttypid, stats->attr->atttypid, true);
if (func_operator != NULL)
{
- int nargs;
-
pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
- fmgr_info(pgopform->oprcode, &(stats->f_cmpeq), &nargs);
+ fmgr_info(pgopform->oprcode, &(stats->f_cmpeq));
}
else
- stats->f_cmpeq = NULL;
+ stats->f_cmpeq.fn_addr = NULL;
func_operator = oper("<", stats->attr->atttypid, stats->attr->atttypid, true);
if (func_operator != NULL)
{
- int nargs;
-
pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
- fmgr_info(pgopform->oprcode, &(stats->f_cmplt), &nargs);
+ fmgr_info(pgopform->oprcode, &(stats->f_cmplt));
}
else
- stats->f_cmplt = NULL;
+ stats->f_cmplt.fn_addr = NULL;
func_operator = oper(">", stats->attr->atttypid, stats->attr->atttypid, true);
if (func_operator != NULL)
{
- int nargs;
-
pgopform = (OperatorTupleForm) GETSTRUCT(func_operator);
- fmgr_info(pgopform->oprcode, &(stats->f_cmpgt), &nargs);
+ fmgr_info(pgopform->oprcode, &(stats->f_cmpgt));
}
else
- stats->f_cmpgt = NULL;
+ stats->f_cmpgt.fn_addr = NULL;
pgttup = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(stats->attr->atttypid),
vpc = (VPageDescr) palloc(sizeof(VPageDescrData) + MaxOffsetNumber * sizeof(OffsetNumber));
vpc->vpd_nusd = 0;
+ elog(MESSAGE_LEVEL, "--Relation %s--", relname);
+
for (blkno = 0; blkno < nblocks; blkno++)
{
buf = ReadBuffer(onerel, blkno);
}
else if (!TransactionIdIsInProgress(htup->t_xmin))
{
+
/*
- * Not Aborted, Not Committed, Not in Progress -
+ * Not Aborted, Not Committed, Not in Progress -
* so it's from crashed process. - vadim 11/26/96
*/
ncrash++;
}
}
- /*
- * here we are concerned about tuples with xmin committed
- * and xmax unknown or committed
+ /*
+ * here we are concerned about tuples with xmin committed and
+ * xmax unknown or committed
*/
- if (htup->t_infomask & HEAP_XMIN_COMMITTED &&
+ if (htup->t_infomask & HEAP_XMIN_COMMITTED &&
!(htup->t_infomask & HEAP_XMAX_INVALID))
{
if (htup->t_infomask & HEAP_XMAX_COMMITTED)
tupgone = true;
else if (!TransactionIdIsInProgress(htup->t_xmax))
{
+
/*
* Not Aborted, Not Committed, Not in Progress - so it
* from crashed process. - vadim 06/02/97
getrusage(RUSAGE_SELF, &ru1);
- elog(MESSAGE_LEVEL, "Rel %s: Pages %u: Changed %u, Reapped %u, Empty %u, New %u; \
+ elog(MESSAGE_LEVEL, "Pages %u: Changed %u, Reapped %u, Empty %u, New %u; \
Tup %u: Vac %u, Crash %u, UnUsed %u, MinLen %u, MaxLen %u; Re-using: Free/Avail. Space %u/%u; EndEmpty/Avail. Pages %u/%u. Elapsed %u/%u sec.",
- relname,
nblocks, nchpg, Vvpl->vpl_npages, nempg, nnepg,
ntups, nvac, ncrash, nunused, min_tlen, max_tlen,
frsize, frsusf, nemend, Fvpl->vpl_npages,
ru1.ru_stime.tv_sec - ru0.ru_stime.tv_sec,
ru1.ru_utime.tv_sec - ru0.ru_utime.tv_sec);
-} /* vc_scanheap */
+} /* vc_scanheap */
/*
dowrite = true;
}
else
- {
Assert(isempty);
- }
--Vnpages;
Assert(Vnpages > 0);
/* get prev reapped page from Vvpl */
}
}
else
- {
Assert(!isempty);
- }
vpc->vpd_blkno = blkno;
maxoff = PageGetMaxOffsetNumber(page);
/*
* If no one tuple can't be added to this page -
* remove page from Fvpl. - vadim 11/27/96
+ *
+ * But we can't remove last page - this is our
+ * "show-stopper" !!! - vadim 02/25/98
*/
- if (!vc_enough_space(ToVpd, vacrelstats->min_tlen))
+ if (ToVpd != Fvplast &&
+ !vc_enough_space(ToVpd, vacrelstats->min_tlen))
{
- if (ToVpd != Fvplast)
- {
- Assert(Fnpages > ToVpI + 1);
- memmove(Fvpl->vpl_pgdesc + ToVpI,
- Fvpl->vpl_pgdesc + ToVpI + 1,
- sizeof(VPageDescr *) * (Fnpages - ToVpI - 1));
- }
- Assert(Fnpages >= 1);
+ Assert(Fnpages > ToVpI + 1);
+ memmove(Fvpl->vpl_pgdesc + ToVpI,
+ Fvpl->vpl_pgdesc + ToVpI + 1,
+ sizeof(VPageDescr *) * (Fnpages - ToVpI - 1));
Fnpages--;
- if (Fnpages == 0)
- break;
- /* get prev reapped page from Fvpl */
- Fvplast = Fvpl->vpl_pgdesc[Fnpages - 1];
- Fblklast = Fvplast->vpd_blkno;
+ Assert(Fvplast == Fvpl->vpl_pgdesc[Fnpages - 1]);
}
}
for (i = 0; i < Fnpages; i++)
InvalidOffsetNumber, LP_USED);
if (newoff == InvalidOffsetNumber)
{
- elog(WARN, "\
+ elog(ERROR, "\
failed to add item with len = %u to page %u (free space %u, nusd %u, noff %u)",
tlen, ToVpd->vpd_blkno, ToVpd->vpd_free,
ToVpd->vpd_nusd, ToVpd->vpd_noff);
{
i = BlowawayRelationBuffers(onerel, blkno);
if (i < 0)
- elog (FATAL, "VACUUM (vc_rpfheap): BlowawayRelationBuffers returned %d", i);
+ elog(FATAL, "VACUUM (vc_rpfheap): BlowawayRelationBuffers returned %d", i);
blkno = smgrtruncate(DEFAULT_SMGR, onerel, blkno);
Assert(blkno >= 0);
vacrelstats->npages = blkno; /* set new number of blocks */
pfree(vpc);
-} /* vc_rpfheap */
+} /* vc_rpfheap */
/*
* vc_vacheap() -- free dead tuples
int i;
nblocks = Vvpl->vpl_npages;
- nblocks -= Vvpl->vpl_nemend; /* nothing to do with them */
+ nblocks -= Vvpl->vpl_nemend;/* nothing to do with them */
for (i = 0, vpp = Vvpl->vpl_pgdesc; i < nblocks; i++, vpp++)
{
* it) before truncation
*/
FlushBufferPool(!TransactionFlushEnabled());
-
+
i = BlowawayRelationBuffers(onerel, nblocks);
if (i < 0)
- elog (FATAL, "VACUUM (vc_vacheap): BlowawayRelationBuffers returned %d", i);
+ elog(FATAL, "VACUUM (vc_vacheap): BlowawayRelationBuffers returned %d", i);
nblocks = smgrtruncate(DEFAULT_SMGR, onerel, nblocks);
Assert(nblocks >= 0);
vacrelstats->npages = nblocks; /* set new number of blocks */
}
-} /* vc_vacheap */
+} /* vc_vacheap */
/*
* vc_vacpage() -- free dead tuples on a page
}
PageRepairFragmentation(page);
-} /* vc_vacpage */
+} /* vc_vacpage */
/*
* _vc_scanoneind() -- scan one index relation to update statistic.
elog(NOTICE, "Ind %s: NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
indrel->rd_rel->relname.data, nitups, nhtups);
-} /* vc_scanoneind */
+} /* vc_scanoneind */
/*
* vc_vaconeind() -- vacuum one index relation.
index_delete(indrel, &res->index_iptr);
}
else
- {
nitups++;
- }
/* be tidy */
pfree(res);
elog(NOTICE, "Ind %s: NUMBER OF INDEX' TUPLES (%u) IS NOT THE SAME AS HEAP' (%u)",
indrel->rd_rel->relname.data, nitups, nhtups);
-} /* vc_vaconeind */
+} /* vc_vaconeind */
/*
* vc_tidreapped() -- is a particular tid reapped?
return (vp);
-} /* vc_tidreapped */
+} /* vc_tidreapped */
/*
* vc_attrstats() -- compute column statistics used by the optimzer
VacAttrStats *stats = &vacattrstats[i];
bool value_hit = true;
- value = heap_getattr(htup, InvalidBuffer,
+ value = heap_getattr(htup,
stats->attr->attnum, tupDesc, &isnull);
if (!VacAttrStatsEqValid(stats))
}
if (VacAttrStatsLtGtValid(stats))
{
- if ((*(stats->f_cmplt)) (value, stats->min))
+ if ((*fmgr_faddr(&stats->f_cmplt)) (value, stats->min))
{
vc_bucketcpy(stats->attr, value, &stats->min, &stats->min_len);
stats->min_cnt = 0;
}
- if ((*(stats->f_cmpgt)) (value, stats->max))
+ if ((*fmgr_faddr(&stats->f_cmpgt)) (value, stats->max))
{
vc_bucketcpy(stats->attr, value, &stats->max, &stats->max_len);
stats->max_cnt = 0;
}
- if ((*(stats->f_cmpeq)) (value, stats->min))
+ if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->min))
stats->min_cnt++;
- else if ((*(stats->f_cmpeq)) (value, stats->max))
+ else if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->max))
stats->max_cnt++;
}
- if ((*(stats->f_cmpeq)) (value, stats->best))
+ if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->best))
stats->best_cnt++;
- else if ((*(stats->f_cmpeq)) (value, stats->guess1))
+ else if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->guess1))
{
stats->guess1_cnt++;
stats->guess1_hits++;
}
- else if ((*(stats->f_cmpeq)) (value, stats->guess2))
+ else if ((*fmgr_faddr(&stats->f_cmpeq)) (value, stats->guess2))
stats->guess2_hits++;
else
value_hit = false;
* update number of tuples and number of pages in pg_class
*/
ScanKeyEntryInitialize(&rskey, 0x0, ObjectIdAttributeNumber,
- ObjectIdEqualRegProcedure,
+ F_OIDEQ,
ObjectIdGetDatum(relid));
rd = heap_openr(RelationRelationName);
rsdesc = heap_beginscan(rd, false, false, 1, &rskey);
if (!HeapTupleIsValid(rtup = heap_getnext(rsdesc, 0, &rbuf)))
- elog(WARN, "pg_class entry for relid %d vanished during vacuuming",
+ elog(ERROR, "pg_class entry for relid %d vanished during vacuuming",
relid);
/* overwrite the existing statistics in the tuple */
*
pgcform->relname.data) */ )
{
- func_ptr out_function;
+ FmgrInfo out_function;
char *out_string;
- int dummy;
for (i = 0; i < Natts_pg_statistic; ++i)
nulls[i] = ' ';
values[i++] = (Datum) relid; /* 1 */
values[i++] = (Datum) attp->attnum; /* 2 */
values[i++] = (Datum) InvalidOid; /* 3 */
- fmgr_info(stats->outfunc, &out_function, &dummy);
- out_string = (*out_function) (stats->min, stats->attr->atttypid);
- values[i++] = (Datum) fmgr(TextInRegProcedure, out_string);
+ fmgr_info(stats->outfunc, &out_function);
+ out_string = (*fmgr_faddr(&out_function)) (stats->min, stats->attr->atttypid);
+ values[i++] = (Datum) fmgr(F_TEXTIN, out_string);
pfree(out_string);
- out_string = (char *) (*out_function) (stats->max, stats->attr->atttypid);
- values[i++] = (Datum) fmgr(TextInRegProcedure, out_string);
+ out_string = (char *) (*fmgr_faddr(&out_function)) (stats->max, stats->attr->atttypid);
+ values[i++] = (Datum) fmgr(F_TEXTIN, out_string);
pfree(out_string);
sdesc = sd->rd_att;
if (relid != InvalidOid)
{
ScanKeyEntryInitialize(&pgskey, 0x0, Anum_pg_statistic_starelid,
- ObjectIdEqualRegProcedure,
+ F_OIDEQ,
ObjectIdGetDatum(relid));
pgsscan = heap_beginscan(pgstatistic, false, false, 1, &pgskey);
}
/* insert this page into vpl list */
vc_vpinsert(vpl, newvpd);
-} /* vc_reappage */
+} /* vc_reappage */
static void
vc_vpinsert(VPageList vpl, VPageDescr vpnew)
first_move = true;
}
-} /* vc_find_eq */
+} /* vc_find_eq */
static int
vc_cmp_blk(char *left, char *right)
return (0);
return (1);
-} /* vc_cmp_blk */
+} /* vc_cmp_blk */
static int
vc_cmp_offno(char *left, char *right)
return (0);
return (1);
-} /* vc_cmp_offno */
+} /* vc_cmp_offno */
static void
pgidesc = RelationGetTupleDescriptor(pgindex);
ScanKeyEntryInitialize(&pgikey, 0x0, Anum_pg_index_indrelid,
- ObjectIdEqualRegProcedure,
+ F_OIDEQ,
ObjectIdGetDatum(relid));
pgiscan = heap_beginscan(pgindex, false, false, 1, &pgikey);
while (HeapTupleIsValid(pgitup = heap_getnext(pgiscan, 0, NULL)))
{
- d = heap_getattr(pgitup, InvalidBuffer, Anum_pg_index_indexrelid,
+ d = heap_getattr(pgitup, Anum_pg_index_indexrelid,
pgidesc, &n);
i++;
if (i % 10 == 0)
*Irel = (Relation *) NULL;
}
-} /* vc_getindices */
+} /* vc_getindices */
static void
return;
while (nindices--)
- {
index_close(Irel[nindices]);
- }
pfree(Irel);
-} /* vc_clsindices */
+} /* vc_clsindices */
static void
idcur->natts = natts;
}
-} /* vc_mkindesc */
+} /* vc_mkindesc */
static bool
return (false);
-} /* vc_enough_space */
+} /* vc_enough_space */