1010 * looked up again. Now we use specialized access code so that the commit
1111 * log can be broken into relatively small, independent segments.
1212 *
13+ * XLOG interactions: this module generates an XLOG record whenever a new
14+ * CLOG page is initialized to zeroes. Other writes of CLOG come from
15+ * recording of transaction commit or abort in xact.c, which generates its
16+ * own XLOG records for these events and will re-perform the status update
17+ * on redo; so we need make no additional XLOG entry here. Also, the XLOG
18+ * is guaranteed flushed through the XLOG commit record before we are called
19+ * to log a commit, so the WAL rule "write xlog before data" is satisfied
20+ * automatically for commits, and we don't really care for aborts. Therefore,
21+ * we don't need to mark CLOG pages with LSN information; we have enough
22+ * synchronization already.
23+ *
1324 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
1425 * Portions Copyright (c) 1994, Regents of the University of California
1526 *
16- * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.22 2004/07/03 02:55:56 tgl Exp $
27+ * $PostgreSQL: pgsql/src/backend/access/transam/clog.c,v 1.23 2004/08/23 23:22:44 tgl Exp $
1728 *
1829 *-------------------------------------------------------------------------
1930 */
2031#include "postgres.h"
2132
22- #include <fcntl.h>
23- #include <dirent.h>
24- #include <sys/stat.h>
25- #include <unistd.h>
26-
2733#include "access/clog.h"
2834#include "access/slru.h"
29- #include "miscadmin.h"
30- #include "storage/lwlock.h"
35+ #include "postmaster/bgwriter.h"
3136
3237
3338/*
34- * Defines for CLOG page and segment sizes. A page is the same BLCKSZ
35- * as is used everywhere else in Postgres.
39+ * Defines for CLOG page sizes. A page is the same BLCKSZ as is used
40+ * everywhere else in Postgres.
3641 *
3742 * Note: because TransactionIds are 32 bits and wrap around at 0xFFFFFFFF,
3843 * CLOG page numbering also wraps around at 0xFFFFFFFF/CLOG_XACTS_PER_PAGE,
5358#define TransactionIdToBIndex (xid ) ((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)
5459
5560
56- /*----------
57- * Shared-memory data structures for CLOG control
58- *
59- * XLOG interactions: this module generates an XLOG record whenever a new
60- * CLOG page is initialized to zeroes. Other writes of CLOG come from
61- * recording of transaction commit or abort in xact.c, which generates its
62- * own XLOG records for these events and will re-perform the status update
63- * on redo; so we need make no additional XLOG entry here. Also, the XLOG
64- * is guaranteed flushed through the XLOG commit record before we are called
65- * to log a commit, so the WAL rule "write xlog before data" is satisfied
66- * automatically for commits, and we don't really care for aborts. Therefore,
67- * we don't need to mark CLOG pages with LSN information; we have enough
68- * synchronization already.
69- *----------
61+ /*
62+ * Link to shared-memory data structures for CLOG control
7063 */
71-
72-
7364static SlruCtlData ClogCtlData ;
74- static SlruCtl ClogCtl = & ClogCtlData ;
65+ #define ClogCtl ( &ClogCtlData)
7566
7667
7768static int ZeroCLOGPage (int pageno , bool writeXlog );
@@ -91,17 +82,18 @@ TransactionIdSetStatus(TransactionId xid, XidStatus status)
9182 int pageno = TransactionIdToPage (xid );
9283 int byteno = TransactionIdToByte (xid );
9384 int bshift = TransactionIdToBIndex (xid ) * CLOG_BITS_PER_XACT ;
85+ int slotno ;
9486 char * byteptr ;
9587 char byteval ;
9688
9789 Assert (status == TRANSACTION_STATUS_COMMITTED ||
9890 status == TRANSACTION_STATUS_ABORTED ||
9991 status == TRANSACTION_STATUS_SUB_COMMITTED );
10092
101- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
93+ LWLockAcquire (CLogControlLock , LW_EXCLUSIVE );
10294
103- byteptr = SimpleLruReadPage (ClogCtl , pageno , xid , true );
104- byteptr += byteno ;
95+ slotno = SimpleLruReadPage (ClogCtl , pageno , xid );
96+ byteptr = ClogCtl -> shared -> page_buffer [ slotno ] + byteno ;
10597
10698 /* Current state should be 0, subcommitted or target state */
10799 Assert (((* byteptr >> bshift ) & CLOG_XACT_BITMASK ) == 0 ||
@@ -114,9 +106,9 @@ TransactionIdSetStatus(TransactionId xid, XidStatus status)
114106 byteval |= (status << bshift );
115107 * byteptr = byteval ;
116108
117- /* ...-> page_status[slotno] = SLRU_PAGE_DIRTY; already done */
109+ ClogCtl -> shared -> page_status [slotno ] = SLRU_PAGE_DIRTY ;
118110
119- LWLockRelease (ClogCtl -> ControlLock );
111+ LWLockRelease (CLogControlLock );
120112}
121113
122114/*
@@ -131,17 +123,18 @@ TransactionIdGetStatus(TransactionId xid)
131123 int pageno = TransactionIdToPage (xid );
132124 int byteno = TransactionIdToByte (xid );
133125 int bshift = TransactionIdToBIndex (xid ) * CLOG_BITS_PER_XACT ;
126+ int slotno ;
134127 char * byteptr ;
135128 XidStatus status ;
136129
137- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
130+ LWLockAcquire (CLogControlLock , LW_EXCLUSIVE );
138131
139- byteptr = SimpleLruReadPage (ClogCtl , pageno , xid , false );
140- byteptr += byteno ;
132+ slotno = SimpleLruReadPage (ClogCtl , pageno , xid );
133+ byteptr = ClogCtl -> shared -> page_buffer [ slotno ] + byteno ;
141134
142135 status = (* byteptr >> bshift ) & CLOG_XACT_BITMASK ;
143136
144- LWLockRelease (ClogCtl -> ControlLock );
137+ LWLockRelease (CLogControlLock );
145138
146139 return status ;
147140}
@@ -160,8 +153,8 @@ CLOGShmemSize(void)
160153void
161154CLOGShmemInit (void )
162155{
163- SimpleLruInit (ClogCtl , "CLOG Ctl" , "pg_clog" );
164156 ClogCtl -> PagePrecedes = CLOGPagePrecedes ;
157+ SimpleLruInit (ClogCtl , "CLOG Ctl" , CLogControlLock , "pg_clog" );
165158}
166159
167160/*
@@ -175,16 +168,16 @@ BootStrapCLOG(void)
175168{
176169 int slotno ;
177170
178- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
171+ LWLockAcquire (CLogControlLock , LW_EXCLUSIVE );
179172
180173 /* Create and zero the first page of the commit log */
181174 slotno = ZeroCLOGPage (0 , false);
182175
183176 /* Make sure it's written out */
184177 SimpleLruWritePage (ClogCtl , slotno , NULL );
185- /* Assert(ClogCtl->page_status[slotno] == SLRU_PAGE_CLEAN); */
178+ Assert (ClogCtl -> shared -> page_status [slotno ] == SLRU_PAGE_CLEAN );
186179
187- LWLockRelease (ClogCtl -> ControlLock );
180+ LWLockRelease (CLogControlLock );
188181}
189182
190183/*
@@ -199,7 +192,9 @@ BootStrapCLOG(void)
199192static int
200193ZeroCLOGPage (int pageno , bool writeXlog )
201194{
202- int slotno = SimpleLruZeroPage (ClogCtl , pageno );
195+ int slotno ;
196+
197+ slotno = SimpleLruZeroPage (ClogCtl , pageno );
203198
204199 if (writeXlog )
205200 WriteZeroPageXlogRec (pageno );
@@ -217,8 +212,7 @@ StartupCLOG(void)
217212 /*
218213 * Initialize our idea of the latest page number.
219214 */
220- SimpleLruSetLatestPage (ClogCtl ,
221- TransactionIdToPage (ShmemVariableCache -> nextXid ));
215+ ClogCtl -> shared -> latest_page_number = TransactionIdToPage (ShmemVariableCache -> nextXid );
222216}
223217
224218/*
@@ -227,6 +221,7 @@ StartupCLOG(void)
227221void
228222ShutdownCLOG (void )
229223{
224+ /* Flush dirty CLOG pages to disk */
230225 SimpleLruFlush (ClogCtl , false);
231226}
232227
@@ -236,6 +231,7 @@ ShutdownCLOG(void)
236231void
237232CheckPointCLOG (void )
238233{
234+ /* Flush dirty CLOG pages to disk */
239235 SimpleLruFlush (ClogCtl , true);
240236}
241237
@@ -263,12 +259,12 @@ ExtendCLOG(TransactionId newestXact)
263259
264260 pageno = TransactionIdToPage (newestXact );
265261
266- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
262+ LWLockAcquire (CLogControlLock , LW_EXCLUSIVE );
267263
268264 /* Zero the page and make an XLOG entry about it */
269265 ZeroCLOGPage (pageno , true);
270266
271- LWLockRelease (ClogCtl -> ControlLock );
267+ LWLockRelease (CLogControlLock );
272268}
273269
274270
@@ -296,6 +292,15 @@ TruncateCLOG(TransactionId oldestXact)
296292 * We pass the *page* containing oldestXact to SimpleLruTruncate.
297293 */
298294 cutoffPage = TransactionIdToPage (oldestXact );
295+
296+ /* Check to see if there's any files that could be removed */
297+ if (!SlruScanDirectory (ClogCtl , cutoffPage , false))
298+ return ; /* nothing to remove */
299+
300+ /* Perform a CHECKPOINT */
301+ RequestCheckpoint (true);
302+
303+ /* Now we can remove the old CLOG segment(s) */
299304 SimpleLruTruncate (ClogCtl , cutoffPage );
300305}
301306
@@ -340,20 +345,51 @@ WriteZeroPageXlogRec(int pageno)
340345 rdata .data = (char * ) (& pageno );
341346 rdata .len = sizeof (int );
342347 rdata .next = NULL ;
343- (void ) XLogInsert (RM_SLRU_ID , CLOG_ZEROPAGE | XLOG_NO_TRAN , & rdata );
348+ (void ) XLogInsert (RM_CLOG_ID , CLOG_ZEROPAGE | XLOG_NO_TRAN , & rdata );
344349}
345350
346- /* Redo a ZEROPAGE action during WAL replay */
351+ /*
352+ * CLOG resource manager's routines
353+ */
347354void
348- clog_zeropage_redo ( int pageno )
355+ clog_redo ( XLogRecPtr lsn , XLogRecord * record )
349356{
350- int slotno ;
357+ uint8 info = record -> xl_info & ~ XLR_INFO_MASK ;
351358
352- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
359+ if (info == CLOG_ZEROPAGE )
360+ {
361+ int pageno ;
362+ int slotno ;
353363
354- slotno = ZeroCLOGPage (pageno , false);
355- SimpleLruWritePage (ClogCtl , slotno , NULL );
356- /* Assert(ClogCtl->page_status[slotno] == SLRU_PAGE_CLEAN); */
364+ memcpy (& pageno , XLogRecGetData (record ), sizeof (int ));
365+
366+ LWLockAcquire (CLogControlLock , LW_EXCLUSIVE );
367+
368+ slotno = ZeroCLOGPage (pageno , false);
369+ SimpleLruWritePage (ClogCtl , slotno , NULL );
370+ Assert (ClogCtl -> shared -> page_status [slotno ] == SLRU_PAGE_CLEAN );
371+
372+ LWLockRelease (CLogControlLock );
373+ }
374+ }
375+
376+ void
377+ clog_undo (XLogRecPtr lsn , XLogRecord * record )
378+ {
379+ }
380+
381+ void
382+ clog_desc (char * buf , uint8 xl_info , char * rec )
383+ {
384+ uint8 info = xl_info & ~XLR_INFO_MASK ;
385+
386+ if (info == CLOG_ZEROPAGE )
387+ {
388+ int pageno ;
357389
358- LWLockRelease (ClogCtl -> ControlLock );
390+ memcpy (& pageno , rec , sizeof (int ));
391+ sprintf (buf + strlen (buf ), "zeropage: %d" , pageno );
392+ }
393+ else
394+ strcat (buf , "UNKNOWN" );
359395}
0 commit comments