/*
 * $Source: /usr/local/cvsroot/erserver/erserver/java/src/com/postgres/replic/server/props/ConnectionPoolProps.java,v $
 * $Author: asullivan $ $Revision: 1.1.1.1 $ $Date: 2003/08/26 19:02:23 $
 *
 */

package com.postgres.replic.server.props;

import com.postgres.util.config.*;
import com.postgres.util.jdbc.*;
import java.util.*;

public class ConnectionPoolProps extends AbstractProperties {

    // Namespace prefixes to get proper ones from the config file:
    public static final String NS_MASTER = "replic.master.";
    public static final String NS_SLAVE = "replic.slave.";

    // Property names:
    public static final String JDBC_DRIVER = ConnectionPool.JDBC_DRIVER;
    public static final String JDBC_USER = ConnectionPool.JDBC_USER;
    public static final String JDBC_PASS = ConnectionPool.JDBC_PASS;
    public static final String JDBC_URL = ConnectionPool.JDBC_URL;
    public static final String SIZE = ConnectionPool.SIZE;
    public static final String SIZE_MAX = ConnectionPool.SIZE_MAX;
    public static final String CONN_TIMEOUT = ConnectionPool.CONN_TIMEOUT;
    public static final String CONN_USE_COUNT = ConnectionPool.CONN_USE_COUNT;

    // Some default constants:
    public static final int DEF_SIZE = 1;
    public static final int DEF_SIZE_MAX = 1;
    public static final int DEF_CONN_TIMEOUT = 2; // minutes
    public static final int DEF_CONN_USE_COUNT = 100;

    // Some defalut properties:
    public String defSize =  (new Integer(DEF_SIZE)).toString();
    public String defSizeMax =  (new Integer(DEF_SIZE_MAX)).toString();
    public String defConnTimeout =  (new Integer(DEF_CONN_TIMEOUT)).toString(); // minutes
    public String defConnUseCount =  (new Integer(DEF_CONN_USE_COUNT)).toString();

    private Properties masterProps;
    private Properties [] slaveProps;
    private Hashtable url2serverMap;

    public void setDefSize(int defSizeInt) {
         this.defSize = new Integer(defSizeInt).toString();
    }

    public void setDefSizeMax(int defSizeMaxInt) {
         this.defSizeMax = new Integer(defSizeMaxInt).toString();
    }

    public void setDefConnTimeout(int defConnTimeoutInt) {
         this.defConnTimeout = new Integer(defConnTimeoutInt).toString();
    }

    public void setDefConnUseCount(int defConnUseCountInt) {
         this.defConnUseCount = new Integer(defConnUseCountInt).toString();
    }

    public ConnectionPoolProps(ConfiguratorIntf config) throws Exception{
        super(config);
        getMasterProperties();
        getSlaveProperties();
    }

    public ConnectionPoolProps(ConfiguratorIntf config, boolean debug) throws Exception{
        super(config);
        setDebug(debug);
        getMasterProperties();
        getSlaveProperties();
    }

    public Properties getMasterProperties() throws Exception{
        if (masterProps != null) {
            return  masterProps;
        }

        try {
            masterProps = new Properties();

            if (getDebug()) getConfigurator().printProps(null);
            getLogger().debug("ConnectionPoolProps::getMasterProperties: getConfigurator().getProperty(NS_MASTER + JDBC_DRIVER) = " + getConfigurator().getProperty(NS_MASTER + JDBC_DRIVER));
            masterProps.put(JDBC_DRIVER, getConfigurator().getProperty(NS_MASTER + JDBC_DRIVER));
            getLogger().debug("ConnectionPoolProps::getMasterProperties: getConfigurator().getProperty(NS_MASTER + JDBC_USER) = " + getConfigurator().getProperty(NS_MASTER + JDBC_USER));
            masterProps.put(JDBC_USER, getConfigurator().getProperty(NS_MASTER + JDBC_USER));
            getLogger().debug("ConnectionPoolProps::getMasterProperties: getConfigurator().getProperty(NS_MASTER + JDBC_PASS) = " + getConfigurator().getProperty(NS_MASTER + JDBC_PASS));
            masterProps.put(JDBC_PASS, getConfigurator().getProperty(NS_MASTER + JDBC_PASS));
            getLogger().debug("ConnectionPoolProps::getMasterProperties: getConfigurator().getProperty(NS_MASTER + JDBC_URL) = " + getConfigurator().getProperty(NS_MASTER + JDBC_URL, defSize));
            masterProps.put(JDBC_URL, getConfigurator().getProperty(NS_MASTER + JDBC_URL));
            getLogger().debug("ConnectionPoolProps::getMasterProperties: getConfigurator().getProperty(NS_MASTER + SIZE) = " + getConfigurator().getProperty(NS_MASTER + SIZE, defSize));
            masterProps.put(SIZE, getConfigurator().getProperty(NS_MASTER + SIZE));
            getLogger().debug("ConnectionPoolProps::getMasterProperties: getConfigurator().getProperty(NS_MASTER + SIZE_MAX) = " + getConfigurator().getProperty(NS_MASTER + SIZE_MAX, defSizeMax));
            masterProps.put(SIZE_MAX, getConfigurator().getProperty(NS_MASTER + SIZE_MAX, defSizeMax));
            getLogger().debug("ConnectionPoolProps::getMasterProperties: getConfigurator().getProperty(NS_MASTER + CONN_TIMEOUT) = " + getConfigurator().getProperty(NS_MASTER + CONN_TIMEOUT, defConnTimeout));
            masterProps.put(CONN_TIMEOUT, getConfigurator().getProperty(NS_MASTER + CONN_TIMEOUT, defConnTimeout));
            getLogger().debug("ConnectionPoolProps::getMasterProperties: getConfigurator().getProperty(NS_MASTER + CONN_USE_COUNT) = " + getConfigurator().getProperty(NS_MASTER + CONN_USE_COUNT, defConnUseCount));
            masterProps.put(CONN_USE_COUNT, getConfigurator().getProperty(NS_MASTER + CONN_USE_COUNT, defConnUseCount));

        } catch (Exception e) {
            throw new Exception("ConnectionPoolProps::getMasterProperties: " + e.toString());
        } finally {
        
        }
        return  masterProps;
    }

