PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
xlogutils.c File Reference
#include "postgres.h"
#include <unistd.h>
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xlogutils.h"
#include "catalog/catalog.h"
#include "miscadmin.h"
#include "storage/smgr.h"
#include "utils/guc.h"
#include "utils/hsearch.h"
#include "utils/rel.h"
Include dependency graph for xlogutils.c:

Go to the source code of this file.

Data Structures

struct  xl_invalid_page_key
 
struct  xl_invalid_page
 
struct  FakeRelCacheEntryData
 

Typedefs

typedef struct xl_invalid_page_key xl_invalid_page_key
 
typedef struct xl_invalid_page xl_invalid_page
 
typedef FakeRelCacheEntryDataFakeRelCacheEntry
 

Functions

static void report_invalid_page (int elevel, RelFileNode node, ForkNumber forkno, BlockNumber blkno, bool present)
 
static void log_invalid_page (RelFileNode node, ForkNumber forkno, BlockNumber blkno, bool present)
 
static void forget_invalid_pages (RelFileNode node, ForkNumber forkno, BlockNumber minblkno)
 
static void forget_invalid_pages_db (Oid dbid)
 
bool XLogHaveInvalidPages (void)
 
void XLogCheckInvalidPages (void)
 
XLogRedoAction XLogReadBufferForRedo (XLogReaderState *record, uint8 block_id, Buffer *buf)
 
Buffer XLogInitBufferForRedo (XLogReaderState *record, uint8 block_id)
 
XLogRedoAction XLogReadBufferForRedoExtended (XLogReaderState *record, uint8 block_id, ReadBufferMode mode, bool get_cleanup_lock, Buffer *buf)
 
Buffer XLogReadBufferExtended (RelFileNode rnode, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode)
 
Relation CreateFakeRelcacheEntry (RelFileNode rnode)
 
void FreeFakeRelcacheEntry (Relation fakerel)
 
void XLogDropRelation (RelFileNode rnode, ForkNumber forknum)
 
void XLogDropDatabase (Oid dbid)
 
void XLogTruncateRelation (RelFileNode rnode, ForkNumber forkNum, BlockNumber nblocks)
 
