From f41551f61f9cf4eedd5b7173f985a3bdb4d9858c Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Mon, 18 Mar 2019 13:57:33 -0400 Subject: [PATCH] Fold vacuum's 'int options' parameter into VacuumParams. Many places need both, so this allows a few functions to take one fewer parameter. More importantly, as soon as we add a VACUUM option that takes a non-Boolean parameter, we need to replace 'int options' with a struct, and it seems better to think of adding more fields to VacuumParams rather than passing around both VacuumParams and a separate struct as well. Patch by me, reviewed by Masahiko Sawada Discussion: http://postgr.es/m/CA+Tgmob6g6-s50fyv8E8he7APfwCYYJ4z0wbZC2yZeSz=26CYQ@mail.gmail.com --- src/backend/access/heap/vacuumlazy.c | 8 +-- src/backend/commands/analyze.c | 24 ++++----- src/backend/commands/vacuum.c | 74 ++++++++++++++-------------- src/backend/postmaster/autovacuum.c | 11 ++--- src/include/access/heapam.h | 2 +- src/include/commands/vacuum.h | 7 +-- 6 files changed, 63 insertions(+), 63 deletions(-) diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index 9416c31889..5c554f9465 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -186,7 +186,7 @@ static bool heap_page_is_all_visible(Relation rel, Buffer buf, * and locked the relation. */ void -heap_vacuum_rel(Relation onerel, int options, VacuumParams *params, +heap_vacuum_rel(Relation onerel, VacuumParams *params, BufferAccessStrategy bstrategy) { LVRelStats *vacrelstats; @@ -217,7 +217,7 @@ heap_vacuum_rel(Relation onerel, int options, VacuumParams *params, starttime = GetCurrentTimestamp(); } - if (options & VACOPT_VERBOSE) + if (params->options & VACOPT_VERBOSE) elevel = INFO; else elevel = DEBUG2; @@ -245,7 +245,7 @@ heap_vacuum_rel(Relation onerel, int options, VacuumParams *params, xidFullScanLimit); aggressive |= MultiXactIdPrecedesOrEquals(onerel->rd_rel->relminmxid, mxactFullScanLimit); - if (options & VACOPT_DISABLE_PAGE_SKIPPING) + if (params->options & VACOPT_DISABLE_PAGE_SKIPPING) aggressive = true; vacrelstats = (LVRelStats *) palloc0(sizeof(LVRelStats)); @@ -261,7 +261,7 @@ heap_vacuum_rel(Relation onerel, int options, VacuumParams *params, vacrelstats->hasindex = (nindexes > 0); /* Do the vacuuming */ - lazy_scan_heap(onerel, options, vacrelstats, Irel, nindexes, aggressive); + lazy_scan_heap(onerel, params->options, vacrelstats, Irel, nindexes, aggressive); /* Done with indexes */ vac_close_indexes(nindexes, Irel, NoLock); diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c index c8192353eb..3465713d10 100644 --- a/src/backend/commands/analyze.c +++ b/src/backend/commands/analyze.c @@ -84,7 +84,7 @@ static MemoryContext anl_context = NULL; static BufferAccessStrategy vac_strategy; -static void do_analyze_rel(Relation onerel, int options, +static void do_analyze_rel(Relation onerel, VacuumParams *params, List *va_cols, AcquireSampleRowsFunc acquirefunc, BlockNumber relpages, bool inh, bool in_outer_xact, int elevel); @@ -115,7 +115,7 @@ static Datum ind_fetch_func(VacAttrStatsP stats, int rownum, bool *isNull); * use it once we've successfully opened the rel, since it might be stale. */ void -analyze_rel(Oid relid, RangeVar *relation, int options, +analyze_rel(Oid relid, RangeVar *relation, VacuumParams *params, List *va_cols, bool in_outer_xact, BufferAccessStrategy bstrategy) { @@ -125,7 +125,7 @@ analyze_rel(Oid relid, RangeVar *relation, int options, BlockNumber relpages = 0; /* Select logging level */ - if (options & VACOPT_VERBOSE) + if (params->options & VACOPT_VERBOSE) elevel = INFO; else elevel = DEBUG2; @@ -147,8 +147,8 @@ analyze_rel(Oid relid, RangeVar *relation, int options, * * Make sure to generate only logs for ANALYZE in this case. */ - onerel = vacuum_open_relation(relid, relation, params, - options & ~(VACOPT_VACUUM), + onerel = vacuum_open_relation(relid, relation, params->options & ~(VACOPT_VACUUM), + params->log_min_duration >= 0, ShareUpdateExclusiveLock); /* leave if relation could not be opened or locked */ @@ -165,7 +165,7 @@ analyze_rel(Oid relid, RangeVar *relation, int options, */ if (!vacuum_is_relation_owner(RelationGetRelid(onerel), onerel->rd_rel, - options & VACOPT_ANALYZE)) + params->options & VACOPT_ANALYZE)) { relation_close(onerel, ShareUpdateExclusiveLock); return; @@ -237,7 +237,7 @@ analyze_rel(Oid relid, RangeVar *relation, int options, else { /* No need for a WARNING if we already complained during VACUUM */ - if (!(options & VACOPT_VACUUM)) + if (!(params->options & VACOPT_VACUUM)) ereport(WARNING, (errmsg("skipping \"%s\" --- cannot analyze non-tables or special system tables", RelationGetRelationName(onerel)))); @@ -257,14 +257,14 @@ analyze_rel(Oid relid, RangeVar *relation, int options, * tables, which don't contain any rows. */ if (onerel->rd_rel->relkind != RELKIND_PARTITIONED_TABLE) - do_analyze_rel(onerel, options, params, va_cols, acquirefunc, + do_analyze_rel(onerel, params, va_cols, acquirefunc, relpages, false, in_outer_xact, elevel); /* * If there are child tables, do recursive ANALYZE. */ if (onerel->rd_rel->relhassubclass) - do_analyze_rel(onerel, options, params, va_cols, acquirefunc, relpages, + do_analyze_rel(onerel, params, va_cols, acquirefunc, relpages, true, in_outer_xact, elevel); /* @@ -292,7 +292,7 @@ analyze_rel(Oid relid, RangeVar *relation, int options, * appropriate acquirefunc for each child table. */ static void -do_analyze_rel(Relation onerel, int options, VacuumParams *params, +do_analyze_rel(Relation onerel, VacuumParams *params, List *va_cols, AcquireSampleRowsFunc acquirefunc, BlockNumber relpages, bool inh, bool in_outer_xact, int elevel) @@ -603,7 +603,7 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params, * VACUUM ANALYZE, don't overwrite the accurate count already inserted by * VACUUM. */ - if (!inh && !(options & VACOPT_VACUUM)) + if (!inh && !(params->options & VACOPT_VACUUM)) { for (ind = 0; ind < nindexes; ind++) { @@ -634,7 +634,7 @@ do_analyze_rel(Relation onerel, int options, VacuumParams *params, (va_cols == NIL)); /* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */ - if (!(options & VACOPT_VACUUM)) + if (!(params->options & VACOPT_VACUUM)) { for (ind = 0; ind < nindexes; ind++) { diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 1b5b50cf01..be03185a7f 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -74,8 +74,7 @@ static void vac_truncate_clog(TransactionId frozenXID, MultiXactId minMulti, TransactionId lastSaneFrozenXid, MultiXactId lastSaneMinMulti); -static bool vacuum_rel(Oid relid, RangeVar *relation, int options, - VacuumParams *params); +static bool vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params); /* * Primary entry point for manual VACUUM and ANALYZE commands @@ -112,6 +111,9 @@ ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel) } } + /* copy options from parse tree */ + params.options = vacstmt->options; + /* * All freeze ages are zero if the FREEZE option is given; otherwise pass * them as -1 which means to use the default values. @@ -138,14 +140,12 @@ ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel) params.log_min_duration = -1; /* Now go through the common routine */ - vacuum(vacstmt->options, vacstmt->rels, ¶ms, NULL, isTopLevel); + vacuum(vacstmt->rels, ¶ms, NULL, isTopLevel); } /* * Internal entry point for VACUUM and ANALYZE commands. * - * options is a bitmask of VacuumOption flags, indicating what to do. - * * relations, if not NIL, is a list of VacuumRelation to process; otherwise, * we process all relevant tables in the database. For each VacuumRelation, * if a valid OID is supplied, the table with that OID is what to process; @@ -163,7 +163,7 @@ ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel) * memory context that will not disappear at transaction commit. */ void -vacuum(int options, List *relations, VacuumParams *params, +vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, bool isTopLevel) { static bool in_vacuum = false; @@ -174,7 +174,7 @@ vacuum(int options, List *relations, VacuumParams *params, Assert(params != NULL); - stmttype = (options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE"; + stmttype = (params->options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE"; /* * We cannot run VACUUM inside a user transaction block; if we were inside @@ -184,7 +184,7 @@ vacuum(int options, List *relations, VacuumParams *params, * * ANALYZE (without VACUUM) can run either way. */ - if (options & VACOPT_VACUUM) + if (params->options & VACOPT_VACUUM) { PreventInTransactionBlock(isTopLevel, stmttype); in_outer_xact = false; @@ -206,8 +206,8 @@ vacuum(int options, List *relations, VacuumParams *params, /* * Sanity check DISABLE_PAGE_SKIPPING option. */ - if ((options & VACOPT_FULL) != 0 && - (options & VACOPT_DISABLE_PAGE_SKIPPING) != 0) + if ((params->options & VACOPT_FULL) != 0 && + (params->options & VACOPT_DISABLE_PAGE_SKIPPING) != 0) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL"))); @@ -216,7 +216,7 @@ vacuum(int options, List *relations, VacuumParams *params, * Send info about dead objects to the statistics collector, unless we are * in autovacuum --- autovacuum.c does this for itself. */ - if ((options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess()) + if ((params->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess()) pgstat_vacuum_stat(); /* @@ -257,7 +257,7 @@ vacuum(int options, List *relations, VacuumParams *params, List *sublist; MemoryContext old_context; - sublist = expand_vacuum_rel(vrel, options); + sublist = expand_vacuum_rel(vrel, params->options); old_context = MemoryContextSwitchTo(vac_context); newrels = list_concat(newrels, sublist); MemoryContextSwitchTo(old_context); @@ -265,7 +265,7 @@ vacuum(int options, List *relations, VacuumParams *params, relations = newrels; } else - relations = get_all_vacuum_rels(options); + relations = get_all_vacuum_rels(params->options); /* * Decide whether we need to start/commit our own transactions. @@ -281,11 +281,11 @@ vacuum(int options, List *relations, VacuumParams *params, * transaction block, and also in an autovacuum worker, use own * transactions so we can release locks sooner. */ - if (options & VACOPT_VACUUM) + if (params->options & VACOPT_VACUUM) use_own_xacts = true; else { - Assert(options & VACOPT_ANALYZE); + Assert(params->options & VACOPT_ANALYZE); if (IsAutoVacuumWorkerProcess()) use_own_xacts = true; else if (in_outer_xact) @@ -335,13 +335,13 @@ vacuum(int options, List *relations, VacuumParams *params, { VacuumRelation *vrel = lfirst_node(VacuumRelation, cur); - if (options & VACOPT_VACUUM) + if (params->options & VACOPT_VACUUM) { - if (!vacuum_rel(vrel->oid, vrel->relation, options, params)) + if (!vacuum_rel(vrel->oid, vrel->relation, params)) continue; } - if (options & VACOPT_ANALYZE) + if (params->options & VACOPT_ANALYZE) { /* * If using separate xacts, start one for analyze. Otherwise, @@ -354,7 +354,7 @@ vacuum(int options, List *relations, VacuumParams *params, PushActiveSnapshot(GetTransactionSnapshot()); } - analyze_rel(vrel->oid, vrel->relation, options, params, + analyze_rel(vrel->oid, vrel->relation, params, vrel->va_cols, in_outer_xact, vac_strategy); if (use_own_xacts) @@ -390,7 +390,7 @@ vacuum(int options, List *relations, VacuumParams *params, StartTransactionCommand(); } - if ((options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess()) + if ((params->options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess()) { /* * Update pg_database.datfrozenxid, and truncate pg_xact if possible. @@ -490,14 +490,13 @@ vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, int options) * or locked, a log is emitted if possible. */ Relation -vacuum_open_relation(Oid relid, RangeVar *relation, VacuumParams *params, - int options, LOCKMODE lmode) +vacuum_open_relation(Oid relid, RangeVar *relation, int options, + bool verbose, LOCKMODE lmode) { Relation onerel; bool rel_lock = true; int elevel; - Assert(params != NULL); Assert((options & (VACOPT_VACUUM | VACOPT_ANALYZE)) != 0); /* @@ -538,13 +537,12 @@ vacuum_open_relation(Oid relid, RangeVar *relation, VacuumParams *params, /* * Determine the log level. * - * For autovacuum logs, we emit a LOG if log_autovacuum_min_duration is - * not disabled. For manual VACUUM or ANALYZE, we emit a WARNING to match - * the log statements in the permission checks. + * For manual VACUUM or ANALYZE, we emit a WARNING to match the log statements + * in the permission checks; otherwise, only log if the caller so requested. */ if (!IsAutoVacuumWorkerProcess()) elevel = WARNING; - else if (params->log_min_duration >= 0) + else if (verbose) elevel = LOG; else return NULL; @@ -1521,7 +1519,7 @@ vac_truncate_clog(TransactionId frozenXID, * At entry and exit, we are not inside a transaction. */ static bool -vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) +vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params) { LOCKMODE lmode; Relation onerel; @@ -1542,7 +1540,7 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) */ PushActiveSnapshot(GetTransactionSnapshot()); - if (!(options & VACOPT_FULL)) + if (!(params->options & VACOPT_FULL)) { /* * In lazy vacuum, we can set the PROC_IN_VACUUM flag, which lets @@ -1582,10 +1580,12 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) * vacuum, but just ShareUpdateExclusiveLock for concurrent vacuum. Either * way, we can be sure that no other backend is vacuuming the same table. */ - lmode = (options & VACOPT_FULL) ? AccessExclusiveLock : ShareUpdateExclusiveLock; + lmode = (params->options & VACOPT_FULL) ? + AccessExclusiveLock : ShareUpdateExclusiveLock; /* open the relation and get the appropriate lock on it */ - onerel = vacuum_open_relation(relid, relation, params, options, lmode); + onerel = vacuum_open_relation(relid, relation, params->options, + params->log_min_duration >= 0, lmode); /* leave if relation could not be opened or locked */ if (!onerel) @@ -1605,7 +1605,7 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) */ if (!vacuum_is_relation_owner(RelationGetRelid(onerel), onerel->rd_rel, - options & VACOPT_VACUUM)) + params->options & VACOPT_VACUUM)) { relation_close(onerel, lmode); PopActiveSnapshot(); @@ -1677,7 +1677,7 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) * us to process it. In VACUUM FULL, though, the toast table is * automatically rebuilt by cluster_rel so we shouldn't recurse to it. */ - if (!(options & VACOPT_SKIPTOAST) && !(options & VACOPT_FULL)) + if (!(params->options & VACOPT_SKIPTOAST) && !(params->options & VACOPT_FULL)) toast_relid = onerel->rd_rel->reltoastrelid; else toast_relid = InvalidOid; @@ -1696,7 +1696,7 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) /* * Do the actual work --- either FULL or "lazy" vacuum */ - if (options & VACOPT_FULL) + if (params->options & VACOPT_FULL) { int cluster_options = 0; @@ -1704,14 +1704,14 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) relation_close(onerel, NoLock); onerel = NULL; - if ((options & VACOPT_VERBOSE) != 0) + if ((params->options & VACOPT_VERBOSE) != 0) cluster_options |= CLUOPT_VERBOSE; /* VACUUM FULL is now a variant of CLUSTER; see cluster.c */ cluster_rel(relid, InvalidOid, cluster_options); } else - heap_vacuum_rel(onerel, options, params, vac_strategy); + heap_vacuum_rel(onerel, params, vac_strategy); /* Roll back any GUC changes executed by index functions */ AtEOXact_GUC(false, save_nestlevel); @@ -1737,7 +1737,7 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params) * totally unimportant for toast relations. */ if (toast_relid != InvalidOid) - vacuum_rel(toast_relid, NULL, options, params); + vacuum_rel(toast_relid, NULL, params); /* * Now release the session-level lock on the master table. diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 3bfac919c4..fa875db816 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -188,7 +188,6 @@ typedef struct av_relation typedef struct autovac_table { Oid at_relid; - int at_vacoptions; /* bitmask of VacuumOption */ VacuumParams at_params; double at_vacuum_cost_delay; int at_vacuum_cost_limit; @@ -2482,7 +2481,7 @@ do_autovacuum(void) * next table in our list. */ HOLD_INTERRUPTS(); - if (tab->at_vacoptions & VACOPT_VACUUM) + if (tab->at_params.options & VACOPT_VACUUM) errcontext("automatic vacuum of table \"%s.%s.%s\"", tab->at_datname, tab->at_nspname, tab->at_relname); else @@ -2883,7 +2882,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map, tab = palloc(sizeof(autovac_table)); tab->at_relid = relid; tab->at_sharedrel = classForm->relisshared; - tab->at_vacoptions = VACOPT_SKIPTOAST | + tab->at_params.options = VACOPT_SKIPTOAST | (dovacuum ? VACOPT_VACUUM : 0) | (doanalyze ? VACOPT_ANALYZE : 0) | (!wraparound ? VACOPT_SKIP_LOCKED : 0); @@ -3110,7 +3109,7 @@ autovacuum_do_vac_analyze(autovac_table *tab, BufferAccessStrategy bstrategy) rel = makeVacuumRelation(rangevar, tab->at_relid, NIL); rel_list = list_make1(rel); - vacuum(tab->at_vacoptions, rel_list, &tab->at_params, bstrategy, true); + vacuum(rel_list, &tab->at_params, bstrategy, true); } /* @@ -3132,10 +3131,10 @@ autovac_report_activity(autovac_table *tab) int len; /* Report the command and possible options */ - if (tab->at_vacoptions & VACOPT_VACUUM) + if (tab->at_params.options & VACOPT_VACUUM) snprintf(activity, MAX_AUTOVAC_ACTIV_LEN, "autovacuum: VACUUM%s", - tab->at_vacoptions & VACOPT_ANALYZE ? " ANALYZE" : ""); + tab->at_params.options & VACOPT_ANALYZE ? " ANALYZE" : ""); else snprintf(activity, MAX_AUTOVAC_ACTIV_LEN, "autovacuum: ANALYZE"); diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 1b6607fe90..eb9e160bfd 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -217,7 +217,7 @@ extern Size SyncScanShmemSize(void); /* in heap/vacuumlazy.c */ struct VacuumParams; -extern void heap_vacuum_rel(Relation onerel, int options, +extern void heap_vacuum_rel(Relation onerel, struct VacuumParams *params, BufferAccessStrategy bstrategy); /* in heap/heapam_visibility.c */ diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h index 0a051ec06e..c0df9c9054 100644 --- a/src/include/commands/vacuum.h +++ b/src/include/commands/vacuum.h @@ -141,6 +141,7 @@ typedef struct VacAttrStats */ typedef struct VacuumParams { + int options; /* bitmask of VacuumOption */ int freeze_min_age; /* min freeze age, -1 to use default */ int freeze_table_age; /* age at which to scan whole table */ int multixact_freeze_min_age; /* min multixact freeze age, -1 to @@ -163,7 +164,7 @@ extern int vacuum_multixact_freeze_table_age; /* in commands/vacuum.c */ extern void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel); -extern void vacuum(int options, List *relations, VacuumParams *params, +extern void vacuum(List *relations, VacuumParams *params, BufferAccessStrategy bstrategy, bool isTopLevel); extern void vac_open_indexes(Relation relation, LOCKMODE lockmode, int *nindexes, Relation **Irel); @@ -194,10 +195,10 @@ extern void vacuum_delay_point(void); extern bool vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, int options); extern Relation vacuum_open_relation(Oid relid, RangeVar *relation, - VacuumParams *params, int options, LOCKMODE lmode); + int options, bool verbose, LOCKMODE lmode); /* in commands/analyze.c */ -extern void analyze_rel(Oid relid, RangeVar *relation, int options, +extern void analyze_rel(Oid relid, RangeVar *relation, VacuumParams *params, List *va_cols, bool in_outer_xact, BufferAccessStrategy bstrategy); extern bool std_typanalyze(VacAttrStats *stats);