int elevel;
AcquireSampleRowsFunc acquirefunc = NULL;
BlockNumber relpages = 0;
- bool rel_lock = true;
/* Select logging level */
if (options & VACOPT_VERBOSE)
* concurrent VACUUM, which doesn't matter much at the moment but might
* matter if we ever try to accumulate stats on dead tuples.) If the rel
* has been dropped since we last saw it, we don't need to process it.
+ *
+ * Make sure to generate only logs for ANALYZE in this case.
*/
- if (!(options & VACOPT_SKIP_LOCKED))
- onerel = try_relation_open(relid, ShareUpdateExclusiveLock);
- else if (ConditionalLockRelationOid(relid, ShareUpdateExclusiveLock))
- onerel = try_relation_open(relid, NoLock);
- else
- {
- onerel = NULL;
- rel_lock = false;
- }
+ onerel = vacuum_open_relation(relid, relation, params,
+ options & ~(VACOPT_VACUUM),
+ ShareUpdateExclusiveLock);
- /*
- * If we failed to open or lock the relation, emit a log message before
- * exiting.
- */
+ /* leave if relation could not be opened or locked */
if (!onerel)
- {
- /*
- * If the RangeVar is not defined, we do not have enough information
- * to provide a meaningful log statement. Chances are that
- * analyze_rel's caller has intentionally not provided this
- * information so that this logging is skipped, anyway.
- */
- if (relation == NULL)
- return;
-
- /*
- * Determine the log level. For autovacuum logs, we emit a LOG if
- * log_autovacuum_min_duration is not disabled. For manual ANALYZE,
- * we emit a WARNING to match the log statements in the permissions
- * checks.
- */
- if (!IsAutoVacuumWorkerProcess())
- elevel = WARNING;
- else if (params->log_min_duration >= 0)
- elevel = LOG;
- else
- return;
-
- if (!rel_lock)
- ereport(elevel,
- (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
- errmsg("skipping analyze of \"%s\" --- lock not available",
- relation->relname)));
- else
- ereport(elevel,
- (errcode(ERRCODE_UNDEFINED_TABLE),
- errmsg("skipping analyze of \"%s\" --- relation no longer exists",
- relation->relname)));
-
return;
- }
/*
* Check if relation needs to be skipped based on ownership. This check
}
+/*
+ * vacuum_open_relation
+ *
+ * This routine is used for attempting to open and lock a relation which
+ * is going to be vacuumed or analyzed. If the relation cannot be opened
+ * or locked, a log is emitted if possible.
+ */
+Relation
+vacuum_open_relation(Oid relid, RangeVar *relation, VacuumParams *params,
+ int options, LOCKMODE lmode)
+{
+ Relation onerel;
+ bool rel_lock = true;
+ int elevel;
+
+ Assert(params != NULL);
+ Assert((options & (VACOPT_VACUUM | VACOPT_ANALYZE)) != 0);
+
+ /*
+ * Open the relation and get the appropriate lock on it.
+ *
+ * There's a race condition here: the relation may have gone away since
+ * the last time we saw it. If so, we don't need to vacuum or analyze it.
+ *
+ * If we've been asked not to wait for the relation lock, acquire it first
+ * in non-blocking mode, before calling try_relation_open().
+ */
+ if (!(options & VACOPT_SKIP_LOCKED))
+ onerel = try_relation_open(relid, lmode);
+ else if (ConditionalLockRelationOid(relid, lmode))
+ onerel = try_relation_open(relid, NoLock);
+ else
+ {
+ onerel = NULL;
+ rel_lock = false;
+ }
+
+ /* if relation is opened, leave */
+ if (onerel)
+ return onerel;
+
+ /*
+ * Relation could not be opened, hence generate if possible a log
+ * informing on the situation.
+ *
+ * If the RangeVar is not defined, we do not have enough information to
+ * provide a meaningful log statement. Chances are that the caller has
+ * intentionally not provided this information so that this logging is
+ * skipped, anyway.
+ */
+ if (relation == NULL)
+ return NULL;
+
+ /*
+ * 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.
+ */
+ if (!IsAutoVacuumWorkerProcess())
+ elevel = WARNING;
+ else if (params->log_min_duration >= 0)
+ elevel = LOG;
+ else
+ return NULL;
+
+ if ((options & VACOPT_VACUUM) != 0)
+ {
+ if (!rel_lock)
+ ereport(elevel,
+ (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
+ errmsg("skipping vacuum of \"%s\" --- lock not available",
+ relation->relname)));
+ else
+ ereport(elevel,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("skipping vacuum of \"%s\" --- relation no longer exists",
+ relation->relname)));
+
+ /*
+ * For VACUUM ANALYZE, both logs could show up, but just generate
+ * information for VACUUM as that would be the first one to be
+ * processed.
+ */
+ return NULL;
+ }
+
+ if ((options & VACOPT_ANALYZE) != 0)
+ {
+ if (!rel_lock)
+ ereport(elevel,
+ (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
+ errmsg("skipping analyze of \"%s\" --- lock not available",
+ relation->relname)));
+ else
+ ereport(elevel,
+ (errcode(ERRCODE_UNDEFINED_TABLE),
+ errmsg("skipping analyze of \"%s\" --- relation no longer exists",
+ relation->relname)));
+ }
+
+ return NULL;
+}
+
+
/*
* Given a VacuumRelation, fill in the table OID if it wasn't specified,
* and optionally add VacuumRelations for partitions of the table.
Oid save_userid;
int save_sec_context;
int save_nestlevel;
- bool rel_lock = true;
Assert(params != NULL);
*/
lmode = (options & VACOPT_FULL) ? AccessExclusiveLock : ShareUpdateExclusiveLock;
- /*
- * Open the relation and get the appropriate lock on it.
- *
- * There's a race condition here: the rel may have gone away since the
- * last time we saw it. If so, we don't need to vacuum it.
- *
- * If we've been asked not to wait for the relation lock, acquire it first
- * in non-blocking mode, before calling try_relation_open().
- */
- if (!(options & VACOPT_SKIP_LOCKED))
- onerel = try_relation_open(relid, lmode);
- else if (ConditionalLockRelationOid(relid, lmode))
- onerel = try_relation_open(relid, NoLock);
- else
- {
- onerel = NULL;
- rel_lock = false;
- }
+ /* open the relation and get the appropriate lock on it */
+ onerel = vacuum_open_relation(relid, relation, params, options, lmode);
- /*
- * If we failed to open or lock the relation, emit a log message before
- * exiting.
- */
+ /* leave if relation could not be opened or locked */
if (!onerel)
{
- int elevel = 0;
-
- /*
- * Determine the log level.
- *
- * If the RangeVar is not defined, we do not have enough information
- * to provide a meaningful log statement. Chances are that
- * vacuum_rel's caller has intentionally not provided this information
- * so that this logging is skipped, anyway.
- *
- * Otherwise, for autovacuum logs, we emit a LOG if
- * log_autovacuum_min_duration is not disabled. For manual VACUUM, we
- * emit a WARNING to match the log statements in the permission
- * checks.
- */
- if (relation != NULL)
- {
- if (!IsAutoVacuumWorkerProcess())
- elevel = WARNING;
- else if (params->log_min_duration >= 0)
- elevel = LOG;
- }
-
- if (elevel != 0)
- {
- if (!rel_lock)
- ereport(elevel,
- (errcode(ERRCODE_LOCK_NOT_AVAILABLE),
- errmsg("skipping vacuum of \"%s\" --- lock not available",
- relation->relname)));
- else
- ereport(elevel,
- (errcode(ERRCODE_UNDEFINED_TABLE),
- errmsg("skipping vacuum of \"%s\" --- relation no longer exists",
- relation->relname)));
- }
-
PopActiveSnapshot();
CommitTransactionCommand();
return false;