static void XLogRead (char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
 
int read_local_xlog_page (XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page, TimeLineID *pageTLI)
 

Variables

static HTABinvalid_page_tab = NULL
 

Typedef Documentation

Function Documentation

Relation CreateFakeRelcacheEntry ( RelFileNode  rnode)

Definition at line 549 of file xlogutils.c.

References Assert, LockRelId::dbId, RelFileNode::dbNode, InRecovery, InvalidBackendId, LockInfoData::lockRelId, NULL, palloc0(), FakeRelCacheEntryData::pgc, RelationData::rd_backend, RelationData::rd_lockInfo, RelationData::rd_node, RelationData::rd_rel, RelationData::rd_smgr, RelationGetRelationName, LockRelId::relId, RelFileNode::relNode, and RELPERSISTENCE_PERMANENT.

Referenced by heap_xlog_delete(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_update(), heap_xlog_visible(), and smgr_redo().

550 {
551  FakeRelCacheEntry fakeentry;
552  Relation rel;
553 
555 
556  /* Allocate the Relation struct and all related space in one block. */
557  fakeentry = palloc0(sizeof(FakeRelCacheEntryData));
558  rel = (Relation) fakeentry;
559 
560  rel->rd_rel = &fakeentry->pgc;
561  rel->rd_node = rnode;
562  /* We will never be working with temp rels during recovery */
564 
565  /* It must be a permanent table if we're in recovery. */
566  rel->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;
567 
568  /* We don't know the name of the relation; use relfilenode instead */
569  sprintf(RelationGetRelationName(rel), "%u", rnode.relNode);
570 
571  /*
572  * We set up the lockRelId in case anything tries to lock the dummy
573  * relation. Note that this is fairly bogus since relNode may be
574  * different from the relation's OID. It shouldn't really matter though,
575  * since we are presumably running by ourselves and can't have any lock
576  * conflicts ...
577  */
578  rel->rd_lockInfo.lockRelId.dbId = rnode.dbNode;
579  rel->rd_lockInfo.lockRelId.relId = rnode.relNode;
580 
581  rel->rd_smgr = NULL;
582 
583  return rel;
584 }
LockRelId lockRelId
Definition: rel.h:44
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
bool InRecovery
Definition: xlog.c:191
Oid dbId
Definition: rel.h:39
Form_pg_class rd_rel
Definition: rel.h:113
#define RELPERSISTENCE_PERMANENT
Definition: pg_class.h:170
struct RelationData * Relation
Definition: relcache.h:21
LockInfoData rd_lockInfo
Definition: rel.h:116
#define RelationGetRelationName(relation)
Definition: rel.h:433
#define InvalidBackendId
Definition: backendid.h:23
void * palloc0(Size size)
Definition: mcxt.c:878
RelFileNode rd_node
Definition: rel.h:85
#define NULL
Definition: c.h:226
BackendId rd_backend
Definition: rel.h:89
#define Assert(condition)
Definition: c.h:671
FormData_pg_class pgc
Definition: xlogutils.c:531
Oid relId
Definition: rel.h:38
static void forget_invalid_pages ( RelFileNode  node,
ForkNumber  forkno,
BlockNumber  minblkno 
)
static

Definition at line 141 of file xlogutils.c.

References xl_invalid_page_key::blkno, client_min_messages, DEBUG2, elog, ERROR, xl_invalid_page_key::forkno, HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), xl_invalid_page::key, log_min_messages, xl_invalid_page_key::node, NULL, pfree(), RelFileNodeEquals, relpathperm, and status().

Referenced by XLogDropRelation(), and XLogTruncateRelation().

142 {
144  xl_invalid_page *hentry;
145 
146  if (invalid_page_tab == NULL)
147  return; /* nothing to do */
148 
150 
151  while ((hentry = (xl_invalid_page *) hash_seq_search(&status)) != NULL)
152  {
153  if (RelFileNodeEquals(hentry->key.node, node) &&
154  hentry->key.forkno == forkno &&
155  hentry->key.blkno >= minblkno)
156  {
158  {
159  char *path = relpathperm(hentry->key.node, forkno);
160 
161  elog(DEBUG2, "page %u of relation %s has been dropped",
162  hentry->key.blkno, path);
163  pfree(path);
164  }
165 
167  (void *) &hentry->key,
168  HASH_REMOVE, NULL) == NULL)
169  elog(ERROR, "hash table corrupted");
170  }
171  }
172 }
#define relpathperm(rnode, forknum)
Definition: relpath.h:67
ForkNumber forkno
Definition: xlogutils.c:46
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
RelFileNode node
Definition: xlogutils.c:45
void pfree(void *pointer)
Definition: mcxt.c:950
#define ERROR
Definition: elog.h:43
#define DEBUG2
Definition: elog.h:24
BlockNumber blkno
Definition: xlogutils.c:47
xl_invalid_page_key key
Definition: xlogutils.c:52
int log_min_messages
Definition: guc.c:453
#define NULL
Definition: c.h:226
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
static HTAB * invalid_page_tab
Definition: xlogutils.c:56
int client_min_messages
Definition: guc.c:454
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88
static void forget_invalid_pages_db ( Oid  dbid)
static

Definition at line 176 of file xlogutils.c.

References xl_invalid_page_key::blkno, client_min_messages, RelFileNode::dbNode, DEBUG2, elog, ERROR, xl_invalid_page_key::forkno, HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), xl_invalid_page::key, log_min_messages, xl_invalid_page_key::node, NULL, pfree(), relpathperm, and status().

Referenced by XLogDropDatabase().

177 {
179  xl_invalid_page *hentry;
180 
181  if (invalid_page_tab == NULL)
182  return; /* nothing to do */
183 
185 
186  while ((hentry = (xl_invalid_page *) hash_seq_search(&status)) != NULL)
187  {
188  if (hentry->key.node.dbNode == dbid)
189  {
191  {
192  char *path = relpathperm(hentry->key.node, hentry->key.forkno);
193 
194  elog(DEBUG2, "page %u of relation %s has been dropped",
195  hentry->key.blkno, path);
196  pfree(path);
197  }
198 
200  (void *) &hentry->key,
201  HASH_REMOVE, NULL) == NULL)
202  elog(ERROR, "hash table corrupted");
203  }
204  }
205 }
#define relpathperm(rnode, forknum)
Definition: relpath.h:67
ForkNumber forkno
Definition: xlogutils.c:46
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
RelFileNode node
Definition: xlogutils.c:45
void pfree(void *pointer)
Definition: mcxt.c:950
#define ERROR
Definition: elog.h:43
#define DEBUG2
Definition: elog.h:24
BlockNumber blkno
Definition: xlogutils.c:47
xl_invalid_page_key key
Definition: xlogutils.c:52
int log_min_messages
Definition: guc.c:453
#define NULL
Definition: c.h:226
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
static HTAB * invalid_page_tab
Definition: xlogutils.c:56
int client_min_messages
Definition: guc.c:454
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
void FreeFakeRelcacheEntry ( Relation  fakerel)

