/*
 * $Source: /opt/cvsroot/erserver/src/com/postgres/replic/server/props/ConnectionPoolProps.java,v $
 * $Author: ronz $ $Revision: 1.3 $ $Date: 2003/12/15 01:07:50 $
 *
 */

package com.postgres.replic.server.props;

import com.postgres.util.config.ConfiguratorIntf;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Properties;

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;*/

	public static final String JDBC_DRIVER = "JDBCDriver";
    public static final String JDBC_USER = "user";
    public static final String JDBC_PASS = "password";
    public static final String JDBC_URL = "JDBCConnectionURL";
    public static final String SIZE = "ConnectionPoolSize";
    public static final String SIZE_MAX = "ConnectionPoolMax";
    public static final String CONN_TIMEOUT = "ConnectionTimeout";
    public static final String CONN_USE_COUNT = "ConnectionUseCount";
	// 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, driver.get(i));
				slaveProps[i].put(JDBC_USER, user.get(i));
				slaveProps[i].put(JDBC_PASS, pass.get(i));
				slaveProps[i].put(JDBC_URL, url.get(i));
				slaveProps[i].put(SIZE, size.get(i));
				slaveProps[i].put(SIZE_MAX, sizeMax.get(i));
				slaveProps[i].put(CONN_TIMEOUT, timeOut.get(i));
				slaveProps[i].put(CONN_USE_COUNT, useCount.get(i));

				// To be able to get server (slave) number by url:
				url2serverMap.put(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]);
		}
	}
}
