Subversion Repositories DevTools

Rev

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
      {
916 mhunt 61
        mLogger.fatal("run calling sleepCheck");
886 mhunt 62
        sleepCheck();
916 mhunt 63
        mLogger.fatal("run calling rippleEngine.collectMetaData");
868 mhunt 64
        rippleEngine.collectMetaData();
65
 
814 mhunt 66
        if ( Thread.currentThread().isInterrupted() )
67
        {
68
          mLogger.warn("run is interrupted");
69
          // unit test technique
70
          throw new ExitException();
71
        }
72
 
896 mhunt 73
        if ( mUnitTest.compareTo("unit test spawn thread") == 0)
814 mhunt 74
        {
75
          throw new Exception();
76
        }
77
 
78
        MutableString buildFileContent = new MutableString();
79
 
896 mhunt 80
        if ( mUnitTest.compareTo("unit test check environment") != 0)
814 mhunt 81
        {
896 mhunt 82
          if ( mUnitTest.compareTo("unit test generate build files") != 0)
814 mhunt 83
          {
896 mhunt 84
            if ((mUnitTest.compareTo("unit test allowed to proceed") != 0) &&
85
                (mUnitTest.compareTo("unit test not allowed to proceed") != 0) &&
86
                (mUnitTest.compareTo("unit test exit") != 0))
814 mhunt 87
            {
886 mhunt 88
              // coordinate slave threads
89
              mLogger.warn("run coordinate slave threads");
90
 
91
              mRunLevel = RunLevel.WAITING;
92
              mLogger.warn("run changing run level to WAITING for rcon_id " + mRconId);
916 mhunt 93
              mLogger.fatal("run calling mRunLevel.persistNew to set WAITING");
890 mhunt 94
              mRunLevel.persistNew(mReleaseManager, mRconId);
886 mhunt 95
 
96
              boolean allSlaveThreadsWaiting = false;
97
              boolean logWarning = true;
98
              boolean logWarning2 = true;
99
 
100
              while ( !allSlaveThreadsWaiting )
882 mhunt 101
              {
916 mhunt 102
                mLogger.fatal("run calling mReleaseManager.queryRunLevel");
886 mhunt 103
                mReleaseManager.queryRunLevel(mRtagId);
104
 
892 mhunt 105
                // anything but WAITING or PAUSED
886 mhunt 106
                current_run_level.value = ReleaseManager.DB_IDLE;
916 mhunt 107
                mLogger.fatal("run calling mReleaseManager.getFirstRunLevel");
886 mhunt 108
                boolean moreRunLevelsConfigured = mReleaseManager.getFirstRunLevel(rconId, current_run_level);
109
 
110
                // attempt to exit loop
111
                allSlaveThreadsWaiting = true;
814 mhunt 112
 
886 mhunt 113
                do
814 mhunt 114
                {
886 mhunt 115
                  if (moreRunLevelsConfigured)
814 mhunt 116
                  {
892 mhunt 117
                    // DEVI 53065 Slave indication that they are done with a package includes
118
                    // having a paused run level
119
                    if ((current_run_level.value != ReleaseManager.DB_WAITING) &&
120
                        (current_run_level.value != ReleaseManager.DB_PAUSED))
816 mhunt 121
                    {
886 mhunt 122
                      if ( logWarning )
123
                      {
124
                        mLogger.warn("run waiting for rcon id " + rconId.value);
125
                        logWarning = false;
126
                      }
127
                      else
128
                      {
129
                        mLogger.info("run waiting for rcon id " + rconId.value);                      
130
                      }
131
                      allSlaveThreadsWaiting = false;
816 mhunt 132
                    }
133
                    else
134
                    {
916 mhunt 135
                      mLogger.fatal("run calling mReleaseManager.getNextRunLevel");
886 mhunt 136
                      moreRunLevelsConfigured = mReleaseManager.getNextRunLevel(rconId, current_run_level);
816 mhunt 137
                    }
814 mhunt 138
                  }
139
                }
886 mhunt 140
                while (moreRunLevelsConfigured && allSlaveThreadsWaiting);
141
 
142
                if ( !allSlaveThreadsWaiting )
814 mhunt 143
                {
886 mhunt 144
                  // to do, sleep for periodicMs
896 mhunt 145
                  if ( mUnitTest.compareTo("unit test coordinate slave threads") == 0 )
820 mhunt 146
                  {
886 mhunt 147
                    Thread.currentThread().interrupt();
820 mhunt 148
                  }
149
                  else
150
                  {
886 mhunt 151
                    if ( logWarning2 )
152
                    {
153
                      mLogger.warn("run sleeping 3 secs waiting for slave threads");
154
                      logWarning2 = false;
155
                    }
156
                    else
157
                    {
158
                      mLogger.info("run sleeping 3 secs waiting for slave threads");
159
                    }
916 mhunt 160
                    mLogger.fatal("run calling Thread.sleep for 3 secs");
886 mhunt 161
                    Thread.sleep(3000);
162
                    mLogger.info("run sleep returned");
820 mhunt 163
                  }
814 mhunt 164
                }
165
              }
886 mhunt 166
 
896 mhunt 167
              if ( mUnitTest.compareTo("unit test coordinate slave threads") == 0 )
814 mhunt 168
              {
886 mhunt 169
                throw new ExitException();
170
              }
171
 
172
              // DEVI 50527
173
              mRunLevel = RunLevel.PUBLISHING;
174
              mLogger.warn("run changing run level to PUBLISHING for rcon_id " + mRconId);
916 mhunt 175
              mLogger.fatal("run calling mRunLevel.persist to set PUBLISHING");
886 mhunt 176
              mRunLevel.persist(mReleaseManager, mRconId);
177
 
916 mhunt 178
              mLogger.fatal("run calling deliverChange on AbtPublish");
886 mhunt 179
              deliverChange(null, "AbtPublish", false);
180
              // preserve 
181
              String reportingFullyPublished = mReportingFullyPublished;
924 dpurdie 182
              String reportingNewVcsTag = mReportingNewVcsTag;
916 mhunt 183
              mLogger.fatal("run calling deliverChange on AbtTearDown");
886 mhunt 184
              deliverChange(null, "AbtTearDown", false);
185
 
186
              // DEVI 47395 delete the build file now
187
              // this will prevent any chance of multiply publishing a package version
188
              File buildFile = new File(mRtagId + "build.xml");
189
 
190
              if ( buildFile.exists() )
191
              {
192
                buildFile.delete();
193
              }
194
 
195
              if ( mReportingPackageName != null )
196
              {
197
                // a dummy build file did not apply
198
                // Publishing is done outside ant by design
199
                // The preference is to do all release manager work outside ant
200
 
201
                boolean buildErrorOccurred = true;
898 mhunt 202
                // max 50 characters
203
                String rootCause = "Error publishing to Release Manager";
886 mhunt 204
                try
814 mhunt 205
                {
908 mhunt 206
                  if ( mReportingTestBuild.compareTo("0") != 0 )
207
                  {
208
                    mLogger.info("run completing test build on " + mReportingPackageName + mReportingPackageExtension);
209
                    // build failure emails will have been sent
210
                    // just left to notify the user of the test build completion
211
                    Package p = rippleEngine.findPackage(mReportingPackageName + mReportingPackageExtension);
212
 
213
                    if (p != ReleaseManager.NULL_PACKAGE)
214
                    {
215
                      boolean success = false;
216
 
217
                      if ( reportingFullyPublished != null && reportingFullyPublished.compareTo("yes") == 0 )
218
                      {
219
                        success = true;
220
                      }
221
 
916 mhunt 222
                      mLogger.fatal("run calling p.completeTestBuild");                      
908 mhunt 223
                      p.completeTestBuild(rippleEngine.mMailServer, rippleEngine.mMailSender, mReleaseManager, rippleEngine.mBaselineName, success);
224
                    }
225
 
226
                    // ... and clean up the mess in the archive
227
                    throw new Exception();                    
228
                  }
229
 
886 mhunt 230
                  if ( reportingFullyPublished != null && reportingFullyPublished.compareTo("yes") == 0 )
814 mhunt 231
                  {
886 mhunt 232
                    buildErrorOccurred = false;
868 mhunt 233
 
924 dpurdie 234
                    if ( reportingNewVcsTag.length() > 0 )
852 mhunt 235
                    {
886 mhunt 236
                      Integer rtagId = new Integer(mRtagId);
237
 
238
                      if ( mGbeGatherMetricsOnly == null )
868 mhunt 239
                      {
906 mhunt 240
                        // publish to release manager
916 mhunt 241
                        mLogger.fatal("run calling mReleaseManager.autoMakeRelease");                      
924 dpurdie 242
                        mReleaseManager.autoMakeRelease(rtagId.toString(),
243
                                                        mReportingPackageName,
244
                                                        mReportingPackageExtension,
245
                                                        mReportingPackageVersion,
246
                                                        reportingNewVcsTag,
247
                                                        mReportingPackageDepends,
248
                                                        mReportingIsRipple);
868 mhunt 249
                      }
886 mhunt 250
 
251
                      FileInputStream abtmetrics = new FileInputStream( rtagId.toString() + "abtmetrics.txt" );
252
                      DataInputStream din = new DataInputStream( abtmetrics );
253
                      InputStreamReader isr = new InputStreamReader( din );
254
                      BufferedReader br = new BufferedReader( isr );
255
                      String metrics = br.readLine();
256
                      mLogger.warn( "execute read metrics string " + metrics );
257
                      br.close();
258
                      isr.close();
259
                      din.close();
260
 
916 mhunt 261
                      mLogger.fatal("run calling mReleaseManager.insertPackageMetrics");                      
886 mhunt 262
                      mReleaseManager.insertPackageMetrics(rtagId.toString(), mReportingPackageName, mReportingPackageExtension, metrics );
852 mhunt 263
                    }
886 mhunt 264
                    else
265
                    {
924 dpurdie 266
                      mLogger.info("run package not labelled in Version Control on " + mReportingPackageName + mReportingPackageVersion);
898 mhunt 267
                      // max 50 characters
924 dpurdie 268
                      rootCause = "Error publishing to Version Control System";
886 mhunt 269
                      throw new Exception();
270
                    }
814 mhunt 271
                  }
272
                  else
273
                  {
886 mhunt 274
                    mLogger.info("run build error occurred on " + mReportingPackageName + mReportingPackageVersion);
814 mhunt 275
                    throw new Exception();
276
                  }
886 mhunt 277
 
814 mhunt 278
                }
886 mhunt 279
                catch( Exception e)
814 mhunt 280
                {
898 mhunt 281
                  // a build error occurred or
924 dpurdie 282
                  // an error occurred publishing to Version Control or Release Manager
886 mhunt 283
                  // take out the archive entry first
284
                  String fs = System.getProperty( "file.separator" );
285
                  String dpkgArchiveEntry = new String(Package.mGbeDpkg + fs + mReportingPackageName + fs + mReportingPackageVersion);
286
                  File dpkgArchiveEntryFile = new File(dpkgArchiveEntry);
287
                  mLogger.info("run checking existence of " + dpkgArchiveEntry);
288
 
289
                  if ( dpkgArchiveEntryFile.exists() )
814 mhunt 290
                  {
886 mhunt 291
                    if ( dpkgArchiveEntryFile.isDirectory() )
292
                    {
293
                      mLogger.warn("run deleting " + dpkgArchiveEntryFile.getName());
916 mhunt 294
                      mLogger.fatal("run calling deleteDirectory on " + dpkgArchiveEntryFile);                      
886 mhunt 295
                      deleteDirectory(dpkgArchiveEntryFile);
296
                    }
814 mhunt 297
                  }
924 dpurdie 298
 
886 mhunt 299
                  Integer rtagId = new Integer(mRtagId);
300
 
301
                  if ( !buildErrorOccurred )
302
                  {
924 dpurdie 303
                    mLogger.fatal("an error occurred publishing to Version Control or Release Manager");
908 mhunt 304
                    // force exclusion by default
305
                    int testBuildInstruction = 0;
306
                    try
307
                    {
308
                      testBuildInstruction = Integer.parseInt( mReportingTestBuild );
309
                    }
310
                    catch( NumberFormatException nfe )
311
                    {
312
                    }
916 mhunt 313
                    mLogger.fatal("run calling excludeFromBuild");                      
908 mhunt 314
                    mReleaseManager.excludeFromBuild(mReportingPackageVersionId, null, rtagId.toString(), null, rootCause, null, false, testBuildInstruction);
924 dpurdie 315
                    throw new Exception("an error occurred publishing to Version Control or Release Manager");
886 mhunt 316
                  }
898 mhunt 317
 
902 mhunt 318
                  // DEVI 55364
319
                  // Package has not been built on all configured platforms
320
                  // Under normal circumstances, this root cause will be masked by a previously reported error
321
                  // Under abnormal circumstances amidst build activity such as:
322
                  // - slave build machine reboots
323
                  // - slave build machines with a read only file system
324
                  // this root cause is required to keep the end user informed
325
                  // max 50 chars
326
                  String cause = "Buildtool env error occurred. Attempt build again";
908 mhunt 327
                  // force exclusion by default
328
                  int testBuildInstruction = 0;
329
                  try
330
                  {
331
                    testBuildInstruction = Integer.parseInt( mReportingTestBuild );
332
                  }
333
                  catch( NumberFormatException nfe )
334
                  {
335
                  }
916 mhunt 336
                  mLogger.fatal("run calling excludeFromBuild");                      
908 mhunt 337
                  mReleaseManager.excludeFromBuild(mReportingPackageVersionId, mReportingPackageVersion, rtagId.toString(), null, mReportingBuildFailureLogFile == null ? cause : null, mReportingBuildFailureLogFile, false, testBuildInstruction);
814 mhunt 338
                }
339
              }
886 mhunt 340
 
896 mhunt 341
              if ( mUnitTest.compareTo("unit test coordinate slave threads") == 0 )            
886 mhunt 342
              {
343
                throw new ExitException();
344
              }
345
              mLogger.info("run coordinate slave threads returned");
814 mhunt 346
            }
347
 
886 mhunt 348
            // DEVI 51366 allowed to proceed after coordinate slave threads
349
            mLogger.warn("run checking allowedToProceed");
916 mhunt 350
            mLogger.fatal("run calling allowedToProceed");                      
886 mhunt 351
            allowedToProceed(true);
352
            mLogger.info("run allowedToProceed returned");
353
 
896 mhunt 354
            if ( mUnitTest.compareTo("unit test allowed to proceed") == 0 )            
886 mhunt 355
            {
356
              throw new ExitException();
357
            }
814 mhunt 358
 
359
            // generate build files
360
            mLogger.warn("run generating build files");
924 dpurdie 361
            mLogger.fatal("run calling planRelease");
814 mhunt 362
            rippleEngine.planRelease();
916 mhunt 363
            mLogger.fatal("run calling reportChange");                      
908 mhunt 364
            rippleEngine.reportChange();
924 dpurdie 365
 
814 mhunt 366
            // get the build file from the ripple engine
367
            rippleEngine.getFirstBuildFileContent(buildFileContent, addendum);
368
 
369
            if ( addendum.value.compareTo("non generic") == 0 )
370
            {
371
              // publish the build file
372
              mLogger.warn("run publishing build file");
916 mhunt 373
              mLogger.fatal("run calling publishBuildFile");                      
814 mhunt 374
              mReleaseManager.publishBuildFile(mRtagId, buildFileContent.value);
375
            }
376
            else
377
            {
378
              // publish a dummy build file for either generic or dummy cases
379
              // this results in the slave not running ant
380
              mLogger.warn("run publishing dummy build file");
916 mhunt 381
              mLogger.fatal("run calling publishBuildFile on dummy");                      
814 mhunt 382
              mReleaseManager.publishBuildFile(mRtagId, mDummyBuildFileContent);
383
            }
384
          }
385
          mLogger.info("run generated build files");
924 dpurdie 386
          // Start of a build cycle. Set new log file to capture entire build log
387
          flagStartBuildCycle();
388
 
814 mhunt 389
 
868 mhunt 390
          if ( mGbeGatherMetricsOnly != null )
391
          {
392
            // set view up early for metrics gathering to ensure build file is fully written before letting the slave loose
916 mhunt 393
            mLogger.fatal("run calling setViewUp");                      
868 mhunt 394
            setViewUp(buildFileContent.value, true);            
395
          }
396
 
814 mhunt 397
          // change the run level for all threads in associated with the baseline
398
          mLogger.warn("run change the run level for all threads in associated with the baseline");
916 mhunt 399
          mLogger.fatal("run calling queryReleaseConfig");                      
814 mhunt 400
          mReleaseManager.queryReleaseConfig(mRtagId);
401
          rconId.value = -1;
402
          boolean moreBuildThreadsConfigured = mReleaseManager.getFirstReleaseConfig(rconId);
403
          mRunLevel = RunLevel.ACTIVE;
404
 
405
          do
406
          {
407
            if (moreBuildThreadsConfigured)
408
            {
816 mhunt 409
                mLogger.warn("run changing run level to ACTIVE for rcon_id " + rconId.value);
916 mhunt 410
                mLogger.fatal("run calling mRunLevel.persist to set ACTIVE");                      
814 mhunt 411
                mRunLevel.persist(mReleaseManager, rconId.value);
412
                moreBuildThreadsConfigured = mReleaseManager.getNextReleaseConfig(rconId);
413
            }
414
          }
415
          while (moreBuildThreadsConfigured);
416
 
896 mhunt 417
          if ( mUnitTest.compareTo("unit test generate build files") == 0 )
814 mhunt 418
          {
419
            throw new ExitException();
420
          }
421
        }
422
 
423
        mLogger.info("run changed run levels");
424
 
425
        // check environment
426
        mLogger.warn("run checkEnvironment");
916 mhunt 427
        mLogger.fatal("run calling checkEnvironment");                      
814 mhunt 428
        checkEnvironment();
429
        mLogger.info("run checkEnvironment returned");
430
 
896 mhunt 431
        if ( mUnitTest.compareTo("unit test check environment") == 0 )
814 mhunt 432
        {
433
          throw new ExitException();
434
        }
435
 
436
        // deliver change to product baseline
437
        mLogger.warn("run deliverChange");
868 mhunt 438
 
439
        if ( mGbeGatherMetricsOnly == null )
440
        {
916 mhunt 441
          mLogger.fatal("run calling setViewUp metrics only");                      
868 mhunt 442
          setViewUp(buildFileContent.value, true);
443
        }
444
 
922 dpurdie 445
        mLogger.fatal("run calling deliverChange - the actual build " + mReportingPackageName + "_" + mReportingPackageVersion);
814 mhunt 446
        deliverChange(null, null, false);
447
        mLogger.info("run deliverChange returned");
886 mhunt 448
 
449
        mSleep = false;
450
        if ( addendum.value.compareTo("dummy") == 0 )
451
        {
452
          // no build requirement, so let things settle
453
          mLogger.warn("run no build requirement, so let things settle");
454
          mSleep = true;
455
        }        
456
 
814 mhunt 457
      }
