/*
 * $Id: ServerInfo.java,v 1.7 2007/08/16 11:10:55 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: ServerInfo.java,v $
 * Revision 1.7  2007/08/16 11:10:55  marbobo
 * + Bugfixes
 * + Refactorings
 *
 * Revision 1.6  2005/04/01 14:31:20  lawern
 * openSocket mit Timeout versehen
 *
 */
package vkc.db.common;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.sql.Connection;
import java.util.Iterator;

import vkc.converter.common.Status;
import vkc.exception.DBException;

/**
 * This class represents some information about a server
 * 
 * @created 07.01.2004
 * @author Andreas Koop
 */
public abstract class ServerInfo extends PersistentObject {
    private int loadFactor = 1;

    private int maxJobsCount = 1;

    private int port = -1;

    private String hostname;

    private String status = Status.SERVER_DOWN;

    private StringBuffer buffer = new StringBuffer(64);

    /**
     * Transmitts the name of table to the PersistenObject's constructor
     */
    public ServerInfo(String table) {
        super(table, "ID");
    }

    public String getHostname() {
        return hostname;
    }

    public int getLoadFactor() {
        return loadFactor;
    }

    public int getPort() {
        return port;
    }

    /**
     * Überprüft, ob die Verbindung zum Server steht und aktualisiert
     * gegebenfalls den Status.
     * 
     * @throws DBException
     */
    public void checkAndUpdateStatus() throws DBException {
        try {
            Socket s = openSocket(5000); // maximal 5 sec warten
            s.close();

            if (status.equals(Status.SERVER_UP)) {
                return;
            }

            // update status flag in DB
            status = Status.SERVER_UP;
            makeStatusPersistent();

            return;
        } catch (UnknownHostException e) {
        } catch (IOException e) {
        }

        // Connection failed, set status to false
        if (status.equals(Status.SERVER_DOWN)) {
            return;
        }

        status = Status.SERVER_DOWN;
        makeStatusPersistent();
    }

    public String getStatus() {
        return status;
    }

    public void setHostname(String string) {
        hostname = string;
    }

    public void setLoadFactor(int i) {
        loadFactor = i;
    }

    public void setPort(int i) {
        port = i;
    }

    public void setStatus(String string) {
        status = string;
    }

    /**
     * Opens a socket on the information this object contains
     * 
     * @param timeout
     *            timeout in milliseconds
     * @return a simple socket
     * @throws UnknownHostException
     * @throws IOException
     */
    public Socket openSocket(int timeout) throws UnknownHostException, IOException {
        Socket s = new Socket();
        s.connect(new InetSocketAddress(getHostname(), getPort()), timeout);
        
        return s;
    }

    /**
     * Makes the jobs count of this server info persistent
     * 
     * @throws DBException
     */
    public abstract void makeJobsCountPersistent() throws DBException;

    /**
     * Makes the status of this server info persistent
     * 
     * @throws DBException
     */
    public void makeStatusPersistent() throws DBException {
        for (Iterator it = pm.getDbUrls().iterator(); it.hasNext();) {
            associateWithDbUrl((String) it.next());
            super.makePersistent(getTable(), "STATUS", getStatus(), getIdColumn(), getId());
        }
    }

    /**
     * Makes the status of this server info persistent
     * 
     * @param conn
     *            using this connection
     * @throws DBException
     */
    public void makeStatusPersistent(Connection conn) throws DBException {
        super.makePersistent(conn, getTable(), "STATUS", getStatus(), getIdColumn(), getId());
    }

    /**
     * Returns the name of this server info
     * 
     * @return name of this server info
     */
    public abstract String getName();

    /**
     * Increases the jobs count
     * 
     * @param by
     *            this amount, can be negativ
     */
    public abstract void incJobsCount(int amount);

    /**
     * Should return the job count
     * 
     * @return numer of currently serving jobs
     */
    public abstract int getJobsCount();

    /**
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    public String toString() {
        buffer.delete(0, buffer.length());

        buffer.append(getId());
        buffer.append(" - ");
        buffer.append(getHostname());
        buffer.append(":");
        buffer.append(getPort());

        return buffer.toString();
    }

    /**
     * Returns the maximum numer of jobs a server with this configuration should
     * serve at the same time.
     * 
     * @return maximum number ob jobs
     */
    public int getMaxJobsCount() {
        return maxJobsCount;
    }

    /**
     * Checks whether the maximum jobs count is exeeded or not
     * 
     * @return true, if the max job count is exeeded
     */
    public boolean maxJobsCountExeeded() {
        return getJobsCount() > getMaxJobsCount();
    }
}