Rev 7033 | Blame | Compare with Previous | Last modification | View Log | RSS feed
package com.erggroup.buildtool.daemon;import com.erggroup.buildtool.abt.BuildToolException;import com.erggroup.buildtool.daemon.BuildThread;import com.erggroup.buildtool.ripple.Package;import com.erggroup.buildtool.ripple.ReleaseManager;import com.erggroup.buildtool.ripple.RippleEngine;import com.erggroup.buildtool.ripple.RunLevel.BuildState;import com.erggroup.buildtool.utilities.MutableDate;import java.sql.SQLException;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/*** Slave Thread sub component*/public class SlaveThread extends BuildThread{/*** Logger** @attribute*/private static final Logger mLogger = LoggerFactory.getLogger(SlaveThread.class);/** Holds the buildFile content**/protected String mBuildFileContent = null;/**constructor* @param rtagId - Identifies the Release* @param rconId - Identifies the Controlling entry* @param releaseManager - A ReleaseManager entry to use* @param unitTest - Unit Test data*/public SlaveThread(int rtagId, int rconId, ReleaseManager releaseManager, String unitTest){super(rtagId, rconId, releaseManager, unitTest);mLogger.warn("SlaveThread rtag_id " + rtagId + " rcon_id " + rconId);}/*** implements the sequence diagrams consume build files, allowed to proceed,* check environment*/public void run(){Integer id = Integer.valueOf(mRtagId);setName(id.toString());mLogger.warn("run");boolean exit = false;mRippleEngine = new RippleEngine(mReleaseManager, mRtagId, true);while (!exit){try{mLogger.error("run calling sleepCheck");mPhase.setPhase("sleepCheck");sleepCheck();mLogger.error("run calling rippleEngine.collectMetaData");mPhase.setPhase("collectMetaData");mRippleEngine.collectMetaData();if (Thread.currentThread().isInterrupted()){mLogger.warn("run is interrupted");// unit test techniquethrow new ExitException();}if (mUnitTest.compareTo("unit test spawn thread") == 0){throw new Exception();}// allowed to proceedif (mUnitTest.compareTo("unit test consume build files") != 0){mLogger.error("run calling allowedToProceed");mPhase.setPhase("allowedToProceed");allowedToProceed(false);mLogger.info("run allowedToProceed returned");}// Indicate that the Slave is WAITING - for a jobmPhase.setPhase("Waiting for work");mLogger.error("run changing run level to WAITING for rcon_id " + mRconId);// Wait for Slave to be set as Activewhile (!BuildDaemon.mShutDown){// Periodically indicate, to Release Manager, that the slave is still alive// A warning will be raised after 10 minutes, so it must be less than thatmRunLevel.persist(mReleaseManager, mRconId, BuildState.DB_WAITING);//// Wait to be notified that a build request is present// Have a timeout just to be sure to be sure//if (mUnitTest.length() == 0) {synchronized (mActiveBuildMonitor) {try {mActiveBuildMonitor.wait(120 * 1000L);}catch ( InterruptedException e ) {Thread.currentThread().interrupt();mLogger.error("InterruptedException in Wait for Active Build");}}}//// Determine if the build cycle can proceed// May be a shutdown request// May be no longer configured// May be stopped// May be paused// May be indefinite pause// Will throw exception if we shouldn't continue on this cycle//mLogger.info("run allowedToContinue");allowedToContinue(false);// Detect build Request// A non-null buildfile published in the databasemLogger.info("run calling mReleaseManager.queryBuildFile");mBuildFileContent = mReleaseManager.queryBuildFile(mRconId);if (mBuildFileContent != null ){// Build request detectedmRunLevel.persist(mReleaseManager, mRconId, BuildState.DB_ACTIVE);break;}}//// Build Request detected// Buildfile has been extracted from the database, but not yet saved//if (BuildDaemon.mShutDown){mLogger.warn("Slave run ShutDown requested");throw new ExitException();}mLogger.info("run consumed build files");if (mUnitTest.compareTo("unit test consume build files") == 0){throw new ExitException();}// set CURRENT_BUILD_FILES to null// Indicates that we have taken the file and will prevent multiple buildsmLogger.info("run calling mReleaseManager.clearBuildFile");mPhase.setPhase("clearBuildFile");mReleaseManager.clearBuildFile(mRconId);// check environmentmLogger.warn("run checkEnvironment");mPhase.setPhase("checkEnvironment");checkEnvironment();mLogger.info("run checkEnvironment returned");mLastBuildWasBenign = true;if (mBuildFileContent.compareTo(mDummyBuildFileContent) != 0){mLastBuildWasBenign = false;// Start of a build cycle. Set new log file to capture// entire build logmPhase.setPhase("flagStartBuildCycle");flagStartBuildCycle();mReporting.resetData();mLogger.error("Collect fresh MetaData");mPhase.setPhase("collectMetaData");mRippleEngine.collectMetaData();// Save the build filemLogger.error("Save buildfile");mPhase.setPhase("Save buildfile");saveBuildFile(mBuildFileContent);// deliver change to product baselinemLogger.error("run calling setViewUp");mPhase.setPhase("Setup View for build");deliverChange("AbtSetUp", true, true);mLogger.error("run calling deliverChange - the actual build");mPhase.setPhase("deliverChange for Build");deliverChange(null, true, false);mLogger.error("run calling deliverChange on AbtTearDown");mPhase.setPhase("AbtTearDown");deliverChange("AbtTearDown", false, true);if (mReporting.buildFailureLogFile != null){mLogger.error("run calling excludeFromBuild");mPhase.setPhase("excludeFromBuild");mReleaseManager.excludeFromBuild(false,mReporting.packageVersionId,mReporting.packageVersion,mRtagId,null,null,mReporting.buildFailureLogFile,false, mReporting.isaTestBuild);}mLogger.info("run deliverChange returned");mPhase.setPhase("End of Build Cycle");}mReleaseManager.clearCurrentPackageBeingBuilt(mRconId);}//---------------------------------------------------------------// Build loop exception handling (only)//catch (ShouldNotContinueExpection e){mLogger.error("ShouldNotContinueExpection:" + e.getMessage());}catch (SQLException e){// oracle connection issues// Request a prolonged sleep at the start of the build loopmLogger.error("run oracle connection issues");mException = true;}catch (ExitException e){mLogger.warn("run ExitException");exit = true;}catch (InterruptedException e){mLogger.warn("run InterruptedException");Thread.currentThread().interrupt();}catch (BuildSystemException e) {// BuildSystem exception - a (possibly) correctable error// Flag as recoverable// - Can't create XML build file// -//mLogger.error("run BuildSystemException");mPhase.setPhase("BuildSystemException indefinitePause");notifyIndefinitePause(e.getMessage());mReleaseManager.indefinitePause(false);mException = true;mRecoverable = true;}catch( BuildToolException e){// Buildtool exception - an uncorrectable error// - Can't parse XML build file// -//mLogger.error("run BuildToolException");mPhase.setPhase("BuildToolException indefinitePause");notifyIndefinitePause(e.getMessage());mReleaseManager.indefinitePause(false);mException = true;}catch (Exception e){// Uncaptured exception// These are not good. Current mechanism to handle this condition is:// 1) Email build system administrator// 2) Pause the build system//mLogger.error("run indefinitePause " + e.toString());// DEVI 51366 force sleep at beginning of while loopmException = true;String cause = e.getMessage();if ( cause == null || cause.compareTo("null") == 0 ){cause = "Internal Error: " + e.toString();}try{// notify first// many reasons for indefinite pause, including database related, so do database lastmRecoverable = false;if (cause.compareTo(Package.mRecoverable) == 0){mRecoverable = true;}mPhase.setPhase("Notify indefinitePause");notifyIndefinitePause(cause);mReleaseManager.indefinitePause(mRecoverable);}catch( Exception f ){mLogger.error("run indefinitePause failed");}}}try {mReleaseManager.clearCurrentPackageBeingBuilt(mRconId);} catch (Exception e) {mLogger.error("Exception in clearCurrentPackageBeingBuilt:" + e.getMessage());}mPhase.setPhase("Exit Thread");}/** Determine if we are allowed to continue in this build cycle* May be no longer configured* May be stopped* May be paused* May be indefinite pause* Will throw exceptions if we shouldn't continue on this cycle* Does not hang around waiting for condition to clear - thats done elsewhere** @param master - is a master machine making this call* @throws ExitException* @throws ShouldNotContinueExpection* @throws SQLException*/private void allowedToContinue(boolean master) throws ExitException, ShouldNotContinueExpection, SQLException, Exception {if (BuildDaemon.mShutDown){mLogger.warn("allowedToContinue. ShutDown requested");throw new ExitException();}try{mLogger.error("allowedToContinue calling mReleaseManager.connect");mReleaseManager.connect();// Ensure that the machine is a part of the current build setmLogger.error("allowedToContinue calling mReleaseManager.queryReleaseConfig");if ( !mReleaseManager.queryReleaseConfig(mRtagId, mRconId, BuildDaemon.mHostname, getMode(), mStartTime) ){mLogger.warn("allowedToContinue queryReleaseConfig failed");mReleaseManager.disconnect();throw new ExitException();}// Check for scheduled downtime or indefinite pauseMutableDate resumeTime = new MutableDate();mLogger.error("allowedToContinue calling mReleaseManager.queryRunLevelSchedule");if ( !mReleaseManager.queryRunLevelSchedule(resumeTime) ){mLogger.info("allowedToContinue scheduled downtime");mReleaseManager.disconnect();throw new ShouldNotContinueExpection("Scheduled downtime");}//// If commanded to pause, then wait around until the command has been removed.//mLogger.error("allowedToContinue calling mReleaseManager.queryDirectedRunLevel");if ( !mReleaseManager.queryDirectedRunLevel(mRconId) ){mLogger.error("allowedToContinue Pause Detected");throw new ShouldNotContinueExpection("Pause Detected");}}finally{// this block is executed regardless of what happens in the try block// even if an exception is thrown// ensure disconnectmLogger.error("allowedToContinue calling mReleaseManager.disconnect");mReleaseManager.disconnect();}// One last test for a shut down requestif (BuildDaemon.mShutDown){mLogger.warn("allowedToContinue. ShutDown requested");throw new ExitException();}}/*** returns 'S'*/protected char getMode(){mLogger.debug("getMode");return 'S';}}