// Thread per il check del Master e l'aggiornamento della lista degli
// slaves

import java.net.*;
import java.io.*;

class ChkMaster extends Thread {
  private DatagramSocket soc;
  private DatagramPacket alivePac;
    
  public ChkMaster() {
    super("ChkMaster");
    try { System.out.print("Init ChkMaster Thread ... ");
          soc=new DatagramSocket(ConstantsS.queryPort+2);
          soc.setSoTimeout(Constants.attesaRec);
          byte[] b="".getBytes();
          alivePac=new DatagramPacket(b,b.length);
          System.out.println("fatto.");
            
    } catch(SocketException ex) {
   	    System.out.println("Slave$ChkMaster: "+ex.toString());
        System.exit(ConstantsS.queryPort+2);
   	  }
   	  catch(SecurityException ex) {
   	    System.out.println("Slave$ChkMaster: "+ex.toString());
   	    System.exit(ConstantsS.queryPort+2);
   	  }
  }
  
  // trasmette a tutti i destinatari in dest il msg pac
  private void transmit(KeySlave[] dest,DatagramPacket pac) {
    int i;
      
    for (i=0;i<dest.length;i++)
     try { pac.setAddress(InetAddress.getByName(dest[i].ipSlave));
           pac.setPort(dest[i].portaSlave+3);
           soc.send(pac);
                     
     } catch(IOException ex) {
        System.out.println("Slave$ChkMaster.transmit: "+ex.toString());
       }
  }	
 
  private void updateSlaveList(String lst) {
    StringReader sr;
    BufferedReader br;
    
    if (lst.equals("")) return;
    br=new BufferedReader(new StringReader(lst));
    try { String l,p;
          int pos;
          while ((l=br.readLine())!=null)
           { pos=l.indexOf(':');
             p=l.substring(pos+1,l.length());
             if (ConstantsS.sv.isAlive(l.substring(0,pos),(new Integer(p)).intValue()))
              { ConstantsS.sv.removeSlave(l.substring(0,pos),(new Integer(p)).intValue());
                System.out.println("Slave$ChkMaster.updateSlaveList: rimosso slave "+l);
              }
           }
          br.close(); 	
    	
    } catch(IOException ex) {
    	  System.out.println("Slave$ChkMaster.updateSlaveList: "+ex.toString());
    	}	
  }	
 
  public void run() {
  	int transmission=0;
         
    while (true)
      try { Thread.sleep(2000);
            byte[] inb=new byte[2048];
            DatagramPacket inPac=new DatagramPacket(inb,inb.length);
            while (transmission<3)
             { /* occorre settare qui l'ind e la porta del master xche'
                  potrebbero essere cambiati in seguito a una rielezio-
                  ne. */
               alivePac.setAddress(InetAddress.getByName(ConstantsS.masterIP));
               alivePac.setPort(ConstantsS.masterPort+3);
               soc.send(alivePac);
               transmission++;
               try { soc.receive(inPac);
                 	   // la receive ha ricevuto un ack
                 	   //System.out.println("Slave$ChkMaster.run ricevuto da "+(inPac.getAddress()).getHostAddress()+" "+inPac.getPort()+" : "+(new String(inPac.getData())).trim());
                 	   updateSlaveList((new String(inPac.getData())).trim());
                 	   if (ConstantsS.reelection && !ConstantsS.waitForNewMaster)
                 	    { byte[] ab="abort".getBytes();
                 	      transmit(ConstantsS.sv.getSlave(),new DatagramPacket(ab,ab.length));
                 	    	ConstantsS.reelection=false;
                 	    	transmission=0;
                 	    	System.out.println("Slave$ChkMaster.run: master vivo, abort rielezione.");
                 	    }
                 	   break;
                 	         
               } catch(InterruptedIOException ex) {
                 	 // il timeout e' espirato: ritrasmissione
                 	 if (transmission<3 && !ConstantsS.reelection) System.out.println("Slave$ChkMaster.run: il timeout e' espirato, ritrasmissione.");
                 }
             } // fine while
            if (transmission==3 && !ConstantsS.reelection) 
             { System.out.println("Slave$ChkMaster.run: master morto, inizio rielezione");
               byte[] ob=(String.valueOf(ConstantsS.slaveLoad)).getBytes();
               transmit(ConstantsS.sv.getSlave(),new DatagramPacket(ob,ob.length));
               ConstantsS.reelection=true;
             }
            transmission=0; 
              
      } catch(IOException ex) {
    	    System.out.println("Slave$ChkMaster.run: "+ex.toString());
    	  }
    	  catch(InterruptedException ex) {
    	    System.out.println("Slave$ChkMaster.run: "+ex.toString());
        }	
  }		
} // fine ChkMaster