Subversion Repositories DevTools

Rev

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