PostgreSQL Source Code: src/backend/access/transam/xlogutils.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

19

21

31

32

33

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

51

52

54

55

56

57

58

59

60

61

62

63

64

66{

71

73{

75 bool present;

77

79

82 char *cur_page, bool wait_for_wal);

83

84

85static void

88{

90

91 if (present)

92 elog(elevel, "page %u of relation %s is uninitialized",

93 blkno, path.str);

94 else

95 elog(elevel, "page %u of relation %s does not exist",

96 blkno, path.str);

97}

98

99

100static void

102 bool present)

103{

106 bool found;

107

108

109

110

111

112

113

114

115

117 {

120 "WAL contains references to invalid pages");

121 }

122

123

124

125

126

127

130

132 {

133

135

138

140 100,

143 }

144

145

146 key.locator = locator;

147 key.forkno = forkno;

148 key.blkno = blkno;

151

152 if (!found)

153 {

154

155 hentry->present = present;

156 }

157 else

158 {

159

160 }

161}

162

163

164static void

167{

170

172 return;

173

175

177 {

180 hentry->key.blkno >= minblkno)

181 {

182 elog(DEBUG2, "page %u of relation %s has been dropped",

185

187 &hentry->key,

189 elog(ERROR, "hash table corrupted");

190 }

191 }

192}

193

194

195static void

197{

200

202 return;

203

205

207 {

209 {

210 elog(DEBUG2, "page %u of relation %s has been dropped",

213

215 &hentry->key,

217 elog(ERROR, "hash table corrupted");

218 }

219 }

220}

221

222

223bool

225{

228 return true;

229 return false;

230}

231

232

233void

235{

238 bool foundone = false;

239

241 return;

242

244

245

246

247

248

250 {

253 foundone = true;

254 }

255

256 if (foundone)

258 "WAL contains references to invalid pages");

259

262}

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

305{

307 false, buf);

308}

309

310

311

312

313

316{

318

321 return buf;

322}

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

344{

349 Buffer prefetch_buffer;

351 bool zeromode;

352 bool willinit;

353

355 &prefetch_buffer))

356 {

357

358 elog(PANIC, "failed to locate backup block with ID %d in WAL record",

359 block_id);

360 }

361

362

363

364

365

368 if (willinit && !zeromode)

369 elog(PANIC, "block with WILL_INIT flag in WAL record must be zeroed by redo routine");

370 if (!willinit && zeromode)

371 elog(PANIC, "block to be initialized in redo routine must be marked with WILL_INIT flag in the WAL record");

372

373

375 {

379 prefetch_buffer);

383 (errcode(ERRCODE_INTERNAL_ERROR),

385

386

387

388

389

391 {

393 }

394

396

397

398

399

400

401

402

405

407 }

408 else

409 {

412 {

414 {

415 if (get_cleanup_lock)

417 else

419 }

422 else

424 }

425 else

427 }

428}

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

462 Buffer recent_buffer)

463{

467

469

470

474 {

475 buffer = recent_buffer;

476 goto recent_buffer_fast_path;

477 }

478

479

481

482

483

484

485

486

487

488

489

491

493

494 if (blkno < lastblock)

495 {

496

498 mode, NULL, true);

499 }

500 else

501 {

502

504 {

507 }

510

511

514 forknum,

515 NULL,

518 blkno + 1,

520 }

521

522recent_buffer_fast_path:

524 {

525

527

528

529

530

531

532

534 {

538 }

539 }

540

541 return buffer;

542}

543

544

545

546

547

548typedef struct

549{

553

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

572{

575

576

579

582

583

584

585

586

588

589

590 rel->rd_rel->relpersistence = RELPERSISTENCE_PERMANENT;

591

592

594

595

596

597

598

599

600

601

604

605

606

607

608

610

611 return rel;

612}

613

614

615

616

617void

619{

621}

622

623

624

625

626

627

628

629void

631{

633}

634

635

636

637

638

639

640void

642{

643

644

645

646

647

648

650

652}

653

654

655

656

657

658

659void

662{

664}

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706void

709{

711 state->segcxt.ws_segsize + state->segoff);

712

714 Assert(wantLength <= XLOG_BLCKSZ);

715 Assert(state->readLen == 0 || state->readLen <= XLOG_BLCKSZ);

716 Assert(currTLI != 0);

717

718

719

720

721

722

723

724

725

726 if (lastReadPage == wantPage &&

727 state->readLen != 0 &&

728 lastReadPage + state->readLen >= wantPage + Min(wantLength, XLOG_BLCKSZ - 1))

729 return;

730

731

732

733

734

735

736

737

738

739

740

741

742 if (state->currTLI == currTLI && wantPage >= lastReadPage)

743 {

745 return;

746 }

747

748

749

750

751

752

754 state->currTLI != currTLI &&

755 state->currTLI != 0 &&

756 ((wantPage + wantLength) / state->segcxt.ws_segsize) <

757 (state->currTLIValidUntil / state->segcxt.ws_segsize))

