@Override public long allocatePages(long pageCount) throws IOException { if (pageCount <= 0) { return 0; } Stats stats = new Stats(); mPageManager.addTo(stats); pageCount -= stats.freePages; if (pageCount <= 0) { return 0; } for (int i = 0; i < pageCount; i++) { CommitLock.Shared shared = mCommitLock.acquireShared(); try { mPageManager.allocAndRecyclePage(); } catch (Throwable e) { throw closeOnFailure(e); } finally { shared.release(); } } return pageCount; }
@Override public void compactionReclaim() throws IOException { try { mPageManager.compactionReclaim(); } catch (Throwable e) { throw closeOnFailure(e); } }
@Override public boolean compactionEnd() throws IOException { try { return mPageManager.compactionEnd(mCommitLock); } catch (Throwable e) { throw closeOnFailure(e); } }
@Override public void recyclePage(long id) throws IOException { checkId(id); CommitLock.Shared shared = mCommitLock.acquireShared(); try { try { mPageManager.recyclePage(id); } catch (IOException e) { mPageManager.deletePage(id); } } catch (IOException e) { throw e; } catch (Throwable e) { throw closeOnFailure(e); } finally { shared.release(); } }
@Override public boolean compactionStart(long targetPageCount) throws IOException { mCommitLock.acquireExclusive(); try { return mPageManager.compactionStart(targetPageCount); } catch (Throwable e) { throw closeOnFailure(e); } finally { mCommitLock.releaseExclusive(); } }
@Override public void commit(boolean resume, long header, final CommitCallback callback) throws IOException { // Acquire a shared lock to prevent concurrent commits after callback has released // exclusive lock. CommitLock.Shared shared = mCommitLock.acquireShared(); try { mHeaderLatch.acquireShared(); final int commitNumber = mCommitNumber + 1; mHeaderLatch.releaseShared(); try { if (!resume) { mPageManager.commitStart(header, I_MANAGER_HEADER); } if (callback != null) { // Invoke the callback to ensure all dirty pages get written. callback.prepare(resume, header); } } catch (DatabaseException e) { if (e.isRecoverable()) { throw e; } else { throw closeOnFailure(e); } } try { commitHeader(header, commitNumber); mPageManager.commitEnd(header, I_MANAGER_HEADER); } catch (Throwable e) { throw closeOnFailure(e); } } finally { shared.release(); } }
@Override public long allocPage() throws IOException { CommitLock.Shared shared = mCommitLock.acquireShared(); try { return mPageManager.allocPage(); } catch (DatabaseException e) { if (e.isRecoverable()) { throw e; } throw closeOnFailure(e); } catch (Throwable e) { throw closeOnFailure(e); } finally { shared.release(); } }
@Override public boolean truncatePages() throws IOException { return mPageManager.truncatePages(); }
@Override public boolean compactionVerify() throws IOException { // Only performs reads and so no commit lock is required. Holding it would block // checkpoints during reserve list scan, which is not desirable. return mPageManager.compactionVerify(); }
@Override public Stats stats() { Stats stats = new Stats(); mPageManager.addTo(stats); return stats; }
@Override public void pageLimitOverride(long bytes) { mPageManager.pageLimitOverride(bytes); }
@Override public long pageLimit() { return mPageManager.pageLimit(); }
@Override public void pageLimit(long limit) { mPageManager.pageLimit(limit); }
/** Must be called when object is no longer referenced. */ @Override void delete() { if (mPageManager != null) { mPageManager.delete(); } }