aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/vacuum.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/vacuum.c')
-rw-r--r--src/backend/commands/vacuum.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index c85bc2c6ecc..215c77bc985 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.389.2.1 2009/08/24 02:18:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.389.2.2 2009/11/10 18:00:26 alvherre Exp $
*
*-------------------------------------------------------------------------
*/
@@ -218,10 +218,10 @@ static List *get_rel_oids(Oid relid, const RangeVar *vacrel,
static void vac_truncate_clog(TransactionId frozenXID);
static void vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast,
bool for_wraparound, bool *scanned_all);
-static void full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
+static bool full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt);
static void scan_heap(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages);
-static void repair_frag(VRelStats *vacrelstats, Relation onerel,
+static bool repair_frag(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages,
int nindexes, Relation *Irel);
static void move_chain_tuple(Relation rel,
@@ -1023,6 +1023,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
Oid toast_relid;
Oid save_userid;
bool save_secdefcxt;
+ bool heldoff;
if (scanned_all)
*scanned_all = false;
@@ -1189,9 +1190,9 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
* Do the actual work --- either FULL or "lazy" vacuum
*/
if (vacstmt->full)
- full_vacuum_rel(onerel, vacstmt);
+ heldoff = full_vacuum_rel(onerel, vacstmt);
else
- lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all);
+ heldoff = lazy_vacuum_rel(onerel, vacstmt, vac_strategy, scanned_all);
/* Restore userid */
SetUserIdAndContext(save_userid, save_secdefcxt);
@@ -1205,6 +1206,10 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
PopActiveSnapshot();
CommitTransactionCommand();
+ /* now we can allow interrupts again, if disabled */
+ if (heldoff)
+ RESUME_INTERRUPTS();
+
/*
* If the relation has a secondary toast rel, vacuum that too while we
* still hold the session lock on the master table. Note however that
@@ -1238,8 +1243,11 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
*
* At entry, we have already established a transaction and opened
* and locked the relation.
+ *
+ * The return value indicates whether this function has held off
+ * interrupts -- caller must RESUME_INTERRUPTS() after commit if true.
*/
-static void
+static bool
full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
{
VacPageListData vacuum_pages; /* List of pages to vacuum and/or
@@ -1250,6 +1258,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
int nindexes,
i;
VRelStats *vacrelstats;
+ bool heldoff = false;
vacuum_set_xid_limits(vacstmt->freeze_min_age, vacstmt->freeze_table_age,
onerel->rd_rel->relisshared,
@@ -1301,7 +1310,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
if (fraged_pages.num_pages > 0)
{
/* Try to shrink heap */
- repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages,
+ heldoff = repair_frag(vacrelstats, onerel, &vacuum_pages, &fraged_pages,
nindexes, Irel);
vac_close_indexes(nindexes, Irel, NoLock);
}
@@ -1327,6 +1336,8 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
/* report results to the stats collector, too */
pgstat_report_vacuum(RelationGetRelid(onerel), onerel->rd_rel->relisshared,
true, vacstmt->analyze, vacrelstats->rel_tuples);
+
+ return heldoff;
}
@@ -1877,8 +1888,11 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
* for them after committing (in hack-manner - without losing locks
* and freeing memory!) current transaction. It truncates relation
* if some end-blocks are gone away.
+ *
+ * The return value indicates whether this function has held off
+ * interrupts -- caller must RESUME_INTERRUPTS() after commit if true.
*/
-static void
+static bool
repair_frag(VRelStats *vacrelstats, Relation onerel,
VacPageList vacuum_pages, VacPageList fraged_pages,
int nindexes, Relation *Irel)
@@ -1903,6 +1917,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
int keep_tuples = 0;
int keep_indexed_tuples = 0;
PGRUsage ru0;
+ bool heldoff = false;
pg_rusage_init(&ru0);
@@ -2708,8 +2723,12 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
*
* XXX This desperately needs to be revisited. Any failure after this
* point will result in a PANIC "cannot abort transaction nnn, it was
- * already committed"!
+ * already committed"! As a precaution, we prevent cancel interrupts
+ * after this point to mitigate this problem; caller is responsible for
+ * re-enabling them after committing the transaction.
*/
+ HOLD_INTERRUPTS();
+ heldoff = true;
ForceSyncCommit();
(void) RecordTransactionCommit();
}
@@ -2909,6 +2928,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
pfree(vacrelstats->vtlinks);
ExecContext_Finish(&ec);
+
+ return heldoff;
}
/*