Package org.teiid.internal.core.index

Source Code of org.teiid.internal.core.index.BlocksIndexInput

/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*     MetaMatrix, Inc - repackaging and updates for use as a metadata store
*******************************************************************************/
package org.teiid.internal.core.index;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;

import org.jboss.virtual.VirtualFile;
import org.teiid.core.index.IDocument;
import org.teiid.core.index.IEntryResult;
import org.teiid.core.index.IQueryResult;
import org.teiid.core.util.LRUCache;
import org.teiid.metadata.index.RuntimeMetadataPlugin;


/**
* This input is used for reading indexes saved using a BlocksIndexOutput.
*/
public class BlocksIndexInput extends IndexInput {
  public static final int CACHE_SIZE= 16; // Cache 16 blocks of 8K each, for a cache size of 128K
  protected FileListBlock currentFileListBlock;
  protected int currentFileListBlockNum;
  protected int currentIndexBlockNum;
  protected IndexBlock currentIndexBlock;
  private RandomAccessFile raf;
  private VirtualRandomAccessFile vraf;
  protected VirtualFile indexFile;
  protected LRUCache blockCache;

  protected IndexSummary summary;

  public BlocksIndexInput(VirtualFile inputFile) {
    this.indexFile= inputFile;
    blockCache= new LRUCache(CACHE_SIZE);
  }
   
  /**
   * @see IndexInput#clearCache()
   */
  public void clearCache() {
    blockCache= new LRUCache(CACHE_SIZE);
  }
   
  /**
   * @see IndexInput#close()
   */
  public void close() throws IOException {
    if (isOpen()) {
            //System.out.println(" Closing Index File: " + this.indexFile.getName());
      summary= null;
      setOpen(false);
      if (raf != null)
        raf.close();
      vraf.close();
    }
  }
   
  /**
   * @see IndexInput#getCurrentFile()
   */
  public IndexedFile getCurrentFile() throws IOException {
    if (!hasMoreFiles())
      return null;
    IndexedFile file= null;
    if ((file= currentFileListBlock.getFile(filePosition)) == null) {
      currentFileListBlockNum= summary.getBlockNumForFileNum(filePosition);
      currentFileListBlock= getFileListBlock(currentFileListBlockNum);
      file= currentFileListBlock.getFile(filePosition);
    }
    return file;
  }
   
  /**
   * Returns the entry corresponding to the given word.
   */
  protected WordEntry getEntry(char[] word) throws IOException {
    int blockNum= summary.getBlockNumForWord(word);
    if (blockNum == -1) return null;
    IndexBlock block= getIndexBlock(blockNum);
    return block.findExactEntry(word);
  }
   
  /**
   * Returns the FileListBlock with the given number.
   */
  protected FileListBlock getFileListBlock(int blockNum) throws IOException {
    Integer key= new Integer(blockNum);
    Block block= (Block) blockCache.get(key);
    if (block != null && block instanceof FileListBlock)
      return (FileListBlock) block;
    FileListBlock fileListBlock= new FileListBlock(IIndexConstants.BLOCK_SIZE);
    fileListBlock.read(raf, blockNum);
    blockCache.put(key, fileListBlock);
    return fileListBlock;
  }
   
  /**
   * Returns the IndexBlock (containing words) with the given number.
   */
  protected IndexBlock getIndexBlock(int blockNum) throws IOException {
    Integer key= new Integer(blockNum);
    Block block= (Block) blockCache.get(key);
    if (block != null && block instanceof IndexBlock)
      return (IndexBlock) block;
    IndexBlock indexBlock= new GammaCompressedIndexBlock(IIndexConstants.BLOCK_SIZE);
    indexBlock.read(raf, blockNum);
    blockCache.put(key, indexBlock);
    return indexBlock;
  }
   
  /**
   * @see IndexInput#getIndexedFile(int)
   */
  public IndexedFile getIndexedFile(int fileNum) throws IOException {
    int blockNum= summary.getBlockNumForFileNum(fileNum);
    if (blockNum == -1)
      return null;
    FileListBlock block= getFileListBlock(blockNum);
    return block.getFile(fileNum);
  }
   
  /**
   * @see IndexInput#getIndexedFile(IDocument)
   */
  public IndexedFile getIndexedFile(IDocument document) throws java.io.IOException {
    setFirstFile();
    String name= document.getName();
    while (hasMoreFiles()) {
      IndexedFile file= getCurrentFile();
      String path= file.getPath();
      if (path.equals(name))
        return file;
      moveToNextFile();
    }
    return null;
  }
   
  /**
   * Returns the list of numbers of files containing the given word.
   */
  protected int[] getMatchingFileNumbers(char[] word) throws IOException {
    int blockNum= summary.getBlockNumForWord(word);
    if (blockNum == -1)
      return new int[0];
    IndexBlock block= getIndexBlock(blockNum);
    WordEntry entry= block.findExactEntry(word);
    return entry == null ? new int[0] : entry.getRefs();
  }
   
  /**
   * @see IndexInput#getNumFiles()
   */
  public int getNumFiles() {
    return summary.getNumFiles();
  }
   
  /**
   * @see IndexInput#getNumWords()
   */
  public int getNumWords() {
    return summary.getNumWords();
  }
   
  /**
   * @see IndexInput#getSource()
   */
  public Object getSource() {
    return indexFile;
  }
   
  /**
   * Initialises the blocksIndexInput
   */
  protected void init() throws IOException {
    clearCache();
    setFirstFile();
    setFirstWord();
  }
  /**
   * @see IndexInput#moveToNextFile()
   */
  public void moveToNextFile() throws IOException {
    filePosition++;
  }
   
  /**
   * @see IndexInput#moveToNextWordEntry()
   */
  public void moveToNextWordEntry() throws IOException {
    wordPosition++;
    if (!hasMoreWords()) {
      return;
    }
    //if end of the current block, we load the next one.
    boolean endOfBlock= !currentIndexBlock.nextEntry(currentWordEntry);
    if (endOfBlock) {
      currentIndexBlock= getIndexBlock(++currentIndexBlockNum);
      currentIndexBlock.nextEntry(currentWordEntry);
    }
  }
   
  /**
   * @see IndexInput#open()
   */
  public void open() throws IOException {
    if (!isOpen()) {
      vraf = new VirtualRandomAccessFile(indexFile, "r");
      raf= vraf.getSafeRandomAccessFile();
      String sig= raf.readUTF();
      if (!sig.equals(IIndexConstants.SIGNATURE))
        throw new IOException(RuntimeMetadataPlugin.Util.getString("exception.wrongFormat")); //$NON-NLS-1$
      int summaryBlockNum= raf.readInt();
      raf.seek(summaryBlockNum * (long) IIndexConstants.BLOCK_SIZE);
      summary= new IndexSummary();
      summary.read(raf);
      init();
      setOpen(true);
    }
  }
   
  /**
   * @see IndexInput#query(String)
   */
  public IQueryResult[] query(String word) throws IOException {
        open();
    int[] fileNums= getMatchingFileNumbers(word.toCharArray());
    int size= fileNums.length;
    IQueryResult[] files= new IQueryResult[size];
    for (int i= 0; i < size; ++i) {
      files[i]= getIndexedFile(fileNums[i]);
    }
    return files;
  }
   
  /**
     * Overloaded the method in BlocksIndexInput to allow a user to specify if the
     * query should be case sensitive.
     * @param pattern
     * @param isCaseSensitive
     * @return
     * @throws IOException
     */
    public IEntryResult[] queryEntriesMatching(char[] pattern, boolean isCaseSensitive) throws IOException {
        open();
   
        if (pattern == null || pattern.length == 0) return null;
        int[] blockNums = null;
        int firstStar = indexOf('*', pattern);
        switch (firstStar){
            case -1 :
                WordEntry entry = getEntry(pattern);
                if (entry == null) return null;
                return new IEntryResult[]{ new EntryResult(entry.getWord(), entry.getRefs()) };
            case 0 :
                blockNums = summary.getAllBlockNums();
                break;
            default :
              char[] prefix = new char[firstStar];
              System.arraycopy(pattern, 0, prefix, 0, firstStar);
                blockNums = summary.getBlockNumsForPrefix(prefix);
        }
        if (blockNums == null || blockNums.length == 0) return null;
               
        IEntryResult[] entries = new IEntryResult[5];
        int count = 0;
        for (int i = 0, max = blockNums.length; i < max; i++) {
            IndexBlock block = getIndexBlock(blockNums[i]);
            block.reset();
            WordEntry entry = new WordEntry();
            while (block.nextEntry(entry)) {
                // Switch argument order to fix bug in BlocksIndexInput
                if (CharOperation.match(pattern, entry.getWord(), isCaseSensitive)) {
                    if (count == entries.length){
                        System.arraycopy(entries, 0, entries = new IEntryResult[count*2], 0, count);
                    }
                    entries[count++] = new EntryResult(entry.getWord(), entry.getRefs());
                }
            }
        }
        if (count != entries.length){
            System.arraycopy(entries, 0, entries = new IEntryResult[count], 0, count);
        }
        return entries;
    }
   
    static final int indexOf(char toBeFound, char[] array) {
        for (int i = 0; i < array.length; i++)
            if (toBeFound == array[i])
                return i;
        return -1;
    }
   
    public IEntryResult[] queryEntriesPrefixedBy(char[] prefix) throws IOException {
        open();
   
    int blockLoc = summary.getFirstBlockLocationForPrefix(prefix);
    if (blockLoc < 0) return null;
     
    IEntryResult[] entries = new IEntryResult[5];
    int count = 0;
    while(blockLoc >= 0){
      IndexBlock block = getIndexBlock(summary.getBlockNum(blockLoc));
      block.reset();
      boolean found = false;
      WordEntry entry = new WordEntry();
      while (block.nextEntry(entry)) {
        if (CharOperation.prefixEquals(prefix, entry.getWord(), true)) {
          if (count == entries.length){
            System.arraycopy(entries, 0, entries = new IEntryResult[count*2], 0, count);
          }
          entries[count++] = new EntryResult(entry.getWord(), entry.getRefs());
          found = true;
        } else {
          if (found) break;
        }
      }
      /* consider next block ? */
      blockLoc = summary.getNextBlockLocationForPrefix(prefix, blockLoc);       
    }
    if (count == 0) return null;
    if (count != entries.length){
      System.arraycopy(entries, 0, entries = new IEntryResult[count], 0, count);
    }
    return entries;
  }

    /**
     * Overloaded the method in BlocksIndexInput to allow a user to specify if the
     * query should be case sensitive.
     */
    public IEntryResult[] queryEntriesPrefixedBy(char[] prefix, boolean isCaseSensitive) throws IOException {
        open();

        int blockLoc = summary.getFirstBlockLocationForPrefix(prefix);
        if (blockLoc < 0) return null;

        IEntryResult[] entries = new IEntryResult[5];
        int count = 0;
        while(blockLoc >= 0){
            IndexBlock block = getIndexBlock(summary.getBlockNum(blockLoc));
            block.reset();
            boolean found = false;
            WordEntry entry = new WordEntry();
            while (block.nextEntry(entry)) {
                if (CharOperation.prefixEquals(prefix, entry.getWord(), isCaseSensitive)) {
                    if (count == entries.length){
                        System.arraycopy(entries, 0, entries = new IEntryResult[count*2], 0, count);
                    }
                    entries[count++] = new EntryResult(entry.getWord(), entry.getRefs());
                    found = true;
                } else {
                    if (found) break;
                }
            }
            /* consider next block ? */
            blockLoc = summary.getNextBlockLocationForPrefix(prefix, blockLoc);            
        }
        if (count == 0) return null;
        if (count != entries.length){
            System.arraycopy(entries, 0, entries = new IEntryResult[count], 0, count);
        }
        return entries;
    }
   
  public IQueryResult[] queryFilesReferringToPrefix(char[] prefix) throws IOException {
        open();

    int blockLoc = summary.getFirstBlockLocationForPrefix(prefix);
    if (blockLoc < 0) return null;

    // each filename must be returned already once
    HashMap<Integer, IndexedFile> fileMatches = new HashMap<Integer, IndexedFile>();
    int count = 0;
    while(blockLoc >= 0){
      IndexBlock block = getIndexBlock(summary.getBlockNum(blockLoc));
      block.reset();
      boolean found = false;
      WordEntry entry = new WordEntry();
      while (block.nextEntry(entry)) {
        if (CharOperation.prefixEquals(prefix, entry.getWord(), true)) {
          int [] refs = entry.getRefs();
          for (int i = 0, max = refs.length; i < max; i++){
            int ref = refs[i];
            Integer key = Integer.valueOf(ref);
            if (!fileMatches.containsKey(key)){
              count++;
              fileMatches.put(key, getIndexedFile(ref));
            }
          }
          found = true;
        } else {
          if (found) break;
        }
      }
      /* consider next block ? */
      blockLoc = summary.getNextBlockLocationForPrefix(prefix, blockLoc);       
    }
    /* extract indexed files */
    IQueryResult[] files = fileMatches.values().toArray(new IQueryResult[count]);
    return files;
  }
   
  /**
   * @see IndexInput#queryInDocumentNames(String)
   */
  public IQueryResult[] queryInDocumentNames(String word) throws IOException {
        open();
    ArrayList matches= new ArrayList();
    setFirstFile();
    while (hasMoreFiles()) {
      IndexedFile file= getCurrentFile();
      if (file.getPath().indexOf(word) != -1)
        matches.add(file);
      moveToNextFile();
    }
    IQueryResult[] match= new IQueryResult[matches.size()];
    matches.toArray(match);
    return match;
  }
   
  /**
   * @see IndexInput#setFirstFile()
   */
  protected void setFirstFile() throws IOException {
    filePosition= 1;
    if (getNumFiles() > 0) {
      currentFileListBlockNum= summary.getBlockNumForFileNum(1);
      currentFileListBlock= getFileListBlock(currentFileListBlockNum);
    }
  }
   
  /**
   * @see IndexInput#setFirstWord()
   */
  protected void setFirstWord() throws IOException {
    wordPosition= 1;
    if (getNumWords() > 0) {
      currentIndexBlockNum= summary.getFirstWordBlockNum();
      currentIndexBlock= getIndexBlock(currentIndexBlockNum);
      currentWordEntry= new WordEntry();
      currentIndexBlock.reset();
      currentIndexBlock.nextEntry(currentWordEntry);
    }
  }
}
TOP

Related Classes of org.teiid.internal.core.index.BlocksIndexInput

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.