PostgreSQL Source Code git master
generic_xlog.h File Reference
#include "access/xlog.h"
#include "access/xlogreader.h"
#include "access/xloginsert.h"
#include "storage/bufpage.h"
#include "utils/rel.h"
Include dependency graph for generic_xlog.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define MAX_GENERIC_XLOG_PAGES   XLR_NORMAL_MAX_BLOCK_ID
 
#define GENERIC_XLOG_FULL_IMAGE   0x0001 /* write full-page image */
 

Typedefs

typedef struct GenericXLogState GenericXLogState
 

Functions

GenericXLogStateGenericXLogStart (Relation relation)
 
Page GenericXLogRegisterBuffer (GenericXLogState *state, Buffer buffer, int flags)
 
XLogRecPtr GenericXLogFinish (GenericXLogState *state)
 
void GenericXLogAbort (GenericXLogState *state)
 
void generic_redo (XLogReaderState *record)
 
const char * generic_identify (uint8 info)
 
void generic_desc (StringInfo buf, XLogReaderState *record)
 
void generic_mask (char *page, BlockNumber blkno)
 

Macro Definition Documentation

◆ GENERIC_XLOG_FULL_IMAGE

#define GENERIC_XLOG_FULL_IMAGE   0x0001 /* write full-page image */

Definition at line 26 of file generic_xlog.h.

◆ MAX_GENERIC_XLOG_PAGES

#define MAX_GENERIC_XLOG_PAGES   XLR_NORMAL_MAX_BLOCK_ID

Definition at line 23 of file generic_xlog.h.

Typedef Documentation

◆ GenericXLogState

Definition at line 30 of file generic_xlog.h.

Function Documentation

◆ generic_desc()

void generic_desc ( StringInfo  buf,
XLogReaderState record 
)

Definition at line 24 of file genericdesc.c.

25{
26 Pointer ptr = XLogRecGetData(record),
27 end = ptr + XLogRecGetDataLen(record);
28
29 while (ptr < end)
30 {
31 OffsetNumber offset,
32 length;
33
34 memcpy(&offset, ptr, sizeof(offset));
35 ptr += sizeof(offset);
36 memcpy(&length, ptr, sizeof(length));
37 ptr += sizeof(length);
38 ptr += length;
39
40 if (ptr < end)
41 appendStringInfo(buf, "offset %u, length %u; ", offset, length);
42 else
43 appendStringInfo(buf, "offset %u, length %u", offset, length);
44 }
45}
char * Pointer
Definition: c.h:493
uint16 OffsetNumber
Definition: off.h:24
static char * buf
Definition: pg_test_fsync.c:72
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:416
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415

References appendStringInfo(), buf, XLogRecGetData, and XLogRecGetDataLen.

◆ generic_identify()

const char * generic_identify ( uint8  info)

Definition at line 52 of file genericdesc.c.

53{
54 return "Generic";
55}

◆ generic_mask()

void generic_mask ( char *  page,
BlockNumber  blkno 
)

Definition at line 539 of file generic_xlog.c.

540{
542
543 mask_unused_space(page);
544}
void mask_page_lsn_and_checksum(Page page)
Definition: bufmask.c:31
void mask_unused_space(Page page)
Definition: bufmask.c:71

References mask_page_lsn_and_checksum(), and mask_unused_space().

◆ generic_redo()

void generic_redo ( XLogReaderState record)

Definition at line 478 of file generic_xlog.c.

