Subversion Repositories DevTools

Rev

Rev 1365 | Rev 4285 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.erggroup.buildtool.daemon;

import com.erggroup.buildtool.ripple.MutableChar;
import com.erggroup.buildtool.ripple.MutableInt;
import com.erggroup.buildtool.ripple.Package;
import com.erggroup.buildtool.ripple.ReleaseManager;
import com.erggroup.buildtool.daemon.NagiosThread;

import java.io.File;
import java.io.IOException;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.net.ServerSocket;

import java.sql.SQLException;

import java.util.Iterator;
import java.util.Vector;

import org.apache.log4j.Logger;
import org.apache.log4j.xml.DOMConfigurator;

/**BuildDaemon sub component and entry point (main BuildDaemon thread)
 */
public class BuildDaemon
{

  /**hostname
   * @attribute
   */
  static String mHostname = new String();

  /**GBE_LOG
   * @attribute
   */
  static String mGbeLog = new String();

  /**Logger
   * @attribute
   */
  private static final Logger mLogger = Logger.getLogger(BuildDaemon.class);

  /**Collection of ThreadIdentifier objects.
   * @attribute
   */
  private Vector<ThreadIdentifier> mThreadCollection = new Vector<ThreadIdentifier>();

  /**Nagios
   * @attribute
   */
  ServerSocket nagiosSrv;
  NagiosThread nagiosChecker;

  /**mThreadCollection items
   */
  private class ThreadIdentifier
  {
    /**rcon_id associated with the thread
     * @attribute
     */
    private final int mRcon_id;

    /**thread identifier
     * @attribute
     */
    private final BuildThread mThread;

    /**constructor
     */
    ThreadIdentifier(int rcon_id, BuildThread thread)
    {
      mLogger.debug("ThreadIdentifier " + rcon_id);
      mRcon_id = rcon_id;
      mThread = thread;
    }

    /**accessor
     */
    int get_rcon_id()
    {
      mLogger.debug("get_rcon_id");
      mLogger.info("get_rcon_id returned " + mRcon_id);
      return mRcon_id;
    }

    /**accessor
     */
    BuildThread get_thread()
    {
      mLogger.debug("get_thread");
      return mThread;
    }
  }

  /**main method for the Build Daemon program
   * instantiates a BuildDaemon object
   */
  public static void main(String[] args)
  {
    String abtdXml = System.getenv("ABT_HOME");
    
    if ( abtdXml != null )
    {
      abtdXml += System.getProperty( "file.separator" ) + "abtd.xml";
    }
    else
    {
      abtdXml = new String("abtd.xml");
    }
    DOMConfigurator.configure(abtdXml);
    mLogger.debug("main");
    String antHome = System.getenv("ANT_HOME");
    
    if ( antHome == null )
    {
      mLogger.fatal("main ANT_HOME not set");
      System.exit(1);
    }

    mGbeLog = System.getenv("GBE_LOG");
    
    if ( mGbeLog == null )
    {
      mLogger.fatal("main GBE_LOG not set");
      System.exit(1);
    }
    
    File gl = new File( mGbeLog );
    
    if ( !gl.isDirectory() )
    {
      mLogger.fatal("main GBE_LOG is not a directory");
    }

    String gbeUNC = System.getenv("GBE_UNC");
    
    if ( gbeUNC == null )
    {
      mLogger.fatal("main GBE_UNC not set");
      System.exit(1);
    }

    String connectionString = System.getenv("GBE_RM_LOCATION");
    String username = System.getenv("GBE_RM_USERNAME");
    String password = System.getenv("GBE_RM_PASSWORD");

    for (int optind = 0; optind < args.length; optind++)
    {
      if (args[optind].equals("-c") && optind < (args.length - 1))
      {
        connectionString = args[++optind];
      }
      else if (args[optind].equals("-u") && optind < (args.length - 1))
      {
        username = args[++optind];
      }
      else if (args[optind].equals("-p") && optind < (args.length - 1))
      {
        password = args[++optind];
      }
    }

    if (connectionString == null ||
        connectionString.length() == 0 ||
        username == null ||
        username.length() == 0 ||
        password == null ||
        password.length() == 0)
    {
      mLogger.fatal("Usage: java -jar abtdD.jar -c connectionString -u username -p password");
      System.exit(1);
    }

    BuildDaemon buildDaemon = new BuildDaemon(connectionString, username, password);
    buildDaemon.cleanUp();
    
  }

