@@ -860,6 +860,18 @@ InitXLogPageRead(XLogReaderData *reader_data, const char *archivedir,
860860 return xlogreader ;
861861}
862862
863+ /*
864+ * Comparison function to sort xlog_thread_arg array.
865+ */
866+ static int
867+ xlog_thread_arg_comp (const void * a1 , const void * a2 )
868+ {
869+ const xlog_thread_arg * arg1 = a1 ;
870+ const xlog_thread_arg * arg2 = a2 ;
871+
872+ return arg1 -> reader_data .xlogsegno - arg2 -> reader_data .xlogsegno ;
873+ }
874+
863875/*
864876 * Run WAL processing routines using threads. Start from startpoint up to
865877 * endpoint. It is possible to send zero endpoint, threads will read WAL
@@ -877,7 +889,6 @@ RunXLogThreads(const char *archivedir, time_t target_time,
877889 int i ;
878890 int threads_need = 0 ;
879891 XLogSegNo endSegNo = 0 ;
880- XLogSegNo errorSegNo = 0 ;
881892 bool result = true;
882893
883894 if (!XRecOffIsValid (startpoint ))
@@ -956,28 +967,27 @@ RunXLogThreads(const char *archivedir, time_t target_time,
956967 result = false;
957968 }
958969
970+ /* Release threads here, use thread_args only below */
971+ pfree (threads );
972+ threads = NULL ;
973+
959974 if (last_rec )
975+ {
976+ /*
977+ * We need to sort xlog_thread_arg array by xlogsegno to return latest
978+ * possible record up to which restore is possible. We need to sort to
979+ * detect failed thread between start segment and target segment.
980+ *
981+ * Loop stops on first failed thread.
982+ */
983+ if (threads_need > 1 )
984+ qsort ((void * ) thread_args , threads_need , sizeof (xlog_thread_arg ),
985+ xlog_thread_arg_comp );
986+
960987 for (i = 0 ; i < threads_need ; i ++ )
961988 {
962989 XLogRecTarget * cur_rec ;
963990
964- if (thread_args [i ].ret != 0 )
965- {
966- /*
967- * Save invalid segment number after which all segments are not
968- * valid.
969- */
970- if (errorSegNo == 0 ||
971- errorSegNo > thread_args [i ].reader_data .xlogsegno )
972- errorSegNo = thread_args [i ].reader_data .xlogsegno ;
973- continue ;
974- }
975-
976- /* Is this segment valid */
977- if (errorSegNo != 0 &&
978- thread_args [i ].reader_data .xlogsegno > errorSegNo )
979- continue ;
980-
981991 cur_rec = & thread_args [i ].reader_data .cur_rec ;
982992 /*
983993 * If we got the target return minimum possible record.
@@ -997,9 +1007,16 @@ RunXLogThreads(const char *archivedir, time_t target_time,
9971007 */
9981008 else if (last_rec -> rec_lsn < cur_rec -> rec_lsn )
9991009 * last_rec = * cur_rec ;
1010+
1011+ /*
1012+ * We reached failed thread, so stop here. We cannot use following
1013+ * WAL records after failed segment.
1014+ */
1015+ if (thread_args [i ].ret != 0 )
1016+ break ;
10001017 }
1018+ }
10011019
1002- pfree (threads );
10031020 pfree (thread_args );
10041021
10051022 return result ;
0 commit comments