479{
480 XLogRecPtr lsn = record->EndRecPtr;
482 uint8 block_id;
483
484 /* Protect limited size of buffers[] array */
486
487 /* Iterate over blocks */
488 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
489 {
491
492 if (!XLogRecHasBlockRef(record, block_id))
493 {
494 buffers[block_id] = InvalidBuffer;
495 continue;
496 }
497
498 action = XLogReadBufferForRedo(record, block_id, &buffers[block_id]);
499
500 /* Apply redo to given block if needed */
501 if (action == BLK_NEEDS_REDO)
502 {
503 Page page;
504 PageHeader pageHeader;
505 char *blockDelta;
506 Size blockDeltaSize;
507
508 page = BufferGetPage(buffers[block_id]);
509 blockDelta = XLogRecGetBlockData(record, block_id, &blockDeltaSize);
510 applyPageRedo(page, blockDelta, blockDeltaSize);
511
512 /*
513 * Since the delta contains no information about what's in the
514 * "hole" between pd_lower and pd_upper, set that to zero to
515 * ensure we produce the same page state that application of the
516 * logged action by GenericXLogFinish did.
517 */
518 pageHeader = (PageHeader) page;
519 memset(page + pageHeader->pd_lower, 0,
520 pageHeader->pd_upper - pageHeader->pd_lower);
521
522 PageSetLSN(page, lsn);
523 MarkBufferDirty(buffers[block_id]);
524 }
525 }
526
527 /* Changes are done: unlock and release all buffers */
528 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
529 {
530 if (BufferIsValid(buffers[block_id]))
531 UnlockReleaseBuffer(buffers[block_id]);
532 }
533}
int Buffer
Definition: buf.h:23
#define InvalidBuffer
Definition: buf.h:25
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4934
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2596
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:401
static bool BufferIsValid(Buffer bufnum)
Definition: bufmgr.h:352
PageHeaderData * PageHeader
Definition: bufpage.h:174
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:391
PageData * Page
Definition: bufpage.h:82
uint8_t uint8
Definition: c.h:500
size_t Size
Definition: c.h:576
static void applyPageRedo(Page page, const char *delta, Size deltaSize)
Definition: generic_xlog.c:453
#define MAX_GENERIC_XLOG_PAGES
Definition: generic_xlog.h:23
Assert(PointerIsAligned(start, uint64))
LocationIndex pd_upper
Definition: bufpage.h:167
LocationIndex pd_lower
Definition: bufpage.h:166
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
uint64 XLogRecPtr
Definition: xlogdefs.h:21
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
Definition: xlogreader.c:2035
#define XLogRecMaxBlockId(decoder)
Definition: xlogreader.h:418
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:420
XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)
Definition: xlogutils.c:303
XLogRedoAction
Definition: xlogutils.h:73
@ BLK_NEEDS_REDO
Definition: xlogutils.h:74

References generate_unaccent_rules::action, applyPageRedo(), Assert(), BLK_NEEDS_REDO, BufferGetPage(), BufferIsValid(), XLogReaderState::EndRecPtr, InvalidBuffer, MarkBufferDirty(), MAX_GENERIC_XLOG_PAGES, PageSetLSN(), PageHeaderData::pd_lower, PageHeaderData::pd_upper, UnlockReleaseBuffer(), XLogReadBufferForRedo(), XLogRecGetBlockData(), XLogRecHasBlockRef, and XLogRecMaxBlockId.

◆ GenericXLogAbort()

void GenericXLogAbort ( GenericXLogState state)

Definition at line 444 of file generic_xlog.c.

445{
446 pfree(state);
447}
void pfree(void *pointer)
Definition: mcxt.c:1524
Definition: regguts.h:323

References pfree().

Referenced by blbulkdelete(), and blinsert().

◆ GenericXLogFinish()

XLogRecPtr GenericXLogFinish ( GenericXLogState state)

Definition at line 337 of file generic_xlog.c.

338{
339 XLogRecPtr lsn;
340 int i;
341
342 if (state->isLogged)
343 {
344 /* Logged relation: make xlog record in critical section. */
346
348
349 /*
350 * Compute deltas if necessary, write changes to buffers, mark buffers
351 * dirty, and register changes.
352 */
353 for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++)
354 {
355 GenericXLogPageData *pageData = &state->pages[i];
356 Page page;
357 PageHeader pageHeader;
358
359 if (BufferIsInvalid(pageData->buffer))
360 continue;
361
362 page = BufferGetPage(pageData->buffer);
363 pageHeader = (PageHeader) pageData->image;
364
365 /*
366 * Compute delta while we still have both the unmodified page and
367 * the new image. Not needed if we are logging the full image.
368 */
369 if (!(pageData->flags & GENERIC_XLOG_FULL_IMAGE))
370 computeDelta(pageData, page, (Page) pageData->image);
371
372 /*
373 * Apply the image, being careful to zero the "hole" between
374 * pd_lower and pd_upper in order to avoid divergence between
375 * actual page state and what replay would produce.
376 */
377 memcpy(page, pageData->image, pageHeader->pd_lower);
378 memset(page + pageHeader->pd_lower, 0,
379 pageHeader->pd_upper - pageHeader->pd_lower);
380 memcpy(page + pageHeader->pd_upper,
381 pageData->image + pageHeader->pd_upper,
382 BLCKSZ - pageHeader->pd_upper);
383
384 MarkBufferDirty(pageData->buffer);
385
386 if (pageData->flags & GENERIC_XLOG_FULL_IMAGE)
387 {
388 XLogRegisterBuffer(i, pageData->buffer,
390 }
391 else
392 {
394 XLogRegisterBufData(i, pageData->delta, pageData->deltaLen);
395 }
396 }
397
398 /* Insert xlog record */
399 lsn = XLogInsert(RM_GENERIC_ID, 0);
400
401 /* Set LSN */
402 for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++)
403 {
404 GenericXLogPageData *pageData = &state->pages[i];
405
406 if (BufferIsInvalid(pageData->buffer))
407 continue;
408 PageSetLSN(BufferGetPage(pageData->buffer), lsn);
409 }
411 }
412 else
413 {
414 /* Unlogged relation: skip xlog-related stuff */
416 for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++)
417 {
418 GenericXLogPageData *pageData = &state->pages[i];
419
420 if (BufferIsInvalid(pageData->buffer))
421 continue;
422 memcpy(BufferGetPage(pageData->buffer),
423 pageData->image,
424 BLCKSZ);
425 /* We don't worry about zeroing the "hole" in this case */
426 MarkBufferDirty(pageData->buffer);
427 }
429 /* We don't have a LSN to return, in this case */
430 lsn = InvalidXLogRecPtr;
431 }
432
433 pfree(state);
434
435 return lsn;
436}
#define BufferIsInvalid(buffer)
Definition: buf.h:31
static void computeDelta(GenericXLogPageData *pageData, Page curpage, Page targetpage)
Definition: generic_xlog.c:228
#define GENERIC_XLOG_FULL_IMAGE
Definition: generic_xlog.h:26
int i
Definition: isn.c:74
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:78
#define START_CRIT_SECTION()
Definition: miscadmin.h:149
#define END_CRIT_SECTION()
Definition: miscadmin.h:151
char delta[MAX_DELTA_SIZE]
Definition: generic_xlog.c:57
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterBufData(uint8 block_id, const void *data, uint32 len)
Definition: xloginsert.c:405
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:242
void XLogBeginInsert(void)
Definition: xloginsert.c:149
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define REGBUF_FORCE_IMAGE
Definition: xloginsert.h:32

