@@ -204,6 +204,7 @@ static void repack_one_table(repack_table *table, const char *order_by);
204
204
static bool repack_table_indexes (PGresult * index_details );
205
205
static bool repack_all_indexes (char * errbuf , size_t errsize );
206
206
static void repack_cleanup (bool fatal , const repack_table * table );
207
+ static void repack_cleanup_callback (bool fatal , void * userdata );
207
208
static bool rebuild_indexes (const repack_table * table );
208
209
209
210
static char * getstr (PGresult * res , int row , int col );
@@ -235,13 +236,20 @@ static bool only_indexes = false;
235
236
static int wait_timeout = 60 ; /* in seconds */
236
237
static int jobs = 0 ; /* number of concurrent worker conns. */
237
238
static bool dryrun = false;
239
+ static unsigned int temp_obj_num = 0 ; /* temporary objects counter */
238
240
239
241
/* buffer should have at least 11 bytes */
240
242
static char *
241
243
utoa (unsigned int value , char * buffer )
242
244
{
243
245
sprintf (buffer , "%u" , value );
244
- return buffer ;
246
+ /* XXX: originally, we would just return buffer here without
247
+ * the pgut_strdup(). But repack_cleanup_callback() seems to
248
+ * depend on getting back a freshly strdup'd copy of buffer,
249
+ * not sure why. So now we are leaking a tiny bit of memory
250
+ * with each utoa() call.
251
+ */
252
+ return pgut_strdup (buffer );
245
253
}
246
254
247
255
static pgut_option options [] =
@@ -898,6 +906,13 @@ rebuild_indexes(const repack_table *table)
898
906
899
907
ret = select (max_fd + 1 , & input_mask , NULL , NULL , & timeout );
900
908
#endif
909
+ /* XXX: the errno != EINTR check means we won't bail
910
+ * out on SIGINT. We should probably just remove this
911
+ * check, though it seems we also need to fix up
912
+ * the on_interrupt handling for workers' index
913
+ * builds (those PGconns don't seem to have c->cancel
914
+ * set, so we don't cancel the in-progress builds).
915
+ */
901
916
if (ret < 0 && errno != EINTR )
902
917
elog (ERROR , "poll() failed: %d, %d" , ret , errno );
903
918
@@ -990,7 +1005,7 @@ static void
990
1005
repack_one_table (repack_table * table , const char * orderby )
991
1006
{
992
1007
PGresult * res = NULL ;
993
- const char * params [2 ];
1008
+ const char * params [3 ];
994
1009
int num ;
995
1010
char * vxid = NULL ;
996
1011
char buffer [12 ];
@@ -1041,6 +1056,9 @@ repack_one_table(repack_table *table, const char *orderby)
1041
1056
1042
1057
if (dryrun )
1043
1058
return ;
1059
+
1060
+ /* push repack_cleanup_callback() on stack to clean temporary objects */
1061
+ pgut_atexit_push (repack_cleanup_callback , & table -> target_oid );
1044
1062
1045
1063
/*
1046
1064
* 1. Setup advisory lock and trigger on main table.
@@ -1146,8 +1164,11 @@ repack_one_table(repack_table *table, const char *orderby)
1146
1164
CLEARPGRES (res );
1147
1165
1148
1166
command (table -> create_pktype , 0 , NULL );
1167
+ temp_obj_num ++ ;
1149
1168
command (table -> create_log , 0 , NULL );
1169
+ temp_obj_num ++ ;
1150
1170
command (table -> create_trigger , 0 , NULL );
1171
+ temp_obj_num ++ ;
1151
1172
command (table -> enable_trigger , 0 , NULL );
1152
1173
printfStringInfo (& sql , "SELECT repack.disable_autovacuum('repack.log_%u')" , table -> target_oid );
1153
1174
command (sql .data , 0 , NULL );
@@ -1283,6 +1304,7 @@ repack_one_table(repack_table *table, const char *orderby)
1283
1304
goto cleanup ;
1284
1305
1285
1306
command (table -> create_table , 0 , NULL );
1307
+ temp_obj_num ++ ;
1286
1308
printfStringInfo (& sql , "SELECT repack.disable_autovacuum('repack.table_%u')" , table -> target_oid );
1287
1309
if (table -> drop_columns )
1288
1310
command (table -> drop_columns , 0 , NULL );
@@ -1375,8 +1397,10 @@ repack_one_table(repack_table *table, const char *orderby)
1375
1397
elog (DEBUG2 , "---- drop ----" );
1376
1398
1377
1399
command ("BEGIN ISOLATION LEVEL READ COMMITTED" , 0 , NULL );
1378
- command ("SELECT repack.repack_drop($1)" , 1 , params );
1400
+ params [1 ] = utoa (temp_obj_num , buffer );
1401
+ command ("SELECT repack.repack_drop($1, $2)" , 2 , params );
1379
1402
command ("COMMIT" , 0 , NULL );
1403
+ temp_obj_num = 0 ; /* reset temporary object counter after cleanup */
1380
1404
1381
1405
/*
1382
1406
* 7. Analyze.
@@ -1395,7 +1419,7 @@ repack_one_table(repack_table *table, const char *orderby)
1395
1419
1396
1420
/* Release advisory lock on table. */
1397
1421
params [0 ] = REPACK_LOCK_PREFIX_STR ;
1398
- params [1 ] = buffer ;
1422
+ params [1 ] = utoa ( table -> target_oid , buffer ) ;
1399
1423
1400
1424
res = pgut_execute (connection , "SELECT pg_advisory_unlock($1, CAST(-2147483648 + $2::bigint AS integer))" ,
1401
1425
2 , params );
@@ -1675,6 +1699,31 @@ lock_exclusive(PGconn *conn, const char *relid, const char *lock_query, bool sta
1675
1699
return ret ;
1676
1700
}
1677
1701
1702
+ /* This function calls to repack_drop() to clean temporary objects on error
1703
+ * in creation of temporary objects.
1704
+ */
1705
+ void
1706
+ repack_cleanup_callback (bool fatal , void * userdata )
1707
+ {
1708
+ Oid target_table = * (Oid * ) userdata ;
1709
+ const char * params [2 ];
1710
+ char buffer [12 ];
1711
+
1712
+ if (fatal )
1713
+ {
1714
+ params [0 ] = utoa (target_table , buffer );
1715
+ params [1 ] = utoa (temp_obj_num , buffer );
1716
+
1717
+ /* testing PQstatus() of connection and conn2, as we do
1718
+ * in repack_cleanup(), doesn't seem to work here,
1719
+ * so just use an unconditional reconnect().
1720
+ */
1721
+ reconnect (ERROR );
1722
+ command ("SELECT repack.repack_drop($1, $2)" , 2 , params );
1723
+ temp_obj_num = 0 ; /* reset temporary object counter after cleanup */
1724
+ }
1725
+ }
1726
+
1678
1727
/*
1679
1728
* The userdata pointing a table being re-organized. We need to cleanup temp
1680
1729
* objects before the program exits.
@@ -1689,7 +1738,7 @@ repack_cleanup(bool fatal, const repack_table *table)
1689
1738
else
1690
1739
{
1691
1740
char buffer [12 ];
1692
- const char * params [1 ];
1741
+ const char * params [2 ];
1693
1742
1694
1743
/* Try reconnection if not available. */
1695
1744
if (PQstatus (connection ) != CONNECTION_OK ||
@@ -1698,7 +1747,9 @@ repack_cleanup(bool fatal, const repack_table *table)
1698
1747
1699
1748
/* do cleanup */
1700
1749
params [0 ] = utoa (table -> target_oid , buffer );
1701
- command ("SELECT repack.repack_drop($1)" , 1 , params );
1750
+ params [1 ] = utoa (temp_obj_num , buffer );
1751
+ command ("SELECT repack.repack_drop($1, $2)" , 2 , params );
1752
+ temp_obj_num = 0 ; /* reset temporary object counter after cleanup */
1702
1753
}
1703
1754
}
1704
1755
0 commit comments