From: Heikki Linnakangas Date: Mon, 10 Nov 2014 14:25:10 +0000 (+0200) Subject: Use block_id as index into registered_buffers array X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=e16ca53289e7c9b83e410e97e1f855be558acbb7;p=users%2Fheikki%2Fpostgres.git Use block_id as index into registered_buffers array --- diff --git a/src/backend/access/transam/xloginsert.c b/src/backend/access/transam/xloginsert.c index f5e1c4fa3d..8d84f27d3d 100644 --- a/src/backend/access/transam/xloginsert.c +++ b/src/backend/access/transam/xloginsert.c @@ -36,13 +36,13 @@ */ 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 @@ -55,8 +55,9 @@ typedef struct } 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 @@ -110,7 +111,7 @@ static XLogRecData *XLogRecordAssemble(RmgrId rmid, uint8 info, 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); @@ -184,8 +185,13 @@ XLogEnsureRecordSpace(int nbuffers, int ndatas) 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; @@ -204,31 +210,36 @@ XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags) 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); @@ -236,7 +247,7 @@ XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags) } #endif - num_registered_buffers++; + regbuf->in_use = true; } /* @@ -248,38 +259,41 @@ XLogRegisterBlock(uint8 block_id, RelFileNode *rnode, ForkNumber forknum, { 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); @@ -287,7 +301,7 @@ XLogRegisterBlock(uint8 block_id, RelFileNode *rnode, ForkNumber forknum, } #endif - num_registered_buffers++; + regbuf->in_use = true; } /* @@ -332,20 +346,14 @@ XLogRegisterBufData(uint8 block_id, char *data, int len) { 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"); @@ -356,7 +364,7 @@ XLogRegisterBufData(uint8 block_id, char *data, int len) regbuf->rdata_tail->next = rdata; regbuf->rdata_tail = rdata; - regbuf->rdata_sz += len; + regbuf->rdata_len += len; } /* @@ -443,9 +451,10 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, { 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. @@ -478,14 +487,17 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, * 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; @@ -511,7 +523,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, } /* 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; @@ -525,11 +537,11 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, 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; @@ -548,6 +560,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, bkpb->node = regbuf->rnode; rdt->len = SizeOfXLogRecordBlockData; + prev_regbuf = regbuf; } if ((regbuf->flags & REGBUF_WILL_INIT) == REGBUF_WILL_INIT) @@ -666,7 +679,7 @@ XLogRecordAssemble(RmgrId rmid, uint8 info, * 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;