table.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 912 行 · 第 1/2 页

JAVA
912
字号
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * *   Free Software Foundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.db.table;import com.caucho.db.Database;import com.caucho.db.index.BTree;import com.caucho.db.index.KeyCompare;import com.caucho.db.sql.CreateQuery;import com.caucho.db.sql.Expr;import com.caucho.db.sql.Parser;import com.caucho.db.sql.QueryContext;import com.caucho.db.store.Block;import com.caucho.db.store.Lock;import com.caucho.db.store.Store;import com.caucho.db.store.Transaction;import com.caucho.log.Log;import com.caucho.sql.SQLExceptionWrapper;import com.caucho.util.L10N;import com.caucho.vfs.Path;import com.caucho.vfs.ReadStream;import com.caucho.vfs.TempBuffer;import com.caucho.vfs.TempStream;import com.caucho.vfs.WriteStream;import java.io.IOException;import java.sql.SQLException;import java.util.ArrayList;import java.util.logging.Level;import java.util.logging.Logger;/** * Table format: * * <pre> * Block 0: allocation table * Block 1: fragment table * Block 2: table definition *   0    - store data *   1024 - table data *    1024 - index pointers *   2048 - CREATE text * Block 3: first data * </pre> */public class Table extends Store {  private final static Logger log = Log.open(Table.class);  private final static L10N L = new L10N(Table.class);  private final static int ROOT_DATA_OFFSET = STORE_CREATE_END;  private final static int INDEX_ROOT_OFFSET = ROOT_DATA_OFFSET + 32;    private final static int ROOT_DATA_END = ROOT_DATA_OFFSET + 1024;    public final static int INLINE_BLOB_SIZE = 120;    public final static long ROW_CLOCK_MIN = 1024;  public final static byte ROW_VALID = 0x1;  public final static byte ROW_ALLOC = 0x2;  public final static byte ROW_MASK = 0x3;  private final static String DB_VERSION = "Resin-DB 3.1.1";  private final static String MIN_VERSION = "Resin-DB 3.1.1";    private final Row _row;  private final int _rowLength;  private final int _rowsPerBlock;  private final int _rowEnd;  private final Constraint[]_constraints;    private final Column _autoIncrementColumn;  private long _entries;  private final Object _rowClockLock = new Object();  private long _rowClockAddr;  private long _rowClockTotal;  private long _rowClockUsed;  private int _rowClockCount;  private int _rowAllocCount;  private long _autoIncrementValue = -1;  private Lock _allocLock;  private Lock _insertLock;  Table(Database database, String name, Row row, Constraint constraints[])  {    super(database, name, null);        _row = row;    _constraints = constraints;    _rowLength = _row.getLength();    _rowsPerBlock = BLOCK_SIZE / _rowLength;    _rowEnd = _rowLength * _rowsPerBlock;    _rowClockAddr = 0;        Column []columns = _row.getColumns();    Column autoIncrementColumn = null;    for (int i = 0; i < columns.length; i++) {      columns[i].setTable(this);            if (columns[i].getAutoIncrement() >= 0)	autoIncrementColumn = columns[i];    }    _autoIncrementColumn = autoIncrementColumn;    _insertLock = new Lock("table-insert:" + name);    _allocLock = new Lock("table-alloc:" + name);  }  Row getRow()  {    return _row;  }  /**   * Returns the length of a row.   */  int getRowLength()  {    return _rowLength;  }  /**   * Returns the end of the row   */  int getRowEnd()  {    return _rowEnd;  }    public final Column []getColumns()  {    return _row.getColumns();  }  /**   * Returns the table's constraints.   */  public final Constraint []getConstraints()  {    return _constraints;  }  /**   * Returns the auto-increment column.   */  public Column getAutoIncrementColumn()  {    return _autoIncrementColumn;  }  /**   * Returns the column for the given column name.   *   * @param name the column name   *   * @return the column   */  public Column getColumn(String name)  {    Column []columns = getColumns();    for (int i = 0; i < columns.length; i++) {      if (columns[i].getName().equals(name))	return columns[i];    }    return null;  }  /**   * Returns the column index for the given column name.   *   * @param name the column name   *   * @return the column index.   */  public int getColumnIndex(String name)    throws SQLException  {    Column []columns = getColumns();    for (int i = 0; i < columns.length; i++) {      if (columns[i].getName().equals(name))	return i;    }    return -1;  }  /**   * Loads the table from the file.   */  public static Table loadFromFile(Database db, String name)    throws IOException, SQLException  {    Path path = db.getPath().lookup(name + ".db");    if (! path.exists()) {      if (log.isLoggable(Level.FINE))	log.fine(db + " '" + path.getNativePath() + "' is an unknown table");            return null; //throw new SQLException(L.l("table {0} does not exist", name));    }    String version = null;    ReadStream is = path.openRead();    try {      // skip allocation table and fragment table      is.skip(DATA_START + ROOT_DATA_OFFSET);      StringBuilder sb = new StringBuilder();      int ch;      while ((ch = is.read()) > 0) {	sb.append((char) ch);      }      version = sb.toString();      if (! version.startsWith("Resin-DB")) {	throw new SQLException(L.l("table {0} is not a Resin DB.  Version '{1}'",				   name, version));      }      else if (version.compareTo(MIN_VERSION) < 0 ||	       DB_VERSION.compareTo(version) < 0) {	throw new SQLException(L.l("table {0} is out of date.  Old version {1}.",				   name, version));      }    } finally {      is.close();    }    is = path.openRead();    try {      // skip allocation table and fragment table      is.skip(DATA_START + ROOT_DATA_END);      StringBuilder cb = new StringBuilder();      int ch;      while ((ch = is.read()) > 0) {	cb.append((char) ch);      }      String sql = cb.toString();      if (log.isLoggable(Level.FINER))	log.finer("Table[" + name + "] " + version + " loading\n" + sql);      try {	CreateQuery query = (CreateQuery) Parser.parse(db, sql);	TableFactory factory = query.getFactory();	if (! factory.getName().equalsIgnoreCase(name))	  throw new IOException(L.l("factory {0} does not match", name));		Table table = new Table(db, factory.getName(), factory.getRow(),				factory.getConstraints());	table.init();	table.clearIndexes();	table.initIndexes();	table.rebuildIndexes();      	return table;      } catch (Exception e) {	log.log(Level.FINE, e.toString(), e);		log.warning(e.toString());	throw new SQLException(L.l("can't load table {0} in {1}.\n{2}",				   name, path.getNativePath(), e.toString()));      }    } finally {      is.close();    }  }  /**   * Creates the table.   */  public void create()    throws IOException, SQLException  {    super.create();    initIndexes();    byte []tempBuffer = new byte[BLOCK_SIZE];    readBlock(BLOCK_SIZE, tempBuffer, 0, BLOCK_SIZE);    TempStream ts = new TempStream();          WriteStream os = new WriteStream(ts);    try {      for (int i = 0; i < ROOT_DATA_OFFSET; i++)	os.write(tempBuffer[i]);            writeTableHeader(os);    } finally {      os.close();    }    TempBuffer head = ts.getHead();    int offset = 0;    for (; head != null; head = head.getNext()) {      byte []buffer = head.getBuffer();            int length = head.getLength();            System.arraycopy(buffer, 0, tempBuffer, offset, length);      for (; length < buffer.length; length++) {	tempBuffer[offset + length] = 0;      }      offset += buffer.length;    }    for (; offset < BLOCK_SIZE; offset++)      tempBuffer[offset] = 0;    writeBlock(BLOCK_SIZE, tempBuffer, 0, BLOCK_SIZE);    _database.addTable(this);  }    /**   * Initialize the indexes   */  private void initIndexes()    throws IOException, SQLException  {    Column []columns = _row.getColumns();    for (int i = 0; i < columns.length; i++) {      Column column = columns[i];      if (! column.isUnique())	continue;      KeyCompare keyCompare = column.getIndexKeyCompare();      if (keyCompare == null)	continue;      Block rootBlock = allocateIndexBlock();      long rootBlockId = rootBlock.getBlockId();      rootBlock.free();      BTree btree = new BTree(this, rootBlockId, column.getLength(),			      keyCompare);      column.setIndex(btree);    }  }    /**   * Clears the indexes   */  private void clearIndexes()    throws IOException  {    Column []columns = _row.getColumns();    for (int i = 0; i < columns.length; i++) {      BTree index = columns[i].getIndex();      if (index == null)	continue;      long rootAddr = index.getIndexRoot();      Block block = readBlock(addressToBlockId(rootAddr));      try {	byte []blockBuffer = block.getBuffer();	synchronized (blockBuffer) {	  for (int j = 0; j < blockBuffer.length; j++) {	    blockBuffer[j] = 0;	  }	  block.setDirty(0, BLOCK_SIZE);	}      } finally {	block.free();      }    }    long blockAddr = 0;        while ((blockAddr = firstBlock(blockAddr + BLOCK_SIZE, ALLOC_INDEX)) > 0) {      freeBlock(blockAddr);    }  }    /**   * Rebuilds the indexes   */  private void rebuildIndexes()    throws IOException, SQLException  {    Transaction xa = Transaction.create();    xa.setAutoCommit(true);    try {      TableIterator iter = createTableIterator();      iter.init(xa);      Column []columns = _row.getColumns();      while (iter.nextBlock()) {	iter.initRow();	byte []blockBuffer = iter.getBuffer();      

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?