@@ -109,7 +109,7 @@ static void do_amcheck(void);
109
109
static void * check_files (void * arg );
110
110
static void * check_indexes (void * arg );
111
111
static parray * get_index_list (PGresult * res_db ,int db_number ,
112
- bool * first_db_with_amcheck ,PGconn * db_conn );
112
+ bool first_db_with_amcheck ,PGconn * db_conn );
113
113
static bool amcheck_one_index (backup_files_arg * arguments ,
114
114
pg_indexEntry * ind );
115
115
@@ -1049,13 +1049,19 @@ do_amcheck(void)
1049
1049
pgBackupGetPath (& current ,database_path ,lengthof (database_path ),
1050
1050
DATABASE_DIR );
1051
1051
1052
- res_db = pgut_execute (backup_conn ,"SELECT datname, oid, dattablespace FROM pg_database" ,
1052
+ res_db = pgut_execute (backup_conn ,
1053
+ "SELECT datname, oid, dattablespace "
1054
+ "FROM pg_database "
1055
+ "WHERE datname NOT IN ('template0', 'template1')" ,
1053
1056
0 ,NULL );
1057
+
1054
1058
n_databases = PQntuples (res_db );
1055
1059
1056
1060
/* TODO Warn user that one connection is used for snaphot */
1057
- if (num_threads > 1 )
1058
- num_threads -- ;
1061
+ //if (num_threads > 1)
1062
+ //num_threads--;
1063
+
1064
+ elog (INFO ,"Start checking instance with amcheck" );
1059
1065
1060
1066
/* For each database check indexes. In parallel. */
1061
1067
for (i = 0 ;i < n_databases ;i ++ )
@@ -1069,14 +1075,17 @@ do_amcheck(void)
1069
1075
}
1070
1076
1071
1077
index_list = get_index_list (res_db ,i ,
1072
- & first_db_with_amcheck ,db_conn );
1078
+ first_db_with_amcheck ,db_conn );
1079
+
1073
1080
if (index_list == NULL )
1074
1081
{
1075
1082
if (db_conn )
1076
1083
pgut_disconnect (db_conn );
1077
1084
continue ;
1078
1085
}
1079
1086
1087
+ first_db_with_amcheck = false;
1088
+
1080
1089
/* init thread args with own file lists */
1081
1090
threads = (pthread_t * )palloc (sizeof (pthread_t )* num_threads );
1082
1091
threads_args = (backup_files_arg * )palloc (sizeof (backup_files_arg )* num_threads );
@@ -1099,8 +1108,6 @@ do_amcheck(void)
1099
1108
1100
1109
pgut_atexit_push (threads_conn_disconnect ,NULL );
1101
1110
1102
- elog (INFO ,"Start checking indexes with amcheck" );
1103
-
1104
1111
/* Run threads */
1105
1112
for (j = 0 ;j < num_threads ;j ++ )
1106
1113
{
@@ -1115,24 +1122,24 @@ do_amcheck(void)
1115
1122
for (j = 0 ;j < num_threads ;j ++ )
1116
1123
{
1117
1124
pthread_join (threads [j ],NULL );
1118
- if (threads_args [j ].ret == 1 )
1125
+ if (threads_args [j ].ret > 0 )
1119
1126
check_isok = false;
1120
1127
}
1121
1128
pgut_disconnect (db_conn );
1122
1129
}
1123
1130
1124
1131
/* TODO write better info message */
1125
1132
if (check_isok )
1126
- elog (INFO ,"Indexes arechecked " );
1133
+ elog (INFO ,"Indexes arevalid " );
1127
1134
else
1128
- elog (ERROR ,"Indexs checking failed " );
1129
-
1130
- if (backup_files_list )
1131
- {
1132
- parray_walk (backup_files_list ,pgFileFree );
1133
- parray_free (backup_files_list );
1134
- backup_files_list = NULL ;
1135
- }
1135
+ elog (ERROR ,"Some indexes are corrupted " );
1136
+
1137
+ // if (backup_files_list)
1138
+ // {
1139
+ // parray_walk(backup_files_list, pgFileFree);
1140
+ // parray_free(backup_files_list);
1141
+ // backup_files_list = NULL;
1142
+ // }
1136
1143
}
1137
1144
1138
1145
/* Entry point of pg_probackup CHECKDB subcommand. */
@@ -1150,8 +1157,8 @@ do_checkdb(bool need_amcheck)
1150
1157
if (!skip_block_validation )
1151
1158
do_block_validation ();
1152
1159
1153
- // if (need_amcheck)
1154
- // do_amcheck();
1160
+ if (need_amcheck )
1161
+ do_amcheck ();
1155
1162
1156
1163
return 0 ;
1157
1164
}
@@ -2540,7 +2547,7 @@ threads_conn_disconnect(bool fatal, void *userdata)
2540
2547
{
2541
2548
//int i;
2542
2549
2543
- elog (VERBOSE ,"threads_conn_disconnect, num_threads %d" ,num_threads );
2550
+ // elog(VERBOSE, "threads_conn_disconnect, num_threads %d", num_threads);
2544
2551
// for (i = 0; i < num_threads; i++)
2545
2552
// {
2546
2553
// backup_files_arg *arg = &(threads_args[i]);
@@ -2654,7 +2661,9 @@ check_indexes(void *arg)
2654
2661
if (interrupted || thread_interrupted )
2655
2662
elog (ERROR ,"interrupted during checkdb --amcheck" );
2656
2663
2657
- elog (VERBOSE ,"Checking index number %d of %d : \"%s\" " ,i ,n_indexes ,ind -> name );
2664
+ if (progress )
2665
+ elog (INFO ,"Progress: (%d/%d). Processing index '%s.%s'" ,
2666
+ i + 1 ,n_indexes ,ind -> amcheck_nspname ,ind -> name );
2658
2667
2659
2668
if (arguments -> backup_conn == NULL )
2660
2669
{
@@ -2666,34 +2675,20 @@ check_indexes(void *arg)
2666
2675
ind -> dbname ,
2667
2676
instance_config .pguser );
2668
2677
arguments -> cancel_conn = PQgetCancel (arguments -> backup_conn );
2669
-
2670
- res = pgut_execute_parallel (arguments -> backup_conn ,
2671
- arguments -> cancel_conn ,
2672
- "BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;" ,0 ,NULL , false);
2673
- PQclear (res );
2674
-
2675
- query = palloc (strlen ("SET TRANSACTION SNAPSHOT '' " )+ strlen (ind -> snapshot ));
2676
- sprintf (query ,"SET TRANSACTION SNAPSHOT '%s'" ,ind -> snapshot );
2677
-
2678
- res = pgut_execute_parallel (arguments -> backup_conn ,
2679
- arguments -> cancel_conn ,
2680
- query ,0 ,NULL , false);
2681
- PQclear (res );
2682
-
2683
- free (query );
2684
2678
}
2685
2679
2686
2680
/* remember that we have a failed check */
2687
2681
if (!amcheck_one_index (arguments ,ind ))
2688
- arguments -> ret = 1 ;
2682
+ arguments -> ret = 2 ;
2689
2683
}
2690
2684
2691
2685
/* Close connection */
2692
2686
if (arguments -> backup_conn )
2693
2687
pgut_disconnect (arguments -> backup_conn );
2694
2688
2695
2689
/* TODO where should we set arguments->ret to 1? */
2696
- arguments -> ret = 0 ;
2690
+ if (arguments -> ret == 1 )
2691
+ arguments -> ret = 0 ;
2697
2692
2698
2693
return NULL ;
2699
2694
}
@@ -3410,7 +3405,7 @@ pg_ptrack_get_block(backup_files_arg *arguments,
3410
3405
res = pgut_execute_parallel (arguments -> backup_conn ,
3411
3406
arguments -> cancel_conn ,
3412
3407
"SELECT pg_catalog.pg_ptrack_get_block_2($1, $2, $3, $4)" ,
3413
- 4 , (const char * * )params , true);
3408
+ 4 , (const char * * )params , true, false );
3414
3409
3415
3410
if (PQnfields (res )!= 1 )
3416
3411
{
@@ -3478,38 +3473,39 @@ check_external_for_tablespaces(parray *external_list)
3478
3473
PQclear (res );
3479
3474
}
3480
3475
3481
- /*Clear ptrack files in all databases of the instance we connected to */
3476
+ /*Get index list for given database */
3482
3477
static parray *
3483
3478
get_index_list (PGresult * res_db ,int db_number ,
3484
- bool * first_db_with_amcheck ,PGconn * db_conn )
3479
+ bool first_db_with_amcheck ,PGconn * db_conn )
3485
3480
{
3486
3481
PGresult * res ;
3487
3482
char * nspname = NULL ;
3488
3483
char * snapshot = NULL ;
3489
3484
int i ;
3490
3485
3491
3486
dbname = PQgetvalue (res_db ,db_number ,0 );
3492
- if (strcmp (dbname ,"template0" )== 0 )
3493
- return NULL ;
3494
3487
3495
3488
db_conn = pgut_connect (instance_config .pghost ,instance_config .pgport ,
3496
3489
dbname ,
3497
3490
instance_config .pguser );
3498
3491
3499
- res = pgut_execute (db_conn ,"select extname, nspname, extversion from pg_namespace "
3500
- "n join pg_extension e on n.oid=e.extnamespace where e.extname='amcheck'" ,
3492
+ res = pgut_execute (db_conn ,"SELECT extname, nspname, extversion "
3493
+ "FROM pg_namespace n "
3494
+ "JOIN pg_extension e "
3495
+ "ON n.oid=e.extnamespace "
3496
+ "WHERE e.extname='amcheck'" ,
3501
3497
0 ,NULL );
3502
3498
3503
3499
if (PQresultStatus (res )!= PGRES_TUPLES_OK )
3504
3500
{
3505
3501
PQclear (res );
3506
- elog (ERROR ,"cannot check if amcheck is installed in database %s: %s" ,
3502
+ elog (ERROR ,"Cannot check if amcheck is installed in database %s: %s" ,
3507
3503
dbname ,PQerrorMessage (db_conn ));
3508
3504
}
3509
3505
3510
3506
if (PQntuples (res )< 1 )
3511
3507
{
3512
- elog (WARNING ,"extension amcheck is not installed in database %s" ,dbname );
3508
+ elog (WARNING ,"Extension amcheck is not installed in database %s" ,dbname );
3513
3509
return NULL ;
3514
3510
}
3515
3511
@@ -3520,56 +3516,32 @@ get_index_list(PGresult *res_db, int db_number,
3520
3516
* In order to avoid duplicates, select global indexes
3521
3517
* (tablespace pg_global with oid 1664) only once
3522
3518
*/
3523
- if (* first_db_with_amcheck )
3519
+ if (first_db_with_amcheck )
3524
3520
{
3525
- res = pgut_execute (db_conn ,"BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;" ,0 ,NULL );
3526
- PQclear (res );
3527
-
3528
- res = pgut_execute (db_conn ,"SELECT pg_export_snapshot();" ,0 ,NULL );
3529
-
3530
- if (PQntuples (res )< 1 )
3531
- elog (ERROR ,"Failed to export snapshot for amcheck in database %s" ,dbname );
3532
-
3533
- snapshot = pgut_malloc (strlen (PQgetvalue (res ,0 ,0 ))+ 1 );
3534
- strcpy (snapshot ,PQgetvalue (res ,0 ,0 ));
3535
-
3536
- PQclear (res );
3537
3521
3522
+ /* select only valid btree and persistent indexes */
3538
3523
res = pgut_execute (db_conn ,"SELECT cls.oid, cls.relname"
3539
3524
" FROM pg_index idx "
3540
3525
" JOIN pg_class cls ON cls.oid=idx.indexrelid "
3541
3526
" JOIN pg_am am ON am.oid=cls.relam "
3542
3527
" WHERE am.amname='btree' AND cls.relpersistence != 't'"
3543
3528
" AND idx.indisready AND idx.indisvalid; " ,0 ,NULL );
3544
- * first_db_with_amcheck = false;
3545
3529
}
3546
3530
else
3547
3531
{
3548
- res = pgut_execute (db_conn ,"BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;" ,0 ,NULL );
3549
- PQclear (res );
3550
-
3551
- res = pgut_execute (db_conn ,"SELECT pg_export_snapshot();" ,0 ,NULL );
3552
-
3553
- if (PQntuples (res )< 1 )
3554
- elog (ERROR ,"Failed to export snapshot for amcheck in database %s" ,dbname );
3555
3532
3556
- if (snapshot )
3557
- free (snapshot );
3558
- snapshot = pgut_malloc (strlen (PQgetvalue (res ,0 ,0 ))+ 1 );
3559
- strcpy (snapshot ,PQgetvalue (res ,0 ,0 ));
3560
-
3561
- PQclear (res );
3562
-
3563
- res = pgut_execute (db_conn ,"SELECT cls.oid, cls.relname"
3564
- " FROM pg_index idx "
3565
- " JOIN pg_class cls ON cls.oid=idx.indexrelid "
3566
- " JOIN pg_am am ON am.oid=cls.relam "
3567
- " WHERE am.amname='btree' AND cls.relpersistence != 't'"
3568
- " AND idx.indisready AND idx.indisvalid AND cls.reltablespace!=1664; " ,0 ,NULL );
3533
+ res = pgut_execute (db_conn ,"SELECT cls.oid, cls.relname "
3534
+ "FROM pg_index idx "
3535
+ "JOIN pg_class cls ON cls.oid=idx.indexrelid "
3536
+ "JOIN pg_am am ON am.oid=cls.relam "
3537
+ "JOIN pg_tablespace tbl ON tbl.oid=cls.reltablespace "
3538
+ "WHERE am.amname='btree' AND cls.relpersistence != 't' "
3539
+ "AND idx.indisready AND idx.indisvalid "
3540
+ "AND tbl.spcname !='pg_global'" ,0 ,NULL );
3569
3541
}
3570
3542
3571
3543
/* add info needed to check indexes into index_list */
3572
- for (i = 0 ;i < PQntuples (res );i ++ )
3544
+ for (i = 0 ;i < PQntuples (res );i ++ )
3573
3545
{
3574
3546
pg_indexEntry * ind = (pg_indexEntry * )pgut_malloc (sizeof (pg_indexEntry ));
3575
3547
char * name = NULL ;
@@ -3582,9 +3554,6 @@ get_index_list(PGresult *res_db, int db_number,
3582
3554
ind -> dbname = pgut_malloc (strlen (dbname )+ 1 );
3583
3555
strcpy (ind -> dbname ,dbname );
3584
3556
3585
- ind -> snapshot = pgut_malloc (strlen (snapshot )+ 1 );
3586
- strcpy (ind -> snapshot ,snapshot );
3587
-
3588
3557
ind -> amcheck_nspname = pgut_malloc (strlen (nspname )+ 1 );
3589
3558
strcpy (ind -> amcheck_nspname ,nspname );
3590
3559
pg_atomic_clear_flag (& ind -> lock );
@@ -3598,6 +3567,8 @@ get_index_list(PGresult *res_db, int db_number,
3598
3567
3599
3568
PQclear (res );
3600
3569
3570
+ elog (INFO ,"Amcheck database '%s'" ,dbname );
3571
+
3601
3572
return index_list ;
3602
3573
}
3603
3574
@@ -3613,27 +3584,26 @@ amcheck_one_index(backup_files_arg *arguments,
3613
3584
3614
3585
sprintf (params [0 ],"%i" ,ind -> indexrelid );
3615
3586
3616
- elog (VERBOSE ,"amcheck index: '%s'" ,ind -> name );
3617
-
3618
3587
query = palloc (strlen (ind -> amcheck_nspname )+ strlen ("SELECT .bt_index_check($1)" )+ 1 );
3619
3588
sprintf (query ,"SELECT %s.bt_index_check($1)" ,ind -> amcheck_nspname );
3620
3589
3621
3590
res = pgut_execute_parallel (arguments -> backup_conn ,
3622
3591
arguments -> cancel_conn ,
3623
- query ,1 , (const char * * )params , true);
3592
+ query ,1 , (const char * * )params , true, true );
3624
3593
3625
3594
if (PQresultStatus (res )!= PGRES_TUPLES_OK )
3626
3595
{
3627
- elog (VERBOSE ,"amcheck failed for relation oid %u: %s" ,
3628
- ind -> indexrelid ,PQresultErrorMessage (res ));
3596
+ elog (WARNING ,"Amcheck failed for index: '%s.%s': %s" ,
3597
+ ind -> amcheck_nspname ,
3598
+ ind -> name ,PQresultErrorMessage (res ));
3629
3599
3630
3600
pfree (params [0 ]);
3631
3601
PQclear (res );
3632
3602
return false;
3633
3603
}
3634
3604
else
3635
- elog (VERBOSE ,"amcheck succeeded forrelation oid %u " ,
3636
- ind -> indexrelid );
3605
+ elog (LOG ,"Amcheck succeeded forindex: '%s.%s' " ,
3606
+ ind -> amcheck_nspname , ind -> name );
3637
3607
3638
3608
pfree (params [0 ]);
3639
3609
PQclear (res );