Subversion Repositories DevTools

Rev

Blame | Last modification | View Log | RSS feed

package com.erggroup.buildtool.daemon;

import com.erggroup.buildtool.daemon.BuildThread;
import com.erggroup.buildtool.ripple.MutableInt;
import com.erggroup.buildtool.ripple.MutableString;
import com.erggroup.buildtool.ripple.Package;
import com.erggroup.buildtool.ripple.ReleaseManager;
import com.erggroup.buildtool.ripple.RippleEngine;

import java.io.BufferedReader;
import java.io.File;

import java.io.FileReader;

import java.io.IOException;

import java.sql.SQLException;

import java.util.Iterator;

import java.util.Vector;

import org.apache.log4j.Logger;
import org.apache.tools.ant.taskdefs.Execute;

/**Master Thread sub component
 */
public class MasterThread
  extends BuildThread
{

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

  /**
   * @attribute
   */
  private String[] command = new String[100];

  /**
   * @attribute
   */
  private int commandIndex = 0;

  /**
   * @attribute
   */
  private Execute thread = new Execute();

  /**constructor
   */
  public MasterThread(int rtag_id, int rcon_id, String gbebuildfilter)
  {
    mLogger.debug("MasterThread " + rtag_id);
    mRtagId = rtag_id;
    mRconId = rcon_id;
    mGbebuildfilter = gbebuildfilter;
  }

  /**implements the sequence diagrams coordinate slave threads, generate build files, allowed to proceed, check environment
   */
  public void run()
  {
    Integer id = new Integer(mRtagId);
    setName(id.toString());
    mLogger.debug("run");
    boolean exit = false;
    RippleEngine rippleEngine = new RippleEngine(mReleaseManager, mRtagId, true);
    MutableInt rconId = new MutableInt();
    MutableInt current_run_level = new MutableInt();
    MutableString addendum = new MutableString();
    boolean runLevelSet = false;

    while(!exit)
    {
      try
      {
        if ( Thread.currentThread().isInterrupted() )
        {
          mLogger.warn("run is interrupted");
          // unit test technique
          throw new ExitException();
        }
        
        if ( mGbebuildfilter.compareTo("unit test spawn thread") == 0)
        {
          throw new Exception();
        }

        // allowed to proceed
        MutableString buildFileContent = new MutableString();
        
        if ( mGbebuildfilter.compareTo("unit test check environment") != 0)
        {
          if ( mGbebuildfilter.compareTo("unit test generate build files") != 0)
          {
            if ( mGbebuildfilter.compareTo("unit test coordinate slave threads") != 0 )
            {
            
              if ( !runLevelSet )
              {
                // IMPORTANT - this is done once before a Thread.sleep by design
                // In the case of an SQLException (signifying a database access issue)
                // avoid accessing the database immediately
                mRunLevel = RunLevel.IDLE;
                mRunLevel.persist(mReleaseManager, mRconId);
                runLevelSet = true;
              }
              
              mLogger.warn("run checking allowedToProceed");
              allowedToProceed();
              mLogger.info("run allowedToProceed returned");
  
              if ( mGbebuildfilter.compareTo("unit test allowed to proceed") == 0 )            
              {
                throw new ExitException();
              }
            }
            
            // coordinate slave threads
            mLogger.warn("run coordinate slave threads");
            boolean allSlaveThreadsWaiting = false;
            
            while ( !allSlaveThreadsWaiting )
            {
              mReleaseManager.queryRunLevel(mRtagId);
              
              // anything but WAITING
              current_run_level.value = ReleaseManager.DB_IDLE;
              boolean moreRunLevelsConfigured = mReleaseManager.getFirstRunLevel(rconId, current_run_level);
                
              // attempt to exit loop
              allSlaveThreadsWaiting = true;
          
              do
              {
                if (moreRunLevelsConfigured)
                {
                  if (current_run_level.value != ReleaseManager.DB_WAITING)
                  {
                    mLogger.warn("run waiting for rcon id " + rconId.value);
                    allSlaveThreadsWaiting = false;
                  }
                  else
                  {
                    moreRunLevelsConfigured = mReleaseManager.getNextRunLevel(rconId, current_run_level);
                  }
                }
              }
              while (moreRunLevelsConfigured && allSlaveThreadsWaiting);
        
              if ( !allSlaveThreadsWaiting )
              {
                // to do, sleep for periodicMs
                if ( mGbebuildfilter.compareTo("unit test coordinate slave threads") == 0 )
                {
                  Thread.currentThread().interrupt();
                }
                else
                {
                  mLogger.warn("run sleeping 3 secs waiting for slave threads");
                  Thread.sleep(3000);
                  mLogger.info("run sleep returned");
                }
              }
            }
            
            if ( mGbebuildfilter.compareTo("unit test coordinate slave threads") == 0 )
            {
              throw new ExitException();
            }
            
            deliverChange(null, "AbtPublish", false);
            
            // Publishing is done outside ant by design
            // The preference is to do all release manager work outside ant
            MutableString packageName = new MutableString();
            MutableString packageExtension = new MutableString();
            MutableString packageVersion = new MutableString();
            MutableString packageDepends = new MutableString();
            MutableString isRipple = new MutableString();
            MutableString packageVersionId = new MutableString();
            MutableString fullyPublished = new MutableString();
            MutableString newLabel = new MutableString();
            boolean buildOccurred = retrieveLastPackage(mRtagId,
                                                        packageName, 
                                                        packageExtension, 
                                                        packageVersion, 
                                                        packageDepends, 
                                                        isRipple,
                                                        packageVersionId, 
                                                        fullyPublished,
                                                        newLabel);
            if ( buildOccurred )
            {
              boolean buildErrorOccurred = true;
              try
              {
                
                if ( fullyPublished.value.compareTo("yes") == 0 )
                {
                  buildErrorOccurred = false;
                  
                  if ( newLabel.value.length() > 0 )
                  {
                    // labelled in ClearCase                
                    Integer rtagId = new Integer(mRtagId);
                    mReleaseManager.autoMakeRelease(rtagId.toString(), packageName.value, packageExtension.value, packageVersion.value, newLabel.value, packageDepends.value, isRipple.value);
                  }
                  else
                  {
                    mLogger.info("run package not labelled in ClearCase on " + packageName.value + packageVersion.value);
                    throw new Exception();
                  }
                }
                
                if ( buildErrorOccurred )
                {
                  mLogger.info("run build error occurred on " + packageName.value + packageVersion.value);
                  throw new Exception();
                }
                
                tearViewDown();
              }
              catch( Exception e)
              {
                // an error occurred publishing to ClearCase or Release Manager
                // take out the archive entry first
                String fs = System.getProperty( "file.separator" );
                String dpkgArchiveEntry = new String(Package.mGbeDpkg + fs + packageName.value + fs + packageVersion.value);
                File dpkgArchiveEntryFile = new File(dpkgArchiveEntry);
                mLogger.info("run checking existence of " + dpkgArchiveEntry);
                
                if ( dpkgArchiveEntryFile.exists() )
                {
                  if ( dpkgArchiveEntryFile.isDirectory() )
                  {
                    mLogger.warn("run deleting " + dpkgArchiveEntryFile.getName());
                    deleteDirectory(dpkgArchiveEntryFile);
                  }
                }
                else
                {
                  String dplyArchiveEntry = new String(Package.mGbeDply + fs + packageName.value + fs + packageVersion.value);
                  File dplyArchiveEntryFile = new File(dplyArchiveEntry);
                  mLogger.info("run checking existence of " + dplyArchiveEntry);
                  
                  if ( dplyArchiveEntryFile.exists() )
                  {
                    if ( dplyArchiveEntryFile.isDirectory() )
                    {
                      mLogger.warn("run deleting " + dplyArchiveEntryFile.getName());
                      deleteDirectory(dplyArchiveEntryFile);
                    }
                  }
                }
                
                if ( buildErrorOccurred )
                {
                  Integer rtagId = new Integer(mRtagId);
                  mReleaseManager.excludeFromBuild(packageVersionId.value, packageVersion.value, rtagId.toString());
                }
                else
                {
                  mLogger.fatal("an error occurred publishing to ClearCase or Release Manager");
                  tearViewDown();
                  throw new Exception();
                }
              }
            }
            
            mLogger.info("run coordinate slave threads returned");
            
            // generate build files
            mLogger.warn("run generating build files");
            rippleEngine.planRelease();
              
            // get the build file from the ripple engine
            rippleEngine.getFirstBuildFileContent(buildFileContent, addendum);
            
            if ( addendum.value.compareTo("non generic") == 0 )
            {
              // publish the build file
              mLogger.warn("run publishing build file");
              mReleaseManager.publishBuildFile(mRtagId, buildFileContent.value);
            }
            else
            {
              // publish a dummy build file for either generic or dummy cases
              // this results in the slave not running ant
              mLogger.warn("run publishing dummy build file");
              mReleaseManager.publishBuildFile(mRtagId, mDummyBuildFileContent);
            }
          }
          mLogger.info("run generated build files");
          
          // change the run level for all threads in associated with the baseline
          mLogger.warn("run change the run level for all threads in associated with the baseline");
          mReleaseManager.queryReleaseConfig(mRtagId);
          rconId.value = -1;
          boolean moreBuildThreadsConfigured = mReleaseManager.getFirstReleaseConfig(rconId);
          mRunLevel = RunLevel.ACTIVE;
            
          do
          {
            if (moreBuildThreadsConfigured)
            {
                mRunLevel.persist(mReleaseManager, rconId.value);
                moreBuildThreadsConfigured = mReleaseManager.getNextReleaseConfig(rconId);
            }
          }
          while (moreBuildThreadsConfigured);
          
          if ( mGbebuildfilter.compareTo("unit test generate build files") == 0 )
          {
            throw new ExitException();
          }
        }
        
        mLogger.info("run changed run levels");
        
        // check environment
        mLogger.warn("run checkEnvironment");
        checkEnvironment();
        mLogger.info("run checkEnvironment returned");
        
        if ( mGbebuildfilter.compareTo("unit test check environment") == 0 )
        {
          throw new ExitException();
        }
        
        // deliver change to product baseline
        mLogger.warn("run deliverChange");
        setViewUp(buildFileContent.value, true);
        deliverChange(null, null, false);
        mLogger.info("run deliverChange returned");
      }
      catch( SQLException e )
      {
        // oracle connection issues        
        mLogger.warn("run oracle connection issues");
      }
      catch( ExitException e )
      {
        mLogger.fatal("run ExitException");
        exit = true;
      }
      catch( InterruptedException e )
      {
        mLogger.warn("run InterruptedException");
      }
      catch( Exception e )
      {
        mLogger.error("run indefinitePause");
        try
        {
          mReleaseManager.indefinitePause();
        }
        catch( Exception f )
        {
          mLogger.error("run indefinitePause failed");
        }
      }

      mSleep = false;
      if ( addendum.value.compareTo("dummy") == 0 )
      {
        // no build requirement, so let things settle
        mLogger.warn("run no build requirement, so let things settle");
        mSleep = true;
      }
    }
  }

  /**returns 'M'
   */
  protected char getMode()
  {
    mLogger.debug("getMode");
    return 'M';
  }

  /**retrieves details concerning the last package built for an rtag_id
   * isRipple = "0" (a WIP or direct change) or "1"
   * generic = "generic" or not
   * buildStandard = "JATS" or "ANT"
   */
  boolean retrieveLastPackage(int rtagId, MutableString packageName, 
                              MutableString packageExtension, 
                              MutableString packageVersion, 
                              MutableString packageDepends, 
                              MutableString isRipple, 
                              MutableString packageVersionId, 
                              MutableString fullyPublished,
                              MutableString newLabel) throws IOException
  {
    mLogger.debug("retrieveLastPackage");
    boolean retVal = false;
    Integer rtag = new Integer(rtagId);
    File rtagIdOfficial = new File(rtag + "official");
    
    if ( rtagIdOfficial.exists() )
    {
      // read <rtagId>offical
      FileReader rtagIdOfficialFileReader = new FileReader(rtagIdOfficial);
      BufferedReader rtagIdOfficialBufferedReader = new BufferedReader(rtagIdOfficialFileReader);
      String line;
      
      while( ( line = rtagIdOfficialBufferedReader.readLine() ) != null)
      {
        String []keyVal = line.split("=", 2);
        if (keyVal[0].compareTo("packageName") == 0)
        {
          packageName.value = keyVal[1];
          mLogger.info("retrieveLastPackage packageName " + packageName.value);
        }
        else
        if (keyVal[0].compareTo("packageExtension") == 0)
        {
          packageExtension.value = keyVal[1];
          mLogger.info("retrieveLastPackage packageExtension " + packageExtension.value);
        }
        else
        if (keyVal[0].compareTo("packageVersion") == 0)
        {
          packageVersion.value = keyVal[1];
          mLogger.info("retrieveLastPackage packageVersion " + packageVersion.value);
        }
        else
        if (keyVal[0].compareTo("packageDepends") == 0)
        {
          packageDepends.value = keyVal[1];
          mLogger.info("retrieveLastPackage packageDepends " + packageDepends.value);
        }
        else
        if (keyVal[0].compareTo("packageRipple") == 0)
        {
          isRipple.value = keyVal[1];
          mLogger.info("retrieveLastPackage packageRipple " + isRipple.value);
        }
        else
        if (keyVal[0].compareTo("packageVersionID") == 0)
        {
          packageVersionId.value = keyVal[1];
          mLogger.info("retrieveLastPackage packageVersionID " + packageVersionId.value);
        }
        else
        if (keyVal[0].compareTo("fullyPublished") == 0)
        {
          fullyPublished.value = keyVal[1];
          mLogger.info("retrieveLastPackage fullyPublished " + fullyPublished.value);
        }
        else
        if (keyVal[0].compareTo("newLabel") == 0)
        {
          newLabel.value = keyVal[1];
          mLogger.info("retrieveLastPackage newLabel " + newLabel.value);
        }
      }
      rtagIdOfficialBufferedReader.close();
      retVal = true;
    }
    
    rtagIdOfficial.delete();
    
    mLogger.info("retrieveLastPackage returned " + retVal);
    return retVal;
  }
}