458
      catch( SQLException e )
459
      {
460
        // oracle connection issues        
461
        mLogger.warn("run oracle connection issues");
886 mhunt 462
        mException = true;
814 mhunt 463
      }
464
      catch( ExitException e )
465
      {
858 mhunt 466
        mLogger.warn("run ExitException");
814 mhunt 467
        exit = true;
468
      }
469
      catch( InterruptedException e )
470
      {
471
        mLogger.warn("run InterruptedException");
472
      }
473
      catch( Exception e )
474
      {
930 dpurdie 475
        mLogger.error("run indefinitePause " + e.toString());
868 mhunt 476
        String cause = e.getMessage();
930 dpurdie 477
        if ( cause == null )
814 mhunt 478
        {
930 dpurdie 479
          cause = e.toString();
480
        }
481
 
482
        try
483
        {
484
          // notify first
485
          // many reasons for indefinite pause, including database related, so do database last
486
          mRecoverable = false;
896 mhunt 487
 
930 dpurdie 488
          if ( cause.compareTo(Package.mRecoverable) == 0 )
868 mhunt 489
          {
930 dpurdie 490
            mRecoverable = true;
868 mhunt 491
          }
930 dpurdie 492
 
493
          indefinitePause(rippleEngine, cause);
494
          mReleaseManager.indefinitePause();
495
          // DEVI 51366 force sleep at beginning of while loop
496
          mException = true;
814 mhunt 497
        }
930 dpurdie 498
        catch( Exception f )
499
        {
500
          mLogger.error("run indefinitePause failed");
501
        }
814 mhunt 502
      }
503
    }
504
  }
505
 
506
  /**returns 'M'
507
   */
508
  protected char getMode()
509
  {
510
    mLogger.debug("getMode");
511
    return 'M';
512
  }
513
}