block.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 361 行

JAVA
361
字号
/* * 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.store;import com.caucho.log.Log;import com.caucho.util.FreeList;import com.caucho.util.L10N;import com.caucho.util.SyncCacheListener;import java.io.IOException;import java.util.logging.Level;import java.util.logging.Logger;/** * Represents a versioned row */abstract public class Block implements SyncCacheListener {  private static final Logger log = Log.open(Block.class);  private static final L10N L = new L10N(Block.class);  protected static final FreeList<byte[]> _freeBuffers    = new FreeList<byte[]>(4);  private final Store _store;  private final long _blockId;  private final Lock _lock;  private int _useCount = 1;  private boolean _isFlushDirtyOnCommit;  private boolean _isValid;    private int _dirtyMin = Store.BLOCK_SIZE;  private int _dirtyMax;  Block(Store store, long blockId)  {    store.validateBlockId(blockId);        _store = store;    _blockId = blockId;        _lock = new Lock("block:" + store.getName() + ":" + _blockId);        _isFlushDirtyOnCommit = _store.isFlushDirtyBlocksOnCommit();    if (log.isLoggable(Level.FINEST))      log.finest(this + " create");  }  /**   * Returns true if the block should be flushed on a commit.   */  public boolean isFlushDirtyOnCommit()  {    return _isFlushDirtyOnCommit;  }  /**   * True if the block should be flushed on a commit.   */  public void setFlushDirtyOnCommit(boolean isFlush)  {    _isFlushDirtyOnCommit = isFlush;  }  /**   * Allocates the block for a query.   */  public boolean allocate()  {    synchronized (this) {      if (getBuffer() == null)	return false;            _useCount++;            if (log.isLoggable(Level.FINEST))	log.finest(this + " allocate (" + _useCount + ")");            //System.out.println(this + " ALLOCATE " + _useCount);      if (_useCount > 32 && log.isLoggable(Level.FINE)) {	Thread.dumpStack();	log.fine("using " + this + " " + _useCount + " times");      }    }    return true;  }  /**   * Returns the block's table.   */  Store getStore()  {    return _store;  }  /**   * Returns the block's id.   */  public long getBlockId()  {    return _blockId;  }  public Lock getLock()  {    return _lock;  }    /**   * Returns the block's buffer.   */  abstract public byte []getBuffer();  /**   * Reads into the block.   */  public void read()    throws IOException  {    synchronized (this) {      if (! _isValid) {	if (log.isLoggable(Level.FINEST))	  log.finest("read db-block " + this);      	_store.readBlock(_blockId & Store.BLOCK_MASK,			 getBuffer(), 0, Store.BLOCK_SIZE);	_isValid = true;	_dirtyMin = Store.BLOCK_SIZE;	_dirtyMax = 0;      }    }  }  /**   * Handle any database writes necessary at commit time.  If   * isFlushDirtyOnCommit() is true, this will write the data to   * the backing file.   */  public void commit()    throws IOException  {    if (! _isFlushDirtyOnCommit)      return;    else      write();  }  /**   * Forces a write of the data (should be private?)   */  public void write()    throws IOException  {    getLock().waitForCommit();    int dirtyMin = 0;    int dirtyMax = 0;        synchronized (this) {      dirtyMin = _dirtyMin;      _dirtyMin = Store.BLOCK_SIZE;      dirtyMax = _dirtyMax;      _dirtyMax = 0;      if (dirtyMax <= dirtyMin)	return;      // temp alloc for sync, matched by the free() below      _useCount++;      _isValid = true;            if (log.isLoggable(Level.FINEST))	log.finest("write alloc " + this + " (" + _useCount + ")");    }    try {      if (log.isLoggable(Level.FINEST))	log.finest("write db-block " + this + " [" + dirtyMin + ", " + dirtyMax + "]");      //System.out.println(this + " WRITE_BEGIN");      writeImpl(dirtyMin, dirtyMax - dirtyMin);      //System.out.println(this + " WRITE_END");    } finally {      free();    }  }  /**   * Write the dirty block.   */  protected void writeImpl(int offset, int length)    throws IOException  {    _store.writeBlock((_blockId & Store.BLOCK_MASK) + offset,		      getBuffer(), offset, length);  }  /**   * Marks the block's data as invalid.   */  public void invalidate()  {    synchronized (this) {      if (_dirtyMin < _dirtyMax)	throw new IllegalStateException();          _isValid = false;      _dirtyMin = Store.BLOCK_SIZE;      _dirtyMax = 0;    }  }  /**   * Marks the data as valid.   */  void validate()  {    _isValid = true;  }  /**   * Marks the block's data as dirty   */  public void setDirty(int min, int max)  {    if (Store.BLOCK_SIZE < max)      Thread.dumpStack();    synchronized (this) {      _isValid = true;      if (min < _dirtyMin)	_dirtyMin = min;          if (_dirtyMax < max)	_dirtyMax = max;    }  }  /**   * Returns true if the block needs writing   */  public boolean isDirty()  {    return _dirtyMin < _dirtyMax;  }  /**   * Return true if this is a free block.   */  public boolean isFree()  {    return _useCount == 0;  }  /**   * Frees a block from a query.   */  public final void free()  {    synchronized (this) {      if (log.isLoggable(Level.FINEST))	log.finest(this + " free (" + _useCount + ")");      _useCount--;            //System.out.println(this + " FREE " + _useCount);      if (_useCount > 0)	return;            // If the block is clean, just discard it      if (_dirtyMax <= _dirtyMin) {	freeImpl();	return;      }    }    // dirty blocks get queued for writing    BlockManager.getBlockManager().addLruDirtyWriteBlock(this);  }  /**   * Called when the block is removed from the cache.   */  public final void syncRemoveEvent()  {    free();  }    /**   * Called when the block is removed from the cache.   */  // called only from BlockManagerWriter.run()  void close()  {    synchronized (this) {      if (_dirtyMin < _dirtyMax) {	try {	  write();	} catch (Throwable e) {	  log.log(Level.FINER, e.toString(), e);	}      }      if (_useCount <= 0)	freeImpl();      if (log.isLoggable(Level.FINEST))	log.finest("db-block remove " + this);    }  }  /**   * Frees any resources.   */  protected void freeImpl()  {  }  public String toString()  {    return "Block[" + _store + "," + _blockId / Store.BLOCK_SIZE + "]";  }}

⌨️ 快捷键说明

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