Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
814 mhunt 1
package com.erggroup.buildtool.daemon;
2
 
3
import com.erggroup.buildtool.daemon.BuildThread;
4
import com.erggroup.buildtool.ripple.MutableInt;
5
import com.erggroup.buildtool.ripple.MutableString;
6
import com.erggroup.buildtool.ripple.Package;
7
import com.erggroup.buildtool.ripple.ReleaseManager;
8
import com.erggroup.buildtool.ripple.RippleEngine;
9
 
10
import java.io.BufferedReader;
834 mhunt 11
import java.io.DataInputStream;
814 mhunt 12
import java.io.File;
834 mhunt 13
import java.io.FileInputStream;
14
import java.io.InputStreamReader;
814 mhunt 15
import java.sql.SQLException;
16
 
17
import org.apache.log4j.Logger;
18
 
19
/**Master Thread sub component
20
 */
21
public class MasterThread
22
  extends BuildThread
23
{
24
 
25
  /**Logger
26
   * @attribute
27
   */
28
  private static final Logger mLogger = Logger.getLogger(MasterThread.class);
29
 
864 mhunt 30
   /**constructor
814 mhunt 31
   */
896 mhunt 32
  public MasterThread(int rtag_id, int rcon_id, String unitTest)
814 mhunt 33
  {
818 mhunt 34
    mLogger.warn("MasterThread rtag_id " + rtag_id + " rcon_id " + rcon_id);
814 mhunt 35
    mRtagId = rtag_id;
36
    mRconId = rcon_id;
896 mhunt 37
    if ( unitTest == null )
38
    {
39
      unitTest = new String();
40
    }
41
    mUnitTest = unitTest;
814 mhunt 42
  }
43
 
44
  /**implements the sequence diagrams coordinate slave threads, generate build files, allowed to proceed, check environment
45
   */
46
  public void run()
47
  {
48
    Integer id = new Integer(mRtagId);
49
    setName(id.toString());
50
    mLogger.debug("run");
51
    boolean exit = false;
52
    RippleEngine rippleEngine = new RippleEngine(mReleaseManager, mRtagId, true);
53
    MutableInt rconId = new MutableInt();
54
    MutableInt current_run_level = new MutableInt();
55
    MutableString addendum = new MutableString();
56
 
57
    while(!exit)
58
    {
59
      try
60
      {
886 mhunt 61
        sleepCheck();
868 mhunt 62
        rippleEngine.collectMetaData();
63
 
814 mhunt 64
        if ( Thread.currentThread().isInterrupted() )
65
        {
66
          mLogger.warn("run is interrupted");
67
          // unit test technique
68
          throw new ExitException();
69
        }
70
 
896 mhunt 71
        if ( mUnitTest.compareTo("unit test spawn thread") == 0)
814 mhunt 72
        {
73
          throw new Exception();
74
        }
75
 
76
        MutableString buildFileContent = new MutableString();
77
 
896 mhunt 78
        if ( mUnitTest.compareTo("unit test check environment") != 0)
814 mhunt 79
        {
896 mhunt 80
          if ( mUnitTest.compareTo("unit test generate build files") != 0)
814 mhunt 81
          {
896 mhunt 82
            if ((mUnitTest.compareTo("unit test allowed to proceed") != 0) &&
83
                (mUnitTest.compareTo("unit test not allowed to proceed") != 0) &&
84
                (mUnitTest.compareTo("unit test exit") != 0))
814 mhunt 85
            {
886 mhunt 86
              // coordinate slave threads
87
              mLogger.warn("run coordinate slave threads");
88
 
89
              mRunLevel = RunLevel.WAITING;
90
              mLogger.warn("run changing run level to WAITING for rcon_id " + mRconId);
890 mhunt 91
              mRunLevel.persistNew(mReleaseManager, mRconId);
886 mhunt 92
 
93
              boolean allSlaveThreadsWaiting = false;
94
              boolean logWarning = true;
95
              boolean logWarning2 = true;
96
 
97
              while ( !allSlaveThreadsWaiting )
882 mhunt 98
              {
886 mhunt 99
                mReleaseManager.queryRunLevel(mRtagId);
100
 
892 mhunt 101
                // anything but WAITING or PAUSED
886 mhunt 102
                current_run_level.value = ReleaseManager.DB_IDLE;
103
                boolean moreRunLevelsConfigured = mReleaseManager.getFirstRunLevel(rconId, current_run_level);
104
 
105
                // attempt to exit loop
106
                allSlaveThreadsWaiting = true;
814 mhunt 107
 
886 mhunt 108
                do
814 mhunt 109
                {
886 mhunt 110
                  if (moreRunLevelsConfigured)
814 mhunt 111
                  {
892 mhunt 112
                    // DEVI 53065 Slave indication that they are done with a package includes
113
                    // having a paused run level
114
                    if ((current_run_level.value != ReleaseManager.DB_WAITING) &&
115
                        (current_run_level.value != ReleaseManager.DB_PAUSED))
816 mhunt 116
                    {
886 mhunt 117
                      if ( logWarning )
118
                      {
119
                        mLogger.warn("run waiting for rcon id " + rconId.value);
120
                        logWarning = false;
121
                      }
122
                      else
123
                      {
124
                        mLogger.info("run waiting for rcon id " + rconId.value);                      
125
                      }
126
                      allSlaveThreadsWaiting = false;
816 mhunt 127
                    }
128
                    else
129
                    {
886 mhunt 130
                      moreRunLevelsConfigured = mReleaseManager.getNextRunLevel(rconId, current_run_level);
816 mhunt 131
                    }
814 mhunt 132
                  }
133
                }
886 mhunt 134
                while (moreRunLevelsConfigured && allSlaveThreadsWaiting);
135
 
136
                if ( !allSlaveThreadsWaiting )
814 mhunt 137
                {
886 mhunt 138
                  // to do, sleep for periodicMs
896 mhunt 139
                  if ( mUnitTest.compareTo("unit test coordinate slave threads") == 0 )
820 mhunt 140
                  {
886 mhunt 141
                    Thread.currentThread().interrupt();
820 mhunt 142
                  }
143
                  else
144
                  {
886 mhunt 145
                    if ( logWarning2 )
146
                    {
147
                      mLogger.warn("run sleeping 3 secs waiting for slave threads");
148
                      logWarning2 = false;
149
                    }
150
                    else
151
                    {
152
                      mLogger.info("run sleeping 3 secs waiting for slave threads");
153
                    }
154
                    Thread.sleep(3000);
155
                    mLogger.info("run sleep returned");
820 mhunt 156
                  }
814 mhunt 157
                }
158
              }
886 mhunt 159
 
896 mhunt 160
              if ( mUnitTest.compareTo("unit test coordinate slave threads") == 0 )
814 mhunt 161
              {
886 mhunt 162
                throw new ExitException();
163
              }
164
 
165
              // DEVI 50527
166
              mRunLevel = RunLevel.PUBLISHING;
167
              mLogger.warn("run changing run level to PUBLISHING for rcon_id " + mRconId);
168
              mRunLevel.persist(mReleaseManager, mRconId);
169
 
170
              deliverChange(null, "AbtPublish", false);
171
              // preserve 
172
              String reportingFullyPublished = mReportingFullyPublished;
173
              String reportingNewLabel = mReportingNewLabel;
174
              deliverChange(null, "AbtTearDown", false);
175
 
176
              // DEVI 47395 delete the build file now
177
              // this will prevent any chance of multiply publishing a package version
178
              File buildFile = new File(mRtagId + "build.xml");
179
 
180
              if ( buildFile.exists() )
181
              {
182
                buildFile.delete();
183
              }
184
 
185
              if ( mReportingPackageName != null )
186
              {
187
                // a dummy build file did not apply
188
                // Publishing is done outside ant by design
189
                // The preference is to do all release manager work outside ant
190
 
191
                boolean buildErrorOccurred = true;
898 mhunt 192
                // max 50 characters
193
                String rootCause = "Error publishing to Release Manager";
886 mhunt 194
                try
814 mhunt 195
                {
886 mhunt 196
                  if ( reportingFullyPublished != null && reportingFullyPublished.compareTo("yes") == 0 )
814 mhunt 197
                  {
886 mhunt 198
                    buildErrorOccurred = false;
868 mhunt 199
 
886 mhunt 200
                    if ( reportingNewLabel.length() > 0 )
852 mhunt 201
                    {
886 mhunt 202
                      Integer rtagId = new Integer(mRtagId);
203
 
204
                      if ( mGbeGatherMetricsOnly == null )
868 mhunt 205
                      {
886 mhunt 206
                        if ( mReportingDoesNotRequireSourceControlInteraction.compareTo("false") == 0 )
207
                        {
208
                          // requires source control interaction ie labelled in ClearCase
209
                          // publish to release manager
210
                          mReleaseManager.autoMakeRelease(rtagId.toString(), mReportingPackageName, mReportingPackageExtension, mReportingPackageVersion, reportingNewLabel, mReportingPackageDepends, mReportingIsRipple);
211
                        }
212
                        else
213
                        {
214
                          // trigger release note generation and on_make_official.wsf, which changes ownership and write access in the archive
215
                          // this should not be through autoMakeRelease (sledgehammer, the package is already official in release manager in this scenario)
216
                          // at the time of writing, calling autoMakeRelease does not help if the package was 'released' more than 24 hours ago
217
                          // this seems to be a business rule in the generate_release_notes package
218
                          // the buildtool has no option but to call autoMakeRelease at present
219
                          mReleaseManager.autoMakeRelease(rtagId.toString(), mReportingPackageName, mReportingPackageExtension, mReportingPackageVersion, reportingNewLabel, mReportingPackageDepends, mReportingIsRipple);
220
                        }
868 mhunt 221
                      }
886 mhunt 222
 
223
                      FileInputStream abtmetrics = new FileInputStream( rtagId.toString() + "abtmetrics.txt" );
224
                      DataInputStream din = new DataInputStream( abtmetrics );
225
                      InputStreamReader isr = new InputStreamReader( din );
226
                      BufferedReader br = new BufferedReader( isr );
227
                      String metrics = br.readLine();
228
                      mLogger.warn( "execute read metrics string " + metrics );
229
                      br.close();
230
                      isr.close();
231
                      din.close();
232
 
233
                      mReleaseManager.insertPackageMetrics(rtagId.toString(), mReportingPackageName, mReportingPackageExtension, metrics );
852 mhunt 234
                    }
886 mhunt 235
                    else
236
                    {
237
                      mLogger.info("run package not labelled in ClearCase on " + mReportingPackageName + mReportingPackageVersion);
898 mhunt 238
                      // max 50 characters
239
                      rootCause = "Error publishing to ClearCase";
886 mhunt 240
                      throw new Exception();
241
                    }
814 mhunt 242
                  }
243
                  else
244
                  {
886 mhunt 245
                    mLogger.info("run build error occurred on " + mReportingPackageName + mReportingPackageVersion);
814 mhunt 246
                    throw new Exception();
247
                  }
886 mhunt 248
 
814 mhunt 249
                }
886 mhunt 250
                catch( Exception e)
814 mhunt 251
                {
898 mhunt 252
                  // a build error occurred or
886 mhunt 253
                  // an error occurred publishing to ClearCase or Release Manager
254
                  // take out the archive entry first
255
                  String fs = System.getProperty( "file.separator" );
256
                  String dpkgArchiveEntry = new String(Package.mGbeDpkg + fs + mReportingPackageName + fs + mReportingPackageVersion);
257
                  File dpkgArchiveEntryFile = new File(dpkgArchiveEntry);
258
                  mLogger.info("run checking existence of " + dpkgArchiveEntry);
259
 
260
                  if ( dpkgArchiveEntryFile.exists() )
814 mhunt 261
                  {
886 mhunt 262
                    if ( dpkgArchiveEntryFile.isDirectory() )
263
                    {
264
                      mLogger.warn("run deleting " + dpkgArchiveEntryFile.getName());
265
                      deleteDirectory(dpkgArchiveEntryFile);
266
                    }
814 mhunt 267
                  }
886 mhunt 268
                  else
814 mhunt 269
                  {
886 mhunt 270
                    String dplyArchiveEntry = new String(Package.mGbeDply + fs + mReportingPackageName + fs + mReportingPackageVersion);
271
                    File dplyArchiveEntryFile = new File(dplyArchiveEntry);
272
                    mLogger.info("run checking existence of " + dplyArchiveEntry);
273
 
274
                    if ( dplyArchiveEntryFile.exists() )
814 mhunt 275
                    {
886 mhunt 276
                      if ( dplyArchiveEntryFile.isDirectory() )
277
                      {
278
                        mLogger.warn("run deleting " + dplyArchiveEntryFile.getName());
279
                        deleteDirectory(dplyArchiveEntryFile);
280
                      }
814 mhunt 281
                    }
282
                  }
886 mhunt 283
 
284
                  Integer rtagId = new Integer(mRtagId);
285
 
286
                  if ( !buildErrorOccurred )
287
                  {
288
                    mLogger.fatal("an error occurred publishing to ClearCase or Release Manager");
900 mhunt 289
                    mReleaseManager.excludeFromBuild(mReportingPackageVersionId, null, rtagId.toString(), null, rootCause, null, true, false);
886 mhunt 290
                    throw new Exception("an error occurred publishing to ClearCase or Release Manager");
291
                  }
898 mhunt 292
 
902 mhunt 293
                  // DEVI 55364
294
                  // Package has not been built on all configured platforms
295
                  // Under normal circumstances, this root cause will be masked by a previously reported error
296
                  // Under abnormal circumstances amidst build activity such as:
297
                  // - slave build machine reboots
298
                  // - slave build machines with a read only file system
299
                  // this root cause is required to keep the end user informed
300
                  // max 50 chars
301
                  String cause = "Buildtool env error occurred. Attempt build again";
302
                  mReleaseManager.excludeFromBuild(mReportingPackageVersionId, mReportingPackageVersion, rtagId.toString(), null, mReportingBuildFailureLogFile == null ? cause : null, mReportingBuildFailureLogFile, true, false);
814 mhunt 303
                }
304
              }
886 mhunt 305
 
896 mhunt 306
              if ( mUnitTest.compareTo("unit test coordinate slave threads") == 0 )            
886 mhunt 307
              {
308
                throw new ExitException();
309
              }
310
              mLogger.info("run coordinate slave threads returned");
814 mhunt 311
            }
312
 
886 mhunt 313
            // DEVI 51366 allowed to proceed after coordinate slave threads
314
            mLogger.warn("run checking allowedToProceed");
315
            allowedToProceed(true);
316
            mLogger.info("run allowedToProceed returned");
317
 
896 mhunt 318
            if ( mUnitTest.compareTo("unit test allowed to proceed") == 0 )            
886 mhunt 319
            {
320
              throw new ExitException();
321
            }
814 mhunt 322
 
323
            // generate build files
324
            mLogger.warn("run generating build files");
325
            rippleEngine.planRelease();
326
 
327
            // get the build file from the ripple engine
328
            rippleEngine.getFirstBuildFileContent(buildFileContent, addendum);
329
 
330
            if ( addendum.value.compareTo("non generic") == 0 )
331
            {
332
              // publish the build file
333
              mLogger.warn("run publishing build file");
334
              mReleaseManager.publishBuildFile(mRtagId, buildFileContent.value);
335
            }
336
            else
337
            {
338
              // publish a dummy build file for either generic or dummy cases
339
              // this results in the slave not running ant
340
              mLogger.warn("run publishing dummy build file");
341
              mReleaseManager.publishBuildFile(mRtagId, mDummyBuildFileContent);
342
            }
343
          }
344
          mLogger.info("run generated build files");
345
 
868 mhunt 346
          if ( mGbeGatherMetricsOnly != null )
347
          {
348
            // set view up early for metrics gathering to ensure build file is fully written before letting the slave loose
349
            setViewUp(buildFileContent.value, true);            
350
          }
351
 
814 mhunt 352
          // change the run level for all threads in associated with the baseline
353
          mLogger.warn("run change the run level for all threads in associated with the baseline");
354
          mReleaseManager.queryReleaseConfig(mRtagId);
355
          rconId.value = -1;
356
          boolean moreBuildThreadsConfigured = mReleaseManager.getFirstReleaseConfig(rconId);
357
          mRunLevel = RunLevel.ACTIVE;
358
 
359
          do
360
          {
361
            if (moreBuildThreadsConfigured)
362
            {
816 mhunt 363
                mLogger.warn("run changing run level to ACTIVE for rcon_id " + rconId.value);
814 mhunt 364
                mRunLevel.persist(mReleaseManager, rconId.value);
365
                moreBuildThreadsConfigured = mReleaseManager.getNextReleaseConfig(rconId);
366
            }
367
          }
368
          while (moreBuildThreadsConfigured);
369
 
896 mhunt 370
          if ( mUnitTest.compareTo("unit test generate build files") == 0 )
814 mhunt 371
          {
372
            throw new ExitException();
373
          }
374
        }
375
 
376
        mLogger.info("run changed run levels");
377
 
378
        // check environment
379
        mLogger.warn("run checkEnvironment");
380
        checkEnvironment();
381
        mLogger.info("run checkEnvironment returned");
382
 
896 mhunt 383
        if ( mUnitTest.compareTo("unit test check environment") == 0 )
814 mhunt 384
        {
385
          throw new ExitException();
386
        }
387
 
388
        // deliver change to product baseline
389
        mLogger.warn("run deliverChange");
868 mhunt 390
 
391
        if ( mGbeGatherMetricsOnly == null )
392
        {
393
          setViewUp(buildFileContent.value, true);
394
        }
395
 
814 mhunt 396
        deliverChange(null, null, false);
397
        mLogger.info("run deliverChange returned");
886 mhunt 398
 
399
        mSleep = false;
400
        if ( addendum.value.compareTo("dummy") == 0 )
401
        {
402
          // no build requirement, so let things settle
403
          mLogger.warn("run no build requirement, so let things settle");
404
          mSleep = true;
405
        }        
406
 
814 mhunt 407
      }
408
      catch( SQLException e )
409
      {
410
        // oracle connection issues        
411
        mLogger.warn("run oracle connection issues");
886 mhunt 412
        mException = true;
814 mhunt 413
      }
414
      catch( ExitException e )
415
      {
858 mhunt 416
        mLogger.warn("run ExitException");
814 mhunt 417
        exit = true;
418
      }
419
      catch( InterruptedException e )
420
      {
421
        mLogger.warn("run InterruptedException");
422
      }
423
      catch( Exception e )
424
      {
425
        mLogger.error("run indefinitePause");
868 mhunt 426
        String cause = e.getMessage();
427
 
428
        if ( cause != null )
814 mhunt 429
        {
868 mhunt 430
          try
431
          {
432
            // notify first
433
            // many reasons for indefinite pause, including database related, so do database last
896 mhunt 434
            mRecoverable = false;
435
 
436
            if ( cause.compareTo(Package.mRecoverable) == 0 )
437
            {
438
              mRecoverable = true;
439
            }
440
 
868 mhunt 441
            indefinitePause(rippleEngine, cause);
442
            mReleaseManager.indefinitePause();
886 mhunt 443
            // DEVI 51366 force sleep at beginning of while loop
444
            mException = true;
868 mhunt 445
          }
446
          catch( Exception f )
447
          {
448
            mLogger.error("run indefinitePause failed");
449
          }
814 mhunt 450
        }
451
      }
452
    }
453
  }
454
 
455
  /**returns 'M'
456
   */
457
  protected char getMode()
458
  {
459
    mLogger.debug("getMode");
460
    return 'M';
461
  }
462
}