注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

anqiang专栏

不要问细节是怎么搞的,源码说明一切

 
 
 

日志

 
 

SimpleFSDirectory源码分析  

2009-11-30 10:53:48|  分类: Lucene |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

这个类是对FSDirectory的一个简单实现,一般的系统都是使用这个Directory对象进行操作的。

这个类里包含了SimpleFSIndexOutputSimpleFSIndexInput实现。

package org.apache.lucene.store;

/**

 * Licensed to the Apache Software Foundation (ASF) under one or more

 * contributor license agreements.  See the NOTICE file distributed with

 * this work for additional information regarding copyright ownership.

 * The ASF licenses this file to You under the Apache License, Version 2.0

 * (the "License"); you may not use this file except in compliance with

 * the License.  You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */

import java.io.File;

import java.io.IOException;

import java.io.RandomAccessFile;

/** A straightforward implementation of {@link FSDirectory}

 *  using java.io.RandomAccessFile.  However, this class has

 *  poor concurrent performance (multiple threads will

 *  bottleneck) as it synchronizes when multiple threads

 *  read from the same file.  It's usually better to use

 *  {@link NIOFSDirectory} or {@link MMapDirectory} instead. */

/**

 * 这个是对FSDirectory的简单实现

 * 一般都是使用这个类的实例进行index的构建工作

 */

public class SimpleFSDirectory extends FSDirectory {

    

  /** Create a new SimpleFSDirectory for the named location.

   *

   * @param path the path of the directory

   * @param lockFactory the lock factory to use, or null for the default

   * ({@link NativeFSLockFactory});

   * @throws IOException

   */

  public SimpleFSDirectory(File path, LockFactory lockFactory) throws IOException {

    super(path, lockFactory);

  }

  

  /** Create a new SimpleFSDirectory for the named location and {@link NativeFSLockFactory}.

   *

   * @param path the path of the directory

   * @throws IOException

   */

  public SimpleFSDirectory(File path) throws IOException {

    super(path, null);

  }

  // back compatibility so FSDirectory can instantiate via reflection

  /** @deprecated */

  SimpleFSDirectory() {}

  /** Creates an IndexOutput for the file with the given name. */

  public IndexOutput createOutput(String name) throws IOException {

    initOutput(name);

    return new SimpleFSIndexOutput(new File(directory, name));

  }

  /** Creates an IndexInput for the file with the given name. */

  /**

   * *默认的buffersize大小为1KB

   */

  public IndexInput openInput(String name, int bufferSize) throws IOException {

    ensureOpen();

    return new SimpleFSIndexInput(new File(directory, name), bufferSize, getReadChunkSize());

  }

  protected static class SimpleFSIndexInput extends BufferedIndexInput {

  

    protected static class Descriptor extends RandomAccessFile {

      // remember if the file is open, so that we don't try to close it

      // more than once

      protected volatile boolean isOpen;

      long position;

      final long length;

      

      public Descriptor(File file, String mode) throws IOException {

        super(file, mode);

        isOpen=true;

        length=length();

      }

  

      public void close() throws IOException {

        if (isOpen) {

          isOpen=false;

          super.close();

        }

      }

    }

  

    protected final Descriptor file;

    boolean isClone;

    //  LUCENE-1566 - maximum read length on a 32bit JVM to prevent incorrect OOM 

    //在32位JVM上一次最大可读入的数据大小

    protected final int chunkSize;

    /** @deprecated Please use ctor taking chunkSize */

    public SimpleFSIndexInput(File path) throws IOException {

      this(path, BufferedIndexInput.BUFFER_SIZE, SimpleFSDirectory.DEFAULT_READ_CHUNK_SIZE);

    }

  

    /** @deprecated Please use ctor taking chunkSize */

    public SimpleFSIndexInput(File path, int bufferSize) throws IOException {

      this(path, bufferSize, SimpleFSDirectory.DEFAULT_READ_CHUNK_SIZE);

    }

    

    public SimpleFSIndexInput(File path, int bufferSize, int chunkSize) throws IOException {

      super(bufferSize);

      file = new Descriptor(path, "r");

      this.chunkSize = chunkSize;

    }

  

    /** IndexInput methods */

    /**

     * 读一定长度len的数据到byte[] 数组中

     * 对于大于chunksize的数据我们每次只读chunksize大小的数据进来

     * 默认的chunksize大小为100MB

     */

    protected void readInternal(byte[] b, int offset, int len)

