1. 搞清楚什么是BufferPool
2. 实现getPage这样一个页面置换算法(简单)
2.4. BufferPool
The buffer pool (class `BufferPool` in SimpleDB) is responsible for caching pages in memory that have been recently read from disk. All operators read and write pages from various files on disk through the buffer pool. It consists of a fixed number of pages, defined by the `numPages` parameter to the `BufferPool` constructor. In later labs, you will implement an eviction policy. For this lab, you only need to implement the constructor and the `BufferPool.getPage()` method used by the SeqScan operator. The BufferPool should store up to `numPages` pages. For this lab, if more than `numPages` requests are made for different pages, then instead of implementing an eviction policy, you may throw a DbException. In future labs you will be required to implement an eviction policy.
The Database
class provides a static method, Database.getBufferPool()
, that returns a reference to the single BufferPool instance for the entire SimpleDB process.
Exercise 3
Implement the getPage()
method in:
- src/java/simpledb/storage/BufferPool.java
We have not provided unit tests for BufferPool. The functionality you implemented will be tested in the implementation of HeapFile below. You should use the DbFile.readPage
method to access pages of a DbFile.
根据BufferPool的定义,想用什么数据结构去存Page,应该是HashMap,为了并发线程安全,这里直接用线程安全的HashMap, 为了线程完全在加一把锁,这里实现构造函数和BufferPool.java
private ConcurrentHashMap<PageId, Page> pages;
private ReadWriteLock rwLock;
public BufferPool(int numPages){
this.pages = new ConcurrentHashMap<>(numPages);
this.rwLock = new ReentrantReadWriteLock();
}
/**
* Retrieve the specified page with the associated permissions.
* Will acquire a lock and may block if that lock is held by another
* transaction.
* <p>
* The retrieved page should be looked up in the buffer pool. If it
* is present, it should be returned. If it is not present, it should
* be added to the buffer pool and returned. If there is insufficient
* space in the buffer pool, a page should be evicted and the new page
* should be added in its place.
*
* @param tid the ID of the transaction requesting the page
* @param pid the ID of the requested page
* @param perm the requested permissions on the page
*/
public Page getPage(TransactionId tid, PageId pid, Permissions perm)
throws TransactionAbortedException, DbException {
// some code goes here
rwLock.readLock().lock();
Page page = this.pages.get(pid);
if(page == null){
if(this.pages.size() >= DEFAULT_PAGES){
evictPage();
}
DbFile file = Database.getCatalog().getDatabaseFile(pid.getTableId());
page = file.readPage(pid);
this.pages.put(pid, page);
}
rwLock.readLock().unlock();
return page;
}