package ModSQL;
import java.sql.*;
import java.io.*;

/* $Id: IndexTable.java,v 1.11 2004/01/04 02:23:08 cvs Exp $
 *
 * Copyright (c) 2004 Chris Studholme <chris.studholme@utoronto.ca>
 *
 * May be copied or modified under the terms of the GNU General Public
 * License.  See COPYING for more information.
 */

/**
 * Abstract base class for built-in table indexing classes.
 *
 * @author chris.studholme@utoronto.ca
 */
abstract class IndexTable implements DatabaseIndex {

  /**
   * Attempt to open index on the specified column of an open table.
   *
   * @param table open table
   * @param columnname name of indexed column
   * @return index on column, or null if index not available
   * @throws DatabaseException if there is a problem with the index
   */
  static IndexTable openIndex(DatabaseTable table, String columnname) 
    throws DatabaseException {
    String filename = getIndexFilename(table.getTableName(),columnname);
    if (filename==null) return null;
    if (DriverConfig.debugLevel>0)
      System.err.println("ModSQL.IndexTable: opening index '"+filename+"'");
    IndexTable index=null;
    Exception e_sort=null;
    Exception e_hash=null;
    try {
      return new IndexTable_Sort(table,filename);
    }
    catch (Exception e) {
      e_sort=e;
    }
    try {
      return new IndexTable_Hash(table,filename);
    }
    catch (Exception e) {
      e_hash=e;
    }
    if (DriverConfig.debugLevel>0) {
      System.err.println("ModSQL.IndexTable: index unavailable");
      System.err.println("  "+e_sort.toString());
      System.err.println("  "+e_hash.toString());
    }
    return null;
  }

  /**
   * Check if the specified index file is available.
   *
   * @param filename full path to index file
   * @return true if the file is there and readable
   */
  public static boolean isIndexAvailable(String filename) {
    if (filename==null)
      return false;
    return new File(filename).canRead();
  }

  /**
   * <p>Return an appropriate filename for an index of the specified
   * column of the specified table.  This method will generate a 
   * single character hash code ([A-P]) for the index and return
   * a filename like:<br>
   *   <i>/data/index/C/table.column</i>
   *
   * <p>Note:<ul>
   *   <li><i>/data/index</i> is the base index directory</li>
   *   <li><i>C</i> is the computed hash code</li>
   *   <li><i>table</i> is the name of the table</li>
   *   <li><i>column</i> is the name of the column</li></ul>
   *
   * <p>This method will ensure that the directory where the index
   * data will be stored exists.
   *
   * @param tablename name of table to index
   * @param columnname name of column to index
   * @return full qualified path name where index data should be stored
   */
  protected static String getIndexFilename(String tablename, 
					   String columnname) {
    String indexpath = DriverConfig.getIndexPath();
    if (indexpath==null)
      return null;
	
    // name of index file
    String indexname = 
      tablename.toLowerCase()+"."+columnname.toLowerCase();
	
    // create has of index filename
    int hash = indexname.hashCode();
    hash = hash ^ (hash>>4) ^ (hash>>8);
	
    // full path to index file (including hashed subdir)
    String fullpath = indexpath + File.separatorChar +
      (char)((hash&0x0F)+0x41);
	
    // attempt to make sure that fullpath exists
    new File(fullpath).mkdir();
	
    // full path to index file
    return new File(fullpath,indexname).getPath();
  }

};
