inode.java

来自「RESIN 3.2 最新源码」· Java 代码 · 共 1,246 行 · 第 1/3 页

JAVA
1,246
字号
/* * 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.util.L10N;import com.caucho.util.Log;import com.caucho.vfs.OutputStreamWithBuffer;import com.caucho.vfs.TempCharBuffer;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.Reader;import java.io.Writer;import java.util.logging.Level;import java.util.logging.Logger;/** * Represents the indexes for a BLOB or CLOB. * * The inode contains 16 long values * <pre> *  0) length of the saved file *  1-14) direct fragment addresses (to 112k) *  15) pointer to the indirect block * </pre> * * <h3>Inline storage (120)</h3> * * If the length of the blob is less than 120, the blob is stored directly * in the inode. * * <h3>mini fragment storage (3840)</h3> * * If the length of the blob is less than 3840, the blob is stored * in mini-fragments of size 256 pointed by the inode's addresses. * * The maximum wasted space for mini-fragment storage is 255 bytes. * * <h3>indirect storage</h3> * * The indirect block (an 8k fragment) itself is divided into sections: * <pre> *  0-511) single indirect fragment addresses (4M, 2^12) *  512-767) double indirect block addresses (128G, 2^37) *  768-1023) triple indirect fragment addresses (to 1P, 2^50) * </pre> */public class Inode {  private static final L10N L = new L10N(Inode.class);  private static final Logger log    = Logger.getLogger(Inode.class.getName());    public static final int INODE_SIZE = 128;  public static final int INLINE_BLOB_SIZE = 120;  public static final int BLOCK_SIZE = Store.BLOCK_SIZE;  public static final int INODE_BLOCK_SIZE = Store.FRAGMENT_SIZE;  public static final int FRAGMENT_SIZE = Store.FRAGMENT_SIZE;    public static final int MINI_FRAG_SIZE = Store.MINI_FRAG_SIZE;  public static final int MINI_FRAG_BLOB_SIZE    = (INLINE_BLOB_SIZE / 8) * MINI_FRAG_SIZE;  public static final int INDIRECT_BLOCKS = INODE_BLOCK_SIZE / 8;  // direct addresses are stored in the inode itself (112k of data).  public static final int DIRECT_BLOCKS = 14;  // single indirect addresses are stored in the indirect block (4M data)  public static final int SINGLE_INDIRECT_BLOCKS = 512;  // double indirect addresses (2^37 = 128G data)  public static final int DOUBLE_INDIRECT_BLOCKS = 256;  // triple indirect addresses (2^50 = 2P data)  public static final int TRIPLE_INDIRECT_BLOCKS = 256;  public static final long INLINE_MAX = 120;    public static final int MINI_FRAG_MAX    = (INLINE_BLOB_SIZE / 8) * MINI_FRAG_SIZE;    public static final long DIRECT_MAX    = FRAGMENT_SIZE * DIRECT_BLOCKS;    public static final long SINGLE_INDIRECT_MAX    = DIRECT_MAX + SINGLE_INDIRECT_BLOCKS * FRAGMENT_SIZE;    public static final long FRAGMENT_MAX    = SINGLE_INDIRECT_MAX;    public static final long DOUBLE_INDIRECT_MAX    = (SINGLE_INDIRECT_MAX       + DOUBLE_INDIRECT_BLOCKS * (BLOCK_SIZE / 8) * BLOCK_SIZE);    private static final byte []NULL_BYTES = new byte[INODE_SIZE];  private Store _store;  private StoreTransaction _xa;  private byte []_bytes = new byte[INODE_SIZE];  public Inode()  {  }  public Inode(Store store, StoreTransaction xa)  {    _store = store;    _xa = xa;  }  public Inode(Store store)  {    this(store, RawTransaction.create());  }  /**   * Returns the backing store.   */  public Store getStore()  {    return _store;  }    /**   * Returns the buffer.   */  public byte []getBuffer()  {    return _bytes;  }  /**   * Returns the length.   */  public long getLength()  {    return readLong(_bytes, 0);  }  public void init(Store store, StoreTransaction xa,		   byte []buffer, int offset)  {    _store = store;    _xa = xa;    System.arraycopy(buffer, offset, _bytes, 0, _bytes.length);  }  /**   * Opens a read stream to the inode.   */  public InputStream openInputStream()  {    return new BlobInputStream(this);  }  /**   * Writes the inode value to a stream.   */  public void writeToStream(OutputStreamWithBuffer os)    throws IOException  {    writeToStream(os, 0, Long.MAX_VALUE / 2);  }  /**   * Writes the inode value to a stream.   */  public void writeToStream(OutputStreamWithBuffer os,			    long offset, long length)    throws IOException  {    byte []buffer = os.getBuffer();    int writeLength = buffer.length;    int writeOffset = os.getBufferOffset();        while (length > 0) {      int sublen = writeLength - writeOffset;      if (sublen == 0) {	buffer = os.nextBuffer(writeOffset);	writeOffset = os.getBufferOffset();	sublen = writeLength - writeOffset;      }      if (length < sublen)	sublen = (int) length;      int len = read(_bytes, 0, _store,		     offset,		     buffer, writeOffset, sublen);      if (len <= 0)	break;      writeOffset += len;      offset += len;      length -= len;    }    os.setBufferOffset(writeOffset);  }  /**   * Writes the inode value to a stream.   */  public void writeToWriter(Writer writer)    throws IOException  {    TempCharBuffer tempBuffer = TempCharBuffer.allocate();    char []buffer = tempBuffer.getBuffer();    int writeLength = buffer.length;    long offset = 0;        while (true) {      int sublen = writeLength;      int len = read(_bytes, 0, _store,		     offset,		     buffer, 0, sublen);      if (len <= 0)	break;      writer.write(buffer, 0, len);      offset += 2 * len;    }    TempCharBuffer.free(tempBuffer);  }  /**   * Reads into a buffer.   *   * @param inode the inode buffer   * @param inodeOffset the offset of the inode data in the buffer   * @param store the owning store   * @param fileOffset the offset into the file to read   * @param buffer the buffer receiving the data   * @param bufferOffset the offset into the receiving buffer   * @param bufferLength the maximum number of bytes to read   *   * @return the number of bytes read   */  static int read(byte []inode, int inodeOffset,		  Store store,		  long fileOffset, 		  byte []buffer, int bufferOffset, int bufferLength)    throws IOException  {    long fileLength = readLong(inode, inodeOffset);    int sublen = bufferLength;    if (fileLength - fileOffset < sublen)      sublen = (int) (fileLength - fileOffset);          if (sublen <= 0)      return -1;    if (fileLength <= INLINE_MAX) {      System.arraycopy(inode, inodeOffset + 8 + (int) fileOffset,		       buffer, bufferOffset, sublen);      return sublen;    }    else if (fileLength <= MINI_FRAG_MAX) {      long fragAddr = readMiniFragAddr(inode, inodeOffset, store, fileOffset);      int fragOffset = (int) (fileOffset % MINI_FRAG_SIZE);      if (MINI_FRAG_SIZE - fragOffset < sublen)	sublen = MINI_FRAG_SIZE - fragOffset;      store.readMiniFragment(fragAddr, fragOffset,			     buffer, bufferOffset, sublen);      return sublen;    }    else if (fileLength <= FRAGMENT_MAX) {      long fragAddr = readFragmentAddr(inode, inodeOffset, store, fileOffset);      int fragOffset = (int) (fileOffset % FRAGMENT_SIZE);      if (FRAGMENT_SIZE - fragOffset < sublen)	sublen = FRAGMENT_SIZE - fragOffset;      store.readFragment(fragAddr, fragOffset, buffer, bufferOffset, sublen);          return sublen;    }    else {      long addr = readBlockAddr(inode, inodeOffset, store, fileOffset);      int offset = (int) ((fileOffset - FRAGMENT_MAX) % BLOCK_SIZE);      if (BLOCK_SIZE - offset < sublen)	sublen = BLOCK_SIZE - offset;      store.readBlock(addr, offset, buffer, bufferOffset, sublen);          return sublen;    }  }    /**   * Updates the buffer.  Called only from the blob classes.   */  static void append(byte []inode, int inodeOffset,		     Store store, StoreTransaction xa,		     byte []buffer, int offset, int length)    throws IOException  {    long currentLength = readLong(inode, inodeOffset);    long newLength = currentLength + length;    writeLong(inode, inodeOffset, newLength);    if (newLength <= INLINE_MAX) {      System.arraycopy(buffer, offset,		       inode, (int) (inodeOffset + 8 + currentLength),		       length);    }    else if (newLength <= MINI_FRAG_MAX) {      while (length > 0) {	int sublen = length;		if (MINI_FRAG_SIZE < sublen)	  sublen = MINI_FRAG_SIZE;		long miniFragAddr = store.allocateMiniFragment(xa);	if (miniFragAddr == 0) {	  store.setCorrupted(true);	  	  throw new IllegalStateException(L.l("{0} illegal mini fragment",					      store));	}	writeMiniFragAddr(inode, inodeOffset,			  store, xa,			  currentLength, miniFragAddr);	store.writeMiniFragment(xa, miniFragAddr, 0, buffer, offset, sublen);	offset += sublen;	length -= sublen;	currentLength += sublen;      }    }    else {      if (currentLength < FRAGMENT_MAX) {	int sublen = length;	if (FRAGMENT_MAX - currentLength < sublen)	  sublen = (int) (FRAGMENT_MAX - currentLength);		appendFragment(inode, inodeOffset, store, xa,		       buffer, offset, length, currentLength);	offset += sublen;	length -= sublen;	currentLength += sublen;      }      if (length > 0) {	appendBlock(inode, inodeOffset, store, xa,		    buffer, offset, length, currentLength);      }    }  }  private static void appendFragment(byte []inode, int inodeOffset,				     Store store, StoreTransaction xa,				     byte []buffer, int offset, int length,				     long currentLength)    throws IOException  {    // XXX: theoretically deal with case of appending to inline, although    // the blobs are the only writers and will avoid that case.    while (length > 0 && currentLength < FRAGMENT_MAX) {      if (currentLength % FRAGMENT_SIZE != 0) {	long fragAddr = readFragmentAddr(inode, inodeOffset,					 store,					 currentLength);	if (fragAddr == 0) {	  store.setCorrupted(true);	  	  throw new IllegalStateException(store + " inode: illegal fragment at " + currentLength);

⌨️ 快捷键说明

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