@@ -150,7 +150,7 @@ typedef struct ReorderBufferIterTXNEntry
150
150
ReorderBufferChange * change ;
151
151
ReorderBufferTXN * txn ;
152
152
TXNEntryFile file ;
153
- XLogSegNo segno ;
153
+ int restore_from ;
154
154
} ReorderBufferIterTXNEntry ;
155
155
156
156
typedef struct ReorderBufferIterTXNState
@@ -216,6 +216,11 @@ static const Size max_changes_in_memory = 4096; /* XXX for restore only */
216
216
/* GUC variable */
217
217
int debug_logical_replication_streaming = DEBUG_LOGICAL_REP_STREAMING_BUFFERED ;
218
218
219
+ typedef struct WalSgmtsEntry
220
+ {
221
+ XLogSegNo segno ;
222
+ } WalSgmtsEntry ;
223
+
219
224
/* ---------------------------------------
220
225
* primary reorderbuffer support routines
221
226
* ---------------------------------------
@@ -255,7 +260,7 @@ static void ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn);
255
260
static void ReorderBufferSerializeChange (ReorderBuffer * rb , ReorderBufferTXN * txn ,
256
261
int fd , ReorderBufferChange * change );
257
262
static Size ReorderBufferRestoreChanges (ReorderBuffer * rb , ReorderBufferTXN * txn ,
258
- TXNEntryFile * file , XLogSegNo * segno );
263
+ TXNEntryFile * file , int * restore_from );
259
264
static void ReorderBufferRestoreChange (ReorderBuffer * rb , ReorderBufferTXN * txn ,
260
265
char * data );
261
266
static void ReorderBufferRestoreCleanup (ReorderBuffer * rb , ReorderBufferTXN * txn );
@@ -435,6 +440,7 @@ ReorderBufferAllocTXN(ReorderBuffer *rb)
435
440
/* InvalidCommandId is not zero, so set it explicitly */
436
441
txn -> command_id = InvalidCommandId ;
437
442
txn -> output_plugin_private = NULL ;
443
+ txn -> walsgmts = NIL ;
438
444
439
445
return txn ;
440
446
}
@@ -1308,7 +1314,7 @@ ReorderBufferIterTXNInit(ReorderBuffer *rb, ReorderBufferTXN *txn,
1308
1314
for (off = 0 ; off < state -> nr_txns ; off ++ )
1309
1315
{
1310
1316
state -> entries [off ].file .vfd = -1 ;
1311
- state -> entries [off ].segno = 0 ;
1317
+ state -> entries [off ].restore_from = 0 ;
1312
1318
}
1313
1319
1314
1320
/* allocate heap */
@@ -1336,7 +1342,7 @@ ReorderBufferIterTXNInit(ReorderBuffer *rb, ReorderBufferTXN *txn,
1336
1342
/* serialize remaining changes */
1337
1343
ReorderBufferSerializeTXN (rb , txn );
1338
1344
ReorderBufferRestoreChanges (rb , txn , & state -> entries [off ].file ,
1339
- & state -> entries [off ].segno );
1345
+ & state -> entries [off ].restore_from );
1340
1346
}
1341
1347
1342
1348
cur_change = dlist_head_element (ReorderBufferChange , node ,
@@ -1366,7 +1372,7 @@ ReorderBufferIterTXNInit(ReorderBuffer *rb, ReorderBufferTXN *txn,
1366
1372
ReorderBufferSerializeTXN (rb , cur_txn );
1367
1373
ReorderBufferRestoreChanges (rb , cur_txn ,
1368
1374
& state -> entries [off ].file ,
1369
- & state -> entries [off ].segno );
1375
+ & state -> entries [off ].restore_from );
1370
1376
}
1371
1377
cur_change = dlist_head_element (ReorderBufferChange , node ,
1372
1378
& cur_txn -> changes );
@@ -1451,7 +1457,7 @@ ReorderBufferIterTXNNext(ReorderBuffer *rb, ReorderBufferIterTXNState *state)
1451
1457
*/
1452
1458
rb -> totalBytes += entry -> txn -> size ;
1453
1459
if (ReorderBufferRestoreChanges (rb , entry -> txn , & entry -> file ,
1454
- & state -> entries [off ].segno ))
1460
+ & state -> entries [off ].restore_from ))
1455
1461
{
1456
1462
/* successfully restored changes from disk */
1457
1463
ReorderBufferChange * next_change =
@@ -3838,6 +3844,7 @@ ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
3838
3844
XLogSegNo curOpenSegNo = 0 ;
3839
3845
Size spilled = 0 ;
3840
3846
Size size = txn -> size ;
3847
+ MemoryContext oldcontext ;
3841
3848
3842
3849
elog (DEBUG2 , "spill %u changes in XID %u to disk" ,
3843
3850
(uint32 ) txn -> nentries_mem , txn -> xid );
@@ -3881,7 +3888,23 @@ ReorderBufferSerializeTXN(ReorderBuffer *rb, ReorderBufferTXN *txn)
3881
3888
3882
3889
/* open segment, create it if necessary */
3883
3890
fd = OpenTransientFile (path ,
3884
- O_CREAT | O_WRONLY | O_APPEND | PG_BINARY );
3891
+ O_CREAT | O_EXCL | O_WRONLY | O_APPEND | PG_BINARY );
3892
+
3893
+ if (fd < 0 )
3894
+ fd = OpenTransientFile (path ,
3895
+ O_CREAT | O_WRONLY | O_APPEND | PG_BINARY );
3896
+ else
3897
+ {
3898
+ WalSgmtsEntry * entry ;
3899
+
3900
+ oldcontext = MemoryContextSwitchTo (rb -> context );
3901
+
3902
+ entry = palloc (sizeof (WalSgmtsEntry ));
3903
+ entry -> segno = curOpenSegNo ;
3904
+
3905
+ txn -> walsgmts = lappend (txn -> walsgmts , entry );
3906
+ MemoryContextSwitchTo (oldcontext );
3907
+ }
3885
3908
3886
3909
if (fd < 0 )
3887
3910
ereport (ERROR ,
@@ -4378,16 +4401,12 @@ ReorderBufferChangeSize(ReorderBufferChange *change)
4378
4401
*/
4379
4402
static Size
4380
4403
ReorderBufferRestoreChanges (ReorderBuffer * rb , ReorderBufferTXN * txn ,
4381
- TXNEntryFile * file , XLogSegNo * segno )
4404
+ TXNEntryFile * file , int * restore_from )
4382
4405
{
4383
4406
Size restored = 0 ;
4384
- XLogSegNo last_segno ;
4385
4407
dlist_mutable_iter cleanup_iter ;
4386
4408
File * fd = & file -> vfd ;
4387
4409
4388
- Assert (txn -> first_lsn != InvalidXLogRecPtr );
4389
- Assert (txn -> final_lsn != InvalidXLogRecPtr );
4390
-
4391
4410
/* free current entries, so we have memory for more */
4392
4411
dlist_foreach_modify (cleanup_iter , & txn -> changes )
4393
4412
{
@@ -4400,9 +4419,8 @@ ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn,
4400
4419
txn -> nentries_mem = 0 ;
4401
4420
Assert (dlist_is_empty (& txn -> changes ));
4402
4421
4403
- XLByteToSeg (txn -> final_lsn , last_segno , wal_segment_size );
4404
-
4405
- while (restored < max_changes_in_memory && * segno <= last_segno )
4422
+ while (restored < max_changes_in_memory &&
4423
+ (* restore_from ) < txn -> walsgmts -> length )
4406
4424
{
4407
4425
int readBytes ;
4408
4426
ReorderBufferDiskChange * ondisk ;
@@ -4412,19 +4430,23 @@ ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn,
4412
4430
if (* fd == -1 )
4413
4431
{
4414
4432
char path [MAXPGPATH ];
4433
+ ListCell * lc ;
4434
+ WalSgmtsEntry * entry ;
4435
+ XLogSegNo segno ;
4415
4436
4416
- /* first time in */
4417
- if (* segno == 0 )
4418
- XLByteToSeg (txn -> first_lsn , * segno , wal_segment_size );
4437
+ /* Next wal segment for the transaction */
4438
+ lc = list_nth_cell (txn -> walsgmts , * restore_from );
4439
+ entry = (WalSgmtsEntry * ) lfirst (lc );
4440
+ segno = entry -> segno ;
4419
4441
4420
- Assert (* segno != 0 || dlist_is_empty (& txn -> changes ));
4442
+ Assert (segno != 0 || dlist_is_empty (& txn -> changes ));
4421
4443
4422
4444
/*
4423
4445
* No need to care about TLIs here, only used during a single run,
4424
4446
* so each LSN only maps to a specific WAL record.
4425
4447
*/
4426
4448
ReorderBufferSerializedPath (path , MyReplicationSlot , txn -> xid ,
4427
- * segno );
4449
+ segno );
4428
4450
4429
4451
* fd = PathNameOpenFile (path , O_RDONLY | PG_BINARY );
4430
4452
@@ -4434,7 +4456,7 @@ ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn,
4434
4456
if (* fd < 0 && errno == ENOENT )
4435
4457
{
4436
4458
* fd = -1 ;
4437
- (* segno )++ ;
4459
+ (* restore_from )++ ;
4438
4460
continue ;
4439
4461
}
4440
4462
else if (* fd < 0 )
@@ -4459,7 +4481,7 @@ ReorderBufferRestoreChanges(ReorderBuffer *rb, ReorderBufferTXN *txn,
4459
4481
{
4460
4482
FileClose (* fd );
4461
4483
* fd = -1 ;
4462
- (* segno )++ ;
4484
+ (* restore_from )++ ;
4463
4485
continue ;
4464
4486
}
4465
4487
else if (readBytes < 0 )
@@ -4689,26 +4711,22 @@ ReorderBufferRestoreChange(ReorderBuffer *rb, ReorderBufferTXN *txn,
4689
4711
static void
4690
4712
ReorderBufferRestoreCleanup (ReorderBuffer * rb , ReorderBufferTXN * txn )
4691
4713
{
4692
- XLogSegNo first ;
4693
- XLogSegNo cur ;
4694
- XLogSegNo last ;
4695
-
4696
- Assert (txn -> first_lsn != InvalidXLogRecPtr );
4697
- Assert (txn -> final_lsn != InvalidXLogRecPtr );
4698
-
4699
- XLByteToSeg (txn -> first_lsn , first , wal_segment_size );
4700
- XLByteToSeg (txn -> final_lsn , last , wal_segment_size );
4714
+ ListCell * cell ;
4701
4715
4702
4716
/* iterate over all possible filenames, and delete them */
4703
- for ( cur = first ; cur <= last ; cur ++ )
4717
+ foreach ( cell , txn -> walsgmts )
4704
4718
{
4719
+ WalSgmtsEntry * entry = (WalSgmtsEntry * )lfirst (cell );
4720
+ XLogSegNo curr_segno = entry -> segno ;
4705
4721
char path [MAXPGPATH ];
4706
4722
4707
- ReorderBufferSerializedPath (path , MyReplicationSlot , txn -> xid , cur );
4723
+ ReorderBufferSerializedPath (path , MyReplicationSlot , txn -> xid , curr_segno );
4708
4724
if (unlink (path ) != 0 && errno != ENOENT )
4709
4725
ereport (ERROR ,
4710
4726
(errcode_for_file_access (),
4711
4727
errmsg ("could not remove file \"%s\": %m" , path )));
4728
+
4729
+ txn -> walsgmts = foreach_delete_current (txn -> walsgmts , cell );
4712
4730
}
4713
4731
}
4714
4732
0 commit comments