    public Properties [] getSlaveProperties() throws Exception{
        if (slaveProps != null) {
            return  slaveProps;
        }
        int [] sizes = new int[8];

        try {
            getLogger().debug("ConnectionPoolProps::getSlaveProperties: BEFORE setting ArrayLists");
            ArrayList driver = getConfigurator().getListProperty(NS_SLAVE + JDBC_DRIVER);
            sizes[0] = driver.size();
            ArrayList user =  getConfigurator().getListProperty(NS_SLAVE + JDBC_USER);
            sizes[1] = user.size();
            ArrayList pass =  getConfigurator().getListProperty(NS_SLAVE + JDBC_PASS);
            sizes[2] = pass.size();
            ArrayList url  =   getConfigurator().getListProperty(NS_SLAVE + JDBC_URL);
            sizes[3] = url.size();
            ArrayList size =  getConfigurator().getListProperty(NS_SLAVE + SIZE);
            sizes[4] = size.size();
            ArrayList sizeMax = getConfigurator().getListProperty(NS_SLAVE + SIZE_MAX);
            sizes[5] = sizeMax.size();
            ArrayList timeOut =  getConfigurator().getListProperty(NS_SLAVE + CONN_TIMEOUT);
            sizes[6] = timeOut.size();
            ArrayList useCount = getConfigurator().getListProperty(NS_SLAVE + CONN_USE_COUNT);
            sizes[7] = useCount.size();

            getLogger().debug("ConnectionPoolProps::getSlaveProperties: AFTER setting ArrayLists");

            int first = sizes[0];
            for (int i=1; i<sizes.length; i++) {
                getLogger().debug("ConnectionPoolProps::getSlaveProperties: cycling i="+i);
            	if (first != sizes[i]) {
                    throw new Exception("ConnectionPoolProps::getSlaveProperties: size of "
                      + i + "-th property list != to that of the 1st");
                }
            }

            getLogger().debug("ConnectionPoolProps::getSlaveProperties: BEFORe adding slave Properties first="+first);
            slaveProps = new Properties [first];
            url2serverMap = new Hashtable();
            for (int i=0; i<first; i++) {
                getLogger().debug("ConnectionPoolProps::getSlaveProperties: adding slave Properties  i="+i);
            	slaveProps[i] = new Properties();
                slaveProps[i].put(JDBC_DRIVER, (String) driver.get(i));
                slaveProps[i].put(JDBC_USER, (String) user.get(i));
                slaveProps[i].put(JDBC_PASS, (String) pass.get(i));
                slaveProps[i].put(JDBC_URL, (String) url.get(i));
                slaveProps[i].put(SIZE, (String) size.get(i));
                slaveProps[i].put(SIZE_MAX, (String) sizeMax.get(i));
                slaveProps[i].put(CONN_TIMEOUT, (String) timeOut.get(i));
                slaveProps[i].put(CONN_USE_COUNT, (String) useCount.get(i));

                // To be able to get server (slave) number by url:
                url2serverMap.put((String) url.get(i), new Integer(i));
            }

        } catch (Exception e) {
            throw new Exception("ConnectionPoolProps::getSlaveProperties: " + e.toString());
        } finally {
        
        }
        return  slaveProps;
    }

    public int getServerId(String url) {
         return ((Integer) url2serverMap.get(url)).intValue();
    }

    private void printProps(String header, Properties props) {
        if (header == null) {
            header = "";
        }
        if (props == null) {
            getLogger().info(header + " : ConnectionPoolProps::printProps: properties are not set!");
            return;
        }

        getLogger().info(header);
        if (props != null) {
            Iterator iterator = props.keySet().iterator();
            while (iterator.hasNext()) {
               String key = (String) iterator.next();
               String value = (String) props.get(key);
               getLogger().info("        key="+key + "; value=" + value);
            }
        }
    }

    public void printMasterProps() {
        printProps("  -- Master Properties --", masterProps);
    }

    public void printSlaveProps() {
        for (int i=0; i<slaveProps.length; i++) {
            printProps("  -- Slave No." + i + " Properties --", slaveProps[i]);
        }
    }
}
