@@ -482,6 +482,112 @@ vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, int options)
482482}
483483
484484
485+ /*
486+ * vacuum_open_relation
487+ *
488+ * This routine is used for attempting to open and lock a relation which
489+ * is going to be vacuumed or analyzed. If the relation cannot be opened
490+ * or locked, a log is emitted if possible.
491+ */
492+ Relation
493+ vacuum_open_relation (Oid relid , RangeVar * relation , VacuumParams * params ,
494+ int options , LOCKMODE lmode )
495+ {
496+ Relation onerel ;
497+ bool rel_lock = true;
498+ int elevel ;
499+
500+ Assert (params != NULL );
501+ Assert ((options & (VACOPT_VACUUM | VACOPT_ANALYZE )) != 0 );
502+
503+ /*
504+ * Open the relation and get the appropriate lock on it.
505+ *
506+ * There's a race condition here: the relation may have gone away since
507+ * the last time we saw it. If so, we don't need to vacuum or analyze it.
508+ *
509+ * If we've been asked not to wait for the relation lock, acquire it first
510+ * in non-blocking mode, before calling try_relation_open().
511+ */
512+ if (!(options & VACOPT_SKIP_LOCKED ))
513+ onerel = try_relation_open (relid , lmode );
514+ else if (ConditionalLockRelationOid (relid , lmode ))
515+ onerel = try_relation_open (relid , NoLock );
516+ else
517+ {
518+ onerel = NULL ;
519+ rel_lock = false;
520+ }
521+
522+ /* if relation is opened, leave */
523+ if (onerel )
524+ return onerel ;
525+
526+ /*
527+ * Relation could not be opened, hence generate if possible a log
528+ * informing on the situation.
529+ *
530+ * If the RangeVar is not defined, we do not have enough information to
531+ * provide a meaningful log statement. Chances are that the caller has
532+ * intentionally not provided this information so that this logging is
533+ * skipped, anyway.
534+ */
535+ if (relation == NULL )
536+ return NULL ;
537+
538+ /*
539+ * Determine the log level.
540+ *
541+ * For autovacuum logs, we emit a LOG if log_autovacuum_min_duration is
542+ * not disabled. For manual VACUUM or ANALYZE, we emit a WARNING to match
543+ * the log statements in the permission checks.
544+ */
545+ if (!IsAutoVacuumWorkerProcess ())
546+ elevel = WARNING ;
547+ else if (params -> log_min_duration >= 0 )
548+ elevel = LOG ;
549+ else
550+ return NULL ;
551+
552+ if ((options & VACOPT_VACUUM ) != 0 )
553+ {
554+ if (!rel_lock )
555+ ereport (elevel ,
556+ (errcode (ERRCODE_LOCK_NOT_AVAILABLE ),
557+ errmsg ("skipping vacuum of \"%s\" --- lock not available" ,
558+ relation -> relname )));
559+ else
560+ ereport (elevel ,
561+ (errcode (ERRCODE_UNDEFINED_TABLE ),
562+ errmsg ("skipping vacuum of \"%s\" --- relation no longer exists" ,
563+ relation -> relname )));
564+
565+ /*
566+ * For VACUUM ANALYZE, both logs could show up, but just generate
567+ * information for VACUUM as that would be the first one to be
568+ * processed.
569+ */
570+ return NULL ;
571+ }
572+
573+ if ((options & VACOPT_ANALYZE ) != 0 )
574+ {
575+ if (!rel_lock )
576+ ereport (elevel ,
577+ (errcode (ERRCODE_LOCK_NOT_AVAILABLE ),
578+ errmsg ("skipping analyze of \"%s\" --- lock not available" ,
579+ relation -> relname )));
580+ else
581+ ereport (elevel ,
582+ (errcode (ERRCODE_UNDEFINED_TABLE ),
583+ errmsg ("skipping analyze of \"%s\" --- relation no longer exists" ,
584+ relation -> relname )));
585+ }
586+
587+ return NULL ;
588+ }
589+
590+
485591/*
486592 * Given a VacuumRelation, fill in the table OID if it wasn't specified,
487593 * and optionally add VacuumRelations for partitions of the table.
@@ -1400,7 +1506,6 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
14001506 Oid save_userid ;
14011507 int save_sec_context ;
14021508 int save_nestlevel ;
1403- bool rel_lock = true;
14041509
14051510 Assert (params != NULL );
14061511
@@ -1455,68 +1560,12 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
14551560 */
14561561 lmode = (options & VACOPT_FULL ) ? AccessExclusiveLock : ShareUpdateExclusiveLock ;
14571562
1458- /*
1459- * Open the relation and get the appropriate lock on it.
1460- *
1461- * There's a race condition here: the rel may have gone away since the
1462- * last time we saw it. If so, we don't need to vacuum it.
1463- *
1464- * If we've been asked not to wait for the relation lock, acquire it first
1465- * in non-blocking mode, before calling try_relation_open().
1466- */
1467- if (!(options & VACOPT_SKIP_LOCKED ))
1468- onerel = try_relation_open (relid , lmode );
1469- else if (ConditionalLockRelationOid (relid , lmode ))
1470- onerel = try_relation_open (relid , NoLock );
1471- else
1472- {
1473- onerel = NULL ;
1474- rel_lock = false;
1475- }
1563+ /* open the relation and get the appropriate lock on it */
1564+ onerel = vacuum_open_relation (relid , relation , params , options , lmode );
14761565
1477- /*
1478- * If we failed to open or lock the relation, emit a log message before
1479- * exiting.
1480- */
1566+ /* leave if relation could not be opened or locked */
14811567 if (!onerel )
14821568 {
1483- int elevel = 0 ;
1484-
1485- /*
1486- * Determine the log level.
1487- *
1488- * If the RangeVar is not defined, we do not have enough information
1489- * to provide a meaningful log statement. Chances are that
1490- * vacuum_rel's caller has intentionally not provided this information
1491- * so that this logging is skipped, anyway.
1492- *
1493- * Otherwise, for autovacuum logs, we emit a LOG if
1494- * log_autovacuum_min_duration is not disabled. For manual VACUUM, we
1495- * emit a WARNING to match the log statements in the permission
1496- * checks.
1497- */
1498- if (relation != NULL )
1499- {
1500- if (!IsAutoVacuumWorkerProcess ())
1501- elevel = WARNING ;
1502- else if (params -> log_min_duration >= 0 )
1503- elevel = LOG ;
1504- }
1505-
1506- if (elevel != 0 )
1507- {
1508- if (!rel_lock )
1509- ereport (elevel ,
1510- (errcode (ERRCODE_LOCK_NOT_AVAILABLE ),
1511- errmsg ("skipping vacuum of \"%s\" --- lock not available" ,
1512- relation -> relname )));
1513- else
1514- ereport (elevel ,
1515- (errcode (ERRCODE_UNDEFINED_TABLE ),
1516- errmsg ("skipping vacuum of \"%s\" --- relation no longer exists" ,
1517- relation -> relname )));
1518- }
1519-
15201569 PopActiveSnapshot ();
15211570 CommitTransactionCommand ();
15221571 return false;
0 commit comments