Subversion Repositories DevTools

Rev

Rev 7033 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6914 dpurdie 1
package com.erggroup.buildtool.daemon;
2
 
3
import com.erggroup.buildtool.abt.BuildToolException;
4
import com.erggroup.buildtool.daemon.BuildThread;
5
import com.erggroup.buildtool.ripple.Package;
6
import com.erggroup.buildtool.ripple.ReleaseManager;
7
import com.erggroup.buildtool.ripple.RippleEngine;
8
import com.erggroup.buildtool.ripple.RunLevel.BuildState;
9
import com.erggroup.buildtool.utilities.MutableDate;
10
 
11
import java.sql.SQLException;
12
 
7033 dpurdie 13
import org.slf4j.Logger;
14
import org.slf4j.LoggerFactory;
6914 dpurdie 15
 
16
/**
17
 * Slave Thread sub component
18
 */
19
public class SlaveThread extends BuildThread
20
{
21
 
22
    /**
23
     * Logger
24
     * 
25
     * @attribute
26
     */
7033 dpurdie 27
    private static final Logger mLogger = LoggerFactory.getLogger(SlaveThread.class);
6914 dpurdie 28
 
29
    /** Holds the buildFile content
30
     * 
31
     */
32
    protected String mBuildFileContent = null;
33
 
34
    /**constructor
35
     * @param rtagId          - Identifies the Release
36
     * @param rconId          - Identifies the Controlling entry
37
     * @param releaseManager  - A ReleaseManager entry to use
38
     * @param unitTest        - Unit Test data 
39
     */
40
    public SlaveThread(int rtagId, int rconId, ReleaseManager releaseManager, String unitTest)
41
    {
42
        super(rtagId, rconId, releaseManager, unitTest);
43
        mLogger.warn("SlaveThread rtag_id " + rtagId + " rcon_id " + rconId);
44
    }
45
 
46
    /**
47
     * implements the sequence diagrams consume build files, allowed to proceed,
48
     * check environment
49
     */
50
    public void run()
51
    {
52
        Integer id = Integer.valueOf(mRtagId);
53
        setName(id.toString());
54
        mLogger.warn("run");
55
        boolean exit = false;
56
        mRippleEngine = new RippleEngine(mReleaseManager, mRtagId, true);
57
 
58
        while (!exit)
59
        {
60
            try
61
            {
7033 dpurdie 62
                mLogger.error("run calling sleepCheck");
6914 dpurdie 63
                mPhase.setPhase("sleepCheck");
64
                sleepCheck();
65
 
7033 dpurdie 66
                mLogger.error("run calling rippleEngine.collectMetaData");
6914 dpurdie 67
                mPhase.setPhase("collectMetaData");
68
                mRippleEngine.collectMetaData();
69
 
70
                if (Thread.currentThread().isInterrupted())
71
                {
72
                    mLogger.warn("run is interrupted");
73
                    // unit test technique
74
                    throw new ExitException();
75
                }
76
 
77
                if (mUnitTest.compareTo("unit test spawn thread") == 0)
78
                {
79
                    throw new Exception();
80
                }
81
 
82
                // allowed to proceed
83
                if (mUnitTest.compareTo("unit test consume build files") != 0)
84
                {
7033 dpurdie 85
                    mLogger.error("run calling allowedToProceed");
6914 dpurdie 86
                    mPhase.setPhase("allowedToProceed");
87
                    allowedToProceed(false);
88
                    mLogger.info("run allowedToProceed returned");
89
                }
90
 
91
                // Indicate that the Slave is WAITING - for a job
92
                mPhase.setPhase("Waiting for work");
7033 dpurdie 93
                mLogger.error("run changing run level to WAITING for rcon_id " + mRconId);
6914 dpurdie 94
 
95
 
96
                // Wait for Slave to be set as Active
97
                while (!BuildDaemon.mShutDown)
98
                {
99
                    // Periodically indicate, to Release Manager, that the slave is still alive
100
                    // A warning will be raised after 10 minutes, so it must be less than that
101
                    mRunLevel.persist(mReleaseManager, mRconId, BuildState.DB_WAITING);
102
 
103
                    //
104
                    //  Wait to be notified that a build request is present
105
                    //  Have a timeout just to be sure to be sure
106
                    //
107
                    if (mUnitTest.length() == 0) {
108
                        synchronized (mActiveBuildMonitor) {
109
                            try {
110
                                mActiveBuildMonitor.wait(120 * 1000L);
111
                            }
112
                            catch ( InterruptedException e  ) {
113
                                Thread.currentThread().interrupt();
114
                                mLogger.error("InterruptedException in Wait for Active Build");
115
                            }
116
                        }
117
                    }
118
 
119
                    //
120
                    //  Determine if the build cycle can proceed
121
                    //      May be a shutdown request
122
                    //      May be no longer configured
123
                    //      May be stopped
124
                    //      May be paused
125
                    //      May be indefinite pause
126
                    //  Will throw exception if we shouldn't continue on this cycle
127
                    //  
128
                    mLogger.info("run allowedToContinue");
129
                    allowedToContinue(false);
130
 
131
                    // Detect build Request
132
                    //  A non-null buildfile published in the database
133
                    mLogger.info("run calling mReleaseManager.queryBuildFile");
134
                    mBuildFileContent =  mReleaseManager.queryBuildFile(mRconId);
135
                    if (mBuildFileContent != null )
136
                    {
137
                        // Build request detected
138
                        mRunLevel.persist(mReleaseManager, mRconId, BuildState.DB_ACTIVE);
139
                        break;
140
                    }
141
 
142
                }
143
 
144
                //
145
                //  Build Request detected
146
                //      Buildfile has been extracted from the database, but not yet saved
147
                //
148
                if (BuildDaemon.mShutDown)
149
                {
150
                    mLogger.warn("Slave run ShutDown requested");
151
                    throw new ExitException();
152
                }
153
 
154
                mLogger.info("run consumed build files");
155
                if (mUnitTest.compareTo("unit test consume build files") == 0)
156
                {
157
                    throw new ExitException();
158
                }
159
 
160
                // set CURRENT_BUILD_FILES to null
161
                //  Indicates that we have taken the file and will prevent multiple builds
162
                mLogger.info("run calling mReleaseManager.clearBuildFile");
163
                mPhase.setPhase("clearBuildFile");
164
                mReleaseManager.clearBuildFile(mRconId);
165
 
166
                // check environment
167
                mLogger.warn("run checkEnvironment");
168
                mPhase.setPhase("checkEnvironment");
169
                checkEnvironment();
170
                mLogger.info("run checkEnvironment returned");
171
 
172
                mLastBuildWasBenign = true;
173
                if (mBuildFileContent.compareTo(mDummyBuildFileContent) != 0)
174
                {
175
                    mLastBuildWasBenign = false;
176
 
177
                    // Start of a build cycle. Set new log file to capture
178
                    // entire build log
179
                    mPhase.setPhase("flagStartBuildCycle");
180
                    flagStartBuildCycle();
181
                    mReporting.resetData();
182
 
7033 dpurdie 183
                    mLogger.error("Collect fresh MetaData");
6914 dpurdie 184
                    mPhase.setPhase("collectMetaData");
185
                    mRippleEngine.collectMetaData();
186
 
187
                    // Save the build file
7033 dpurdie 188
                    mLogger.error("Save buildfile");
6914 dpurdie 189
                    mPhase.setPhase("Save buildfile");
190
                    saveBuildFile(mBuildFileContent);
191
 
192
                    // deliver change to product baseline
7033 dpurdie 193
                    mLogger.error("run calling setViewUp");
6914 dpurdie 194
                    mPhase.setPhase("Setup View for build");
195
                    deliverChange("AbtSetUp", true, true);
196
 
7033 dpurdie 197
                    mLogger.error("run calling deliverChange - the actual build");
6914 dpurdie 198
                    mPhase.setPhase("deliverChange for Build");
199
                    deliverChange(null, true, false);
200
 
7033 dpurdie 201
                    mLogger.error("run calling deliverChange on AbtTearDown");
6914 dpurdie 202
                    mPhase.setPhase("AbtTearDown");
203
                    deliverChange("AbtTearDown", false, true);
204
 
205
                    if (mReporting.buildFailureLogFile != null)
206
                    {
7033 dpurdie 207
                        mLogger.error("run calling excludeFromBuild");
6914 dpurdie 208
                        mPhase.setPhase("excludeFromBuild");
209
                        mReleaseManager.excludeFromBuild(false, 
210
                                                         mReporting.packageVersionId,
211
                                                         mReporting.packageVersion, 
212
                                                         mRtagId, 
213
                                                         null, 
214
                                                         null, 
215
                                                         mReporting.buildFailureLogFile,
216
                                                         false, mReporting.isaTestBuild);
217
                    }
218
 
219
                    mLogger.info("run deliverChange returned");
220
                    mPhase.setPhase("End of Build Cycle");
221
                }
222
                mReleaseManager.clearCurrentPackageBeingBuilt(mRconId);
223
            } 
224
            //---------------------------------------------------------------
225
            //    Build loop exception handling (only)
226
            //
227
            catch (ShouldNotContinueExpection e)
228
            {
7033 dpurdie 229
                mLogger.error("ShouldNotContinueExpection:" + e.getMessage());
6914 dpurdie 230
            }
231
            catch (SQLException e)
232
            {
233
                // oracle connection issues
234
                //  Request a prolonged sleep at the start of the build loop
7033 dpurdie 235
                mLogger.error("run oracle connection issues");
6914 dpurdie 236
                mException = true;
237
            } 
238
            catch (ExitException e)
239
            {
240
                mLogger.warn("run ExitException");
241
                exit = true;
242
            } 
243
            catch (InterruptedException e)
244
            {
245
                mLogger.warn("run InterruptedException");
246
                Thread.currentThread().interrupt();
247
            }
248
            catch (BuildSystemException e) {
249
                // BuildSystem exception - a (possibly) correctable error
250
                // Flag as recoverable
251
                //    - Can't create XML build file
252
                //    - 
253
                // 
7033 dpurdie 254
                mLogger.error("run BuildSystemException");
6914 dpurdie 255
                mPhase.setPhase("BuildSystemException indefinitePause");
256
                notifyIndefinitePause(e.getMessage());
257
                mReleaseManager.indefinitePause(false);
258
                mException = true;
259
                mRecoverable = true;
260
 
261
            }
262
            catch( BuildToolException e)
263
            {
264
                // Buildtool exception - an uncorrectable error
265
                //    - Can't parse XML build file
266
                //    - 
267
                // 
7033 dpurdie 268
                mLogger.error("run BuildToolException");
6914 dpurdie 269
                mPhase.setPhase("BuildToolException indefinitePause");
270
                notifyIndefinitePause(e.getMessage());
271
                mReleaseManager.indefinitePause(false);
272
                mException = true;
273
            }
274
            catch (Exception e)
275
            {
276
	        //  Uncaptured exception
277
	        //  These are not good. Current mechanism to handle this condition is:
278
	        //      1) Email build system administrator
279
	        //      2) Pause the build system
280
	        //  
281
                mLogger.error("run indefinitePause " + e.toString());
282
 
283
                // DEVI 51366 force sleep at beginning of while loop
284
                mException = true;
285
 
286
                String cause = e.getMessage();
287
                if ( cause == null || cause.compareTo("null") == 0 )
288
                {
289
                  cause = "Internal Error: " + e.toString();
290
                }
291
 
292
                try
293
                {
294
                    // notify first
295
                    // many reasons for indefinite pause, including database related, so do database last
296
                    mRecoverable = false;
297
 
298
                    if (cause.compareTo(Package.mRecoverable) == 0)
299
                    {
300
                        mRecoverable = true;
301
                    }
302
 
303
                    mPhase.setPhase("Notify indefinitePause");
304
                    notifyIndefinitePause(cause);
305
                    mReleaseManager.indefinitePause(mRecoverable);
306
        	}
307
        	catch( Exception f )
308
                {
309
                    mLogger.error("run indefinitePause failed");
310
                }
311
            }
312
        }
313
        try {
314
            mReleaseManager.clearCurrentPackageBeingBuilt(mRconId);
315
        } catch (Exception e) {
316
            mLogger.error("Exception in clearCurrentPackageBeingBuilt:" + e.getMessage());
317
        }
318
        mPhase.setPhase("Exit Thread");
319
    }
320
 
321
    /** Determine if we are allowed to continue in this build cycle
322
     *      May be no longer configured
323
     *      May be stopped
324
     *      May be paused
325
     *      May be indefinite pause
326
     *  Will throw exceptions if we shouldn't continue on this cycle
327
     *  Does not hang around waiting for condition to clear - thats done elsewhere
328
     *  
329
     * @param master - is a master machine making this call
330
     * @throws ExitException 
331
     * @throws ShouldNotContinueExpection 
332
     * @throws SQLException 
333
     */
334
    private void allowedToContinue(boolean master) throws ExitException, ShouldNotContinueExpection, SQLException, Exception {
335
 
336
        if (BuildDaemon.mShutDown)
337
        {
338
            mLogger.warn("allowedToContinue. ShutDown requested");
339
            throw new ExitException();
340
        }
341
 
342
        try
343
        {
7033 dpurdie 344
            mLogger.error("allowedToContinue calling mReleaseManager.connect");                      
6914 dpurdie 345
            mReleaseManager.connect();
346
 
347
            //  Ensure that the machine is a part of the current build set
7033 dpurdie 348
            mLogger.error("allowedToContinue calling mReleaseManager.queryReleaseConfig");                      
6914 dpurdie 349
            if ( !mReleaseManager.queryReleaseConfig(mRtagId, mRconId, BuildDaemon.mHostname, getMode(), mStartTime) )
350
            {
351
                mLogger.warn("allowedToContinue queryReleaseConfig failed");
352
                mReleaseManager.disconnect();
353
                throw new ExitException();
354
            }
355
 
356
 
357
            //  Check for scheduled downtime or indefinite pause
358
            MutableDate resumeTime = new MutableDate();
7033 dpurdie 359
            mLogger.error("allowedToContinue calling mReleaseManager.queryRunLevelSchedule");                      
6914 dpurdie 360
            if ( !mReleaseManager.queryRunLevelSchedule(resumeTime) )
361
            {
362
              mLogger.info("allowedToContinue scheduled downtime");
363
              mReleaseManager.disconnect();
364
              throw new ShouldNotContinueExpection("Scheduled downtime");
365
            }
366
 
367
            //
368
            //  If commanded to pause, then wait around until the command has been removed.
369
            //
7033 dpurdie 370
            mLogger.error("allowedToContinue calling mReleaseManager.queryDirectedRunLevel");                      
6914 dpurdie 371
            if ( !mReleaseManager.queryDirectedRunLevel(mRconId) )
372
            {
7033 dpurdie 373
                mLogger.error("allowedToContinue Pause Detected");
6914 dpurdie 374
                throw new ShouldNotContinueExpection("Pause Detected");
375
            }
376
 
377
        }
378
        finally
379
        {
380
          // this block is executed regardless of what happens in the try block
381
          // even if an exception is thrown
382
          // ensure disconnect
7033 dpurdie 383
          mLogger.error("allowedToContinue calling mReleaseManager.disconnect");                      
6914 dpurdie 384
          mReleaseManager.disconnect();
385
        }
386
 
387
        // One last test for a shut down request
388
        if (BuildDaemon.mShutDown)
389
        {
390
            mLogger.warn("allowedToContinue. ShutDown requested");
391
            throw new ExitException();
392
        }
393
 
394
    }
395
 
396
    /**
397
     * returns 'S'
398
     */
399
    protected char getMode()
400
    {
401
        mLogger.debug("getMode");
402
        return 'S';
403
    }
404
}