/*
 * $Id: VKCServerInfo.java,v 1.11 2007/08/16 11:10:54 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: VKCServerInfo.java,v $
 * Revision 1.11  2007/08/16 11:10:54  marbobo
 * + Bugfixes
 * + Refactorings
 *
 * Revision 1.10  2006/07/07 10:59:40  lawern
 * Postgres-Bugfix
 *
 */
package vkc.db.common;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

import vkc.converter.common.Status;
import vkc.db.PersistenceManager;
import vkc.db.helper.DBHelper;
import vkc.exception.DBException;
import vkc.misc.VKCLogManager;

/**
 * This class represents a bean for the information of a VKC Server
 * (communicating with a converter server.
 * 
 * @created 07.01.2004
 * @author Andreas Koop
 */
public class VKCServerInfo extends ServerInfo {
    private int jobsRequestedCount = 0;

    /**
     * Construtcs a new VKCServerInfo object corresponding to
     * <code>VKCSERVER</code> table.
     */
    public VKCServerInfo() {
        super("VKCSERVER");
    }

    /**
     * (non-Javadoc)
     * 
     * @see vkc.db.common.PersistentObject#initialize(java.lang.Integer,
     *      java.sql.Connection)
     */
    public void initialize(Integer id, Connection conn) throws DBException {
        PreparedStatement pStmt = null;
        ResultSet rs = null;

        try {
            pStmt = conn.prepareStatement("SELECT * FROM " + getTable() + " WHERE ID = ?");
            pStmt.setInt(1, id.intValue());
            rs = pStmt.executeQuery();

            if (rs.next()) {
                setId(id);
                setHostname(rs.getString("HOSTNAME"));
                setPort(rs.getInt("PORT"));
                setStatus(rs.getString("STATUS"));
                setLoadFactor(rs.getInt("LOADFACTOR"));
                jobsRequestedCount = rs.getInt("JOBS_REQUESTED");
            } else {
                throw new DBException("VKCSERVER for id = " + id + " not found!");
            }
        } catch (Exception e) {
            throw new DBException(e);
        } finally {
            DBHelper.close(rs);
            DBHelper.close(pStmt);
        }
    }

    /**
     * Makes the jobs counter of this server info persistent
     * 
     * @throws DBException
     */
    public void makeJobsCountPersistent() throws DBException {
        super.makePersistent(getTable(), "JOBS_REQUESTED", new Integer(jobsRequestedCount), getIdColumn(), getId());
    }

    /**
     * Makes the jobs counter of this server info persistent
     * 
     * @param conn
     *            using this connection
     * @throws DBException
     */
    public void makeJobsCountPersistent(Connection conn) throws DBException {
        super.makePersistent(conn, getTable(), "JOBS_REQUESTED", new Integer(jobsRequestedCount), getIdColumn(), getId());
    }

    /**
     * Registers the converter in the DB The ID and other specific information
     * is taken from the properties
     * 
     * @param props
     * @throws DBException
     */
    public static final void register(Properties props) throws DBException {
        PersistenceManager pm = PersistenceManager.getInstance();
        Connection conn = pm.getConnection();
        PreparedStatement pStmt = null;

        try {
            int serverId = Integer.parseInt(props.getProperty("vkc.server.id"));

            if (DBHelper.existsEntry(conn, "VKCSERVER", "ID", new Integer(serverId))) {
                pStmt = conn.prepareStatement("UPDATE VKCSERVER SET HOSTNAME = ?, PORT = ?, STATUS = ?, LOADFACTOR = ? WHERE ID = ?");
            } else {
                pStmt = conn.prepareStatement("INSERT INTO VKCSERVER ( HOSTNAME, PORT, STATUS, LOADFACTOR, ID ) VALUES ( ?, ?, ?, ?, ? )");
            }

            pStmt.setString(1, props.getProperty("vkc.server.hostname"));
            pStmt.setInt(2, Integer.parseInt(props.getProperty("vkc.server.port")));
            pStmt.setString(3, Status.SERVER_DOWN);
            pStmt.setInt(4, Integer.parseInt(props.getProperty("vkc.server.loadfactor", "1")));
            pStmt.setInt(5, serverId);
            pStmt.execute();
            conn.commit();
        } catch (Exception e) {
            VKCLogManager.errorLog(ConverterInfo.class, "", e.getMessage(), e);
            DBHelper.rollBack(conn);
            throw new DBException(e);
        } finally {
            DBHelper.close(pStmt);
            DBHelper.close(conn);
        }
    }

    /**
     * Returns server information to the most under-worked VKC-Server
     * 
     * @return VKCServerInfo to the most under-worked VKCServer
     * @throws DBException
     */
    public static final VKCServerInfo getMostUnderWorkedServer(String dbUrl) throws DBException {
        PersistenceManager pm = PersistenceManager.getInstance();
        Connection conn = pm.getConnection(dbUrl);
        PreparedStatement pStmt = null;
        ResultSet rs = null;

        try {
            pStmt = conn.prepareStatement("SELECT * FROM VKCSERVER WHERE STATUS = ? ORDER BY JOBS_REQUESTED ASC, LOADFACTOR DESC");
            pStmt.setString(1, Status.SERVER_UP);
            rs = pStmt.executeQuery();

            if (rs.next()) {
                VKCServerInfo s = new VKCServerInfo();
                s.associateWithDbUrl(dbUrl);
                s.setId(new Integer(rs.getInt("ID")));
                s.setHostname(rs.getString("HOSTNAME"));
                s.setLoadFactor(rs.getInt("LOADFACTOR"));
                s.setPort(rs.getInt("PORT"));
                s.setStatus(rs.getString("STATUS"));
                s.jobsRequestedCount = rs.getInt("JOBS_REQUESTED");

                return s;
            }

            return null;
        } catch (Exception e) {
            VKCLogManager.errorLog(ConversionStatus.class, "", e.getMessage(), e);
            throw new DBException(e);
        } finally {
            DBHelper.close(rs);
            DBHelper.close(pStmt);
            DBHelper.close(conn);
        }
    }

    /**
     * Returns the name of this server info
     * 
     * @return name of this server info
     */
    public String getName() {
        return "VKC Server";
    }

    public int getJobsRequestedCount() {
        return jobsRequestedCount;
    }

    /**
     * (non-Javadoc)
     * 
     * @see vkc.db.common.ServerInfo#incJobsCount(int)
     */
    public void incJobsCount(int amount) {
        jobsRequestedCount += amount;
    }

    /**
     * (non-Javadoc)
     * 
     * @see vkc.db.common.ServerInfo#getJobsCount()
     */
    public int getJobsCount() {
        return getJobsRequestedCount();
    }

    public void setJobsRequestedCount(int i) {
        jobsRequestedCount = i;
    }
}