Definition at line 590 of file xlogutils.c.

References NULL, pfree(), RelationData::rd_smgr, and smgrclearowner().

Referenced by heap_xlog_delete(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_update(), heap_xlog_visible(), and smgr_redo().

591 {
592  /* make sure the fakerel is not referenced by the SmgrRelation anymore */
593  if (fakerel->rd_smgr != NULL)
594  smgrclearowner(&fakerel->rd_smgr, fakerel->rd_smgr);
595  pfree(fakerel);
596 }
void smgrclearowner(SMgrRelation *owner, SMgrRelation reln)
Definition: smgr.c:222
struct SMgrRelationData * rd_smgr
Definition: rel.h:87
void pfree(void *pointer)
Definition: mcxt.c:950
#define NULL
Definition: c.h:226
static void log_invalid_page ( RelFileNode  node,
ForkNumber  forkno,
BlockNumber  blkno,
bool  present 
)
static

Definition at line 77 of file xlogutils.c.

References xl_invalid_page_key::blkno, client_min_messages, DEBUG1, elog, HASHCTL::entrysize, xl_invalid_page_key::forkno, HASH_BLOBS, hash_create(), HASH_ELEM, HASH_ENTER, hash_search(), HASHCTL::keysize, log_min_messages, xl_invalid_page_key::node, NULL, PANIC, xl_invalid_page::present, reachedConsistency, report_invalid_page(), and WARNING.

Referenced by XLogReadBufferExtended().

79 {
81  xl_invalid_page *hentry;
82  bool found;
83 
84  /*
85  * Once recovery has reached a consistent state, the invalid-page table
86  * should be empty and remain so. If a reference to an invalid page is
87  * found after consistency is reached, PANIC immediately. This might seem
88  * aggressive, but it's better than letting the invalid reference linger
89  * in the hash table until the end of recovery and PANIC there, which
90  * might come only much later if this is a standby server.
91  */
93  {
94  report_invalid_page(WARNING, node, forkno, blkno, present);
95  elog(PANIC, "WAL contains references to invalid pages");
96  }
97 
98  /*
99  * Log references to invalid pages at DEBUG1 level. This allows some
100  * tracing of the cause (note the elog context mechanism will tell us
101  * something about the XLOG record that generated the reference).
102  */
104  report_invalid_page(DEBUG1, node, forkno, blkno, present);
105 
106  if (invalid_page_tab == NULL)
107  {
108  /* create hash table when first needed */
109  HASHCTL ctl;
110 
111  memset(&ctl, 0, sizeof(ctl));
112  ctl.keysize = sizeof(xl_invalid_page_key);
113  ctl.entrysize = sizeof(xl_invalid_page);
114 
115  invalid_page_tab = hash_create("XLOG invalid-page table",
116  100,
117  &ctl,
119  }
120 
121  /* we currently assume xl_invalid_page_key contains no padding */
122  key.node = node;
123  key.forkno = forkno;
124  key.blkno = blkno;
125  hentry = (xl_invalid_page *)
126  hash_search(invalid_page_tab, (void *) &key, HASH_ENTER, &found);
127 
128  if (!found)
129  {
130  /* hash_search already filled in the key */
131  hentry->present = present;
132  }
133  else
134  {
135  /* repeat reference ... leave "present" as it was */
136  }
137 }
#define DEBUG1
Definition: elog.h:25
struct xl_invalid_page xl_invalid_page
#define HASH_ELEM
Definition: hsearch.h:87
Size entrysize
Definition: hsearch.h:73
struct xl_invalid_page_key xl_invalid_page_key
ForkNumber forkno
Definition: xlogutils.c:46
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
#define PANIC
Definition: elog.h:53
RelFileNode node
Definition: xlogutils.c:45
static void report_invalid_page(int elevel, RelFileNode node, ForkNumber forkno, BlockNumber blkno, bool present)
Definition: xlogutils.c:61
BlockNumber blkno
Definition: xlogutils.c:47
#define WARNING
Definition: elog.h:40
#define HASH_BLOBS
Definition: hsearch.h:88
HTAB * hash_create(const char *tabname, long nelem, HASHCTL *info, int flags)
Definition: dynahash.c:301
Size keysize
Definition: hsearch.h:72
int log_min_messages
Definition: guc.c:453
bool reachedConsistency
Definition: xlog.c:821
#define NULL
Definition: c.h:226
static HTAB * invalid_page_tab
Definition: xlogutils.c:56
int client_min_messages
Definition: guc.c:454
#define elog
Definition: elog.h:219
int read_local_xlog_page ( XLogReaderState state,
XLogRecPtr  targetPagePtr,
int  reqLen,
XLogRecPtr  targetRecPtr,
char *  cur_page,
TimeLineID pageTLI 
)

Definition at line 765 of file xlogutils.c.

References CHECK_FOR_INTERRUPTS, GetFlushRecPtr(), GetXLogReplayRecPtr(), pg_usleep(), RecoveryInProgress(), ThisTimeLineID, and XLogRead().

Referenced by logical_read_local_xlog_page(), and XlogReadTwoPhaseData().

768 {
769  XLogRecPtr read_upto,
770  loc;
771  int count;
772 
773  loc = targetPagePtr + reqLen;
774  while (1)
775  {
776  /*
777  * TODO: we're going to have to do something more intelligent about
778  * timelines on standbys. Use readTimeLineHistory() and
779  * tliOfPointInHistory() to get the proper LSN? For now we'll catch
780  * that case earlier, but the code and TODO is left in here for when
781  * that changes.
782  */
783  if (!RecoveryInProgress())
784  {
785  *pageTLI = ThisTimeLineID;
786  read_upto = GetFlushRecPtr();
787  }
788  else
789  read_upto = GetXLogReplayRecPtr(pageTLI);
790 
791  if (loc <= read_upto)
792  break;
793 
795  pg_usleep(1000L);
796  }
797 
798  if (targetPagePtr + XLOG_BLCKSZ <= read_upto)
799  {
800  /*
801  * more than one block available; read only that block, have caller
802  * come back if they need more.
803  */
804  count = XLOG_BLCKSZ;
805  }
806  else if (targetPagePtr + reqLen > read_upto)
807  {
808  /* not enough data there */
809  return -1;
810  }
811  else
812  {
813  /* enough bytes available to satisfy the request */
814  count = read_upto - targetPagePtr;
815  }
816 
817  /*
818  * Even though we just determined how much of the page can be validly read
819  * as 'count', read the whole page anyway. It's guaranteed to be
820  * zero-padded up to the page boundary if it's incomplete.
821  */
822  XLogRead(cur_page, *pageTLI, targetPagePtr, XLOG_BLCKSZ);
823 
824  /* number of valid bytes in the buffer */
825  return count;
826 }
static void XLogRead(char *buf, TimeLineID tli, XLogRecPtr startptr, Size count)
Definition: xlogutils.c:655
XLogRecPtr GetFlushRecPtr(void)
Definition: xlog.c:8154
bool RecoveryInProgress(void)
Definition: xlog.c:7805
void pg_usleep(long microsec)
Definition: signal.c:53
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
Definition: xlog.c:10984
TimeLineID ThisTimeLineID
Definition: xlog.c:178
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:97
static void report_invalid_page ( int  elevel,
RelFileNode  node,
ForkNumber  forkno,
BlockNumber  blkno,
bool  present 
)
static

Definition at line 61 of file xlogutils.c.

References elog, pfree(), and relpathperm.

Referenced by log_invalid_page(), and XLogCheckInvalidPages().

63 {
64  char *path = relpathperm(node, forkno);
65 
66  if (present)
67  elog(elevel, "page %u of relation %s is uninitialized",
68  blkno, path);
69  else
70  elog(elevel, "page %u of relation %s does not exist",
71  blkno, path);
72  pfree(path);
73 }
#define relpathperm(rnode, forknum)
Definition: relpath.h:67
void pfree(void *pointer)
Definition: mcxt.c:950
static int elevel
Definition: vacuumlazy.c:136
#define elog
Definition: elog.h:219
void XLogCheckInvalidPages ( void  )

Definition at line 219 of file xlogutils.c.

References xl_invalid_page_key::blkno, elog, xl_invalid_page_key::forkno, hash_destroy(), hash_seq_init(), hash_seq_search(), xl_invalid_page::key, xl_invalid_page_key::node, NULL, PANIC, xl_invalid_page::present, report_invalid_page(), status(), and WARNING.

Referenced by CheckRecoveryConsistency().

220 {
222  xl_invalid_page *hentry;
223  bool foundone = false;
224 
225  if (invalid_page_tab == NULL)
226  return; /* nothing to do */
227 
229 
230  /*
231  * Our strategy is to emit WARNING messages for all remaining entries and
232  * only PANIC after we've dumped all the available info.
233  */
234  while ((hentry = (xl_invalid_page *) hash_seq_search(&status)) != NULL)
235  {
236  report_invalid_page(WARNING, hentry->key.node, hentry->key.forkno,
237  hentry->key.blkno, hentry->present);
238  foundone = true;
239  }
240 
241  if (foundone)
242  elog(PANIC, "WAL contains references to invalid pages");
243 
246 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:793
ForkNumber forkno
Definition: xlogutils.c:46
#define PANIC
Definition: elog.h:53
RelFileNode node
Definition: xlogutils.c:45
static void report_invalid_page(int elevel, RelFileNode node, ForkNumber forkno, BlockNumber blkno, bool present)
Definition: xlogutils.c:61
BlockNumber blkno
Definition: xlogutils.c:47
xl_invalid_page_key key
Definition: xlogutils.c:52
#define WARNING
Definition: elog.h:40
#define NULL
Definition: c.h:226
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1353
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1343
static HTAB * invalid_page_tab
Definition: xlogutils.c:56
#define elog
Definition: elog.h:219
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:222
void XLogDropDatabase ( Oid  dbid)

Definition at line 616 of file xlogutils.c.

References forget_invalid_pages_db(), and smgrcloseall().

Referenced by dbase_redo().

617 {
618  /*
619  * This is unnecessarily heavy-handed, as it will close SMgrRelation
620  * objects for other databases as well. DROP DATABASE occurs seldom enough
621  * that it's not worth introducing a variant of smgrclose for just this
622  * purpose. XXX: Or should we rather leave the smgr entries dangling?
623  */
624  smgrcloseall();
625 
627 }
static void forget_invalid_pages_db(Oid dbid)
Definition: xlogutils.c:176
void smgrcloseall(void)
Definition: smgr.c:326
void XLogDropRelation ( RelFileNode  rnode,
ForkNumber  forknum 
)

Definition at line 605 of file xlogutils.c.

References forget_invalid_pages().

Referenced by xact_redo_abort(), and xact_redo_commit().

606 {
607  forget_invalid_pages(rnode, forknum, 0);
608 }
static void forget_invalid_pages(RelFileNode node, ForkNumber forkno, BlockNumber minblkno)
Definition: xlogutils.c:141
bool XLogHaveInvalidPages ( void  )

Definition at line 209 of file xlogutils.c.

References hash_get_num_entries(), and NULL.

Referenced by RecoveryRestartPoint().

210 {
211  if (invalid_page_tab != NULL &&
213  return true;
214  return false;
215 }
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1297
#define NULL
Definition: c.h:226
static HTAB * invalid_page_tab
Definition: xlogutils.c:56
static void XLogRead ( char *  buf,
TimeLineID  tli,
XLogRecPtr  startptr,
Size  count 
)
static

Definition at line 655 of file xlogutils.c.

References BasicOpenFile(), buf, close, ereport, errcode_for_file_access(), errmsg(), ERROR, MAXPGPATH, PG_BINARY, read, sendFile, sendOff, sendSegNo, XLByteInSeg, XLByteToSeg, XLogFilePath, and XLogSegSize.

Referenced by read_local_xlog_page().

656 {
657  char *p;
658  XLogRecPtr recptr;
659  Size nbytes;
660 
661  /* state maintained across calls */
662  static int sendFile = -1;
663  static XLogSegNo sendSegNo = 0;
664  static uint32 sendOff = 0;
665 
666  p = buf;
667  recptr = startptr;
668  nbytes = count;
669 
670  while (nbytes > 0)
671  {
672  uint32 startoff;
673  int segbytes;
674  int readbytes;
675 
676  startoff = recptr % XLogSegSize;
677 
678  /* Do we need to switch to a different xlog segment? */
679  if (sendFile < 0 || !XLByteInSeg(recptr, sendSegNo))
680  {
681  char path[MAXPGPATH];
682 
683  if (sendFile >= 0)
684  close(sendFile);
685 
686  XLByteToSeg(recptr, sendSegNo);
687 
688  XLogFilePath(path, tli, sendSegNo);
689 
690  sendFile = BasicOpenFile(path, O_RDONLY | PG_BINARY, 0);
691 
692  if (sendFile < 0)
693  {
694  if (errno == ENOENT)
695  ereport(ERROR,
697  errmsg("requested WAL segment %s has already been removed",
698  path)));
699  else
700  ereport(ERROR,
702  errmsg("could not open file \"%s\": %m",
703  path)));
704  }
705  sendOff = 0;
706  }
707 
708  /* Need to seek in the file? */
709  if (sendOff != startoff)
710  {
711  if (lseek(sendFile, (off_t) startoff, SEEK_SET) < 0)
712  {
713  char path[MAXPGPATH];
714 
715  XLogFilePath(path, tli, sendSegNo);
716 
717  ereport(ERROR,
719  errmsg("could not seek in log segment %s to offset %u: %m",
720  path, startoff)));
721  }
722  sendOff = startoff;
723  }
724 
725  /* How many bytes are within this segment? */
726  if (nbytes > (XLogSegSize - startoff))
727  segbytes = XLogSegSize - startoff;
728  else
729  segbytes = nbytes;
730 
731  readbytes = read(sendFile, p, segbytes);
732  if (readbytes <= 0)
733  {
734  char path[MAXPGPATH];
735 
736  XLogFilePath(path, tli, sendSegNo);
737 
738  ereport(ERROR,
740  errmsg("could not read from log segment %s, offset %u, length %lu: %m",
741  path, sendOff, (unsigned long) segbytes)));
742  }
743 
744  /* Update state for read */
745  recptr += readbytes;
746 
747  sendOff += readbytes;
748  nbytes -= readbytes;
749  p += readbytes;
750  }
751 }
#define XLogSegSize
Definition: xlog_internal.h:92
static int sendFile
Definition: walsender.c:126
#define PG_BINARY
Definition: c.h:1038
#define ERROR
Definition: elog.h:43
#define MAXPGPATH
#define XLogFilePath(path, tli, logSegNo)
static char * buf
Definition: pg_test_fsync.c:65
uint64 XLogSegNo
Definition: xlogdefs.h:34
int errcode_for_file_access(void)
Definition: elog.c:598
unsigned int uint32
Definition: c.h:265
#define ereport(elevel, rest)
Definition: elog.h:122
#define XLByteToSeg(xlrp, logSegNo)
uint64 XLogRecPtr
Definition: xlogdefs.h:21
size_t Size
Definition: c.h:353
static XLogSegNo sendSegNo
Definition: walsender.c:127
int errmsg(const char *fmt,...)
Definition: elog.c:797
static uint32 sendOff
Definition: walsender.c:128
#define close(a)
Definition: win32.h:17
#define XLByteInSeg(xlrp, logSegNo)
#define read(a, b, c)
Definition: win32.h:18
int BasicOpenFile(FileName fileName, int fileFlags, int fileMode)
Definition: fd.c:899
Buffer XLogReadBufferExtended ( RelFileNode  rnode,
ForkNumber  forknum,
BlockNumber  blkno,
ReadBufferMode  mode 
)

