Subversion Repositories DevTools

Rev

Rev 882 | 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.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.SQLException;

import org.apache.log4j.Logger;

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

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

   /**constructor
   */
  public MasterThread(int rtag_id, int rcon_id, String gbebuildfilter)
  {
    mLogger.warn("MasterThread rtag_id " + rtag_id + " rcon_id " + rcon_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();

    while(!exit)
    {
      try
      {
        sleepCheck();
        rippleEngine.collectMetaData();
        
        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();
        }

        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 allowed to proceed") != 0) &&
                (mGbebuildfilter.compareTo("unit test not allowed to proceed") != 0) &&
                (mGbebuildfilter.compareTo("unit test exit") != 0))
            {
              // coordinate slave threads
              mLogger.warn("run coordinate slave threads");

              mRunLevel = RunLevel.WAITING;
              mLogger.warn("run changing run level to WAITING for rcon_id " + mRconId);
              mRunLevel.persist(mReleaseManager, mRconId);

              boolean allSlaveThreadsWaiting = false;
              boolean logWarning = true;
              boolean logWarning2 = true;
              
              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)
                    {
                      if ( logWarning )
                      {
                        mLogger.warn("run waiting for rcon id " + rconId.value);
                        logWarning = false;
                      }
                      else
                      {
                        mLogger.info("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
                  {
                    if ( logWarning2 )
                    {
                      mLogger.warn("run sleeping 3 secs waiting for slave threads");
                      logWarning2 = false;
                    }
                    else
                    {
                      mLogger.info("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();
              }
              
              // DEVI 50527
              mRunLevel = RunLevel.PUBLISHING;
              mLogger.warn("run changing run level to PUBLISHING for rcon_id " + mRconId);
              mRunLevel.persist(mReleaseManager, mRconId);
              
              deliverChange(null, "AbtPublish", false);
              // preserve 
              String reportingFullyPublished = mReportingFullyPublished;
              String reportingNewLabel = mReportingNewLabel;
              deliverChange(null, "AbtTearDown", false);
              
              // DEVI 47395 delete the build file now
              // this will prevent any chance of multiply publishing a package version
              File buildFile = new File(mRtagId + "build.xml");
              
              if ( buildFile.exists() )
              {
                buildFile.delete();
              }
              
              if ( mReportingPackageName != null )
              {
                // a dummy build file did not apply
                // Publishing is done outside ant by design
                // The preference is to do all release manager work outside ant
  
                boolean buildErrorOccurred = true;
                try
                {
                  if ( reportingFullyPublished != null && reportingFullyPublished.compareTo("yes") == 0 )
                  {
                    buildErrorOccurred = false;
                    
                    if ( reportingNewLabel.length() > 0 )
                    {
                      Integer rtagId = new Integer(mRtagId);
                      
                      if ( mGbeGatherMetricsOnly == null )
                      {
                        if ( mReportingDoesNotRequireSourceControlInteraction.compareTo("false") == 0 )
                        {
                          // requires source control interaction ie labelled in ClearCase
                          // publish to release manager
                          mReleaseManager.autoMakeRelease(rtagId.toString(), mReportingPackageName, mReportingPackageExtension, mReportingPackageVersion, reportingNewLabel, mReportingPackageDepends, mReportingIsRipple);
                        }
                        else
                        {
                          // trigger release note generation and on_make_official.wsf, which changes ownership and write access in the archive
                          // this should not be through autoMakeRelease (sledgehammer, the package is already official in release manager in this scenario)
                          // at the time of writing, calling autoMakeRelease does not help if the package was 'released' more than 24 hours ago
                          // this seems to be a business rule in the generate_release_notes package
                          // the buildtool has no option but to call autoMakeRelease at present
                          mReleaseManager.autoMakeRelease(rtagId.toString(), mReportingPackageName, mReportingPackageExtension, mReportingPackageVersion, reportingNewLabel, mReportingPackageDepends, mReportingIsRipple);
                        }
                      }
                      
                      FileInputStream abtmetrics = new FileInputStream( rtagId.toString() + "abtmetrics.txt" );
                      DataInputStream din = new DataInputStream( abtmetrics );
                      InputStreamReader isr = new InputStreamReader( din );
                      BufferedReader br = new BufferedReader( isr );
                      String metrics = br.readLine();
                      mLogger.warn( "execute read metrics string " + metrics );
                      br.close();
                      isr.close();
                      din.close();
  
                      mReleaseManager.insertPackageMetrics(rtagId.toString(), mReportingPackageName, mReportingPackageExtension, metrics );
                    }
                    else
                    {
                      mLogger.info("run package not labelled in ClearCase on " + mReportingPackageName + mReportingPackageVersion);
                      throw new Exception();
                    }
                  }
                  else
                  {
                    mLogger.info("run build error occurred on " + mReportingPackageName + mReportingPackageVersion);
                    throw new Exception();
                  }
                  
                }
                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 + mReportingPackageName + fs + mReportingPackageVersion);
                  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 + mReportingPackageName + fs + mReportingPackageVersion);
                    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);
                      }
                    }
                  }
                  
                  Integer rtagId = new Integer(mRtagId);
                  // pass root file
                  mReleaseManager.excludeFromBuild(mReportingPackageVersionId, mReportingPackageVersion, rtagId.toString(), null, null, mReportingBuildFailureLogFile);
  
                  if ( !buildErrorOccurred )
                  {
                    mLogger.fatal("an error occurred publishing to ClearCase or Release Manager");
                    throw new Exception("an error occurred publishing to ClearCase or Release Manager");
                  }
                }
              }
              
              if ( mGbebuildfilter.compareTo("unit test coordinate slave threads") == 0 )            
              {
                throw new ExitException();
              }
              mLogger.info("run coordinate slave threads returned");
            }
            
            // DEVI 51366 allowed to proceed after coordinate slave threads
            mLogger.warn("run checking allowedToProceed");
            allowedToProceed(true);
            mLogger.info("run allowedToProceed returned");

            if ( mGbebuildfilter.compareTo("unit test allowed to proceed") == 0 )            
            {
              throw new ExitException();
            }
            
            // 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");
          
          if ( mGbeGatherMetricsOnly != null )
          {
            // set view up early for metrics gathering to ensure build file is fully written before letting the slave loose
            setViewUp(buildFileContent.value, true);            
          }
          
          // 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)
            {
                mLogger.warn("run changing run level to ACTIVE for rcon_id " + rconId.value);
                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");
        
        if ( mGbeGatherMetricsOnly == null )
        {
          setViewUp(buildFileContent.value, true);
        }
        
        deliverChange(null, null, false);
        mLogger.info("run deliverChange returned");
        
        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;
        }        
        
      }
      catch( SQLException e )
      {
        // oracle connection issues        
        mLogger.warn("run oracle connection issues");
        mException = true;
      }
      catch( ExitException e )
      {
        mLogger.warn("run ExitException");
        exit = true;
      }
      catch( InterruptedException e )
      {
        mLogger.warn("run InterruptedException");
      }
      catch( Exception e )
      {
        mLogger.error("run indefinitePause");
        String cause = e.getMessage();
        
        if ( cause != null )
        {
          try
          {
            // notify first
            // many reasons for indefinite pause, including database related, so do database last
            indefinitePause(rippleEngine, cause);
            mReleaseManager.indefinitePause();
            // DEVI 51366 force sleep at beginning of while loop
            mException = true;
          }
          catch( Exception f )
          {
            mLogger.error("run indefinitePause failed");
          }
        }
      }
    }
  }

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