| 3613 | |
| 3614 | |
| 3615 | static BufferDesc* get_dirty_buffer(thread_db* tdbb) |
| 3616 | { |
| 3617 | // This code is only used by the background I/O threads: |
| 3618 | // cache writer, cache reader and garbage collector. |
| 3619 | |
| 3620 | SET_TDBB(tdbb); |
| 3621 | Database* dbb = tdbb->getDatabase(); |
| 3622 | BufferControl* bcb = dbb->dbb_bcb; |
| 3623 | int walk = bcb->bcb_free_minimum; |
| 3624 | int chained = walk; |
| 3625 | |
| 3626 | Sync lruSync(&bcb->bcb_syncLRU, FB_FUNCTION); |
| 3627 | lruSync.lock(SYNC_SHARED); |
| 3628 | |
| 3629 | for (QUE que_inst = bcb->bcb_in_use.que_backward; |
| 3630 | que_inst != &bcb->bcb_in_use; que_inst = que_inst->que_backward) |
| 3631 | { |
| 3632 | BufferDesc* bdb = BLOCK(que_inst, BufferDesc, bdb_in_use); |
| 3633 | |
| 3634 | if (bdb->bdb_flags & BDB_lru_chained) |
| 3635 | { |
| 3636 | if (!--chained) |
| 3637 | break; |
| 3638 | continue; |
| 3639 | } |
| 3640 | |
| 3641 | if (bdb->bdb_use_count || (bdb->bdb_flags & BDB_free_pending)) |
| 3642 | continue; |
| 3643 | |
| 3644 | if (bdb->bdb_flags & BDB_db_dirty) |
| 3645 | { |
| 3646 | //tdbb->bumpStats(RuntimeStatistics::PAGE_FETCHES); shouldn't it be here? |
| 3647 | return bdb; |
| 3648 | } |
| 3649 | |
| 3650 | if (!--walk) |
| 3651 | break; |
| 3652 | } |
| 3653 | |
| 3654 | if (!chained) |
| 3655 | { |
| 3656 | lruSync.unlock(); |
| 3657 | lruSync.lock(SYNC_EXCLUSIVE); |
| 3658 | requeueRecentlyUsed(bcb); |
| 3659 | } |
| 3660 | else |
| 3661 | bcb->bcb_flags &= ~BCB_free_pending; |
| 3662 | |
| 3663 | return NULL; |
| 3664 | } |
| 3665 | |
| 3666 | |
| 3667 | static BufferDesc* get_oldest_buffer(thread_db* tdbb, BufferControl* bcb) |
no test coverage detected