Improve API of GenericXLogRegister().

Rename this function to GenericXLogRegisterBuffer() to make it clearer
what it does, and leave room for other sorts of "register" actions in
future.  Also, replace its "bool isNew" argument with an integer flags
argument, so as to allow adding more flags in future without an API
break.

Alexander Korotkov, adjusted slightly by me
This commit is contained in:
Tom Lane 2016-04-12 11:42:06 -04:00
parent bdf7db8192
commit 5713f03973
6 changed files with 41 additions and 31 deletions

View File

@ -49,7 +49,7 @@ flushCachedPage(Relation index, BloomBuildState *buildstate)
GenericXLogState *state;
state = GenericXLogStart(index);
page = GenericXLogRegister(state, buffer, true);
page = GenericXLogRegisterBuffer(state, buffer, GENERIC_XLOG_FULL_IMAGE);
memcpy(page, buildstate->data, BLCKSZ);
GenericXLogFinish(state);
UnlockReleaseBuffer(buffer);
@ -221,7 +221,7 @@ blinsert(Relation index, Datum *values, bool *isnull,
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
state = GenericXLogStart(index);
page = GenericXLogRegister(state, buffer, false);
page = GenericXLogRegisterBuffer(state, buffer, 0);
if (BloomPageAddItem(&blstate, page, itup))
{
@ -268,7 +268,7 @@ blinsert(Relation index, Datum *values, bool *isnull,
state = GenericXLogStart(index);
/* get modifiable copy of metapage */
metaPage = GenericXLogRegister(state, metaBuffer, false);
metaPage = GenericXLogRegisterBuffer(state, metaBuffer, 0);
metaData = BloomPageGetMeta(metaPage);
if (nStart >= metaData->nEnd)
@ -279,7 +279,7 @@ blinsert(Relation index, Datum *values, bool *isnull,
buffer = ReadBuffer(index, blkno);
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
page = GenericXLogRegister(state, buffer, false);
page = GenericXLogRegisterBuffer(state, buffer, 0);
if (BloomPageAddItem(&blstate, page, itup))
{
@ -305,7 +305,7 @@ blinsert(Relation index, Datum *values, bool *isnull,
*/
buffer = BloomNewBuffer(index);
page = GenericXLogRegister(state, buffer, true);
page = GenericXLogRegisterBuffer(state, buffer, GENERIC_XLOG_FULL_IMAGE);
BloomInitPage(page, 0);
if (!BloomPageAddItem(&blstate, page, itup))

View File

@ -39,7 +39,7 @@ PG_FUNCTION_INFO_V1(blhandler);
/* Kind of relation optioms for bloom index */
static relopt_kind bl_relopt_kind;
static int32 myRand();
static int32 myRand(void);
static void mySrand(uint32 seed);
/*
@ -173,15 +173,16 @@ initBloomState(BloomState *state, Relation index)
static int32 next;
static int32
myRand()
myRand(void)
{
/*
/*----------
* Compute x = (7^5 * x) mod (2^31 - 1)
* without overflowing 31 bits:
* (2^31 - 1) = 127773 * (7^5) + 2836
* From "Random number generators: good ones are hard to find",
* Park and Miller, Communications of the ACM, vol. 31, no. 10,
* October 1988, p. 1195.
*----------
*/
int32 hi, lo, x;
@ -418,7 +419,7 @@ BloomInitMetapage(Relation index)
/* Initialize contents of meta page */
state = GenericXLogStart(index);
metaPage = GenericXLogRegister(state, metaBuffer, true);
metaPage = GenericXLogRegisterBuffer(state, metaBuffer, GENERIC_XLOG_FULL_IMAGE);
BloomInitPage(metaPage, BLOOM_META);
metadata = BloomPageGetMeta(metaPage);

View File

@ -65,7 +65,7 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
gxlogState = GenericXLogStart(index);
page = GenericXLogRegister(gxlogState, buffer, false);
page = GenericXLogRegisterBuffer(gxlogState, buffer, 0);
if (BloomPageIsDeleted(page))
{
@ -145,7 +145,7 @@ blbulkdelete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats,
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
gxlogState = GenericXLogStart(index);
page = GenericXLogRegister(gxlogState, buffer, false);
page = GenericXLogRegisterBuffer(gxlogState, buffer, 0);
metaData = BloomPageGetMeta(page);
memcpy(metaData->notFullPage, notFullPage, sizeof(BlockNumber) * countPage);

View File

@ -31,15 +31,18 @@
<listitem>
<para>
<function>page = GenericXLogRegister(state, buffer, isNew)</> &mdash;
register a buffer to be modified within the current generic WAL
<function>page = GenericXLogRegisterBuffer(state, buffer, flags)</>
&mdash; register a buffer to be modified within the current generic WAL
record. This function returns a pointer to a temporary copy of the
buffer's page, where modifications should be made. (Do not modify the
buffer's contents directly.) The third argument indicates if the page
is new; if true, this will result in a full-page image rather than a
delta update being included in the WAL record.
<function>GenericXLogRegister</> can be repeated if the WAL-logged
action needs to modify multiple pages.
buffer's contents directly.) The third argument is a bitmask of flags
applicable to the operation. Currently the only such flag is
<literal>GENERIC_XLOG_FULL_IMAGE</>, which indicates that a full-page
image rather than a delta update should be included in the WAL record.
Typically this flag would be set if the page is new or has been
rewritten completely.
<function>GenericXLogRegisterBuffer</> can be repeated if the
WAL-logged action needs to modify multiple pages.
</para>
</listitem>
@ -71,13 +74,13 @@
<itemizedlist>
<listitem>
<para>
No direct modifications of buffers are allowed! All modifications
must be done in copies acquired from <function>GenericXLogRegister()</>.
No direct modifications of buffers are allowed! All modifications must
be done in copies acquired from <function>GenericXLogRegisterBuffer()</>.
In other words, code that makes generic WAL records should never call
<function>BufferGetPage()</> for itself. However, it remains the
caller's responsibility to pin/unpin and lock/unlock the buffers at
appropriate times. Exclusive lock must be held on each target buffer
from before <function>GenericXLogRegister()</> until after
from before <function>GenericXLogRegisterBuffer()</> until after
<function>GenericXLogFinish()</>.
</para>
</listitem>
@ -145,10 +148,11 @@
<listitem>
<para>
If a registered buffer is not new, the generic WAL record contains
a delta between the old and the new page images. This delta is based
on byte-by-byte comparison. This is not very compact for the case of
moving data within a page, and might be improved in the future.
If <literal>GENERIC_XLOG_FULL_IMAGE</> is not specified for a
registered buffer, the generic WAL record contains a delta between
the old and the new page images. This delta is based on byte-by-byte
comparison. This is not very compact for the case of moving data
within a page, and might be improved in the future.
</para>
</listitem>
</itemizedlist>

View File

@ -50,7 +50,7 @@
typedef struct
{
Buffer buffer; /* registered buffer */
bool fullImage; /* are we taking a full image of this page? */
int flags; /* flags for this buffer */
int deltaLen; /* space consumed in delta field */
char image[BLCKSZ]; /* copy of page image for modification */
char delta[MAX_DELTA_SIZE]; /* delta between page images */
@ -280,9 +280,11 @@ GenericXLogStart(Relation relation)
* is what the caller should modify.
*
* If the buffer is already registered, just return its existing entry.
* (It's not very clear what to do with the flags in such a case, but
* for now we stay with the original flags.)
*/
Page
GenericXLogRegister(GenericXLogState *state, Buffer buffer, bool isNew)
GenericXLogRegisterBuffer(GenericXLogState *state, Buffer buffer, int flags)
{
int block_id;
@ -295,7 +297,7 @@ GenericXLogRegister(GenericXLogState *state, Buffer buffer, bool isNew)
{
/* Empty slot, so use it (there cannot be a match later) */
page->buffer = buffer;
page->fullImage = isNew;
page->flags = flags;
memcpy(page->image,
BufferGetPage(buffer, NULL, NULL, BGP_NO_SNAPSHOT_TEST),
BLCKSZ);
@ -347,7 +349,7 @@ GenericXLogFinish(GenericXLogState *state)
BGP_NO_SNAPSHOT_TEST);
pageHeader = (PageHeader) pageData->image;
if (pageData->fullImage)
if (pageData->flags & GENERIC_XLOG_FULL_IMAGE)
{
/*
* A full-page image does not require us to supply any xlog

View File

@ -22,14 +22,17 @@
#define MAX_GENERIC_XLOG_PAGES XLR_NORMAL_MAX_BLOCK_ID
/* Flag bits for GenericXLogRegisterBuffer */
#define GENERIC_XLOG_FULL_IMAGE 0x0001 /* write full-page image */
/* state of generic xlog record construction */
struct GenericXLogState;
typedef struct GenericXLogState GenericXLogState;
/* API for construction of generic xlog records */
extern GenericXLogState *GenericXLogStart(Relation relation);
extern Page GenericXLogRegister(GenericXLogState *state, Buffer buffer,
bool isNew);
extern Page GenericXLogRegisterBuffer(GenericXLogState *state, Buffer buffer,
int flags);
extern XLogRecPtr GenericXLogFinish(GenericXLogState *state);
extern void GenericXLogAbort(GenericXLogState *state);