References GenericXLogPageData::buffer, BufferGetPage(), BufferIsInvalid, computeDelta(), GenericXLogPageData::delta, GenericXLogPageData::deltaLen, END_CRIT_SECTION, GenericXLogPageData::flags, GENERIC_XLOG_FULL_IMAGE, i, if(), GenericXLogPageData::image, InvalidXLogRecPtr, MarkBufferDirty(), MAX_GENERIC_XLOG_PAGES, PageSetLSN(), PageHeaderData::pd_lower, PageHeaderData::pd_upper, pfree(), REGBUF_FORCE_IMAGE, REGBUF_STANDARD, START_CRIT_SECTION, XLogBeginInsert(), XLogInsert(), XLogRegisterBufData(), and XLogRegisterBuffer().

Referenced by blbulkdelete(), blinsert(), BloomInitMetapage(), and flushCachedPage().

◆ GenericXLogRegisterBuffer()

Page GenericXLogRegisterBuffer ( GenericXLogState state,
Buffer  buffer,
int  flags 
)

Definition at line 299 of file generic_xlog.c.

300{
301 int block_id;
302
303 /* Search array for existing entry or first unused slot */
304 for (block_id = 0; block_id < MAX_GENERIC_XLOG_PAGES; block_id++)
305 {
306 GenericXLogPageData *page = &state->pages[block_id];
307
308 if (BufferIsInvalid(page->buffer))
309 {
310 /* Empty slot, so use it (there cannot be a match later) */
311 page->buffer = buffer;
312 page->flags = flags;
313 memcpy(page->image, BufferGetPage(buffer), BLCKSZ);
314 return (Page) page->image;
315 }
316 else if (page->buffer == buffer)
317 {
318 /*
319 * Buffer is already registered. Just return the image, which is
320 * already prepared.
321 */
322 return (Page) page->image;
323 }
324 }
325
326 elog(ERROR, "maximum number %d of generic xlog buffers is exceeded",
328 /* keep compiler quiet */
329 return NULL;
330}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225

References GenericXLogPageData::buffer, BufferGetPage(), BufferIsInvalid, elog, ERROR, GenericXLogPageData::flags, GenericXLogPageData::image, and MAX_GENERIC_XLOG_PAGES.

Referenced by blbulkdelete(), blinsert(), BloomInitMetapage(), and flushCachedPage().

◆ GenericXLogStart()

GenericXLogState * GenericXLogStart ( Relation  relation)

Definition at line 269 of file generic_xlog.c.

270{
272 int i;
273
276 0);
277 state->isLogged = RelationNeedsWAL(relation);
278
279 for (i = 0; i < MAX_GENERIC_XLOG_PAGES; i++)
280 {
281 state->pages[i].image = state->images[i].data;
282 state->pages[i].buffer = InvalidBuffer;
283 }
284
285 return state;
286}
void * palloc_aligned(Size size, Size alignto, int flags)
Definition: mcxt.c:1514
#define PG_IO_ALIGN_SIZE
#define RelationNeedsWAL(relation)
Definition: rel.h:636

References i, InvalidBuffer, MAX_GENERIC_XLOG_PAGES, palloc_aligned(), PG_IO_ALIGN_SIZE, and RelationNeedsWAL.

Referenced by blbulkdelete(), blinsert(), BloomInitMetapage(), and flushCachedPage().