📄 cache.java
字号:
/* Copyrights and Licenses * * This product includes Hypersonic SQL. * Originally developed by Thomas Mueller and the Hypersonic SQL Group. * * Copyright (c) 1995-2000 by the Hypersonic SQL Group. All rights reserved. * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, this list of conditions * and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * - All advertising materials mentioning features or use of this software must display the * following acknowledgment: "This product includes Hypersonic SQL." * - Products derived from this software may not be called "Hypersonic SQL" nor may * "Hypersonic SQL" appear in their names without prior written permission of the * Hypersonic SQL Group. * - Redistributions of any form whatsoever must retain the following acknowledgment: "This * product includes Hypersonic SQL." * This software is provided "as is" and any expressed or implied warranties, including, but * not limited to, the implied warranties of merchantability and fitness for a particular purpose are * disclaimed. In no event shall the Hypersonic SQL Group or its contributors be liable for any * direct, indirect, incidental, special, exemplary, or consequential damages (including, but * not limited to, procurement of substitute goods or services; loss of use, data, or profits; * or business interruption). However caused any on any theory of liability, whether in contract, * strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this * software, even if advised of the possibility of such damage. * This software consists of voluntary contributions made by many individuals on behalf of the * Hypersonic SQL Group. * * * For work added by the HSQL Development Group: * * Copyright (c) 2001-2002, The HSQL Development Group * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer, including earlier * license statements (above) and comply with all above license conditions. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution, including earlier * license statements (above) and comply with all above license conditions. * * Neither the name of the HSQL Development Group nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG, * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */package org.hsqldb;import java.io.IOException;import java.io.File;import java.sql.SQLException;// fredt@users 20011220 - patch 437174 by hjb@users - cache update// most changes and comments by HSB are kept unchanged// fredt@users 20020221 - patch 513005 by sqlbob@users (RMP) - cache update// fredt@users 20020320 - doc 1.7.0 by boucherb@users - doc update/** * * Handles cached tables through a .data file and memory cache. * * @version 1.7.1 * @see Row * @see CacheFree */class Cache { private HsqlDatabaseProperties props; private boolean newCacheType; private final int cacheLength; private final int writerLength; private final int maxCacheSize; private final int multiplierMask; private CachedRow rData[]; private CachedRow rWriter[]; private CachedRow rFirst; // must point to one of rData[] private CachedRow rLastChecked; // can be any row // sqlbob@users - changed visibility for children. protected String sName; protected int iFreePos; protected DatabaseFile rFile; private static final int FREE_POS_POS = 16; // where iFreePos is saved private static final int INITIAL_FREE_POS = 32; private static final int MAX_FREE_COUNT = 1024; private CacheFree fRoot; private int iFreeCount; private int iCacheSize; /** * Construct a new Cache object with the given database path name and * the properties object to get the initial settings from. */ Cache(String name, HsqlDatabaseProperties props) { this.props = props; int cacheScale = 0; try { cacheScale = props.getIntegerProperty("hsqldb.cache_scale", 0); } catch (NumberFormatException e) { Trace.printSystemOut( "bad value for hsqldb.cache_scale in properties file"); } if (cacheScale == 0) { // HJB-2001-06-21: use larger cache size cacheScale = 15; } else if (cacheScale < 8) { cacheScale = 8; } else if (cacheScale > 16) { cacheScale = 16; } cacheLength = 1 << cacheScale; // HJB-2001-06-21: use different smaller size for the writer writerLength = cacheLength - 3; // HJB-2001-06-21: let the cache be larger than the array maxCacheSize = cacheLength * 3; multiplierMask = cacheLength - 1; sName = name; rData = new CachedRow[cacheLength]; rWriter = new CachedRow[writerLength]; // HJB-2001-06-21 } /** * Opens this object's database file. */ void open(boolean readonly) throws SQLException { try { boolean exists = false; File f = new File(sName); if (f.exists() && f.length() > FREE_POS_POS) { exists = true; } rFile = new DatabaseFile(sName, readonly ? "r" : "rw", 2048); if (exists) { rFile.readSeek(FREE_POS_POS); iFreePos = rFile.readInteger(); } else { iFreePos = INITIAL_FREE_POS; props.setProperty("hsqldb.cache_version", "1.7.0"); } String cacheVersion = props.getProperty("hsqldb.cache_version", "1.6.0"); if (cacheVersion.equals("1.7.0")) { newCacheType = true; } } catch (Exception e) { throw Trace.error(Trace.FILE_IO_ERROR, "error " + e + " opening " + sName); } } /** * Writes out all cached data and the free position to this * object's database file and then closes the file. */ void flush() throws SQLException { if (rFile == null) { return; } try { rFile.seek(FREE_POS_POS); rFile.writeInteger(iFreePos); saveAll(); boolean empty = (rFile.length() < INITIAL_FREE_POS); rFile.close(); rFile = null; if (empty) { new File(sName).delete(); } } catch (Exception e) { throw Trace.error(Trace.FILE_IO_ERROR, "error " + e + " closing " + sName); } } /** * Closes this object's database file without flushing pending writes. */ void closeFile() throws SQLException { if (rFile == null) { return; } try { rFile.close(); rFile = null; } catch (Exception e) { throw Trace.error(Trace.FILE_IO_ERROR, "error " + e + " in shutdown " + sName); } } /** * Marks space in this object's cache file as free. <p> * * <B>Note:</B> If there exists more than MAX_FREE_COUNT free positions, * then they are probably all too small, so we start a new list. <p> * * todo: This is wrong when deleting lots of records */ void free(CachedRow r) throws SQLException { iFreeCount++; CacheFree n = new CacheFree(); n.iPos = r.iPos; n.iLength = r.storageSize; if (iFreeCount > MAX_FREE_COUNT) { iFreeCount = 0; } else { n.fNext = fRoot; } fRoot = n; // it's possible to remove roots too remove(r); } /** * Calculates the number of bytes required to store a Row in this object's * database file. */ protected void setStorageSize(CachedRow r) throws SQLException { // 32 bytes overhead for each index + iSize, iPos Table t = r.getTable(); int size = 8 + 32 * t.getIndexCount(); if (newCacheType) { size += BinaryServerRowOutput.getSize(r); } else { size += BinaryDatabaseRowOutput.getSize(r); } size = ((size + 7) / 8) * 8; // align to 8 byte blocks r.storageSize = size; } /** * Adds a Row to the Cache. <p> * * A Row is added by walking the list of CacheFree * objects to see if there is available space to store it, * reusing space if it exists. Otherwise , this object's cache * file is grown to accomadate it. */ void add(CachedRow r) throws SQLException { setStorageSize(r); int rowSize = r.storageSize; int size = rowSize; CacheFree f = fRoot; CacheFree last = null; int i = iFreePos; while (f != null) { if (Trace.TRACE) { Trace.stop(); } // first that is long enough if (f.iLength >= size) { i = f.iPos; size = f.iLength - size; if (size < 8) { // remove almost empty blocks if (last == null) { fRoot = f.fNext; } else { last.fNext = f.fNext; } iFreeCount--; } else { f.iLength = size; f.iPos += rowSize; } break; } last = f; f = f.fNext; } r.setPos(i); if (i == iFreePos) { iFreePos += size; } // HJB-2001-06-21 int k = (i >> 3) & multiplierMask; CachedRow before = rData[k]; if (before == null) { before = rFirst; } r.insert(before); iCacheSize++; rData[k] = r; rFirst = r; } /** * Constructs a new Row for the specified table, using row data read * at the specified position (pos) in this object's database file. */ protected CachedRow makeRow(int pos, Table t) throws SQLException { CachedRow r = null; try { rFile.readSeek(pos); int size = rFile.readInteger(); byte buffer[] = new byte[size]; rFile.read(buffer); DatabaseRowInputInterface in; if (newCacheType) { in = new BinaryServerRowInput(buffer, pos); } else { in = new BinaryDatabaseRowInput(buffer, pos); } r = new CachedRow(t, in);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -