/*

   Derby - Class org.apache.derbyTesting.junit.IndexStatsUtil

   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.

 */

package org.apache.derbyTesting.junit;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import junit.framework.Assert;

/**
 * Helper class for obtaining index statistics and doing asserts on them.
 * <p>
 * This implementation assumes all tables/indexes belong to the current schema.
 * <p>
 * The <em>timeout</em> value is used to make the utility more resilient to
 * differences in timing due to varying scheduling decisions, processor speeds,
 * etc. If the system table contains the wrong number of statistics objects for
 * the query, it will be queried repeatedly until the right number of statistics
 * objects is obtained or the query times out.
 */
public class IndexStatsUtil {

    private static final boolean INDEX = false;
    private static final boolean TABLE = true;
    private static final int NO_EXPECTATION = -1;
    private static final String SEP =
                BaseJDBCTestCase.getSystemProperty("line.separator");

    private final Connection con;
    /** Timeout in milliseconds. */
    private final long timeout;
    private PreparedStatement psGetTableId;
    private PreparedStatement psGetStatsForTable;
    private PreparedStatement psGetIndexId;
    private PreparedStatement psGetStatsForIndex;
    private PreparedStatement psGetStats;
    private PreparedStatement psGetIdToNameMapConglom;
    private PreparedStatement psGetIdToNameMapTable;

    /**
     * Creates an instance querying the given database with no timeout set.
     * <p>
     * Querying with no timeout means that if there are too few or too many
     * statistics objects matching the query, a failure will be raised
     * immediately.
     *
     * @param con connection to the database to query
     */
    public IndexStatsUtil(Connection con) {
        this(con, 0L);
    }

    /**
     * Creates an instance querying the given database with the specified
     * timeout value.
     *
     * @param con connection to the database to query
     * @param timeout the longest time to wait to see if the expectations for a
     *      query are met (milliseconds)
     */
    public IndexStatsUtil(Connection con, long timeout) {
        // Rely on auto-commit to release locks.
        try {
            Assert.assertTrue(con.getAutoCommit());
        } catch (SQLException sqle) {
            Assert.fail("Failed to get auto commit: " + sqle.getMessage());
        }
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout cannot be negative");
        }
        this.con = con;
        this.timeout = timeout;
    }

    /**
     * Asserts that there are no existing statistics in the database.
     *
     * @throws SQLException if obtaining the statistics fails
     */
    public void assertNoStats()
            throws SQLException {
        assertStats(0);
    }

    /**
     * Asserts that there are no existing statistics for the specified table.
     *
     * @throws SQLException if obtaining the statistics fails
     */
    public void assertNoStatsTable(String table)
            throws SQLException {
        assertTableStats(table, 0);
    }

    /**
     * Asserts that the expected number of statistics exists.
     *
     * @param expectedCount expected number of statistics
     * @throws SQLException if obtaining the statistics fails
     */
    public void assertStats(int expectedCount)
            throws SQLException {
        IdxStats[] ret = getStats();
        if (ret.length != expectedCount) {
            Assert.assertEquals(buildStatString(ret, "<ALL TABLES>"),
                    expectedCount, ret.length);
        }
    }

    /**
     * Asserts that the expected number of statistics exists for the specified
     * table.
     *
     * @param table the target table
     * @param expectedCount expected number of statistics
     * @throws SQLException if obtaining the statistics fails
     */
    public void assertTableStats(String table, int expectedCount)
            throws SQLException {
        getStatsTable(table, expectedCount);
    }

    /**
     * Asserts that the expected number of statistics exists for the specified
     * index.
     *
     * @param index the target index
     * @param expectedCount expected number of statistics
     * @throws SQLException if obtaining the statistics fails
     */
    public void assertIndexStats(String index, int expectedCount)
            throws SQLException {
        getStatsIndex(index, expectedCount);
    }

    /**
     * Builds a human readable representation of a list of statistics objects.
     *
     * @param stats a list of statistics (possibly empty)
     * @param name the name of the table(s)/index(es) associated with the stats
     * @return A string representation of the statistics.
     */
    public static String buildStatString(IdxStats[] stats, String name) {
        StringBuffer sb = new StringBuffer(
                "Index statistics for " + name + SEP);
        for (int i=0; i < stats.length; i++) {
            sb.append(i+1).append(": ").append(stats[i].toString()).
                    append(SEP);
        }
        if (stats.length == 0) {
            sb.append(" : <no stats>").append(SEP);
        }
        return sb.toString();
    }

    /**
     * Obtains all existing statistics entries.
     *
     * @return A list of statistics entries (possibly empty).
     * @throws SQLException if obtaining the statistics fail
     */
    public IdxStats[] getStats()
            throws SQLException {
        if (psGetStats == null) {
            psGetStats = con.prepareStatement(
                    "select * from SYS.SYSSTATISTICS " +
                    "order by TABLEID, REFERENCEID, COLCOUNT");
        }
        return buildStatisticsList(psGetStats.executeQuery(), getIdToNameMap());
    }

    /**
     * Obtains statistics for the specified table.
     *
     * @param table table name
     * @return A list of statistics entries (possibly empty).
     * @throws SQLException if obtaining the statistics fail
     */
    public IdxStats[] getStatsTable(String table)
            throws SQLException {
        return getStatsTable(table, NO_EXPECTATION);
    }

    /**
     * Obtains statistics for the specified table, fails if the number of
     * statistics objects isn't as expected within the timeout.
     *
     * @param table table name
     * @param expectedCount number of expected statistics objects
     * @return A list of statistics entries (possibly empty).
     * @throws SQLException if obtaining the statistics fail
     */
    public IdxStats[] getStatsTable(String table, int expectedCount)
            throws SQLException {
        if (psGetTableId == null) {
            psGetTableId = con.prepareStatement(
                "select TABLEID from SYS.SYSTABLES where TABLENAME = ?");
        }
        psGetTableId.setString(1, table);
        ResultSet rs = psGetTableId.executeQuery();
        Assert.assertTrue("No such table: " + table, rs.next());
        String tableId = rs.getString(1);
        Assert.assertFalse("More than one table named " + table, rs.next());
        rs.close();

        IdxStats[] ret = querySystemTable(tableId, TABLE, expectedCount);
        // Avoid building the stat string if not necessary.
        if (expectedCount != NO_EXPECTATION && ret.length != expectedCount) {
            Assert.assertEquals("failed to get statistics for table " + table +
                    " (#expected=" + expectedCount + ", timeout=" + timeout +
                    ")" + SEP + buildStatString(ret, table),
                    expectedCount, ret.length);
        }
        return ret;
    }

    /**
     * Waits for the current statistics to disappear and expects to fetch the
     * same number of new statistics for the table.
     *
     * @param table the table to get statistics for
     * @param currentStats the current statistics
     * @return The new statistics.
     * @throws SQLException if obtaining statistics fails
     */
    public IdxStats[] getNewStatsTable(String table, IdxStats[] currentStats)
            throws SQLException {
        if (timeout == 0) {
            throw new IllegalStateException(
                    "no timeout specified in the constructor");
        }
        awaitChange(currentStats, timeout);
        return getStatsTable(table, currentStats.length);
    }

    /**
     * Obtains statistics for the specified index.
     *
     * @param index index name
     * @return A list of statistics entries (possibly empty).
     * @throws SQLException if obtaining the statistics fail
     */
    public IdxStats[] getStatsIndex(String index)
             throws SQLException {
        return getStatsIndex(index, NO_EXPECTATION);
    }

    /**
     * Obtains statistics for the specified index, fails if the number of
     * statistics objects isn't as expected within the timeout.
     *
     * @param index index name
     * @param expectedCount number of expected statistics objects
     * @return A list of statistics entries (possibly empty).
     * @throws SQLException if obtaining the statistics fail
     */
    public IdxStats[] getStatsIndex(String index, int expectedCount)
             throws SQLException {
        if (psGetIndexId == null) {
            psGetIndexId = con.prepareStatement(
                    "select CONGLOMERATEID from SYS.SYSCONGLOMERATES where " +
                    "CONGLOMERATENAME = ? and " +
                    "CAST(ISINDEX as VARCHAR(5)) = 'true'");
        }
        psGetIndexId.setString(1, index);
        ResultSet rs = psGetIndexId.executeQuery();
        Assert.assertTrue("No such index: " + index, rs.next());
        String indexId = rs.getString(1);
        Assert.assertFalse("More than one index named " + index, rs.next());
        rs.close();

        IdxStats[] ret = querySystemTable(indexId, INDEX, expectedCount);
        // Avoid building the stat string if not necessary.
        if (expectedCount != NO_EXPECTATION && ret.length != expectedCount) {
            Assert.assertEquals("failed to get statistics for index " + index +
                    " (#expected=" + expectedCount + ", timeout=" + timeout +
                    ")" + SEP + buildStatString(ret, index),
                    expectedCount, ret.length);
        }
        return ret;
    }

    /**
     * Queries the system table {@code SYS.SYSSTATISTICS} for statistics
     * associated with a specific table or index.
     *
     * @param conglomId conglomerate id (UUID)
     * @param isTable tells if the conglomerate is a table or an index
     * @param expectedCount the number of statistics objects expected, use
     *      {@code NO_EXPECTATION} to return whatever matches the query
     *      immediately
     */
    private IdxStats[] querySystemTable(String conglomId, boolean isTable,
                                        int expectedCount)
            throws SQLException {
        // Assign the correct prepared statement.
        PreparedStatement ps;
        if (isTable) {
            if (psGetStatsForTable == null) {
                psGetStatsForTable = con.prepareStatement(
                        "select * from SYS.SYSSTATISTICS " +
                            "where TABLEID = ? " +
                            "order by REFERENCEID, COLCOUNT");
            }
            ps = psGetStatsForTable;
        } else {
            if (psGetStatsForIndex == null) {
                psGetStatsForIndex = con.prepareStatement(
                        "select * from SYS.SYSSTATISTICS " +
                            "where REFERENCEID = ? " +
                            "order by COLCOUNT");
            }
            ps = psGetStatsForIndex;
        }
        ps.setString(1, conglomId);

        long started = System.currentTimeMillis();
        long waited = -1;
        IdxStats[] ret = null;
        while (waited < timeout) {
            // Don't wait the first time.
            if (ret != null) {
                Utilities.sleep(Math.min(250L, timeout - waited));
            }
            ret = buildStatisticsList(ps.executeQuery(), getIdToNameMap());
            if (expectedCount == NO_EXPECTATION || ret.length == expectedCount){
                break;
            }
            waited = System.currentTimeMillis() - started;
        }
        return ret;
    }

    /**
     * Prints all entries in the {@code SYS.SYSSTATISTICS} system table.
     *
     * @throws SQLException if obtaining the statistics fails
     */
    public void printStats()
            throws SQLException {
        System.out.println(buildStatString(getStats(), "all tables"));
    }

    /**
     * Generates a map from ids to names for conglomerates in the database.
     * <p>
     * Convenience method, used for better reporting.
     *
     * @return Mappings from conglomerate id to conglomerate name.
     * @throws SQLException if accessing the system tables fail
     */
    private Map<String, String> getIdToNameMap()
            throws SQLException {
        if (psGetIdToNameMapConglom == null) {
            psGetIdToNameMapConglom = con.prepareStatement(
                    "select CONGLOMERATEID, CONGLOMERATENAME " +
                    "from SYS.SYSCONGLOMERATES");
        }
        if (psGetIdToNameMapTable == null) {
            psGetIdToNameMapTable = con.prepareStatement(
                    "select TABLEID, TABLENAME from SYS.SYSTABLES");
        }
        Map<String, String> map = new HashMap<String, String>();
        ResultSet rs = psGetIdToNameMapConglom.executeQuery();
        while (rs.next()) {
            map.put(rs.getString(1), rs.getString(2));
        }
        rs.close();
        rs = psGetIdToNameMapTable.executeQuery();
        while (rs.next()) {
            map.put(rs.getString(1), rs.getString(2));
        }
        rs.close();
        return map;
    }

    /**
     * Builds an array of statistics objects from data from the
     * {@code SYS.SYSSTATISTICS} system table.
     *
     * @param rs a result set containing rows from {@code SYS.SYSSTATISTICS}
     * @return A list of statistics objects
     * @throws SQLException if accessing the result set fails
     */
    private IdxStats[] buildStatisticsList(
            ResultSet rs, Map<String, String> idToName)
            throws SQLException {
        List<IdxStats> stats = new ArrayList<IdxStats>();
        while (rs.next()) {
            // NOTE: Bad practice to call rs.getString(X) twice, but it works
            //       for Derby with the string type...
            stats.add(new IdxStats(rs.getString(1), rs.getString(2),
                    idToName.get(rs.getString(2)),
                    rs.getString(3),
                    idToName.get(rs.getString(3)),
                    rs.getTimestamp(4), rs.getInt(7),
                    rs.getString(8)));
        }
        rs.close();
        return stats.toArray(new IdxStats[stats.size()]);
    }

    /**
     * Releases resources and closes the associated connection.
     */
    public void release() {
        release(true);
    }

    /**
     * Releases resources.
     *
     * @param closeConnection whether to close the associated connection
     */
    public void release(boolean closeConnection) {
        PreparedStatement[] psToClose = new PreparedStatement[] {
            psGetStats, psGetIndexId, psGetStatsForIndex,
            psGetStatsForTable, psGetTableId,
            psGetIdToNameMapConglom, psGetIdToNameMapTable
        };
        for (int i=0; i < psToClose.length; i++) {
            try {
                if (psToClose[i] != null) {
                    psToClose[i].close();
                }
            } catch (SQLException sqle) {
                // Ignore
            }
        }
        try {
            if (!con.isClosed()) {
                con.rollback();
            }
            if (closeConnection) {
                con.close();
            }
        } catch (SQLException sqle) {
            // Ignore
        }
    }

    /**
     * Waits until all given statistics entries have been changed, or until
     * the call times out.
     * <p>
     * <em>NOTE</em>: The method is built on the assumption that the UUIDs of
     * statistics objects aren't reused. That is, when statistics are updated,
     * the old row in SYS.SYSSTATISTICS will be dropped and a new row will be
     * inserted.
     *
     * @param current the statistics that must change / be replaced
     * @param timeout maximum number of milliseconds to wait before giving up
     * @throws SQLException if obtaining statistics fails
     */
    private void awaitChange(IdxStats[] current, long timeout)
            throws SQLException {
        Set<IdxStats> oldStats = new HashSet<IdxStats>(Arrays.asList(current));
        Set<IdxStats> newStats = null;
        long start = System.currentTimeMillis();
        // Make sure we run at least once.
        while (System.currentTimeMillis() - start < timeout ||
                newStats == null) {
            newStats = new HashSet<IdxStats>(Arrays.asList(getStats()));
            newStats.retainAll(oldStats);
            if (newStats.isEmpty()) {
                return;
            }
            Utilities.sleep(200);
        }
        IdxStats[] outstanding = new IdxStats[newStats.size()];
        newStats.toArray(outstanding);
        Assert.fail(outstanding.length + " missing statistics changes " +
                "(timeout=" + timeout + "ms): " +
                buildStatString(outstanding, "<unchanged statistics>"));
    }

    /**
     * Immutable class representing index statistics.
     */
    public static final class IdxStats {
        private static final String NA = "<n/a>";
        /** Number of rows in the table / index. */
        public final long rows;
        /** Cardinality of the index. */
        public final long card;
        /** Number of leading columns (in the index) for this stats object. */
        public final int lcols;
        public final String id;
        public final String tableId;
        public final String tableName;
        public final String indexId;
        public final String indexName;
        public final Timestamp created;

        /**
         * Creates a new statistics object with names for the table and the
         * index specified for convenience.
         *
         * @param id statistics identifier
         * @param indexId index identifier
         * @param indexName index name (may be {@code null})
         * @param tableId table identifier
         * @param tableName table name (may be {@code null})
         * @param created creation timestamp
         * @param lcols number of leading columns
         * @param stats the statistics, as reported when doing {@code getString}
         *      on the column {@code STATISTICS} in {@code SYS.SYSSTATISTICS}
         *      (number of unique rows and total rows, for instance
         *      "numunique= 3 numrows= 3")
         */
        public IdxStats(String id, String indexId, String indexName,
                        String tableId, String tableName,
                        Timestamp created, int lcols, String stats) {
            this.id = id;
            this.indexId = indexId;
            this.indexName = indexName != null ? indexName : NA;
            this.tableId = tableId;
            this.tableName = tableName != null ? tableName : NA;
            this.created = created;
            this.lcols = lcols;
            // "numunique= 3 numrows= 3"
            int uniqPos = stats.indexOf('=');
            int space = stats.indexOf(' ', uniqPos+2);
            int rowsPos = stats.indexOf('=', space);
            this.card =
                    Integer.parseInt(stats.substring(uniqPos+1, space).trim());
            this.rows =
                    Integer.parseInt(stats.substring(rowsPos+1).trim());
        }

        public boolean after(IdxStats other) {
            return created.after(other.created);
        }

        public boolean before(IdxStats other) {
            return created.before(other.created);
        }

        public String toString() {
            // Note that not all available information is printed.
            // Add more if required for debugging.
            StringBuffer sb = new StringBuffer(200);
            sb.append("{tableId=").append(tableId).
                    append(", tableName=").append(tableName).
                    append(", indexName=").append(indexName).
                    append(", lcols=").append(lcols).
                    append(", rows=").append(rows).
                    append(", unique/card=").append(card).
                    append(", created=").append(created).append('}');
            return sb.toString();
        }

        /**
         * Equality is based on the statistics entry UUID.
         *
         * @param obj other object
         * @return {@code true} if the other object is considered equal to this
         */
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final IdxStats other = (IdxStats) obj;
            return this.id.equals(other.id);
        }

        public int hashCode() {
            int hash = 7;
            hash = 17 * hash + this.id.hashCode();
            return hash;
        }
    }
}