758 return;

759

760

761

762

763

764

765

766

767

768

769

770

771

772 {

773

774

775

776

779

780 endOfSegment = ((wantPage / state->segcxt.ws_segsize) + 1) *

781 state->segcxt.ws_segsize - 1;

782 Assert(wantPage / state->segcxt.ws_segsize ==

783 endOfSegment / state->segcxt.ws_segsize);

784

785

786

787

788

791 &state->nextTLI);

792

794 wantPage + wantLength < state->currTLIValidUntil);

795

797

798 elog(DEBUG3, "switched to timeline %u valid until %X/%X",

801 }

802}

803

804

805void

808{

811

814 if (state->seg.ws_file >= 0)

815 return;

816

817 if (errno == ENOENT)

820 errmsg("requested WAL segment %s has already been removed",

821 path)));

822 else

825 errmsg("could not open file \"%s\": %m",

826 path)));

827}

828

829

830void

832{

834

835 state->seg.ws_file = -1;

836}

837

838

839

840

841

842

843

844int

846 int reqLen, XLogRecPtr targetRecPtr, char *cur_page)

847{

849 targetRecPtr, cur_page, true);

850}

851

852

853

854

855

856int

859 char *cur_page)

860{

862 targetRecPtr, cur_page, false);

863}

864

865

866

867

868static int

871 char *cur_page, bool wait_for_wal)

872{

874 loc;

876 int count;

879

880 loc = targetPagePtr + reqLen;

881

882

883

884

885

886

887

888

889

890 while (1)

891 {

892

893

894

895

898 else

900 tli = currTLI;

901

902

903

904

905

906

907

908

909

910

911

912

913

914

915

916

917

918

919

920

921

922

923

924

925

927

928 if (state->currTLI == currTLI)

929 {

930

931 if (loc <= read_upto)

932 break;

933

934

935 if (!wait_for_wal)

936 {

938

939

940

941

942

944 state->private_data;

946 break;

947 }

948

951 }

952 else

953 {

954

955

956

957

958

959

960

961

962 read_upto = state->currTLIValidUntil;

963

964

965

966

967

968

969

970

971

972 tli = state->currTLI;

973

974

975 break;

976 }

977 }

978

979 if (targetPagePtr + XLOG_BLCKSZ <= read_upto)

980 {

981

982

983

984

985 count = XLOG_BLCKSZ;

986 }

987 else if (targetPagePtr + reqLen > read_upto)

988 {

989

990 return -1;

991 }

992 else

993 {

994

995 count = read_upto - targetPagePtr;

996 }

997

998 if (WALRead(state, cur_page, targetPagePtr, count, tli,

999 &errinfo))

1001

1002

1003 return count;

1004}

1005

1006

1007

1008

1009

1010void

1012{

1015

1017

1019 {

1023 errmsg("could not read from WAL segment %s, offset %d: %m",

1024 fname, errinfo->wre_off)));

1025 }

1026 else if (errinfo->wre_read == 0)

1027 {

1030 errmsg("could not read from WAL segment %s, offset %d: read %d of %d",

1033 }

1034}

List * readTimeLineHistory(TimeLineID targetTLI)

TimeLineID tliOfPointInHistory(XLogRecPtr ptr, List *history)

XLogRecPtr tliSwitchPoint(TimeLineID tli, List *history, TimeLineID *nextTLI)

Buffer ExtendBufferedRelTo(BufferManagerRelation bmr, ForkNumber fork, BufferAccessStrategy strategy, uint32 flags, BlockNumber extend_to, ReadBufferMode mode)

void ReleaseBuffer(Buffer buffer)

void MarkBufferDirty(Buffer buffer)

void LockBufferForCleanup(Buffer buffer)

void LockBuffer(Buffer buffer, int mode)

Buffer ReadBufferWithoutRelcache(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy, bool permanent)

