10
10
* looked up again. Now we use specialized access code so that the commit
11
11
* log can be broken into relatively small, independent segments.
12
12
*
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
+ *
13
24
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
14
25
* Portions Copyright (c) 1994, Regents of the University of California
15
26
*
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 $
17
28
*
18
29
*-------------------------------------------------------------------------
19
30
*/
20
31
#include "postgres.h"
21
32
22
- #include <fcntl.h>
23
- #include <dirent.h>
24
- #include <sys/stat.h>
25
- #include <unistd.h>
26
-
27
33
#include "access/clog.h"
28
34
#include "access/slru.h"
29
- #include "miscadmin.h"
30
- #include "storage/lwlock.h"
35
+ #include "postmaster/bgwriter.h"
31
36
32
37
33
38
/*
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.
36
41
*
37
42
* Note: because TransactionIds are 32 bits and wrap around at 0xFFFFFFFF,
38
43
* CLOG page numbering also wraps around at 0xFFFFFFFF/CLOG_XACTS_PER_PAGE,
53
58
#define TransactionIdToBIndex (xid ) ((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)
54
59
55
60
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
70
63
*/
71
-
72
-
73
64
static SlruCtlData ClogCtlData ;
74
- static SlruCtl ClogCtl = & ClogCtlData ;
65
+ #define ClogCtl ( &ClogCtlData)
75
66
76
67
77
68
static int ZeroCLOGPage (int pageno , bool writeXlog );
@@ -91,17 +82,18 @@ TransactionIdSetStatus(TransactionId xid, XidStatus status)
91
82
int pageno = TransactionIdToPage (xid );
92
83
int byteno = TransactionIdToByte (xid );
93
84
int bshift = TransactionIdToBIndex (xid ) * CLOG_BITS_PER_XACT ;
85
+ int slotno ;
94
86
char * byteptr ;
95
87
char byteval ;
96
88
97
89
Assert (status == TRANSACTION_STATUS_COMMITTED ||
98
90
status == TRANSACTION_STATUS_ABORTED ||
99
91
status == TRANSACTION_STATUS_SUB_COMMITTED );
100
92
101
- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
93
+ LWLockAcquire (CLogControlLock , LW_EXCLUSIVE );
102
94
103
- byteptr = SimpleLruReadPage (ClogCtl , pageno , xid , true );
104
- byteptr += byteno ;
95
+ slotno = SimpleLruReadPage (ClogCtl , pageno , xid );
96
+ byteptr = ClogCtl -> shared -> page_buffer [ slotno ] + byteno ;
105
97
106
98
/* Current state should be 0, subcommitted or target state */
107
99
Assert (((* byteptr >> bshift ) & CLOG_XACT_BITMASK ) == 0 ||
@@ -114,9 +106,9 @@ TransactionIdSetStatus(TransactionId xid, XidStatus status)
114
106
byteval |= (status << bshift );
115
107
* byteptr = byteval ;
116
108
117
- /* ...-> page_status[slotno] = SLRU_PAGE_DIRTY; already done */
109
+ ClogCtl -> shared -> page_status [slotno ] = SLRU_PAGE_DIRTY ;
118
110
119
- LWLockRelease (ClogCtl -> ControlLock );
111
+ LWLockRelease (CLogControlLock );
120
112
}
121
113
122
114
/*
@@ -131,17 +123,18 @@ TransactionIdGetStatus(TransactionId xid)
131
123
int pageno = TransactionIdToPage (xid );
132
124
int byteno = TransactionIdToByte (xid );
133
125
int bshift = TransactionIdToBIndex (xid ) * CLOG_BITS_PER_XACT ;
126
+ int slotno ;
134
127
char * byteptr ;
135
128
XidStatus status ;
136
129
137
- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
130
+ LWLockAcquire (CLogControlLock , LW_EXCLUSIVE );
138
131
139
- byteptr = SimpleLruReadPage (ClogCtl , pageno , xid , false );
140
- byteptr += byteno ;
132
+ slotno = SimpleLruReadPage (ClogCtl , pageno , xid );
133
+ byteptr = ClogCtl -> shared -> page_buffer [ slotno ] + byteno ;
141
134
142
135
status = (* byteptr >> bshift ) & CLOG_XACT_BITMASK ;
143
136
144
- LWLockRelease (ClogCtl -> ControlLock );
137
+ LWLockRelease (CLogControlLock );
145
138
146
139
return status ;
147
140
}
@@ -160,8 +153,8 @@ CLOGShmemSize(void)
160
153
void
161
154
CLOGShmemInit (void )
162
155
{
163
- SimpleLruInit (ClogCtl , "CLOG Ctl" , "pg_clog" );
164
156
ClogCtl -> PagePrecedes = CLOGPagePrecedes ;
157
+ SimpleLruInit (ClogCtl , "CLOG Ctl" , CLogControlLock , "pg_clog" );
165
158
}
166
159
167
160
/*
@@ -175,16 +168,16 @@ BootStrapCLOG(void)
175
168
{
176
169
int slotno ;
177
170
178
- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
171
+ LWLockAcquire (CLogControlLock , LW_EXCLUSIVE );
179
172
180
173
/* Create and zero the first page of the commit log */
181
174
slotno = ZeroCLOGPage (0 , false);
182
175
183
176
/* Make sure it's written out */
184
177
SimpleLruWritePage (ClogCtl , slotno , NULL );
185
- /* Assert(ClogCtl->page_status[slotno] == SLRU_PAGE_CLEAN); */
178
+ Assert (ClogCtl -> shared -> page_status [slotno ] == SLRU_PAGE_CLEAN );
186
179
187
- LWLockRelease (ClogCtl -> ControlLock );
180
+ LWLockRelease (CLogControlLock );
188
181
}
189
182
190
183
/*
@@ -199,7 +192,9 @@ BootStrapCLOG(void)
199
192
static int
200
193
ZeroCLOGPage (int pageno , bool writeXlog )
201
194
{
202
- int slotno = SimpleLruZeroPage (ClogCtl , pageno );
195
+ int slotno ;
196
+
197
+ slotno = SimpleLruZeroPage (ClogCtl , pageno );
203
198
204
199
if (writeXlog )
205
200
WriteZeroPageXlogRec (pageno );
@@ -217,8 +212,7 @@ StartupCLOG(void)
217
212
/*
218
213
* Initialize our idea of the latest page number.
219
214
*/
220
- SimpleLruSetLatestPage (ClogCtl ,
221
- TransactionIdToPage (ShmemVariableCache -> nextXid ));
215
+ ClogCtl -> shared -> latest_page_number = TransactionIdToPage (ShmemVariableCache -> nextXid );
222
216
}
223
217
224
218
/*
@@ -227,6 +221,7 @@ StartupCLOG(void)
227
221
void
228
222
ShutdownCLOG (void )
229
223
{
224
+ /* Flush dirty CLOG pages to disk */
230
225
SimpleLruFlush (ClogCtl , false);
231
226
}
232
227
@@ -236,6 +231,7 @@ ShutdownCLOG(void)
236
231
void
237
232
CheckPointCLOG (void )
238
233
{
234
+ /* Flush dirty CLOG pages to disk */
239
235
SimpleLruFlush (ClogCtl , true);
240
236
}
241
237
@@ -263,12 +259,12 @@ ExtendCLOG(TransactionId newestXact)
263
259
264
260
pageno = TransactionIdToPage (newestXact );
265
261
266
- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
262
+ LWLockAcquire (CLogControlLock , LW_EXCLUSIVE );
267
263
268
264
/* Zero the page and make an XLOG entry about it */
269
265
ZeroCLOGPage (pageno , true);
270
266
271
- LWLockRelease (ClogCtl -> ControlLock );
267
+ LWLockRelease (CLogControlLock );
272
268
}
273
269
274
270
@@ -296,6 +292,15 @@ TruncateCLOG(TransactionId oldestXact)
296
292
* We pass the *page* containing oldestXact to SimpleLruTruncate.
297
293
*/
298
294
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) */
299
304
SimpleLruTruncate (ClogCtl , cutoffPage );
300
305
}
301
306
@@ -340,20 +345,51 @@ WriteZeroPageXlogRec(int pageno)
340
345
rdata .data = (char * ) (& pageno );
341
346
rdata .len = sizeof (int );
342
347
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 );
344
349
}
345
350
346
- /* Redo a ZEROPAGE action during WAL replay */
351
+ /*
352
+ * CLOG resource manager's routines
353
+ */
347
354
void
348
- clog_zeropage_redo ( int pageno )
355
+ clog_redo ( XLogRecPtr lsn , XLogRecord * record )
349
356
{
350
- int slotno ;
357
+ uint8 info = record -> xl_info & ~ XLR_INFO_MASK ;
351
358
352
- LWLockAcquire (ClogCtl -> ControlLock , LW_EXCLUSIVE );
359
+ if (info == CLOG_ZEROPAGE )
360
+ {
361
+ int pageno ;
362
+ int slotno ;
353
363
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 ;
357
389
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" );
359
395
}
0 commit comments