Definition at line 436 of file xlogutils.c.

References Assert, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferGetPage, InRecovery, InvalidBackendId, InvalidBuffer, LockBuffer(), log_invalid_page(), NULL, P_NEW, PageIsNew, RBM_NORMAL, RBM_NORMAL_NO_LOG, RBM_ZERO_AND_CLEANUP_LOCK, RBM_ZERO_AND_LOCK, ReadBufferWithoutRelcache(), ReleaseBuffer(), smgrcreate(), smgrnblocks(), and smgropen().

Referenced by btree_xlog_delete_get_latestRemovedXid(), btree_xlog_vacuum(), checkXLogConsistency(), XLogReadBufferForRedoExtended(), and XLogRecordPageWithFreeSpace().

438 {
439  BlockNumber lastblock;
440  Buffer buffer;
441  SMgrRelation smgr;
442 
443  Assert(blkno != P_NEW);
444 
445  /* Open the relation at smgr level */
446  smgr = smgropen(rnode, InvalidBackendId);
447 
448  /*
449  * Create the target file if it doesn't already exist. This lets us cope
450  * if the replay sequence contains writes to a relation that is later
451  * deleted. (The original coding of this routine would instead suppress
452  * the writes, but that seems like it risks losing valuable data if the
453  * filesystem loses an inode during a crash. Better to write the data
454  * until we are actually told to delete the file.)
455  */
456  smgrcreate(smgr, forknum, true);
457 
458  lastblock = smgrnblocks(smgr, forknum);
459 
460  if (blkno < lastblock)
461  {
462  /* page exists in file */
463  buffer = ReadBufferWithoutRelcache(rnode, forknum, blkno,
464  mode, NULL);
465  }
466  else
467  {
468  /* hm, page doesn't exist in file */
469  if (mode == RBM_NORMAL)
470  {
471  log_invalid_page(rnode, forknum, blkno, false);
472  return InvalidBuffer;
473  }
474  if (mode == RBM_NORMAL_NO_LOG)
475  return InvalidBuffer;
476  /* OK to extend the file */
477  /* we do this in recovery only - no rel-extension lock needed */
479  buffer = InvalidBuffer;
480  do
481  {
482  if (buffer != InvalidBuffer)
483  {
484  if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
486  ReleaseBuffer(buffer);
487  }
488  buffer = ReadBufferWithoutRelcache(rnode, forknum,
489  P_NEW, mode, NULL);
490  }
491  while (BufferGetBlockNumber(buffer) < blkno);
492  /* Handle the corner case that P_NEW returns non-consecutive pages */
493  if (BufferGetBlockNumber(buffer) != blkno)
494  {
495  if (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK)
497  ReleaseBuffer(buffer);
498  buffer = ReadBufferWithoutRelcache(rnode, forknum, blkno,
499  mode, NULL);
500  }
501  }
502 
503  if (mode == RBM_NORMAL)
504  {
505  /* check that page has been initialized */
506  Page page = (Page) BufferGetPage(buffer);
507 
508  /*
509  * We assume that PageIsNew is safe without a lock. During recovery,
510  * there should be no other backends that could modify the buffer at
511  * the same time.
512  */
513  if (PageIsNew(page))
514  {
515  ReleaseBuffer(buffer);
516  log_invalid_page(rnode, forknum, blkno, true);
517  return InvalidBuffer;
518  }
519  }
520 
521  return buffer;
522 }
#define BUFFER_LOCK_UNLOCK
Definition: bufmgr.h:87
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:376
bool InRecovery
Definition: xlog.c:191
#define InvalidBuffer
Definition: buf.h:25
Buffer ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:682
uint32 BlockNumber
Definition: block.h:31
void ReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3292
#define P_NEW
Definition: bufmgr.h:82
static void log_invalid_page(RelFileNode node, ForkNumber forkno, BlockNumber blkno, bool present)
Definition: xlogutils.c:77
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:137
#define InvalidBackendId
Definition: backendid.h:23
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3529
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:672
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:2588
#define PageIsNew(page)
Definition: bufpage.h:226
int Buffer
Definition: buf.h:23
Pointer Page
Definition: bufpage.h:74
XLogRedoAction XLogReadBufferForRedoExtended ( XLogReaderState record,
uint8  block_id,
ReadBufferMode  mode,
bool  get_cleanup_lock,
Buffer buf 
)