         throws IOException {

      synchronized (file) {

        long position = getFilePointer();

        if (position != file.position) {

          file.seek(position);

          file.position = position;

        }

        int total = 0;

        try {

          do {

            final int readLength;

            if (total + chunkSize > len) {

              readLength = len - total;

            } else {

              // LUCENE-1566 - work around JVM Bug by breaking very large reads into chunks

              readLength = chunkSize;

            }

            final int i = file.read(b, offset + total, readLength);

            if (i == -1) {

              throw new IOException("read past EOF");

            }

            file.position += i;

            total += i;

          } while (total < len);

        } catch (OutOfMemoryError e) {

          // propagate OOM up and add a hint for 32bit VM Users hitting the bug

          // with a large chunk size in the fast path.

         //由于chunk size太大而引起的内存溢出现象

          final OutOfMemoryError outOfMemoryError = new OutOfMemoryError(

              "OutOfMemoryError likely caused by the Sun VM Bug described in "

              + "https://issues.apache.org/jira/browse/LUCENE-1566; try calling FSDirectory.setReadChunkSize "

              + "with a a value smaller than the current chunks size (" + chunkSize + ")");

          outOfMemoryError.initCause(e);

          throw outOfMemoryError;

        }

      }

    }

  

    /**

     * 只有对非克隆对象才起作用

     */

    public void close() throws IOException {

      // only close the file if this is not a clone

      if (!isClonefile.close();

    }

  

    protected void seekInternal(long position) {

    }

  

    public long length() {

      return file.length;

    }

  

    /**

     * 这个克隆有什么用??

     */

    public Object clone() {

      SimpleFSIndexInput clone = (SimpleFSIndexInput)super.clone();

      clone.isClone = true;

      return clone;

    }

  

    /** Method used for testing. Returns true if the underlying

     *  file descriptor is valid.

     *  不知所云

     */

    boolean isFDValid() throws IOException {

      return file.getFD().valid();

    }

  }

  protected static class SimpleFSIndexOutput extends BufferedIndexOutput {

    RandomAccessFile file = null;

  

    // remember if the file is open, so that we don't try to close it

    // more than once

    private volatile boolean isOpen;

    public SimpleFSIndexOutput(File path) throws IOException {

      file = new RandomAccessFile(path, "rw");

      isOpen = true;

    }

  

    /** output methods: */

    /**

     * 将bytes[]数据写入到file中去

     * 写信息中不会遇到读信息中的读异常

     */

    public void flushBuffer(byte[] b, int offset, int size) throws IOException {

      file.write(b, offset, size);

    }

    public void close() throws IOException {

      // only close the file if it has not been closed yet

      if (isOpen) {

        boolean success = false;

        try {

         /**

          * super == BufferedIndexOutput 将剩余的buffer中的数据写入到文件中去

          * 

          */

          super.close();

          success = true;

        } finally {

          isOpen = false;

          if (!success) {

            try {

              file.close();

            } catch (Throwable t) {

              // Suppress so we don't mask original exception

            }

          } else

            file.close();

        }

      }

    }

  

    /** Random-access methods */

    /**

     * 先将缓存中的数据写入到文件中

     * 然后才开始seek的操作

     */

    public void seek(long pos) throws IOException {

      super.seek(pos);

      file.seek(pos);

    }

    public long length() throws IOException {

      return file.length();

    }

    public void setLength(long length) throws IOException {

      file.setLength(length);

    }

  }

}

protected void readInternal(byte[] b, int offset, int len)

         throws IOException

这个函数读入bytes数组的信息,在这里要避免出现JDK的一个bug。一次读入的信息量不能大于100MB,这是对于32位处理器而言的。在64位的情况下不会出现这个问题。

public void seek(long pos) throws IOException

这个函数实现文件的seek功能,一开始不是很明白这个pos是什么意思.file.seek(pos)JDK的操作,查看一下API,它的说明如下:

/**

     * Sets the file-pointer offset, measured from the beginning of this 

     * file, at which the next read or write occurs.  The offset may be 

     * set beyond the end of the file. Setting the offset beyond the end 

     * of the file does not change the file length.  The file length will 

     * change only by writing after the offset has been set beyond the end 

     * of the file. 

     *

     * @param      pos   the offset position, measured in bytes from the 

     *                   beginning of the file, at which to set the file 

     *                   pointer.

     * @exception  IOException  if <code>pos</code> is less than 

     *                          <code>0</code> or if an I/O error occurs.

     */

    public native void seek(long pos) throws IOException;/**

     * Sets the file-pointer offset, measured from the beginning of this 

     * file, at which the next read or write occurs.  The offset may be 

     * set beyond the end of the file. Setting the offset beyond the end 

     * of the file does not change the file length.  The file length will 

     * change only by writing after the offset has been set beyond the end 

     * of the file. 

     *

     * @param      pos   the offset position, measured in bytes from the 

     *                   beginning of the file, at which to set the file 

     *                   pointer.

     * @exception  IOException  if <code>pos</code> is less than 

     *                          <code>0</code> or if an I/O error occurs.

     */

    也就是posoffset的位置,按照byte进行计算,即每次跳转1就等于跳转一个byte位。

  评论这张
 
阅读(1298)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017