Skip to content

Commit 7415105

Browse files
committed
XLOG stuff for sequences.
CommitDelay in guc.c
1 parent 680b735 commit 7415105

File tree

10 files changed

+241
-67
lines changed

10 files changed

+241
-67
lines changed

src/backend/access/transam/rmgr.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@
77
#include "access/xact.h"
88
#include "access/xlog.h"
99
#include "storage/smgr.h"
10-
11-
#ifdef XLOG
10+
#include "commands/sequence.h"
1211

1312
RmgrData RmgrTable[] = {
1413
{"XLOG", xlog_redo, xlog_undo, xlog_desc},
@@ -25,15 +24,7 @@ RmgrData RmgrTable[] = {
2524
{"Btree", btree_redo, btree_undo, btree_desc},
2625
{"Hash", hash_redo, hash_undo, hash_desc},
2726
{"Rtree", rtree_redo, rtree_undo, rtree_desc},
28-
{"Gist", gist_redo, gist_undo, gist_desc}
27+
{"Gist", gist_redo, gist_undo, gist_desc},
28+
{"Sequence", seq_redo, seq_undo, seq_desc}
2929
};
3030

31-
#else /* not XLOG */
32-
33-
/*
34-
* This is a dummy, but don't write RmgrTable[] = {} here,
35-
* that's not accepted by some compilers. -- petere
36-
*/
37-
RmgrData RmgrTable[1];
38-
39-
#endif /* not XLOG */

src/backend/access/transam/xact.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.84 2000/11/21 21:15:57 petere Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.85 2000/11/30 01:47:31 vadim Exp $
1212
*
1313
* NOTES
1414
* Transaction aborts can now occur two ways:
@@ -222,7 +222,7 @@ int XactIsoLevel;
222222
#ifdef XLOG
223223
#include "access/xlogutils.h"
224224

225-
int CommitDelay = 5; /* 1/200 sec */
225+
int CommitDelay = 5; /* 1/200000 sec */
226226

227227
static void (*_RollbackFunc)(void*) = NULL;
228228
static void *_RollbackData = NULL;

src/backend/access/transam/xlog.c

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.36 2000/11/28 23:27:54 tgl Exp $
9+
* $Header: /cvsroot/pgsql/src/backend/access/transam/xlog.c,v 1.37 2000/11/30 01:47:31 vadim Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -240,17 +240,26 @@ static bool InRedo = false;
240240
XLogRecPtr
241241
XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32 buflen)
242242
{
243-
XLogCtlInsert *Insert = &XLogCtl->Insert;
244-
XLogRecord *record;
245-
XLogSubRecord *subrecord;
246-
XLogRecPtr RecPtr;
247-
uint32 len = hdrlen + buflen,
248-
freespace,
249-
wlen;
250-
uint16 curridx;
251-
bool updrqst = false;
243+
XLogCtlInsert *Insert = &XLogCtl->Insert;
244+
XLogRecord *record;
245+
XLogSubRecord *subrecord;
246+
XLogRecPtr RecPtr;
247+
uint32 len = hdrlen + buflen,
248+
freespace,
249+
wlen;
250+
uint16 curridx;
251+
bool updrqst = false;
252+
bool no_tran = (rmid == RM_XLOG_ID) ? true : false;
253+
254+
if (info & XLR_INFO_MASK)
255+
{
256+
if ((info & XLR_INFO_MASK) != XLOG_NO_TRAN)
257+
elog(STOP, "XLogInsert: invalid info mask %02X",
258+
(info & XLR_INFO_MASK));
259+
no_tran = true;
260+
info &= ~XLR_INFO_MASK;
261+
}
252262

253-
Assert(!(info & XLR_INFO_MASK));
254263
if (len == 0 || len > MAXLOGRECSZ)
255264
elog(STOP, "XLogInsert: invalid record len %u", len);
256265

@@ -324,13 +333,14 @@ XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32
324333
freespace -= SizeOfXLogRecord;
325334
record = (XLogRecord *) Insert->currpos;
326335
record->xl_prev = Insert->PrevRecord;
327-
if (rmid != RM_XLOG_ID)
328-
record->xl_xact_prev = MyLastRecPtr;
329-
else
336+
if (no_tran)
330337
{
331338
record->xl_xact_prev.xlogid = 0;
332339
record->xl_xact_prev.xrecoff = 0;
333340
}
341+
else
342+
record->xl_xact_prev = MyLastRecPtr;
343+
334344
record->xl_xid = GetCurrentTransactionId();
335345
record->xl_len = (len > freespace) ? freespace : len;
336346
record->xl_info = (len > freespace) ?
@@ -340,7 +350,7 @@ XLogInsert(RmgrId rmid, uint8 info, char *hdr, uint32 hdrlen, char *buf, uint32
340350
RecPtr.xrecoff =
341351
XLogCtl->xlblocks[curridx].xrecoff - BLCKSZ +
342352
Insert->currpos - ((char *) Insert->currpage);
343-
if (MyLastRecPtr.xrecoff == 0 && rmid != RM_XLOG_ID)
353+
if (MyLastRecPtr.xrecoff == 0 && !no_tran)
344354
{
345355
SpinAcquire(SInvalLock);
346356
MyProc->logRec = RecPtr;

src/backend/commands/sequence.c

Lines changed: 155 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,12 @@
2222
#define SEQ_MAXVALUE ((int4)0x7FFFFFFF)
2323
#define SEQ_MINVALUE -(SEQ_MAXVALUE)
2424

25-
typedef struct FormData_pg_sequence
26-
{
27-
NameData sequence_name;
28-
int4 last_value;
29-
int4 increment_by;
30-
int4 max_value;
31-
int4 min_value;
32-
int4 cache_value;
33-
char is_cycled;
34-
char is_called;
35-
} FormData_pg_sequence;
36-
37-
typedef FormData_pg_sequence *Form_pg_sequence;
25+
/*
26+
* We don't want to log each fetching values from sequences,
27+
* so we pre-log a few fetches in advance. In the event of
28+
* crash we can lose as much as we pre-logged.
29+
*/
30+
#define SEQ_LOG_VALS 32
3831

3932
typedef struct sequence_magic
4033
{
@@ -138,6 +131,11 @@ DefineSequence(CreateSeqStmt *seq)
138131
coldef->colname = "cache_value";
139132
value[i - 1] = Int32GetDatum(new.cache_value);
140133
break;
134+
case SEQ_COL_LOG:
135+
typnam->name = "int4";
136+
coldef->colname = "log_cnt";
137+
value[i - 1] = Int32GetDatum((int32)1);
138+
break;
141139
case SEQ_COL_CYCLE:
142140
typnam->name = "char";
143141
coldef->colname = "is_cycled";
@@ -196,10 +194,14 @@ nextval(PG_FUNCTION_ARGS)
196194
int32 incby,
197195
maxv,
198196
minv,
199-
cache;
197+
cache,
198+
log,
199+
fetch,
200+
last;
200201
int32 result,
201202
next,
202203
rescnt = 0;
204+
bool logit = false;
203205

204206
if (pg_aclcheck(seqname, GetUserId(), ACL_WR) != ACLCHECK_OK)
205207
elog(ERROR, "%s.nextval: you don't have permissions to set sequence %s",
@@ -219,16 +221,27 @@ nextval(PG_FUNCTION_ARGS)
219221
seq = read_info("nextval", elm, &buf); /* lock page' buffer and
220222
* read tuple */
221223

222-
next = result = seq->last_value;
224+
last = next = result = seq->last_value;
223225
incby = seq->increment_by;
224226
maxv = seq->max_value;
225227
minv = seq->min_value;
226-
cache = seq->cache_value;
228+
fetch = cache = seq->cache_value;
229+
log = seq->log_cnt;
227230

228231
if (seq->is_called != 't')
232+
{
229233
rescnt++; /* last_value if not called */
234+
fetch--;
235+
log--;
236+
}
230237

231-
while (rescnt < cache) /* try to fetch cache numbers */
238+
if (log < fetch)
239+
{
240+
fetch = log = fetch - log + SEQ_LOG_VALS;
241+
logit = true;
242+
}
243+
244+
while (fetch) /* try to fetch cache [+ log ] numbers */
232245
{
233246

234247
/*
@@ -242,7 +255,7 @@ nextval(PG_FUNCTION_ARGS)
242255
(maxv < 0 && next + incby > maxv))
243256
{
244257
if (rescnt > 0)
245-
break; /* stop caching */
258+
break; /* stop fetching */
246259
if (seq->is_cycled != 't')
247260
elog(ERROR, "%s.nextval: got MAXVALUE (%d)",
248261
elm->name, maxv);
@@ -258,7 +271,7 @@ nextval(PG_FUNCTION_ARGS)
258271
(minv >= 0 && next + incby < minv))
259272
{
260273
if (rescnt > 0)
261-
break; /* stop caching */
274+
break; /* stop fetching */
262275
if (seq->is_cycled != 't')
263276
elog(ERROR, "%s.nextval: got MINVALUE (%d)",
264277
elm->name, minv);
@@ -267,17 +280,43 @@ nextval(PG_FUNCTION_ARGS)
267280
else
268281
next += incby;
269282
}
270-
rescnt++; /* got result */
271-
if (rescnt == 1) /* if it's first one - */
272-
result = next; /* it's what to return */
283+
fetch--;
284+
if (rescnt < cache)
285+
{
286+
log--;
287+
rescnt++;
288+
last = next;
289+
if (rescnt == 1) /* if it's first result - */
290+
result = next; /* it's what to return */
291+
}
273292
}
274293

275294
/* save info in local cache */
276295
elm->last = result; /* last returned number */
277-
elm->cached = next; /* last cached number */
296+
elm->cached = last; /* last fetched number */
297+
298+
if (logit)
299+
{
300+
xl_seq_rec xlrec;
301+
XLogRecPtr recptr;
302+
303+
if (fetch) /* not all numbers were fetched */
304+
log -= fetch;
305+
306+
xlrec.node = elm->rel->rd_node;
307+
xlrec.value = next;
308+
309+
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG|XLOG_NO_TRAN,
310+
(char*) &xlrec, sizeof(xlrec), NULL, 0);
311+
312+
PageSetLSN(BufferGetPage(buf), recptr);
313+
PageSetSUI(BufferGetPage(buf), ThisStartUpID);
314+
}
278315

279316
/* save info in sequence relation */
280-
seq->last_value = next; /* last fetched number */
317+
seq->last_value = last; /* last fetched number */
318+
Assert(log >= 0);
319+
seq->log_cnt = log; /* how much is logged */
281320
seq->is_called = 't';
282321

283322
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
@@ -349,6 +388,21 @@ do_setval(char *seqname, int32 next, bool iscalled)
349388
/* save info in sequence relation */
350389
seq->last_value = next; /* last fetched number */
351390
seq->is_called = iscalled ? 't' : 'f';
391+
seq->log_cnt = (iscalled) ? 0 : 1;
392+
393+
{
394+
xl_seq_rec xlrec;
395+
XLogRecPtr recptr;
396+
397+
xlrec.node = elm->rel->rd_node;
398+
xlrec.value = next;
399+
400+
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_SET|XLOG_NO_TRAN,
401+
(char*) &xlrec, sizeof(xlrec), NULL, 0);
402+
403+
PageSetLSN(BufferGetPage(buf), recptr);
404+
PageSetSUI(BufferGetPage(buf), ThisStartUpID);
405+
}
352406

353407
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
354408

@@ -638,7 +692,6 @@ init_params(CreateSeqStmt *seq, Form_pg_sequence new)
638692

639693
}
640694

641-
642695
static int
643696
get_param(DefElem *def)
644697
{
@@ -651,3 +704,80 @@ get_param(DefElem *def)
651704
elog(ERROR, "DefineSequence: \"%s\" is to be integer", def->defname);
652705
return -1;
653706
}
707+
708+
void seq_redo(XLogRecPtr lsn, XLogRecord *record)
709+
{
710+
uint8 info = record->xl_info & ~XLR_INFO_MASK;
711+
Relation reln;
712+
Buffer buffer;
713+
Page page;
714+
ItemId lp;
715+
HeapTupleData tuple;
716+
Form_pg_sequence seq;
717+
xl_seq_rec *xlrec;
718+
719+
if (info != XLOG_SEQ_LOG && info != XLOG_SEQ_SET)
720+
elog(STOP, "seq_redo: unknown op code %u", info);
721+
722+
xlrec = (xl_seq_rec*) XLogRecGetData(record);
723+
724+
reln = XLogOpenRelation(true, RM_SEQ_ID, xlrec->node);
725+
if (!RelationIsValid(reln))
726+
return;
727+
728+
buffer = XLogReadBuffer(false, reln, 0);
729+
if (!BufferIsValid(buffer))
730+
elog(STOP, "seq_redo: can't read block of %u/%u",
731+
xlrec->node.tblNode, xlrec->node.relNode);
732+
733+
page = (Page) BufferGetPage(buffer);
734+
if (PageIsNew((PageHeader) page) ||
735+
((sequence_magic *) PageGetSpecialPointer(page))->magic != SEQ_MAGIC)
736+
elog(STOP, "seq_redo: uninitialized page of %u/%u",
737+
xlrec->node.tblNode, xlrec->node.relNode);
738+
739+
if (XLByteLE(lsn, PageGetLSN(page)))
740+
{
741+
UnlockAndReleaseBuffer(buffer);
742+
return;
743+
}
744+
745+
lp = PageGetItemId(page, FirstOffsetNumber);
746+
Assert(ItemIdIsUsed(lp));
747+
tuple.t_data = (HeapTupleHeader) PageGetItem((Page) page, lp);
748+
749+
seq = (Form_pg_sequence) GETSTRUCT(&tuple);
750+
751+
seq->last_value = xlrec->value; /* last logged value */
752+
seq->is_called = 't';
753+
seq->log_cnt = 0;
754+
755+
PageSetLSN(page, lsn);
756+
PageSetSUI(page, ThisStartUpID);
757+
UnlockAndWriteBuffer(buffer);
758+
759+
return;
760+
}
761+
762+
void seq_undo(XLogRecPtr lsn, XLogRecord *record)
763+
{
764+
}
765+
766+
void seq_desc(char *buf, uint8 xl_info, char* rec)
767+
{
768+
uint8 info = xl_info & ~XLR_INFO_MASK;
769+
xl_seq_rec *xlrec = (xl_seq_rec*) rec;
770+
771+
if (info == XLOG_SEQ_LOG)
772+
strcat(buf, "log: ");
773+
else if (info == XLOG_SEQ_SET)
774+
strcat(buf, "set: ");
775+
else
776+
{
777+
strcat(buf, "UNKNOWN");
778+
return;
779+
}
780+
781+
sprintf(buf + strlen(buf), "node %u/%u; value %d",
782+
xlrec->node.tblNode, xlrec->node.relNode, xlrec->value);
783+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy