Package org.teiid.core.types

Source Code of org.teiid.core.types.LobSearchUtil$StreamProvider

/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.  Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/

package org.teiid.core.types;

import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;

import org.teiid.core.CorePlugin;


public class LobSearchUtil {

  private static final int MOD = 37;

  public interface StreamProvider {
   
    InputStream getBinaryStream() throws SQLException;   
   
  }
   
    static long position(StreamProvider pattern, long patternLength, StreamProvider target, long targetLength, long start, int bytesPerComparison) throws SQLException {
        if (pattern == null) {
            return -1;
        }
       
        patternLength *= bytesPerComparison;
        targetLength *= bytesPerComparison;

        if (start < 1) {
            Object[] params = new Object[] {new Long(start)};
            throw new SQLException(CorePlugin.Util.getString("MMClob_MMBlob.2", params)); //$NON-NLS-1$
        }
       
        start = (start - 1)*bytesPerComparison;
       
        if (start + patternLength > targetLength) {
            return -1;
        }
        /*
         * Use karp-rabin matching to reduce the cost of back tracing for failed matches
         *
         * TODO: optimize for patterns that are small enough to fit in a reasonable buffer
         */
        try {
          InputStream patternStream = pattern.getBinaryStream();
          InputStream targetStream = target.getBinaryStream();
          InputStream laggingTargetStream = target.getBinaryStream();
          try {
            int patternHash = computeStreamHash(patternStream, patternLength);
            int lastMod = 1;
            for (int i = 0; i < patternLength; i++) {
              lastMod *= MOD;
            }             
            targetStream.skip(start);
            laggingTargetStream.skip(start);
           
            long position = start + 1;
           
            int streamHash = computeStreamHash(targetStream, patternLength);
           
            do {
              if ((position -1)%bytesPerComparison == 0 && patternHash == streamHash && validateMatch(pattern, target, position)) {
                return (position - 1)/bytesPerComparison + 1;
              }
             
              streamHash = MOD * streamHash + targetStream.read() - lastMod * laggingTargetStream.read();
              position++;
           
            } while (position + patternLength - 1 <= targetLength);
           
            return -1;
          } finally {
            if (patternStream != null) {
              patternStream.close();
            }
            if (targetStream != null) {
              targetStream.close();
            }
            if (laggingTargetStream != null) {
              laggingTargetStream.close();
            }
          }
        } catch (IOException e) {
          throw new SQLException(e);
        }
    }
   
    /**
     * validate that the pattern matches the given position.
     *
     * TODO: optimize to reuse the same targetstream/buffer for small patterns
     * @throws SQLException
     */
    static private boolean validateMatch(StreamProvider pattern, StreamProvider target, long position) throws IOException, SQLException {
      InputStream targetStream = target.getBinaryStream();
      InputStream patternStream = pattern.getBinaryStream();
      try {
        targetStream.skip(position -1);     
        int value = 0;
        while ((value = patternStream.read()) != -1) {
          if (value != targetStream.read()) {
            return false;
          }
        }
      } finally {
        targetStream.close();
        patternStream.close();
      }
      return true;
    }
   
    static private int computeStreamHash(InputStream is, long length) throws IOException {
      int result = 0;
      for (int i = 0; i < length; i++) {
          result = result * MOD + is.read();
      }
      return result;
    }

}
TOP

Related Classes of org.teiid.core.types.LobSearchUtil$StreamProvider

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.