/*
 * $Source: /usr/local/cvsroot/erserver/erserver/java/src/com/postgres/replic/tools/desc/MasterInit.java,v $
 * $Author: asullivan $ $Revision: 1.1.1.1 $ $Date: 2003/08/26 19:02:26 $
 *
 */

package com.postgres.replic.tools.desc;

import com.postgres.replic.tools.*;
import java.sql.*;

public class MasterInit extends GeneratorDescriptor {

    private class FunctionDesc {
         public String nameDB;
         public String nameLib;
         public String returnType;

         public FunctionDesc (String nameDB, String nameLib, String returnType){
             this.nameDB = nameDB;
             this.nameLib = nameLib;
             this.returnType = returnType;
         }
    };

    //
    // Functions
    //
    public final FunctionDesc [] funcName = {
        new FunctionDesc ("_rserv_log_()", "erserver.so", "opaque"),
        new FunctionDesc ("_rserv_sync_(int4)", "erserver.so", "int4"),
        new FunctionDesc ("_rserv_debug_(int4)", "erserver.so", "int4"),
        new FunctionDesc ("_rserv_lock_altid_(int4)", "erserver.so", "int4"),
        new FunctionDesc ("_rserv_unlock_altid_(int4)", "erserver.so", "int4"),
        new FunctionDesc ("_pte_get_snapshot_()", "pte.so", "int4"),
        new FunctionDesc ("_pte_set_snapshot_(text)", "pte.so", "int4"),
    };


    private final String [] createSQL = {
         "create table _RSERV_SERVERS_ " +
                      " (server serial, host text, post int4, dbase text)",
          "create table _RSERV_TABLES_" +
	                  " (tname name, cname name, reloid oid, key int4)",
          "create table _RSERV_LOG_1_" +
	                  " (reloid oid, logid int4, logtime timestamp, deleted int4, key text)",
          "create index _RSERV_LOG_1_INDX_REL_KEY_ on _RSERV_LOG_1_ (reloid, key)",
          "create index _RSERV_LOG_1_INDX_REL_ID_ on _RSERV_LOG_1_ (reloid, logid)",
          "create table _RSERV_LOG_2_" +
	                  " (reloid oid, logid int4, logtime timestamp, deleted int4, key text)",
          "create index _RSERV_LOG_2_INDX_REL_KEY_ on _RSERV_LOG_2_ (reloid, key)",
          "create index _RSERV_LOG_2_INDX_REL_ID_ on _RSERV_LOG_2_ (reloid, logid)",
          "create table _RSERV_SYNC_" +
	                  " (server int4, syncid int4, synctime timestamp" +
	                  ", status int4, minid int4, maxid int4, active text)",
          "create index _RSERV_SYNC_INDX_SRV_ID_ on _RSERV_SYNC_ (server, syncid)",
          "create sequence _rserv_sync_seq_",
          "create sequence _rserv_active_log_id_ MINVALUE 1 MAXVALUE 2",
          "select setval('_rserv_active_log_id_', 1)",
          "create sequence _rserv_old_log_status_ MINVALUE 0 MAXVALUE 2",
          "select setval('_rserv_old_log_status_', 0)",

    };



    private final String [] dropSQL = {
        "drop table _RSERV_SERVERS_",
        "drop table _RSERV_TABLES_",
        "drop table _RSERV_LOG_1_",
        "drop table _RSERV_LOG_2_",
        "drop table _RSERV_SYNC_",
        "drop sequence _rserv_servers__server_seq",
        "drop sequence _rserv_sync_seq_",
        "drop sequence _rserv_active_log_id_",
        "drop sequence _rserv_old_log_status_",
    } ;



    private static final String LIB_DIR = "lib";

    private String postgresDir;


    /*
    */

    public MasterInit(
    Connection conn,
    String postgresDir) throws Exception {
        if (postgresDir == null || postgresDir.trim().equals("")) {
            throw new Exception("MasterInit:: postgresDir may not be empty");
        }
        if (conn == null) {
            throw new Exception ("MasterInit:: conn == null");
        }
        this.postgresDir = postgresDir;
        this.conn = conn;
    }


    /*
    */

    public void masterDrop() throws Exception {
         for (int i=0; i<dropSQL.length; i++) {
         	 executeUpdate(dropSQL[i]);
         }
    }

    /*
    */

    public void masterCreate() throws Exception {
         for (int i=0; i<createSQL.length; i++) {
              executeUpdate(createSQL[i]);
         }
    }

    /*
    */

    public void masterCreateFun() throws Exception {
         for (int i=0; i<funcName.length; i++) {
              String funcPath = postgresDir + "/" + LIB_DIR + "/" + funcName[i].nameLib;
              String sql = "CREATE FUNCTION " + funcName[i].nameDB + " RETURNS "
                  + funcName[i].returnType + " AS '" + funcPath + "' LANGUAGE 'c'";
              executeUpdate(sql);
         }
    }

    /*
    */

    public void  masterDropFun () throws Exception {
         for (int i=0; i<funcName.length; i++) {
              String sql = "DROP FUNCTION " + funcName[i].nameDB;
              executeUpdate(sql);
         }
    }

    /*
    */

    public void masterInit () throws Exception {
         masterDrop();
         masterCreate();
         masterDropFun();
         masterCreateFun();
    }

    private void executeUpdate(String sql){
         Statement stmt = null;
         try {
            stmt = getConnection().createStatement();
            if (debug) System.out.println("MasterInit::executeUpdate sql=" + sql);
             stmt.executeUpdate(sql);
             System.out.println("Successfully executed " + sql);
         } catch (Exception e) {
             System.out.println("MasterInit::executeUpdate: " + e.toString());
         } finally {
            if (stmt != null) {
                try { stmt.close(); } catch (Exception e) { };
            }
         }
    }
}