  /**constructor, implements the sequence diagram spawn thread
   */
  public BuildDaemon(String connectionString, String username, 
                     String password)
  {
    mLogger.warn("BuildDaemon");
    ReleaseManager releaseManager = 
      new ReleaseManager(connectionString, username + "[release_manager]", password);
    boolean run = true;
    MutableInt rtag_id = new MutableInt();
    MutableInt rcon_id = new MutableInt();
    MutableChar daemon_mode = new MutableChar();
    String hostname = new String("");
    
    try
    {
      InetAddress local = InetAddress.getLocalHost();
      hostname = local.getHostName();
      mHostname = hostname;
      mLogger.info("BuildDaemon set hostname " + mHostname);

      if ( Package.mGenericMachtype == null )
      {
        mLogger.fatal("run GBE_MACHTYPE not set");
        throw new Exception("run GBE_MACHTYPE not set");
      }

      if ( Package.mGbeDpkg == null )
      {
        mLogger.fatal("run GBE_DPKG not set");
        throw new Exception("run GBE_DPKG not set");
      }

      //Set the default handler invoked when a thread abruptly terminates due to an
      //uncaught exception, and no other handler has been defined for that thread.
      Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());

      //
      //  Start the Nagios Interface Thread
      //
      if ( connectionString.compareTo("unit test spawn thread") != 0 )
      {
        try {
          nagiosSrv = new ServerSocket(1111);
          nagiosChecker = new NagiosThread(nagiosSrv, this);
          nagiosChecker.start();
        } catch ( IOException e ) {
              mLogger.fatal("Failed to start Nagios Service. Port already in use");
              throw new Exception("Nagios port in use");
        }
      }

      boolean firstTime = true;
      
      while (run)
      {
        try
        {
          if ( !firstTime )
          {
            mLogger.warn("BuildDaemon sleep for 10 mins");
            Thread.sleep(600000);
            mLogger.info("BuildDaemon sleep returned");
          }
          else
          {
            firstTime = false;    
          }

          releaseManager.queryReleaseConfig(hostname);
  
          rtag_id.value = 0;
          rcon_id.value = 0;
          daemon_mode.value = 'X';
  
          boolean moreReleasesConfigured = 
            releaseManager.getFirstReleaseConfig(rtag_id, rcon_id, 
                                                 daemon_mode);
  
          do
          {
            if (moreReleasesConfigured)
            {
              if (!isActive(rcon_id.value))
              {
                mLogger.warn("BuildDaemon activating " + rtag_id.value + " " + rcon_id.value + " " + daemon_mode.value);
                
                String utf = null;
                
                if ( connectionString.compareTo("unit test spawn thread") == 0 )
                {
                  utf = connectionString;
                }
                
                // spawn and run the BuildThread
                if (daemon_mode.value == 'M')
                {
                  MasterThread thread = new MasterThread(rtag_id.value, rcon_id.value, utf);
                  ThreadIdentifier threadIdentifier = 
                    new ThreadIdentifier(rcon_id.value, thread);
                  mThreadCollection.add(threadIdentifier);
                  // begin thread execution and invoke thread.run();
                  thread.start();
                }
                else if (daemon_mode.value == 'S')
                {
                  SlaveThread thread = new SlaveThread(rtag_id.value, rcon_id.value, utf);
                  ThreadIdentifier threadIdentifier = 
                    new ThreadIdentifier(rcon_id.value, thread);
                  mThreadCollection.add(threadIdentifier);
                  // begin thread execution and invoke thread.run();
                  thread.start();
                }
              }
  
              moreReleasesConfigured = 
                  releaseManager.getNextReleaseConfig(rtag_id, rcon_id, 
                                                      daemon_mode);
            }
          }
          while (moreReleasesConfigured);
  
          if ( connectionString.compareTo("unit test spawn thread") == 0)
          {
            run = false;
          }
          
        }
        catch (SQLException e)
        {
          mLogger.warn("BuildDaemon caught SQLException");
        }
        catch (InterruptedException e)
        {
          mLogger.warn("BuildDaemon caught InterruptedException");
        }
        catch (Exception e)
        {
          mLogger.warn("BuildDaemon caught Exception");
        }
      }
    }
    catch( UnknownHostException e )
    {
      mLogger.fatal("BuildDaemon caught UnknownHostException");
    }
    catch( Exception e )
    {
      mLogger.fatal("BuildDaemon caught Exception");
    }
  }

  /**calls isAlive on the Thread object associated with the rcon_id
   */
  public boolean isActive(final int rcon_id)
  {
    mLogger.debug("isActive " + rcon_id);
    boolean retVal = false;
    boolean found = false;

    for (Iterator<ThreadIdentifier> it = mThreadCollection.iterator(); it.hasNext(); )
    {
      ThreadIdentifier threadIdentifier = it.next();

      if (threadIdentifier.get_rcon_id() == rcon_id)
      {
        found = true;
        if (threadIdentifier.get_thread().isAlive())
        {
          retVal = true;
          break;
        }
        else
        {
            mLogger.warn("isActive found dead thread " + rcon_id );
        }
      }
    }

    if ( !found )
    {
        mLogger.warn("isActive thread not found " + rcon_id);
    }

    mLogger.warn("isActive returned " + retVal);
    return retVal;
  }

    /**
     *  Nagios interface
     *      Returns true if ALL the thread looks OK
     *      Must have one active thread
    */
    boolean checkThreads()
    {
      boolean retVal = false;
        mLogger.info("checkThreads called");
      for (Iterator<ThreadIdentifier> it = mThreadCollection.iterator(); it.hasNext(); )
      {
        ThreadIdentifier threadIdentifier = it.next();

        if (threadIdentifier.get_thread().checkThread())
        {
          retVal = true;
        }
        else
        {
          retVal = false;
          break;
        }
      }

      mLogger.info("checkThreads returned " + retVal);
      return retVal;
    }
  

  /**terminates all BuildThreads
   */
  public void cleanUp()
  {
    mLogger.warn("cleanUp");
    if ( nagiosChecker != null )
    {
        nagiosChecker.terminate();
    }

    for (Iterator<ThreadIdentifier> it = mThreadCollection.iterator(); it.hasNext(); )
    {
      ThreadIdentifier threadIdentifier = it.next();

      if (threadIdentifier.get_thread().isAlive())
      {
        try
        {
          threadIdentifier.get_thread().interrupt();
          threadIdentifier.get_thread().join();
        }
        catch( InterruptedException e )
        {
        }
      }
    }
  }
}

class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler
{
    private static final Logger mLogger = Logger.getLogger(UncaughtExceptionHandler.class);

    //Implements Thread.UncaughtExceptionHandler.uncaughtException()
    public void uncaughtException(Thread th, Throwable ex)
    {
        System.out.println("You crashed thread " + th.getName());
        System.out.println("Exception was: " + ex.toString());

        mLogger.fatal("UncaughtException ThreadName: " + th.getName());
        mLogger.fatal("UncaughtException was: " + ex.toString());
    }
}