Definition at line 325 of file xlogutils.c.

References Assert, BKPBLOCK_WILL_INIT, BLK_DONE, BLK_NEEDS_REDO, BLK_NOTFOUND, BLK_RESTORED, XLogReaderState::blocks, BUFFER_LOCK_EXCLUSIVE, BufferGetPage, BufferIsValid, elog, XLogReaderState::EndRecPtr, ERROR, DecodedBkpBlock::flags, FlushOneBuffer(), INIT_FORKNUM, LockBuffer(), LockBufferForCleanup(), MarkBufferDirty(), PageGetLSN, PageIsNew, PageSetLSN, PANIC, RBM_ZERO_AND_CLEANUP_LOCK, RBM_ZERO_AND_LOCK, RestoreBlockImage(), XLogReadBufferExtended(), XLogRecBlockImageApply, XLogRecGetBlockTag(), and XLogRecHasBlockImage.

Referenced by btree_xlog_vacuum(), heap_xlog_clean(), heap_xlog_visible(), XLogInitBufferForRedo(), and XLogReadBufferForRedo().

329 {
330  XLogRecPtr lsn = record->EndRecPtr;
331  RelFileNode rnode;
332  ForkNumber forknum;
333  BlockNumber blkno;
334  Page page;
335  bool zeromode;
336  bool willinit;
337 
338  if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno))
339  {
340  /* Caller specified a bogus block_id */
341  elog(PANIC, "failed to locate backup block with ID %d", block_id);
342  }
343 
344  /*
345  * Make sure that if the block is marked with WILL_INIT, the caller is
346  * going to initialize it. And vice versa.
347  */
348  zeromode = (mode == RBM_ZERO_AND_LOCK || mode == RBM_ZERO_AND_CLEANUP_LOCK);
349  willinit = (record->blocks[block_id].flags & BKPBLOCK_WILL_INIT) != 0;
350  if (willinit && !zeromode)
351  elog(PANIC, "block with WILL_INIT flag in WAL record must be zeroed by redo routine");
352  if (!willinit && zeromode)
353  elog(PANIC, "block to be initialized in redo routine must be marked with WILL_INIT flag in the WAL record");
354 
355  /* If it has a full-page image and it should be restored, do it. */
356  if (XLogRecBlockImageApply(record, block_id))
357  {
358  Assert(XLogRecHasBlockImage(record, block_id));
359  *buf = XLogReadBufferExtended(rnode, forknum, blkno,
360  get_cleanup_lock ? RBM_ZERO_AND_CLEANUP_LOCK : RBM_ZERO_AND_LOCK);
361  page = BufferGetPage(*buf);
362  if (!RestoreBlockImage(record, block_id, page))
363  elog(ERROR, "failed to restore block image");
364 
365  /*
366  * The page may be uninitialized. If so, we can't set the LSN because
367  * that would corrupt the page.
368  */
369  if (!PageIsNew(page))
370  {
371  PageSetLSN(page, lsn);
372  }
373 
375 
376  /*
377  * At the end of crash recovery the init forks of unlogged relations
378  * are copied, without going through shared buffers. So we need to
379  * force the on-disk state of init forks to always be in sync with the
380  * state in shared buffers.
381  */
382  if (forknum == INIT_FORKNUM)
384 
385  return BLK_RESTORED;
386  }
387  else
388  {
389  *buf = XLogReadBufferExtended(rnode, forknum, blkno, mode);
390  if (BufferIsValid(*buf))
391  {
392  if (mode != RBM_ZERO_AND_LOCK && mode != RBM_ZERO_AND_CLEANUP_LOCK)
393  {
394  if (get_cleanup_lock)
396  else
398  }
399  if (lsn <= PageGetLSN(BufferGetPage(*buf)))
400  return BLK_DONE;
401  else
402  return BLK_NEEDS_REDO;
403  }
404  else
405  return BLK_NOTFOUND;
406  }
407 }
void LockBufferForCleanup(Buffer buffer)
Definition: bufmgr.c:3586
#define XLogRecHasBlockImage(decoder, block_id)
Definition: xlogreader.h:207
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1445
Buffer XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode)
Definition: xlogutils.c:436
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:89
#define PANIC
Definition: elog.h:53
XLogRecPtr EndRecPtr
Definition: xlogreader.h:115
#define ERROR
Definition: elog.h:43
static char * buf
Definition: pg_test_fsync.c:65
#define BufferGetPage(buffer)
Definition: bufmgr.h:160
#define BKPBLOCK_WILL_INIT
Definition: xlogrecord.h:182
ForkNumber
Definition: relpath.h:24
bool XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: xlogreader.c:1307
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3529
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:671
#define BufferIsValid(bufnum)
Definition: bufmgr.h:114
void FlushOneBuffer(Buffer buffer)
Definition: bufmgr.c:3272
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
Definition: xlogreader.c:1360
#define PageGetLSN(page)
Definition: bufpage.h:363
#define PageIsNew(page)
Definition: bufpage.h:226
#define elog
Definition: elog.h:219
#define XLogRecBlockImageApply(decoder, block_id)
Definition: xlogreader.h:209
#define PageSetLSN(page, lsn)
Definition: bufpage.h:365
Pointer Page
Definition: bufpage.h:74
DecodedBkpBlock blocks[XLR_MAX_BLOCK_ID+1]
Definition: xlogreader.h:134
void XLogTruncateRelation ( RelFileNode  rnode,
ForkNumber  forkNum,
BlockNumber  nblocks 
)

Definition at line 635 of file xlogutils.c.

References forget_invalid_pages().

Referenced by smgr_redo().

637 {
638  forget_invalid_pages(rnode, forkNum, nblocks);
639 }
static void forget_invalid_pages(RelFileNode node, ForkNumber forkno, BlockNumber minblkno)
Definition: xlogutils.c:141

Variable Documentation

HTAB* invalid_page_tab = NULL
static

Definition at line 56 of file xlogutils.c.