@Override public int pageSize() { return mPageArray.pageSize(); }
private _DurablePageDb( final PageArray rawArray, final PageCache cache, final Crypto crypto, final boolean destroy) throws IOException, WrongPageSize { mCrypto = crypto; PageArray array = crypto == null ? rawArray : new CryptoPageArray(rawArray, crypto); mPageArray = new _SnapshotPageArray(array, rawArray, cache); mHeaderLatch = new Latch(); try { int pageSize = mPageArray.pageSize(); checkPageSize(pageSize); if (destroy || mPageArray.isEmpty()) { // Newly created file. mPageManager = new _PageManager(mPageArray); mCommitNumber = -1; // Commit twice to ensure both headers have valid data. long header = p_calloc(pageSize); try { mCommitLock.acquireExclusive(); try { commit(false, header, null); commit(false, header, null); } finally { mCommitLock.releaseExclusive(); } } finally { p_delete(header); } mPageArray.setPageCount(2); } else { // Opened an existing file. // Previous header commit operation might have been interrupted before final // header sync completed. Pages cannot be safely recycled without this. mPageArray.sync(false); long header0 = p_null(); long header1 = p_null(); try { final long header; final int commitNumber; findHeader: { int pageSize0; int commitNumber0, commitNumber1; CorruptDatabaseException ex0; try { header0 = readHeader(0); commitNumber0 = p_intGetLE(header0, I_COMMIT_NUMBER); pageSize0 = p_intGetLE(header0, I_PAGE_SIZE); ex0 = null; } catch (CorruptDatabaseException e) { header0 = p_null(); commitNumber0 = -1; pageSize0 = pageSize; ex0 = e; } if (pageSize0 != pageSize) { throw new WrongPageSize(pageSize, pageSize0); } try { header1 = readHeader(1); commitNumber1 = p_intGetLE(header1, I_COMMIT_NUMBER); } catch (CorruptDatabaseException e) { if (ex0 != null) { // File is completely unusable. throw ex0; } header = header0; commitNumber = commitNumber0; break findHeader; } int pageSize1 = p_intGetLE(header1, I_PAGE_SIZE); if (pageSize0 != pageSize1) { throw new CorruptDatabaseException( "Mismatched page sizes: " + pageSize0 + " != " + pageSize1); } if (header0 == p_null()) { header = header1; commitNumber = commitNumber1; } else { // Modulo comparison. int diff = commitNumber1 - commitNumber0; if (diff > 0) { header = header1; commitNumber = commitNumber1; } else if (diff < 0) { header = header0; commitNumber = commitNumber0; } else { throw new CorruptDatabaseException( "Both headers have same commit number: " + commitNumber0); } } } mHeaderLatch.acquireExclusive(); mCommitNumber = commitNumber; mHeaderLatch.releaseExclusive(); mPageManager = new _PageManager(mPageArray, header, I_MANAGER_HEADER); } finally { p_delete(header0); p_delete(header1); } } } catch (WrongPageSize e) { delete(); closeQuietly(null, this); throw e; } catch (Throwable e) { delete(); throw closeOnFailure(e); } }