--- src/backend/access/transam/subtrans.c Tue Nov 29 14:34:58 2005 *************** *** 110,118 **** if (!TransactionIdIsNormal(xid)) return InvalidTransactionId; ! LWLockAcquire(SubtransControlLock, LW_EXCLUSIVE); ! ! slotno = SimpleLruReadPage(SubTransCtl, pageno, xid); ptr = (TransactionId *) SubTransCtl->shared->page_buffer[slotno]; ptr += entryno; --- 110,116 ---- if (!TransactionIdIsNormal(xid)) return InvalidTransactionId; ! slotno = SimpleLruReadPage_ReadOnly(SubTransCtl, pageno, xid); ptr = (TransactionId *) SubTransCtl->shared->page_buffer[slotno]; ptr += entryno; *** src/backend/access/transam/slru.c.orig Tue Nov 22 16:06:16 2005 --- src/backend/access/transam/slru.c Tue Nov 29 14:34:51 2005 *************** *** 352,357 **** --- 352,395 ---- } /* + * Find a page in a shared buffer, reading it in if necessary. + * The page number must correspond to an already-initialized page. + * + * The passed-in xid is used only for error reporting, and may be + * InvalidTransactionId if no specific xid is associated with the action. + * + * Return value is the shared-buffer slot number now holding the page. + * The buffer's LRU access info is updated. + * + * Control lock must be held at entry, and will be held at exit. + */ + int + SimpleLruReadPage_ReadOnly(SlruCtl ctl, int pageno, TransactionId xid) + { + SlruShared shared = ctl->shared; + int slotno; + + LWLockAcquire(shared->ControlLock, LW_SHARED); + + /* See if page is already in a buffer */ + for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) + { + if (shared->page_number[slotno] == pageno && + shared->page_status[slotno] != SLRU_PAGE_EMPTY && + shared->page_status[slotno] != SLRU_PAGE_READ_IN_PROGRESS) + { + shared->page_lru_count[slotno] = 0; + return slotno; + } + } + + LWLockRelease(shared->ControlLock); + LWLockAcquire(shared->ControlLock, LW_EXCLUSIVE); + + return SimpleLruReadPage(ctl, pageno, xid); + } + + /* * Write a page from a shared buffer, if necessary. * Does nothing if the specified slot is not dirty. * *************** *** 729,736 **** for (;;) { int slotno; ! int bestslot = 0; ! unsigned int bestcount = 0; /* See if page already has a buffer assigned */ for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) --- 767,775 ---- for (;;) { int slotno; ! int bestslot; ! unsigned int bestcount; ! int best_page_number; /* See if page already has a buffer assigned */ for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) *************** *** 744,758 **** * If we find any EMPTY slot, just select that one. Else locate the * least-recently-used slot that isn't the latest page. */ for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) { if (shared->page_status[slotno] == SLRU_PAGE_EMPTY) return slotno; ! if (shared->page_lru_count[slotno] > bestcount && ! shared->page_number[slotno] != shared->latest_page_number) { bestslot = slotno; ! bestcount = shared->page_lru_count[slotno]; } } --- 783,808 ---- * If we find any EMPTY slot, just select that one. Else locate the * least-recently-used slot that isn't the latest page. */ + bestslot = 0; + bestcount = 0; + best_page_number = shared->latest_page_number; for (slotno = 0; slotno < NUM_SLRU_BUFFERS; slotno++) { + unsigned int this_lru_count; + int this_page_number; + if (shared->page_status[slotno] == SLRU_PAGE_EMPTY) return slotno; ! this_lru_count = shared->page_lru_count[slotno]; ! this_page_number = shared->page_number[slotno]; ! if ((this_lru_count > bestcount || ! (this_lru_count == bestcount && ! ctl->PagePrecedes(this_page_number, best_page_number))) && ! this_page_number != shared->latest_page_number) { bestslot = slotno; ! bestcount = this_lru_count; ! best_page_number = this_page_number; } }