|
6 | 6 | * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
|
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.47 2000/12/30 06:52:34 vadim Exp $ |
| 9 | + * $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.48 2001/01/09 06:24:32 vadim Exp $ |
10 | 10 | *
|
11 | 11 | *-------------------------------------------------------------------------
|
12 | 12 | */
|
|
40 | 40 | #include"miscadmin.h"
|
41 | 41 |
|
42 | 42 | intXLOGbuffers=8;
|
| 43 | +intXLOGfiles=0;/* how many files to pre-allocate */ |
43 | 44 | XLogRecPtrMyLastRecPtr= {0,0};
|
44 | 45 | uint32CritSectionCount=0;
|
45 | 46 | boolInRecovery= false;
|
@@ -182,6 +183,18 @@ typedef struct BkpBlock
|
182 | 183 | #defineXLogLastSeg(0xffffffff / XLogSegSize)
|
183 | 184 | #defineXLogFileSize(XLogLastSeg * XLogSegSize)
|
184 | 185 |
|
| 186 | +#defineNextLogSeg(_logId,_logSeg)\ |
| 187 | +{\ |
| 188 | +if (_logSeg >= XLogLastSeg)\ |
| 189 | +{\ |
| 190 | +_logId++;\ |
| 191 | +_logSeg = 0;\ |
| 192 | +}\ |
| 193 | +else\ |
| 194 | +_logSeg++;\ |
| 195 | +} |
| 196 | + |
| 197 | + |
185 | 198 | #defineXLogFileName(path,log,seg)\
|
186 | 199 | snprintf(path, MAXPGPATH, "%s%c%08X%08X",\
|
187 | 200 | XLogDir, SEP_CHAR, log, seg)
|
@@ -856,8 +869,8 @@ XLogWrite(char *buffer)
|
856 | 869 | UpdateControlFile();
|
857 | 870 | SpinRelease(ControlFileLockId);
|
858 | 871 | if (!usexistent)/* there was no file */
|
859 |
| -elog(LOG,"XLogWrite:had to createnew log file - " |
860 |
| -"you probably should do checkpoints more often"); |
| 872 | +elog(LOG,"XLogWrite: new log file created - " |
| 873 | +"try to increase WAL_FILES"); |
861 | 874 | }
|
862 | 875 |
|
863 | 876 | if (logFile<0)
|
@@ -1186,7 +1199,7 @@ ReadRecord(XLogRecPtr *RecPtr, char *buffer)
|
1186 | 1199 | tmpRecPtr.xrecoff+=SizeOfXLogPHD;
|
1187 | 1200 | }
|
1188 | 1201 | elseif (!XRecOffIsValid(RecPtr->xrecoff))
|
1189 |
| -elog(STOP,"ReadRecord: invalid record offsetin (%u, %u)", |
| 1202 | +elog(STOP,"ReadRecord: invalid record offsetat (%u, %u)", |
1190 | 1203 | RecPtr->xlogid,RecPtr->xrecoff);
|
1191 | 1204 |
|
1192 | 1205 | if (readFile >=0&& (RecPtr->xlogid!=readId||
|
@@ -1232,15 +1245,21 @@ ReadRecord(XLogRecPtr *RecPtr, char *buffer)
|
1232 | 1245 | record= (XLogRecord*) ((char*)readBuf+RecPtr->xrecoff %BLCKSZ);
|
1233 | 1246 |
|
1234 | 1247 | got_record:;
|
| 1248 | +if (record->xl_len==0) |
| 1249 | +{ |
| 1250 | +elog(emode,"ReadRecord: record with zero len at (%u, %u)", |
| 1251 | +RecPtr->xlogid,RecPtr->xrecoff); |
| 1252 | +gotonext_record_is_invalid; |
| 1253 | +} |
1235 | 1254 | if (record->xl_len>_INTL_MAXLOGRECSZ)
|
1236 | 1255 | {
|
1237 |
| -elog(emode,"ReadRecord: too long record len %uin (%u, %u)", |
| 1256 | +elog(emode,"ReadRecord: too long record len %uat (%u, %u)", |
1238 | 1257 | record->xl_len,RecPtr->xlogid,RecPtr->xrecoff);
|
1239 | 1258 | gotonext_record_is_invalid;
|
1240 | 1259 | }
|
1241 | 1260 | if (record->xl_rmid>RM_MAX_ID)
|
1242 | 1261 | {
|
1243 |
| -elog(emode,"ReadRecord: invalid resource managed id %uin (%u, %u)", |
| 1262 | +elog(emode,"ReadRecord: invalid resource managed id %uat (%u, %u)", |
1244 | 1263 | record->xl_rmid,RecPtr->xlogid,RecPtr->xrecoff);
|
1245 | 1264 | gotonext_record_is_invalid;
|
1246 | 1265 | }
|
@@ -1841,8 +1860,6 @@ StartupXLOG()
|
1841 | 1860 | elog(STOP,"Invalid redo in checkPoint record");
|
1842 | 1861 | if (checkPoint.undo.xrecoff==0)
|
1843 | 1862 | checkPoint.undo=RecPtr;
|
1844 |
| -if (XLByteLT(RecPtr,checkPoint.undo)) |
1845 |
| -elog(STOP,"Invalid undo in checkPoint record"); |
1846 | 1863 |
|
1847 | 1864 | if (XLByteLT(checkPoint.undo,RecPtr)||
|
1848 | 1865 | XLByteLT(checkPoint.redo,RecPtr))
|
@@ -1969,6 +1986,23 @@ StartupXLOG()
|
1969 | 1986 | CreateCheckPoint(true);
|
1970 | 1987 | XLogCloseRelationCache();
|
1971 | 1988 | }
|
| 1989 | + |
| 1990 | +if (XLOGfiles>0)/* pre-allocate log files */ |
| 1991 | +{ |
| 1992 | +uint32_logId=logId, |
| 1993 | +_logSeg=logSeg; |
| 1994 | +intlf,i; |
| 1995 | +boolusexistent; |
| 1996 | + |
| 1997 | +for (i=1;i <=XLOGfiles;i++) |
| 1998 | +{ |
| 1999 | +NextLogSeg(_logId,_logSeg); |
| 2000 | +usexistent= false; |
| 2001 | +lf=XLogFileInit(_logId,_logSeg,&usexistent); |
| 2002 | +close(lf); |
| 2003 | +} |
| 2004 | +} |
| 2005 | + |
1972 | 2006 | InRecovery= false;
|
1973 | 2007 |
|
1974 | 2008 | ControlFile->state=DB_IN_PRODUCTION;
|
@@ -2117,48 +2151,70 @@ CreateCheckPoint(bool shutdown)
|
2117 | 2151 |
|
2118 | 2152 | SpinAcquire(ControlFileLockId);
|
2119 | 2153 | if (shutdown)
|
| 2154 | +{ |
| 2155 | +/* probably should delete extra log files */ |
2120 | 2156 | ControlFile->state=DB_SHUTDOWNED;
|
2121 |
| -else/* create new log file */ |
| 2157 | +} |
| 2158 | +else/* create new log file(s) */ |
2122 | 2159 | {
|
2123 |
| -if (recptr.xrecoff %XLogSegSize >= |
2124 |
| -(uint32) (0.75*XLogSegSize)) |
| 2160 | +intlf; |
| 2161 | +boolusexistent= true; |
| 2162 | + |
| 2163 | +_logId=recptr.xlogid; |
| 2164 | +_logSeg= (recptr.xrecoff-1) /XLogSegSize; |
| 2165 | +if (XLOGfiles>0) |
2125 | 2166 | {
|
2126 |
| -intlf; |
2127 |
| -boolusexistent= true; |
| 2167 | +structtimevaldelay; |
| 2168 | +inti; |
2128 | 2169 |
|
2129 |
| -_logId=recptr.xlogid; |
2130 |
| -_logSeg=recptr.xrecoff /XLogSegSize; |
2131 |
| -if (_logSeg >=XLogLastSeg) |
| 2170 | +for (i=1;i <=XLOGfiles;i++) |
2132 | 2171 | {
|
2133 |
| -_logId++; |
2134 |
| -_logSeg=0; |
| 2172 | +usexistent= true; |
| 2173 | +NextLogSeg(_logId,_logSeg); |
| 2174 | +lf=XLogFileInit(_logId,_logSeg,&usexistent); |
| 2175 | +close(lf); |
| 2176 | +/* |
| 2177 | + * Give up ControlFileLockId for 1/50 sec to let other |
| 2178 | + * backends switch to new log file in XLogWrite() |
| 2179 | + */ |
| 2180 | +SpinRelease(ControlFileLockId); |
| 2181 | +delay.tv_sec=0; |
| 2182 | +delay.tv_usec=20000; |
| 2183 | +(void)select(0,NULL,NULL,NULL,&delay); |
| 2184 | +SpinAcquire(ControlFileLockId); |
2135 | 2185 | }
|
2136 |
| -else |
2137 |
| -_logSeg++; |
| 2186 | +} |
| 2187 | +elseif ((recptr.xrecoff-1) %XLogSegSize >= |
| 2188 | +(uint32) (0.75*XLogSegSize)) |
| 2189 | +{ |
| 2190 | +NextLogSeg(_logId,_logSeg); |
2138 | 2191 | lf=XLogFileInit(_logId,_logSeg,&usexistent);
|
2139 | 2192 | close(lf);
|
2140 | 2193 | }
|
2141 | 2194 | }
|
2142 | 2195 |
|
2143 | 2196 | ControlFile->checkPoint=MyLastRecPtr;
|
2144 |
| - |
2145 |
| -_logId=ControlFile->logId; |
2146 |
| -_logSeg=ControlFile->logSeg-1; |
2147 | 2197 | strcpy(archdir,ControlFile->archdir);
|
2148 |
| - |
2149 | 2198 | ControlFile->time=time(NULL);
|
2150 | 2199 | UpdateControlFile();
|
2151 | 2200 | SpinRelease(ControlFileLockId);
|
2152 | 2201 |
|
2153 | 2202 | /*
|
2154 | 2203 | * Delete offline log files. Get oldest online
|
2155 |
| - * log file from undo rec if it's valid. |
| 2204 | + * log file from redo or undo record, whatever |
| 2205 | + * is older. |
2156 | 2206 | */
|
2157 |
| -if (checkPoint.undo.xrecoff!=0) |
| 2207 | +if (checkPoint.undo.xrecoff!=0&& |
| 2208 | +XLByteLT(checkPoint.undo,checkPoint.redo)) |
2158 | 2209 | {
|
2159 | 2210 | _logId=checkPoint.undo.xlogid;
|
2160 | 2211 | _logSeg=checkPoint.undo.xrecoff /XLogSegSize;
|
2161 | 2212 | }
|
| 2213 | +else |
| 2214 | +{ |
| 2215 | +_logId=checkPoint.redo.xlogid; |
| 2216 | +_logSeg=checkPoint.redo.xrecoff /XLogSegSize; |
| 2217 | +} |
2162 | 2218 | if (_logId||_logSeg)
|
2163 | 2219 | {
|
2164 | 2220 | if (_logSeg)
|
|