6
6
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7
7
* Portions Copyright (c) 1994, Regents of the University of California
8
8
*
9
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.53 2001/02/13 20:40:25 vadim Exp $
9
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.54 2001/02/18 04:39:42 tgl Exp $
10
10
*
11
11
*-------------------------------------------------------------------------
12
12
*/
39
39
40
40
#include "miscadmin.h"
41
41
42
+
43
+ /* Max time to wait to acquire XLog activity locks */
44
+ #define XLOG_LOCK_TIMEOUT (5*60*1000000) /* 5 minutes */
45
+ /* Max time to wait to acquire checkpoint lock */
46
+ #define CHECKPOINT_LOCK_TIMEOUT (10*60*1000000) /* 10 minutes */
47
+
48
+
42
49
int XLOGbuffers = 8 ;
43
50
int XLOGfiles = 0 ; /* how many files to pre-allocate */
44
51
XLogRecPtr MyLastRecPtr = {0 , 0 };
@@ -178,8 +185,8 @@ typedef struct BkpBlock
178
185
/*
179
186
* We break each log file in 16Mb segments
180
187
*/
181
- #define XLogSegSize (16*1024*1024)
182
- #define XLogLastSeg (0xffffffff / XLogSegSize)
188
+ #define XLogSegSize ((uint32) ( 16*1024*1024) )
189
+ #define XLogLastSeg (((uint32) 0xffffffff) / XLogSegSize)
183
190
#define XLogFileSize (XLogLastSeg * XLogSegSize)
184
191
185
192
#define NextLogSeg (_logId , _logSeg ) \
@@ -423,7 +430,7 @@ begin:;
423
430
}
424
431
}
425
432
}
426
- S_LOCK_SLEEP (& (XLogCtl -> insert_lck ), i ++ );
433
+ S_LOCK_SLEEP (& (XLogCtl -> insert_lck ), i ++ , XLOG_LOCK_TIMEOUT );
427
434
if (!TAS (& (XLogCtl -> insert_lck )))
428
435
break ;
429
436
}
@@ -721,7 +728,7 @@ XLogFlush(XLogRecPtr record)
721
728
break ;
722
729
}
723
730
}
724
- S_LOCK_SLEEP (& (XLogCtl -> lgwr_lck ), spins ++ );
731
+ S_LOCK_SLEEP (& (XLogCtl -> lgwr_lck ), spins ++ , XLOG_LOCK_TIMEOUT );
725
732
}
726
733
727
734
if (logFile >= 0 && (LgwrResult .Write .xlogid != logId ||
@@ -741,7 +748,7 @@ XLogFlush(XLogRecPtr record)
741
748
logFile = XLogFileOpen (logId , logSeg , false);
742
749
}
743
750
744
- if (pg_fsync (logFile ) != 0 )
751
+ if (pg_fdatasync (logFile ) != 0 )
745
752
elog (STOP , "fsync(logfile %u seg %u) failed: %m" ,
746
753
logId , logSeg );
747
754
LgwrResult .Flush = LgwrResult .Write ;
@@ -826,7 +833,7 @@ GetFreeXLBuffer()
826
833
InitXLBuffer (curridx );
827
834
return ;
828
835
}
829
- S_LOCK_SLEEP (& (XLogCtl -> lgwr_lck ), spins ++ );
836
+ S_LOCK_SLEEP (& (XLogCtl -> lgwr_lck ), spins ++ , XLOG_LOCK_TIMEOUT );
830
837
}
831
838
}
832
839
@@ -846,7 +853,7 @@ XLogWrite(char *buffer)
846
853
{
847
854
if (wcnt > 0 )
848
855
{
849
- if (pg_fsync (logFile ) != 0 )
856
+ if (pg_fdatasync (logFile ) != 0 )
850
857
elog (STOP , "fsync(logfile %u seg %u) failed: %m" ,
851
858
logId , logSeg );
852
859
if (LgwrResult .Write .xlogid != logId )
@@ -928,7 +935,7 @@ XLogWrite(char *buffer)
928
935
if (XLByteLT (LgwrResult .Flush , LgwrRqst .Flush ) &&
929
936
XLByteLE (LgwrRqst .Flush , LgwrResult .Write ))
930
937
{
931
- if (pg_fsync (logFile ) != 0 )
938
+ if (pg_fdatasync (logFile ) != 0 )
932
939
elog (STOP , "fsync(logfile %u seg %u) failed: %m" ,
933
940
logId , logSeg );
934
941
LgwrResult .Flush = LgwrResult .Write ;
@@ -948,13 +955,14 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
948
955
{
949
956
char path [MAXPGPATH ];
950
957
char tpath [MAXPGPATH ];
958
+ char zbuffer [BLCKSZ ];
951
959
int fd ;
960
+ int nbytes ;
952
961
953
962
XLogFileName (path , log , seg );
954
963
955
964
/*
956
- * Try to use existent file (checkpoint maker
957
- * creates it sometime).
965
+ * Try to use existent file (checkpoint maker creates it sometimes).
958
966
*/
959
967
if (* usexistent )
960
968
{
@@ -963,7 +971,7 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
963
971
{
964
972
if (errno != ENOENT )
965
973
elog (STOP , "InitOpen(logfile %u seg %u) failed: %m" ,
966
- logId , logSeg );
974
+ logId , logSeg );
967
975
}
968
976
else
969
977
return (fd );
@@ -979,33 +987,44 @@ XLogFileInit(uint32 log, uint32 seg, bool *usexistent)
979
987
elog (STOP , "InitCreate(logfile %u seg %u) failed: %m" ,
980
988
logId , logSeg );
981
989
982
- if (lseek (fd , XLogSegSize - 1 , SEEK_SET ) != (off_t ) (XLogSegSize - 1 ))
983
- elog (STOP , "lseek(logfile %u seg %u) failed: %m" ,
984
- logId , logSeg );
985
-
986
- if (write (fd , "" , 1 ) != 1 )
987
- elog (STOP , "write(logfile %u seg %u) failed: %m" ,
988
- logId , logSeg );
990
+ /*
991
+ * Zero-fill the file. We have to do this the hard way to ensure that
992
+ * all the file space has really been allocated --- on platforms that
993
+ * allow "holes" in files, just seeking to the end doesn't allocate
994
+ * intermediate space. This way, we know that we have all the space
995
+ * and (after the fsync below) that all the indirect blocks are down
996
+ * on disk. Therefore, fdatasync(2) will be sufficient to sync future
997
+ * writes to the log file.
998
+ */
999
+ MemSet (zbuffer , 0 , sizeof (zbuffer ));
1000
+ for (nbytes = 0 ; nbytes < XLogSegSize ; nbytes += sizeof (zbuffer ))
1001
+ {
1002
+ if ((int ) write (fd , zbuffer , sizeof (zbuffer )) != (int ) sizeof (zbuffer ))
1003
+ elog (STOP , "ZeroFill(logfile %u seg %u) failed: %m" ,
1004
+ logId , logSeg );
1005
+ }
989
1006
990
1007
if (pg_fsync (fd ) != 0 )
991
1008
elog (STOP , "fsync(logfile %u seg %u) failed: %m" ,
992
1009
logId , logSeg );
993
1010
994
- if (lseek (fd , 0 , SEEK_SET ) < 0 )
995
- elog (STOP , "lseek(logfile %u seg %u off %u) failed: %m" ,
996
- log , seg , 0 );
997
-
998
1011
close (fd );
999
1012
1013
+ /*
1014
+ * Prefer link() to rename() here just to be sure that we don't overwrite
1015
+ * an existing logfile. However, there shouldn't be one, so rename()
1016
+ * is an acceptable substitute except for the truly paranoid.
1017
+ */
1000
1018
#ifndef __BEOS__
1001
1019
if (link (tpath , path ) < 0 )
1020
+ elog (STOP , "InitRelink(logfile %u seg %u) failed: %m" ,
1021
+ logId , logSeg );
1022
+ unlink (tpath );
1002
1023
#else
1003
1024
if (rename (tpath , path ) < 0 )
1004
- #endif
1005
1025
elog (STOP , "InitRelink(logfile %u seg %u) failed: %m" ,
1006
1026
logId , logSeg );
1007
-
1008
- unlink (tpath );
1027
+ #endif
1009
1028
1010
1029
fd = BasicOpenFile (path , O_RDWR | PG_BINARY , S_IRUSR | S_IWUSR );
1011
1030
if (fd < 0 )
@@ -2101,7 +2120,8 @@ CreateCheckPoint(bool shutdown)
2101
2120
/* Grab lock, using larger than normal sleep between tries (1 sec) */
2102
2121
while (TAS (& (XLogCtl -> chkp_lck )))
2103
2122
{
2104
- S_LOCK_SLEEP_INTERVAL (& (XLogCtl -> chkp_lck ), spins ++ , 1000000 );
2123
+ S_LOCK_SLEEP_INTERVAL (& (XLogCtl -> chkp_lck ), spins ++ ,
2124
+ CHECKPOINT_LOCK_TIMEOUT , 1000000 );
2105
2125
}
2106
2126
2107
2127
memset (& checkPoint , 0 , sizeof (checkPoint ));
0 commit comments