package combdServlet;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.Date;

import combd.*;

/**
*   Servlet que fornece comunicação com o BD.
*
* @author Marcos V. S. Godinho
*/

public class CombdServlet extends HttpServlet{

  //Parâmetros para conexão com o banco de dados
  private static String DRIVER = "com.mysql.jdbc.Driver";
  private static String URL = "jdbc:mysql://fmc2.graco.unb.br:3306/webmachining_temp";
  private static String USER = "webmachining";
  private static String PSW = "webmachining";

  private BancoDeDados banco;

  private volatile boolean ocupado = false;
  //Métodos para controle de requisições de query.
  private final synchronized boolean estaOcupado(){ return ocupado; }
  private final synchronized void notificaAcesso(){
    ocupado = true;
  System.err.println(Thread.currentThread() + " in");}

  private final synchronized void notificaSaida(){
    ocupado = false;
  System.err.println(Thread.currentThread() + " out ");}

  private volatile boolean erro = false;
  //Métodos para controle de erros.
  private final synchronized boolean houveErro(){ return erro; }
  private final synchronized void sinalizaErro(){ erro = true; }
  private final synchronized void erroCorrigido(){ erro = false; }


  public void init(ServletConfig config) throws ServletException{

    super.init(config);
    banco = BancoDeDados.getBancoDeDados();
    System.out.println(new Date() + " CombdServlet iniciado com sucesso.");
  }


  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException{
  }



  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException{

    boolean esperando = false;

    synchronized(this){

      while( houveErro() || estaOcupado() ){//Espera a vez.

        //Já estava conectado.
        System.err.println(Thread.currentThread() + " esperando...");
        esperando = true;

        try{
          wait();
        }
        catch(InterruptedException ie){}
      }

      if( !esperando )//Se o banco não tiver conectado.
        banco.conecta(DRIVER, URL, USER, PSW);

      //Notifica início da operação.
      notificaAcesso();
      esperando = false;
    }

    ObjectInputStream objin = new ObjectInputStream(request.getInputStream());
    ObjectOutputStream objout = new ObjectOutputStream(response.getOutputStream());
    ProcedimentoPSttmt proc = null;
    try{//Obtem pedido.
      PedidoQuery pedido = (PedidoQuery)objin.readObject();
      //Prepara conexão com o BD.
      proc = new ProcedimentoPSttmt( banco.preparaPrepared(pedido.getQuery()) );
      proc.setParamIN(pedido.getParametros());
      //Executa a query e analiza o resultado.
      int resultado = proc.executeProcedimento();

      if(resultado == -1)//Houve erro.
        throw new Exception();

      else if( resultado == proc.EXISTE_RESULTADO)//Existe Resultado de busca.
        objout.writeObject(proc.getTabelaDeResultado());

      else
        objout.writeObject(new Integer(resultado));
    }
    catch(Exception e){

      sinalizaErro();//Deve reiniciar o BD.
      System.err.println("Erro no processamento de requisição ao Servlet");
      e.printStackTrace();
    }
    finally{
      //fecha as streams de entreda e saída.
      objin.close();
      objout.close();
      if(proc != null) proc.fechaStatement();

      synchronized(this){
        //Notifica término da operação.
        notificaSaida();
        System.out.println(esperando + " ***" + houveErro());

        //Se não há ninguem dentro deste método, fecha a conexão.
        if ( houveErro() || !esperando ){

          System.err.println("desconectou");
          banco.desconecta();
          //Notifica que o erro foi corrigido.
          erroCorrigido();
        }//if
        //Proximo...
        notifyAll();
      }//sync
    }//finally
  }//doPost


  public void destroy(){

    banco = null;
    System.out.println(new Date() + " CombdServlet finalizado com sucesso.");
  }

}