bool ReadRecentBuffer(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber blockNum, Buffer recent_buffer)

void FlushOneBuffer(Buffer buffer)

static Page BufferGetPage(Buffer buffer)

#define BMR_SMGR(p_smgr, p_relpersistence)

#define BUFFER_LOCK_EXCLUSIVE

@ RBM_ZERO_AND_CLEANUP_LOCK

static bool BufferIsValid(Buffer bufnum)

static bool PageIsNew(const PageData *page)

static void PageSetLSN(Page page, XLogRecPtr lsn)

static XLogRecPtr PageGetLSN(const PageData *page)

void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)

void hash_destroy(HTAB *hashp)

void * hash_seq_search(HASH_SEQ_STATUS *status)

long hash_get_num_entries(HTAB *hashp)

HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)

void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)

int errmsg_internal(const char *fmt,...)

int errcode_for_file_access(void)

bool message_level_is_interesting(int elevel)

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

int BasicOpenFile(const char *fileName, int fileFlags)

Assert(PointerIsAligned(start, uint64))

void list_free_deep(List *list)

void pfree(void *pointer)

void * palloc0(Size size)

#define CHECK_FOR_INTERRUPTS()

#define ERRCODE_DATA_CORRUPTED

static PgChecksumMode mode

#define INVALID_PROC_NUMBER

#define RelationGetRelationName(relation)

struct RelationData * Relation

#define RelFileLocatorEquals(locator1, locator2)

#define relpathperm(rlocator, forknum)

void pg_usleep(long microsec)

BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)

SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)

void smgrdestroyall(void)

void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)

char str[REL_PATH_STR_MAXLEN+1]

RelFileLocator rd_locator

bool RecoveryInProgress(void)

XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)

static void XLogFilePath(char *path, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)

static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)

#define LSN_FORMAT_ARGS(lsn)

#define InvalidXLogRecPtr

bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)

bool WALRead(XLogReaderState *state, char *buf, XLogRecPtr startptr, Size count, TimeLineID tli, WALReadError *errinfo)

bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)

#define XLogRecBlockImageApply(decoder, block_id)

#define XLogRecGetBlock(decoder, i)

#define XLogRecHasBlockImage(decoder, block_id)

#define BKPBLOCK_WILL_INIT

XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)

void wal_segment_close(XLogReaderState *state)

void FreeFakeRelcacheEntry(Relation fakerel)

void wal_segment_open(XLogReaderState *state, XLogSegNo nextSegNo, TimeLineID *tli_p)

bool ignore_invalid_pages

static void report_invalid_page(int elevel, RelFileLocator locator, ForkNumber forkno, BlockNumber blkno, bool present)

void XLogReadDetermineTimeline(XLogReaderState *state, XLogRecPtr wantPage, uint32 wantLength, TimeLineID currTLI)

FakeRelCacheEntryData * FakeRelCacheEntry

bool XLogHaveInvalidPages(void)

XLogRedoAction XLogReadBufferForRedo(XLogReaderState *record, uint8 block_id, Buffer *buf)

Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)

Buffer XLogReadBufferExtended(RelFileLocator rlocator, ForkNumber forknum, BlockNumber blkno, ReadBufferMode mode, Buffer recent_buffer)

void XLogTruncateRelation(RelFileLocator rlocator, ForkNumber forkNum, BlockNumber nblocks)

struct xl_invalid_page xl_invalid_page

Relation CreateFakeRelcacheEntry(RelFileLocator rlocator)

HotStandbyState standbyState

struct xl_invalid_page_key xl_invalid_page_key

int read_local_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page)

void XLogCheckInvalidPages(void)

static void forget_invalid_pages(RelFileLocator locator, ForkNumber forkno, BlockNumber minblkno)

void WALReadRaiseError(WALReadError *errinfo)

static void log_invalid_page(RelFileLocator locator, ForkNumber forkno, BlockNumber blkno, bool present)

static int read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page, bool wait_for_wal)

void XLogDropRelation(RelFileLocator rlocator, ForkNumber forknum)

int read_local_xlog_page_no_wait(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page)

static HTAB * invalid_page_tab

XLogRedoAction XLogReadBufferForRedoExtended(XLogReaderState *record, uint8 block_id, ReadBufferMode mode, bool get_cleanup_lock, Buffer *buf)

static void forget_invalid_pages_db(Oid dbid)

void XLogDropDatabase(Oid dbid)