*/
typedef struct
{
+ bool in_use;
+ uint8 flags; /* REGBUF_* flags */
RelFileNode rnode; /* identifies the relation and block */
ForkNumber forkno;
BlockNumber block;
Page page; /* page content */
- uint8 block_id; /* ID the buffer was registered with */
- uint8 flags; /* REGBUF_* flags */
- uint32 rdata_sz; /* total length of data in rdata chain */
+ uint32 rdata_len; /* total length of data in rdata chain */
XLogRecData *rdata_head; /* head of the chain of data registered with
* this block */
XLogRecData *rdata_tail; /* last entry in the chain, or &rdata_head if
} registered_buffer;
static registered_buffer *registered_buffers;
-static int num_registered_buffers = 0; /* # of structs in use */
static int max_registered_buffers; /* allocated size */
+static int max_registered_block_id = 0; /* highest block_id + 1 currently
+ * registered */
/*
* A chain of XLogRecDatas to hold the "main data" of a WAL record, registered
void
XLogBeginInsert(void)
{
- Assert(num_registered_buffers == 0);
+ Assert(max_registered_block_id == 0);
Assert(mainrdata_last == (XLogRecData *) &mainrdata_head);
Assert(mainrdata_len == 0);
Assert(!begininsert_called);
void
XLogResetInsertion(void)
{
+ int i;
+
+ for (i = 0; i < max_registered_block_id; i++)
+ registered_buffers[i].in_use = false;
+
num_rdatas = 0;
- num_registered_buffers = 0;
+ max_registered_block_id = 0;
mainrdata_len = 0;
mainrdata_last = (XLogRecData *) &mainrdata_head;
begininsert_called = false;
Assert(!((flags & REGBUF_FORCE_IMAGE) && (flags & (REGBUF_NO_IMAGE))));
Assert(begininsert_called);
- if (num_registered_buffers > max_registered_buffers)
- elog(ERROR, "too many registered buffers");
+ if (block_id >= max_registered_block_id)
+ {
+ if (block_id >= max_registered_buffers)
+ elog(ERROR, "too many registered buffers");
+ max_registered_block_id = block_id + 1;
+ }
- regbuf = ®istered_buffers[num_registered_buffers];
+ regbuf = ®istered_buffers[block_id];
- regbuf->block_id = block_id;
BufferGetTag(buffer, ®buf->rnode, ®buf->forkno, ®buf->block);
regbuf->page = BufferGetPage(buffer);
regbuf->flags = flags;
regbuf->rdata_tail = (XLogRecData *) ®buf->rdata_head;
- regbuf->rdata_sz = 0;
+ regbuf->rdata_len = 0;
/*
- * Check that this page, or some other page with the same block_id,
- * hasn't already been registered.
+ * Check that this page hasn't already been registered with some other
+ * block_id.
*/
#ifdef USE_ASSERT_CHECKING
{
int i;
- for (i = 0; i < num_registered_buffers; i++)
+ for (i = 0; i < max_registered_block_id; i++)
{
registered_buffer *regbuf_old = ®istered_buffers[i];
- Assert (regbuf_old->block_id != block_id);
+ if (i == block_id || !regbuf_old->in_use)
+ continue;
+
Assert (!RelFileNodeEquals(regbuf_old->rnode, regbuf->rnode) ||
regbuf_old->forkno != regbuf->forkno ||
regbuf_old->block != regbuf->block);
}
#endif
- num_registered_buffers++;
+ regbuf->in_use = true;
}
/*
{
registered_buffer *regbuf;
- if (num_registered_buffers > max_registered_buffers)
- elog(ERROR, "too many registered buffers");
-
/* This is currently only used to WAL-log a full-page image of a page */
Assert(flags & REGBUF_FORCE_IMAGE);
+ Assert(begininsert_called);
- regbuf = ®istered_buffers[num_registered_buffers];
+ if (block_id >= max_registered_block_id)
+ max_registered_block_id = block_id + 1;
- Assert(begininsert_called);
+ if (block_id >= max_registered_buffers)
+ elog(ERROR, "too many registered buffers");
+
+ regbuf = ®istered_buffers[block_id];
- regbuf->block_id = block_id;
regbuf->rnode = *rnode;
regbuf->forkno = forknum;
regbuf->block = blknum;
regbuf->page = page;
regbuf->flags = flags;
regbuf->rdata_tail = (XLogRecData *) ®buf->rdata_head;
- regbuf->rdata_sz = 0;
+ regbuf->rdata_len = 0;
/*
- * Check that this page, or some other page with the same block_id,
- * hasn't already been registered.
+ * Check that this page hasn't already been registered with some other
+ * block_id.
*/
#ifdef USE_ASSERT_CHECKING
{
int i;
- for (i = 0; i < num_registered_buffers; i++)
+ for (i = 0; i < max_registered_block_id; i++)
{
registered_buffer *regbuf_old = ®istered_buffers[i];
- Assert (regbuf_old->block_id != block_id);
+ if (i == block_id || !regbuf_old->in_use)
+ continue;
+
Assert (!RelFileNodeEquals(regbuf_old->rnode, regbuf->rnode) ||
regbuf_old->forkno != regbuf->forkno ||
regbuf_old->block != regbuf->block);
}
#endif
- num_registered_buffers++;
+ regbuf->in_use = true;
}
/*
{
registered_buffer *regbuf;
XLogRecData *rdata;
- int i;
Assert(begininsert_called);
/* find the registered buffer struct */
- for (i = 0; i < num_registered_buffers; i++)
- {
- if (registered_buffers[i].block_id == block_id)
- break;
- }
- if (i >= num_registered_buffers)
+ regbuf = ®istered_buffers[block_id];
+ if (!regbuf->in_use)
elog(ERROR, "no block with id %d registered with WAL insertion",
block_id);
- regbuf = ®istered_buffers[i];
if (num_rdatas >= max_rdatas)
elog(ERROR, "too much WAL data");
regbuf->rdata_tail->next = rdata;
regbuf->rdata_tail = rdata;
- regbuf->rdata_sz += len;
+ regbuf->rdata_len += len;
}
/*
{
XLogRecData *rdt;
uint32 total_len;
- int i;
+ int block_id;
int used_rdatas = num_rdatas;
pg_crc32 rdata_crc;
+ registered_buffer *prev_regbuf = NULL;
/*
* Note: this function can be called multiple times for the same record.
* Make additional rdata chain entries for the backup blocks.
*/
*fpw_lsn = InvalidXLogRecPtr;
- for (i = 0; i < num_registered_buffers; i++)
+ for (block_id = 0; block_id < max_registered_block_id; block_id++)
{
- registered_buffer *regbuf = ®istered_buffers[i];
+ registered_buffer *regbuf = ®istered_buffers[block_id];
XLogRecordBlockData *bkpb = ®buf->dtbuf_xlg;
bool needs_backup;
bool needs_data;
int padlen;
+ if (!regbuf->in_use)
+ continue;
+
/* Determine if this block needs to be backed up */
if (regbuf->flags & REGBUF_FORCE_IMAGE)
needs_backup = true;
}
/* Determine if the buffer data needs to included */
- if (regbuf->rdata_sz == 0)
+ if (regbuf->rdata_len == 0)
needs_data = false;
else if ((regbuf->flags & REGBUF_KEEP_DATA) != 0)
needs_data = true;
rdt->next = &rdatas[used_rdatas++];
rdt = rdt->next;
- bkpb->id = regbuf->block_id;
+ bkpb->id = block_id;
bkpb->fork_flags = (uint8) regbuf->forkno;
bkpb->block = regbuf->block;
- if (i > 0 && RelFileNodeEquals(bkpb->node, registered_buffers[i - 1].rnode))
+ if (prev_regbuf && RelFileNodeEquals(regbuf->rnode, prev_regbuf->rnode))
{
bkpb->fork_flags |= BKPBLOCK_SAME_REL;
bkpb->node = regbuf->rnode;
rdt->len = SizeOfXLogRecordBlockData;
+ prev_regbuf = regbuf;
}
if ((regbuf->flags & REGBUF_WILL_INIT) == REGBUF_WILL_INIT)
* overall list.
*/
bkpb->fork_flags |= BKPBLOCK_HAS_DATA;
- bkpb->data_length += regbuf->rdata_sz;
+ bkpb->data_length += regbuf->rdata_len;
rdt->next = regbuf->rdata_head;
rdt = regbuf->rdata_tail;