@@ -141,12 +141,13 @@ static void *
141141doExtractPageMap (void * arg )
142142{
143143 xlog_thread_arg * extract_arg = (xlog_thread_arg * ) arg ;
144+ XLogPageReadPrivate * private_data ;
144145 XLogReaderState * xlogreader ;
145146 XLogSegNo nextSegNo = 0 ;
146147 char * errormsg ;
147148
148- xlogreader = XLogReaderAllocate ( & SimpleXLogPageRead ,
149- & extract_arg -> private_data );
149+ private_data = & extract_arg -> private_data ;
150+ xlogreader = XLogReaderAllocate ( & SimpleXLogPageRead , private_data );
150151 if (xlogreader == NULL )
151152 elog (ERROR , "out of memory" );
152153
@@ -158,6 +159,9 @@ doExtractPageMap(void *arg)
158159 (uint32 ) (extract_arg -> startpoint >> 32 ),
159160 (uint32 ) (extract_arg -> startpoint ));
160161
162+ /* Switch WAL segment manually below without using SimpleXLogPageRead() */
163+ private_data -> manual_switch = true;
164+
161165 do
162166 {
163167 XLogRecord * record ;
@@ -171,23 +175,28 @@ doExtractPageMap(void *arg)
171175 {
172176 XLogRecPtr errptr ;
173177
174- /* Try to switch to the next WAL segment */
175- if (extract_arg -> private_data .need_switch )
178+ /*
179+ * Try to switch to the next WAL segment. Usually
180+ * SimpleXLogPageRead() does it by itself. But here we need to do it
181+ * manually to support threads.
182+ */
183+ if (private_data -> need_switch )
176184 {
177- extract_arg -> private_data . need_switch = false;
185+ private_data -> need_switch = false;
178186
187+ /* Critical section */
179188 pthread_lock (& wal_segment_mutex );
180189 Assert (nextSegNoToRead );
181- extract_arg -> private_data . xlogsegno = nextSegNoToRead ;
190+ private_data -> xlogsegno = nextSegNoToRead ;
182191 nextSegNoToRead ++ ;
183192 pthread_mutex_unlock (& wal_segment_mutex );
184193
185194 /* We reach the end */
186- if (extract_arg -> private_data . xlogsegno > extract_arg -> endSegNo )
195+ if (private_data -> xlogsegno > extract_arg -> endSegNo )
187196 break ;
188197
189198 /* Adjust next record position */
190- XLogSegNoOffsetToRecPtr (extract_arg -> private_data . xlogsegno , 0 ,
199+ XLogSegNoOffsetToRecPtr (private_data -> xlogsegno , 0 ,
191200 extract_arg -> startpoint );
192201 /* Skip over the page header */
193202 extract_arg -> startpoint = XLogFindNextRecord (xlogreader ,
@@ -217,7 +226,7 @@ doExtractPageMap(void *arg)
217226 * start_lsn, we won't be able to build page map and PAGE backup will
218227 * be incorrect. Stop it and throw an error.
219228 */
220- PrintXLogCorruptionMsg (& extract_arg -> private_data , ERROR );
229+ PrintXLogCorruptionMsg (private_data , ERROR );
221230 }
222231
223232 extractPageInfo (xlogreader );
@@ -255,8 +264,8 @@ extractPageMap(const char *archivedir, XLogRecPtr startpoint, TimeLineID tli,
255264 int threads_need = 0 ;
256265 XLogSegNo endSegNo ;
257266 bool extract_isok = true;
258- pthread_t threads [ num_threads ] ;
259- xlog_thread_arg thread_args [ num_threads ] ;
267+ pthread_t * threads ;
268+ xlog_thread_arg * thread_args ;
260269 time_t start_time ,
261270 end_time ;
262271
@@ -276,6 +285,9 @@ extractPageMap(const char *archivedir, XLogRecPtr startpoint, TimeLineID tli,
276285 nextSegNoToRead = 0 ;
277286 time (& start_time );
278287
288+ threads = (pthread_t * ) palloc (sizeof (pthread_t ) * num_threads );
289+ thread_args = (xlog_thread_arg * ) palloc (sizeof (xlog_thread_arg )* num_threads );
290+
279291 /*
280292 * Initialize thread args.
281293 *
@@ -286,7 +298,6 @@ extractPageMap(const char *archivedir, XLogRecPtr startpoint, TimeLineID tli,
286298 {
287299 InitXLogPageRead (& thread_args [i ].private_data , archivedir , tli , false);
288300 thread_args [i ].thread_num = i ;
289- thread_args [i ].private_data .manual_switch = true;
290301
291302 thread_args [i ].startpoint = startpoint ;
292303 thread_args [i ].endpoint = endpoint ;
@@ -327,6 +338,9 @@ extractPageMap(const char *archivedir, XLogRecPtr startpoint, TimeLineID tli,
327338 extract_isok = false;
328339 }
329340
341+ pfree (threads );
342+ pfree (thread_args );
343+
330344 time (& end_time );
331345 if (extract_isok )
332346 elog (LOG , "Pagemap compiled, time elapsed %.0f sec" ,
@@ -700,6 +714,10 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
700714 if (!XLByteInSeg (targetPagePtr , private_data -> xlogsegno ))
701715 {
702716 CleanupXLogPageRead (xlogreader );
717+ /*
718+ * Do not switch to next WAL segment in this function. Currently it is
719+ * manually switched only in doExtractPageMap().
720+ */
703721 if (private_data -> manual_switch )
704722 {
705723 private_data -> need_switch = true;
@@ -709,6 +727,7 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr,
709727
710728 XLByteToSeg (targetPagePtr , private_data -> xlogsegno );
711729
730+ /* Try to switch to the next WAL segment */
712731 if (!private_data -> xlogexists )
713732 {
714733 char xlogfname [MAXFNAMELEN ];
0 commit comments