@@ -184,6 +184,7 @@ static bool rebuild_indexes(const repack_table *table);
184
184
185
185
static char * getstr (PGresult * res , int row , int col );
186
186
static Oid getoid (PGresult * res , int row , int col );
187
+ static bool advisory_lock (PGconn * conn , const char * relid );
187
188
static bool lock_exclusive (PGconn * conn , const char * relid , const char * lock_query , bool start_xact );
188
189
static bool kill_ddl (PGconn * conn , Oid relid , bool terminate );
189
190
static bool lock_access_share (PGconn * conn , Oid relid , const char * target_name );
@@ -1005,26 +1006,12 @@ repack_one_table(const repack_table *table, const char *orderby)
1005
1006
*/
1006
1007
elog (DEBUG2 , "---- setup ----" );
1007
1008
1008
- /* Obtain an advisory lock on the table's OID, to make sure no other
1009
- * pg_repack is working on the table. (Not a real concern with only
1010
- * full-table repacks, but mainly for index-only repacks.)
1011
- */
1012
1009
params [0 ] = utoa (table -> target_oid , buffer );
1013
- res = pgut_execute (connection , "SELECT pg_try_advisory_lock($1::bigint)" ,
1014
- 1 , params );
1015
- if (PQresultStatus (res ) != PGRES_TUPLES_OK )
1016
- {
1017
- elog (ERROR , "%s" , PQerrorMessage (connection ));
1018
- goto cleanup ;
1019
- }
1020
- else if (strcmp (getstr (res , 0 , 0 ), "t" ) != 0 )
1021
- {
1022
- elog (WARNING , "Another pg_repack command may be running on the table. Please try again later." );
1010
+
1011
+ if (!advisory_lock (connection , buffer ))
1023
1012
goto cleanup ;
1024
- }
1025
- CLEARPGRES (res );
1026
1013
1027
- if (!(lock_exclusive (connection , utoa ( table -> target_oid , buffer ) , table -> lock_table , TRUE)))
1014
+ if (!(lock_exclusive (connection , buffer , table -> lock_table , TRUE)))
1028
1015
{
1029
1016
elog (WARNING , "lock_exclusive() failed for %s" , table -> target_name );
1030
1017
goto cleanup ;
@@ -1465,6 +1452,40 @@ lock_access_share(PGconn *conn, Oid relid, const char *target_name)
1465
1452
}
1466
1453
1467
1454
1455
+ /* XXX: Make sure that repack_one_table() also obtains an advisory
1456
+ * lock on the table, so that we can't have a table-wide repack running
1457
+ * along with an indexes-only repack. Also, since advisory locks are
1458
+ * 8 bytes wide and OIDs are only 4 bytes, consider using our own prefix
1459
+ * rather than just the table OID, to avoid inadvertent conflict with
1460
+ * other applications using advisory locks.
1461
+ */
1462
+
1463
+ /* Obtain an advisory lock on the table's OID, to make sure no other
1464
+ * pg_repack is working on the table. This is not so much a concern with
1465
+ * full-table repacks, but mainly so that index-only repacks don't interfere
1466
+ * with each other or a full-table repack.
1467
+ */
1468
+ static bool advisory_lock (PGconn * conn , const char * relid )
1469
+ {
1470
+ PGresult * res = NULL ;
1471
+ bool ret = false;
1472
+
1473
+ res = pgut_execute (conn , "SELECT pg_try_advisory_lock($1::bigint)" ,
1474
+ 1 , & relid );
1475
+
1476
+ if (PQresultStatus (res ) != PGRES_TUPLES_OK ) {
1477
+ elog (ERROR , "%s" , PQerrorMessage (connection ));
1478
+ }
1479
+ else if (strcmp (getstr (res , 0 , 0 ), "t" ) != 0 ) {
1480
+ elog (WARNING , "Another pg_repack command may be running on the table. Please try again later." );
1481
+ }
1482
+ else {
1483
+ ret = true;
1484
+ }
1485
+ CLEARPGRES (res );
1486
+ return ret ;
1487
+ }
1488
+
1468
1489
/*
1469
1490
* Try acquire an ACCESS EXCLUSIVE table lock, avoiding deadlocks and long
1470
1491
* waits by killing off other sessions.
@@ -1668,12 +1689,14 @@ repack_one_index(Oid table, const char *table_name, Oid index, const char *schem
1668
1689
* Call repack_one_index for each of the indexes
1669
1690
*/
1670
1691
static bool
1671
- repack_all_indexes (char * errbuf , size_t errsize ){
1692
+ repack_all_indexes (char * errbuf , size_t errsize )
1693
+ {
1672
1694
bool ret = false;
1673
- PGresult * res = NULL , * res2 = NULL ;
1695
+ PGresult * res = NULL ;
1674
1696
int i ;
1675
1697
int num ;
1676
1698
StringInfoData sql ;
1699
+ char buffer [12 ];
1677
1700
const char * params [1 ];
1678
1701
const char * table_name = NULL ;
1679
1702
const char * schema_name = NULL ;
@@ -1710,12 +1733,12 @@ repack_all_indexes(char *errbuf, size_t errsize){
1710
1733
{
1711
1734
ereport (ERROR ,
1712
1735
(errcode (EINVAL ),
1713
- errmsg ("index \"%s\" doesnot exist.\n" , r_index )));
1736
+ errmsg ("index \"%s\" does not exist.\n" , r_index )));
1714
1737
goto cleanup ;
1715
1738
}
1716
1739
}
1717
1740
1718
- // seperate schema name and index name
1741
+ // separate schema name and index name. FIXME: kludge
1719
1742
pos = strchr (params [0 ], '.' );
1720
1743
if (pos )
1721
1744
{
@@ -1751,7 +1774,7 @@ repack_all_indexes(char *errbuf, size_t errsize){
1751
1774
}
1752
1775
}
1753
1776
1754
- // seperate schema name and table name
1777
+ // separate schema name and table name. FIXME: kludge
1755
1778
pos = strchr (params [0 ], '.' );
1756
1779
if (pos )
1757
1780
{
@@ -1763,30 +1786,14 @@ repack_all_indexes(char *errbuf, size_t errsize){
1763
1786
table_name = params [0 ];
1764
1787
}
1765
1788
1766
- /* XXX: Make sure that repack_one_table() also obtains an advisory
1767
- * lock on the table, so that we can't have a table-wide repack running
1768
- * along with an indexes-only repack. Also, since advisory locks are
1769
- * 8 bytes wide and OIDs are only 4 bytes, consider using our own prefix
1770
- * rather than just the table OID, to avoid inadvertent conflict with
1771
- * other applications using advisory locks.
1789
+ /* Check if any concurrent pg_repack command is being run on the same
1790
+ * table.
1772
1791
*/
1773
-
1774
- /* Check if any concurrent pg_repack command is being run on the same table */
1775
- initStringInfo (& sql );
1776
- appendStringInfo (& sql , "SELECT pg_try_advisory_lock(%u)" , getoid (res , 0 , 3 ));
1777
-
1778
- res2 = execute_elevel (sql .data , 0 , NULL , DEBUG2 );
1779
- if (PQresultStatus (res2 ) != PGRES_TUPLES_OK )
1780
- {
1781
- elog (ERROR , "%s" , PQerrorMessage (connection ));
1792
+ if (!advisory_lock (connection , utoa (getoid (res , 0 , 3 ), buffer ))) {
1793
+ snprintf (errbuf , errsize , "Unable to obtain advisory lock on %s" ,
1794
+ table_name );
1782
1795
goto cleanup ;
1783
1796
}
1784
- else if (strcmp (getstr (res2 , 0 , 0 ), "t" ) != 0 )
1785
- {
1786
- snprintf (errbuf , errsize , "Another pg_repack command may be running on the table. Please try again later." );
1787
- goto cleanup ;
1788
- }
1789
-
1790
1797
for (i = 0 ; i < num ; i ++ )
1791
1798
{
1792
1799
char * isvalid = getstr (res , i , 2 );
@@ -1797,8 +1804,10 @@ repack_all_indexes(char *errbuf, size_t errsize){
1797
1804
else
1798
1805
elog (INFO , "repacking index \"%s\"" , getstr (res , i , 0 ));
1799
1806
1800
- if (!(repack_one_index (getoid (res , i , 3 ), table_name , getoid (res , i , 1 ), schema_name )))
1807
+ if (!(repack_one_index (getoid (res , i , 3 ), table_name , getoid (res , i , 1 ), schema_name ))) {
1808
+ /* FIXME: fill in errbuf here */
1801
1809
goto cleanup ;
1810
+ }
1802
1811
}
1803
1812
else
1804
1813
if (schema_name )
@@ -1810,7 +1819,6 @@ repack_all_indexes(char *errbuf, size_t errsize){
1810
1819
1811
1820
cleanup :
1812
1821
CLEARPGRES (res );
1813
- CLEARPGRES (res2 );
1814
1822
disconnect ();
1815
1823
termStringInfo (& sql );
1816
1824
return ret ;
0 commit comments