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 pageand 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)
9182int pageno = TransactionIdToPage (xid );
9283int byteno = TransactionIdToByte (xid );
9384int bshift = TransactionIdToBIndex (xid )* CLOG_BITS_PER_XACT ;
85+ int slotno ;
9486char * byteptr ;
9587char byteval ;
9688
9789Assert (status == TRANSACTION_STATUS_COMMITTED ||
9890status == TRANSACTION_STATUS_ABORTED ||
9991status == 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 */
10799Assert (((* byteptr >>bshift )& CLOG_XACT_BITMASK )== 0 ||
@@ -114,9 +106,9 @@ TransactionIdSetStatus(TransactionId xid, XidStatus status)
114106byteval |= (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)
131123int pageno = TransactionIdToPage (xid );
132124int byteno = TransactionIdToByte (xid );
133125int bshift = TransactionIdToBIndex (xid )* CLOG_BITS_PER_XACT ;
126+ int slotno ;
134127char * byteptr ;
135128XidStatus 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
142135status = (* byteptr >>bshift )& CLOG_XACT_BITMASK ;
143136
144- LWLockRelease (ClogCtl -> ControlLock );
137+ LWLockRelease (CLogControlLock );
145138
146139return status ;
147140}
@@ -160,8 +153,8 @@ CLOGShmemSize(void)
160153void
161154CLOGShmemInit (void )
162155{
163- SimpleLruInit (ClogCtl ,"CLOG Ctl" ,"pg_clog" );
164156ClogCtl -> PagePrecedes = CLOGPagePrecedes ;
157+ SimpleLruInit (ClogCtl ,"CLOG Ctl" ,CLogControlLock ,"pg_clog" );
165158}
166159
167160/*
@@ -175,16 +168,16 @@ BootStrapCLOG(void)
175168{
176169int 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 */
181174slotno = ZeroCLOGPage (0 , false);
182175
183176/* Make sure it's written out */
184177SimpleLruWritePage (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
204199if (writeXlog )
205200WriteZeroPageXlogRec (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 */
230225SimpleLruFlush (ClogCtl , false);
231226}
232227
@@ -236,6 +231,7 @@ ShutdownCLOG(void)
236231void
237232CheckPointCLOG (void )
238233{
234+ /* Flush dirty CLOG pages to disk */
239235SimpleLruFlush (ClogCtl , true);
240236}
241237
@@ -263,12 +259,12 @@ ExtendCLOG(TransactionId newestXact)
263259
264260pageno = 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 */
269265ZeroCLOGPage (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 */
298294cutoffPage = 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) */
299304SimpleLruTruncate (ClogCtl ,cutoffPage );
300305}
301306
@@ -340,20 +345,51 @@ WriteZeroPageXlogRec(int pageno)
340345rdata .data = (char * ) (& pageno );
341346rdata .len = sizeof (int );
342347rdata .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}