13
13
*
14
14
*
15
15
* IDENTIFICATION
16
- * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.394 2009/10/26 02:26:29 tgl Exp $
16
+ * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.395 2009/11/10 18:00:06 alvherre Exp $
17
17
*
18
18
*-------------------------------------------------------------------------
19
19
*/
@@ -217,10 +217,10 @@ static List *get_rel_oids(Oid relid, const RangeVar *vacrel,
217
217
static void vac_truncate_clog (TransactionId frozenXID );
218
218
static void vacuum_rel (Oid relid , VacuumStmt * vacstmt , bool do_toast ,
219
219
bool for_wraparound , bool * scanned_all );
220
- static void full_vacuum_rel (Relation onerel , VacuumStmt * vacstmt );
220
+ static bool full_vacuum_rel (Relation onerel , VacuumStmt * vacstmt );
221
221
static void scan_heap (VRelStats * vacrelstats , Relation onerel ,
222
222
VacPageList vacuum_pages , VacPageList fraged_pages );
223
- static void repair_frag (VRelStats * vacrelstats , Relation onerel ,
223
+ static bool repair_frag (VRelStats * vacrelstats , Relation onerel ,
224
224
VacPageList vacuum_pages , VacPageList fraged_pages ,
225
225
int nindexes , Relation * Irel );
226
226
static void move_chain_tuple (Relation rel ,
@@ -1020,6 +1020,7 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
1020
1020
Oid toast_relid ;
1021
1021
Oid save_userid ;
1022
1022
bool save_secdefcxt ;
1023
+ bool heldoff ;
1023
1024
1024
1025
if (scanned_all )
1025
1026
* scanned_all = false;
@@ -1186,9 +1187,9 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
1186
1187
* Do the actual work --- either FULL or "lazy" vacuum
1187
1188
*/
1188
1189
if (vacstmt -> full )
1189
- full_vacuum_rel (onerel , vacstmt );
1190
+ heldoff = full_vacuum_rel (onerel , vacstmt );
1190
1191
else
1191
- lazy_vacuum_rel (onerel , vacstmt , vac_strategy , scanned_all );
1192
+ heldoff = lazy_vacuum_rel (onerel , vacstmt , vac_strategy , scanned_all );
1192
1193
1193
1194
/* Restore userid */
1194
1195
SetUserIdAndContext (save_userid , save_secdefcxt );
@@ -1202,6 +1203,10 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
1202
1203
PopActiveSnapshot ();
1203
1204
CommitTransactionCommand ();
1204
1205
1206
+ /* now we can allow interrupts again, if disabled */
1207
+ if (heldoff )
1208
+ RESUME_INTERRUPTS ();
1209
+
1205
1210
/*
1206
1211
* If the relation has a secondary toast rel, vacuum that too while we
1207
1212
* still hold the session lock on the master table. Note however that
@@ -1235,8 +1240,11 @@ vacuum_rel(Oid relid, VacuumStmt *vacstmt, bool do_toast, bool for_wraparound,
1235
1240
*
1236
1241
* At entry, we have already established a transaction and opened
1237
1242
* and locked the relation.
1243
+ *
1244
+ * The return value indicates whether this function has held off
1245
+ * interrupts -- caller must RESUME_INTERRUPTS() after commit if true.
1238
1246
*/
1239
- static void
1247
+ static bool
1240
1248
full_vacuum_rel (Relation onerel , VacuumStmt * vacstmt )
1241
1249
{
1242
1250
VacPageListData vacuum_pages ; /* List of pages to vacuum and/or
@@ -1247,6 +1255,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
1247
1255
int nindexes ,
1248
1256
i ;
1249
1257
VRelStats * vacrelstats ;
1258
+ bool heldoff = false;
1250
1259
1251
1260
vacuum_set_xid_limits (vacstmt -> freeze_min_age , vacstmt -> freeze_table_age ,
1252
1261
onerel -> rd_rel -> relisshared ,
@@ -1298,7 +1307,7 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
1298
1307
if (fraged_pages .num_pages > 0 )
1299
1308
{
1300
1309
/* Try to shrink heap */
1301
- repair_frag (vacrelstats , onerel , & vacuum_pages , & fraged_pages ,
1310
+ heldoff = repair_frag (vacrelstats , onerel , & vacuum_pages , & fraged_pages ,
1302
1311
nindexes , Irel );
1303
1312
vac_close_indexes (nindexes , Irel , NoLock );
1304
1313
}
@@ -1324,6 +1333,8 @@ full_vacuum_rel(Relation onerel, VacuumStmt *vacstmt)
1324
1333
/* report results to the stats collector, too */
1325
1334
pgstat_report_vacuum (RelationGetRelid (onerel ), onerel -> rd_rel -> relisshared ,
1326
1335
true, vacstmt -> analyze , vacrelstats -> rel_tuples );
1336
+
1337
+ return heldoff ;
1327
1338
}
1328
1339
1329
1340
@@ -1874,8 +1885,11 @@ scan_heap(VRelStats *vacrelstats, Relation onerel,
1874
1885
* for them after committing (in hack-manner - without losing locks
1875
1886
* and freeing memory!) current transaction. It truncates relation
1876
1887
* if some end-blocks are gone away.
1888
+ *
1889
+ * The return value indicates whether this function has held off
1890
+ * interrupts -- caller must RESUME_INTERRUPTS() after commit if true.
1877
1891
*/
1878
- static void
1892
+ static bool
1879
1893
repair_frag (VRelStats * vacrelstats , Relation onerel ,
1880
1894
VacPageList vacuum_pages , VacPageList fraged_pages ,
1881
1895
int nindexes , Relation * Irel )
@@ -1900,6 +1914,7 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
1900
1914
int keep_tuples = 0 ;
1901
1915
int keep_indexed_tuples = 0 ;
1902
1916
PGRUsage ru0 ;
1917
+ bool heldoff = false;
1903
1918
1904
1919
pg_rusage_init (& ru0 );
1905
1920
@@ -2705,8 +2720,12 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
2705
2720
*
2706
2721
* XXX This desperately needs to be revisited. Any failure after this
2707
2722
* point will result in a PANIC "cannot abort transaction nnn, it was
2708
- * already committed"!
2723
+ * already committed"! As a precaution, we prevent cancel interrupts
2724
+ * after this point to mitigate this problem; caller is responsible for
2725
+ * re-enabling them after committing the transaction.
2709
2726
*/
2727
+ HOLD_INTERRUPTS ();
2728
+ heldoff = true;
2710
2729
ForceSyncCommit ();
2711
2730
(void ) RecordTransactionCommit ();
2712
2731
}
@@ -2906,6 +2925,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
2906
2925
pfree (vacrelstats -> vtlinks );
2907
2926
2908
2927
ExecContext_Finish (& ec );
2928
+
2929
+ return heldoff ;
2909
2930
}
2910
2931
2911
2932
/*
0 commit comments