7
7
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
8
8
* Portions Copyright (c) 1994, Regents of the University of California
9
9
*
10
- * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.166 2004/08/29 05:06:40 momjian Exp $
10
+ * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.167 2004/08/29 16:34:47 tgl Exp $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -409,6 +409,10 @@ static uint32 readOff = 0;
409
409
/* Buffer for currently read page (BLCKSZ bytes) */
410
410
static char * readBuf = NULL ;
411
411
412
+ /* Buffer for current ReadRecord result (expandable) */
413
+ static char * readRecordBuf = NULL ;
414
+ static uint32 readRecordBufSize = 0 ;
415
+
412
416
/* State information for XLOG reading */
413
417
static XLogRecPtr ReadRecPtr ;
414
418
static XLogRecPtr EndRecPtr ;
@@ -440,11 +444,9 @@ static bool RestoreArchivedFile(char *path, const char *xlogfname,
440
444
const char * recovername , off_t expectedSize );
441
445
static void PreallocXlogFiles (XLogRecPtr endptr );
442
446
static void MoveOfflineLogs (uint32 log , uint32 seg , XLogRecPtr endptr );
443
- static XLogRecord * ReadRecord (XLogRecPtr * RecPtr , int emode , char * buffer );
447
+ static XLogRecord * ReadRecord (XLogRecPtr * RecPtr , int emode );
444
448
static bool ValidXLOGHeader (XLogPageHeader hdr , int emode );
445
- static XLogRecord * ReadCheckpointRecord (XLogRecPtr RecPtr ,
446
- int whichChkpt ,
447
- char * buffer );
449
+ static XLogRecord * ReadCheckpointRecord (XLogRecPtr RecPtr , int whichChkpt );
448
450
static List * readTimeLineHistory (TimeLineID targetTLI );
449
451
static bool existsTimeLineHistory (TimeLineID probeTLI );
450
452
static TimeLineID findNewestTimeLine (TimeLineID startTLI );
@@ -627,7 +629,7 @@ begin:;
627
629
* may not be true forever. If you need to remove the len == 0 check,
628
630
* also remove the check for xl_len == 0 in ReadRecord, below.
629
631
*/
630
- if (len == 0 || len > MAXLOGRECSZ )
632
+ if (len == 0 )
631
633
elog (PANIC , "invalid xlog record length %u" , len );
632
634
633
635
START_CRIT_SECTION ();
@@ -745,14 +747,6 @@ begin:;
745
747
/* Insert record header */
746
748
747
749
record -> xl_prev = Insert -> PrevRecord ;
748
- if (no_tran )
749
- {
750
- record -> xl_xact_prev .xlogid = 0 ;
751
- record -> xl_xact_prev .xrecoff = 0 ;
752
- }
753
- else
754
- record -> xl_xact_prev = MyLastRecPtr ;
755
-
756
750
record -> xl_xid = GetCurrentTransactionId ();
757
751
record -> xl_len = len ; /* doesn't include backup blocks */
758
752
record -> xl_info = info ;
@@ -2316,14 +2310,14 @@ RecordIsValid(XLogRecord *record, XLogRecPtr recptr, int emode)
2316
2310
* If no valid record is available, returns NULL, or fails if emode is PANIC.
2317
2311
* (emode must be either PANIC or LOG.)
2318
2312
*
2319
- * buffer is a workspace at least _INTL_MAXLOGRECSZ bytes long. It is needed
2320
- * to reassemble a record that crosses block boundaries. Note that on
2321
- * successful return, the returned record pointer always points at buffer.
2313
+ * The record is copied into readRecordBuf, so that on successful return,
2314
+ * the returned record pointer always points there.
2322
2315
*/
2323
2316
static XLogRecord *
2324
- ReadRecord (XLogRecPtr * RecPtr , int emode , char * buffer )
2317
+ ReadRecord (XLogRecPtr * RecPtr , int emode )
2325
2318
{
2326
2319
XLogRecord * record ;
2320
+ char * buffer ;
2327
2321
XLogRecPtr tmpRecPtr = EndRecPtr ;
2328
2322
bool randAccess = false;
2329
2323
uint32 len ,
@@ -2467,6 +2461,13 @@ got_record:;
2467
2461
RecPtr -> xlogid , RecPtr -> xrecoff )));
2468
2462
goto next_record_is_invalid ;
2469
2463
}
2464
+ if (record -> xl_rmid > RM_MAX_ID )
2465
+ {
2466
+ ereport (emode ,
2467
+ (errmsg ("invalid resource manager ID %u at %X/%X" ,
2468
+ record -> xl_rmid , RecPtr -> xlogid , RecPtr -> xrecoff )));
2469
+ goto next_record_is_invalid ;
2470
+ }
2470
2471
2471
2472
/*
2472
2473
* Compute total length of record including any appended backup
@@ -2481,24 +2482,34 @@ got_record:;
2481
2482
}
2482
2483
2483
2484
/*
2484
- * Make sure it will fit in buffer (currently, it is mechanically
2485
- * impossible for this test to fail, but it seems like a good idea
2486
- * anyway).
2485
+ * Allocate or enlarge readRecordBuf as needed. To avoid useless
2486
+ * small increases, round its size to a multiple of BLCKSZ, and make
2487
+ * sure it's at least 4*BLCKSZ to start with. (That is enough for
2488
+ * all "normal" records, but very large commit or abort records might
2489
+ * need more space.)
2487
2490
*/
2488
- if (total_len > _INTL_MAXLOGRECSZ )
2489
- {
2490
- ereport (emode ,
2491
- (errmsg ("record length %u at %X/%X too long" ,
2492
- total_len , RecPtr -> xlogid , RecPtr -> xrecoff )));
2493
- goto next_record_is_invalid ;
2494
- }
2495
- if (record -> xl_rmid > RM_MAX_ID )
2491
+ if (total_len > readRecordBufSize )
2496
2492
{
2497
- ereport (emode ,
2498
- (errmsg ("invalid resource manager ID %u at %X/%X" ,
2499
- record -> xl_rmid , RecPtr -> xlogid , RecPtr -> xrecoff )));
2500
- goto next_record_is_invalid ;
2493
+ uint32 newSize = total_len ;
2494
+
2495
+ newSize += BLCKSZ - (newSize % BLCKSZ );
2496
+ newSize = Max (newSize , 4 * BLCKSZ );
2497
+ if (readRecordBuf )
2498
+ free (readRecordBuf );
2499
+ readRecordBuf = (char * ) malloc (newSize );
2500
+ if (!readRecordBuf )
2501
+ {
2502
+ readRecordBufSize = 0 ;
2503
+ /* We treat this as a "bogus data" condition */
2504
+ ereport (emode ,
2505
+ (errmsg ("record length %u at %X/%X too long" ,
2506
+ total_len , RecPtr -> xlogid , RecPtr -> xrecoff )));
2507
+ goto next_record_is_invalid ;
2508
+ }
2509
+ readRecordBufSize = newSize ;
2501
2510
}
2511
+
2512
+ buffer = readRecordBuf ;
2502
2513
nextRecord = NULL ;
2503
2514
len = BLCKSZ - RecPtr -> xrecoff % BLCKSZ ;
2504
2515
if (total_len > len )
@@ -3481,8 +3492,6 @@ BootStrapXLOG(void)
3481
3492
record = (XLogRecord * ) ((char * ) page + SizeOfXLogLongPHD );
3482
3493
record -> xl_prev .xlogid = 0 ;
3483
3494
record -> xl_prev .xrecoff = 0 ;
3484
- record -> xl_xact_prev .xlogid = 0 ;
3485
- record -> xl_xact_prev .xrecoff = 0 ;
3486
3495
record -> xl_xid = InvalidTransactionId ;
3487
3496
record -> xl_len = sizeof (checkPoint );
3488
3497
record -> xl_info = XLOG_CHECKPOINT_SHUTDOWN ;
@@ -3981,12 +3990,8 @@ StartupXLOG(void)
3981
3990
uint32 endLogId ;
3982
3991
uint32 endLogSeg ;
3983
3992
XLogRecord * record ;
3984
- char * buffer ;
3985
3993
uint32 freespace ;
3986
3994
3987
- /* Use malloc() to ensure record buffer is MAXALIGNED */
3988
- buffer = (char * ) malloc (_INTL_MAXLOGRECSZ );
3989
-
3990
3995
CritSectionCount ++ ;
3991
3996
3992
3997
/*
@@ -4063,7 +4068,7 @@ StartupXLOG(void)
4063
4068
* from the checkpoint it identifies, rather than using
4064
4069
* pg_control.
4065
4070
*/
4066
- record = ReadCheckpointRecord (checkPointLoc , 0 , buffer );
4071
+ record = ReadCheckpointRecord (checkPointLoc , 0 );
4067
4072
if (record != NULL )
4068
4073
{
4069
4074
ereport (LOG ,
@@ -4085,7 +4090,7 @@ StartupXLOG(void)
4085
4090
* according to pg_control is broken, try the next-to-last one.
4086
4091
*/
4087
4092
checkPointLoc = ControlFile -> checkPoint ;
4088
- record = ReadCheckpointRecord (checkPointLoc , 1 , buffer );
4093
+ record = ReadCheckpointRecord (checkPointLoc , 1 );
4089
4094
if (record != NULL )
4090
4095
{
4091
4096
ereport (LOG ,
@@ -4095,7 +4100,7 @@ StartupXLOG(void)
4095
4100
else
4096
4101
{
4097
4102
checkPointLoc = ControlFile -> prevCheckPoint ;
4098
- record = ReadCheckpointRecord (checkPointLoc , 2 , buffer );
4103
+ record = ReadCheckpointRecord (checkPointLoc , 2 );
4099
4104
if (record != NULL )
4100
4105
{
4101
4106
ereport (LOG ,
@@ -4198,12 +4203,12 @@ StartupXLOG(void)
4198
4203
if (XLByteLT (checkPoint .redo , RecPtr ))
4199
4204
{
4200
4205
/* back up to find the record */
4201
- record = ReadRecord (& (checkPoint .redo ), PANIC , buffer );
4206
+ record = ReadRecord (& (checkPoint .redo ), PANIC );
4202
4207
}
4203
4208
else
4204
4209
{
4205
4210
/* just have to read next record after CheckPoint */
4206
- record = ReadRecord (NULL , LOG , buffer );
4211
+ record = ReadRecord (NULL , LOG );
4207
4212
}
4208
4213
4209
4214
if (record != NULL )
@@ -4263,7 +4268,7 @@ StartupXLOG(void)
4263
4268
4264
4269
LastRec = ReadRecPtr ;
4265
4270
4266
- record = ReadRecord (NULL , LOG , buffer );
4271
+ record = ReadRecord (NULL , LOG );
4267
4272
} while (record != NULL && recoveryContinue );
4268
4273
4269
4274
/*
@@ -4287,7 +4292,7 @@ StartupXLOG(void)
4287
4292
* Re-fetch the last valid or last applied record, so we can identify
4288
4293
* the exact endpoint of what we consider the valid portion of WAL.
4289
4294
*/
4290
- record = ReadRecord (& LastRec , PANIC , buffer );
4295
+ record = ReadRecord (& LastRec , PANIC );
4291
4296
EndOfLog = EndRecPtr ;
4292
4297
XLByteToPrevSeg (EndOfLog , endLogId , endLogSeg );
4293
4298
@@ -4404,7 +4409,7 @@ StartupXLOG(void)
4404
4409
RecPtr .xlogid , RecPtr .xrecoff )));
4405
4410
do
4406
4411
{
4407
- record = ReadRecord (& RecPtr , PANIC , buffer );
4412
+ record = ReadRecord (& RecPtr , PANIC );
4408
4413
if (TransactionIdIsValid (record -> xl_xid ) &&
4409
4414
!TransactionIdDidCommit (record -> xl_xid ))
4410
4415
RmgrTable [record -> xl_rmid ].rm_undo (EndRecPtr , record );
@@ -4498,8 +4503,12 @@ StartupXLOG(void)
4498
4503
free (readBuf );
4499
4504
readBuf = NULL ;
4500
4505
}
4501
-
4502
- free (buffer );
4506
+ if (readRecordBuf )
4507
+ {
4508
+ free (readRecordBuf );
4509
+ readRecordBuf = NULL ;
4510
+ readRecordBufSize = 0 ;
4511
+ }
4503
4512
}
4504
4513
4505
4514
/*
@@ -4509,9 +4518,7 @@ StartupXLOG(void)
4509
4518
* 1 for "primary", 2 for "secondary", 0 for "other" (backup_label)
4510
4519
*/
4511
4520
static XLogRecord *
4512
- ReadCheckpointRecord (XLogRecPtr RecPtr ,
4513
- int whichChkpt ,
4514
- char * buffer )
4521
+ ReadCheckpointRecord (XLogRecPtr RecPtr , int whichChkpt )
4515
4522
{
4516
4523
XLogRecord * record ;
4517
4524
@@ -4535,7 +4542,7 @@ ReadCheckpointRecord(XLogRecPtr RecPtr,
4535
4542
return NULL ;
4536
4543
}
4537
4544
4538
- record = ReadRecord (& RecPtr , LOG , buffer );
4545
+ record = ReadRecord (& RecPtr , LOG );
4539
4546
4540
4547
if (record == NULL )
4541
4548
{
@@ -5080,9 +5087,8 @@ xlog_outrec(char *buf, XLogRecord *record)
5080
5087
int bkpb ;
5081
5088
int i ;
5082
5089
5083
- sprintf (buf + strlen (buf ), "prev %X/%X; xprev %X/%X; xid %u" ,
5090
+ sprintf (buf + strlen (buf ), "prev %X/%X; xid %u" ,
5084
5091
record -> xl_prev .xlogid , record -> xl_prev .xrecoff ,
5085
- record -> xl_xact_prev .xlogid , record -> xl_xact_prev .xrecoff ,
5086
5092
record -> xl_xid );
5087
5093
5088
5094
for (i = 0 , bkpb = 0 ; i < XLR_MAX_BKP_BLOCKS ; i ++ )
0 commit comments