* ReadRecentBuffer -- try to pin a block in a recently observed buffer * * Compared to ReadBuffer(), this avoids a buffer mapping lookup when it's * successful. Return true if the buffer is valid and still has the expected * tag. In that case, the buffer is pinned and the usage count is bumped. */
| 702 | * tag. In that case, the buffer is pinned and the usage count is bumped. |
| 703 | */ |
| 704 | bool |
| 705 | ReadRecentBuffer(RelFileNode rnode, ForkNumber forkNum, BlockNumber blockNum, |
| 706 | Buffer recent_buffer) |
| 707 | { |
| 708 | BufferDesc *bufHdr; |
| 709 | BufferTag tag; |
| 710 | uint32 buf_state; |
| 711 | bool have_private_ref; |
| 712 | |
| 713 | Assert(BufferIsValid(recent_buffer)); |
| 714 | |
| 715 | ResourceOwnerEnlargeBuffers(CurrentResourceOwner); |
| 716 | ReservePrivateRefCountEntry(); |
| 717 | INIT_BUFFERTAG(tag, rnode, forkNum, blockNum); |
| 718 | |
| 719 | if (BufferIsLocal(recent_buffer)) |
| 720 | { |
| 721 | bufHdr = GetBufferDescriptor(-recent_buffer - 1); |
| 722 | buf_state = pg_atomic_read_u32(&bufHdr->state); |
| 723 | |
| 724 | /* Is it still valid and holding the right tag? */ |
| 725 | if ((buf_state & BM_VALID) && BUFFERTAGS_EQUAL(tag, bufHdr->tag)) |
| 726 | { |
| 727 | /* Bump local buffer's ref and usage counts. */ |
| 728 | ResourceOwnerRememberBuffer(CurrentResourceOwner, recent_buffer); |
| 729 | LocalRefCount[-recent_buffer - 1]++; |
| 730 | if (BUF_STATE_GET_USAGECOUNT(buf_state) < BM_MAX_USAGE_COUNT) |
| 731 | pg_atomic_write_u32(&bufHdr->state, |
| 732 | buf_state + BUF_USAGECOUNT_ONE); |
| 733 | |
| 734 | return true; |
| 735 | } |
| 736 | } |
| 737 | else |
| 738 | { |
| 739 | bufHdr = GetBufferDescriptor(recent_buffer - 1); |
| 740 | have_private_ref = GetPrivateRefCount(recent_buffer) > 0; |
| 741 | |
| 742 | /* |
| 743 | * Do we already have this buffer pinned with a private reference? If |
| 744 | * so, it must be valid and it is safe to check the tag without |
| 745 | * locking. If not, we have to lock the header first and then check. |
| 746 | */ |
| 747 | if (have_private_ref) |
| 748 | buf_state = pg_atomic_read_u32(&bufHdr->state); |
| 749 | else |
| 750 | buf_state = LockBufHdr(bufHdr); |
| 751 | |
| 752 | if ((buf_state & BM_VALID) && BUFFERTAGS_EQUAL(tag, bufHdr->tag)) |
| 753 | { |
| 754 | /* |
| 755 | * It's now safe to pin the buffer. We can't pin first and ask |
| 756 | * questions later, because because it might confuse code paths |
| 757 | * like InvalidateBuffer() if we pinned a random non-matching |
| 758 | * buffer. |
| 759 | */ |
| 760 | if (have_private_ref) |
| 761 | PinBuffer(bufHdr, NULL); /* bump pin count */ |
nothing calls this directly
no test coverage detected