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
                {
908 mhunt 196
                  if ( mReportingTestBuild.compareTo("0") != 0 )
197
                  {
198
                    mLogger.info("run completing test build on " + mReportingPackageName + mReportingPackageExtension);
199
                    // build failure emails will have been sent
200
                    // just left to notify the user of the test build completion
201
                    Package p = rippleEngine.findPackage(mReportingPackageName + mReportingPackageExtension);
202
 
203
                    if (p != ReleaseManager.NULL_PACKAGE)
204
                    {
205
                      boolean success = false;
206
 
207
                      if ( reportingFullyPublished != null && reportingFullyPublished.compareTo("yes") == 0 )
208
                      {
209
                        success = true;
210
                      }
211
 
212
                      p.completeTestBuild(rippleEngine.mMailServer, rippleEngine.mMailSender, mReleaseManager, rippleEngine.mBaselineName, success);
213
                    }
214
 
215
                    // ... and clean up the mess in the archive
216
                    throw new Exception();                    
217
                  }
218
 
886 mhunt 219
                  if ( reportingFullyPublished != null && reportingFullyPublished.compareTo("yes") == 0 )
814 mhunt 220
                  {
886 mhunt 221
                    buildErrorOccurred = false;
868 mhunt 222
 
886 mhunt 223
                    if ( reportingNewLabel.length() > 0 )
852 mhunt 224
                    {
886 mhunt 225
                      Integer rtagId = new Integer(mRtagId);
226
 
227
                      if ( mGbeGatherMetricsOnly == null )
868 mhunt 228
                      {
906 mhunt 229
                        // publish to release manager
230
                        mReleaseManager.autoMakeRelease(rtagId.toString(), mReportingPackageName, mReportingPackageExtension, mReportingPackageVersion, reportingNewLabel, mReportingPackageDepends, mReportingIsRipple);
868 mhunt 231
                      }
886 mhunt 232
 
233
                      FileInputStream abtmetrics = new FileInputStream( rtagId.toString() + "abtmetrics.txt" );
234
                      DataInputStream din = new DataInputStream( abtmetrics );
235
                      InputStreamReader isr = new InputStreamReader( din );
236
                      BufferedReader br = new BufferedReader( isr );
237
                      String metrics = br.readLine();
238
                      mLogger.warn( "execute read metrics string " + metrics );
239
                      br.close();
240
                      isr.close();
241
                      din.close();
242
 
243
                      mReleaseManager.insertPackageMetrics(rtagId.toString(), mReportingPackageName, mReportingPackageExtension, metrics );
852 mhunt 244
                    }
886 mhunt 245
                    else
246
                    {
247
                      mLogger.info("run package not labelled in ClearCase on " + mReportingPackageName + mReportingPackageVersion);
898 mhunt 248
                      // max 50 characters
249
                      rootCause = "Error publishing to ClearCase";
886 mhunt 250
                      throw new Exception();
251
                    }
814 mhunt 252
                  }
253
                  else
254
                  {
886 mhunt 255
                    mLogger.info("run build error occurred on " + mReportingPackageName + mReportingPackageVersion);
814 mhunt 256
                    throw new Exception();
257
                  }
886 mhunt 258
 
814 mhunt 259
                }
886 mhunt 260
                catch( Exception e)
814 mhunt 261
                {
898 mhunt 262
                  // a build error occurred or
886 mhunt 263
                  // an error occurred publishing to ClearCase or Release Manager
264
                  // take out the archive entry first
265
                  String fs = System.getProperty( "file.separator" );
266
                  String dpkgArchiveEntry = new String(Package.mGbeDpkg + fs + mReportingPackageName + fs + mReportingPackageVersion);
267
                  File dpkgArchiveEntryFile = new File(dpkgArchiveEntry);
268
                  mLogger.info("run checking existence of " + dpkgArchiveEntry);
269
 
270
                  if ( dpkgArchiveEntryFile.exists() )
814 mhunt 271
                  {
886 mhunt 272
                    if ( dpkgArchiveEntryFile.isDirectory() )
273
                    {
274
                      mLogger.warn("run deleting " + dpkgArchiveEntryFile.getName());
275
                      deleteDirectory(dpkgArchiveEntryFile);
276
                    }
814 mhunt 277
                  }
886 mhunt 278
                  else
814 mhunt 279
                  {
886 mhunt 280
                    String dplyArchiveEntry = new String(Package.mGbeDply + fs + mReportingPackageName + fs + mReportingPackageVersion);
281
                    File dplyArchiveEntryFile = new File(dplyArchiveEntry);
282
                    mLogger.info("run checking existence of " + dplyArchiveEntry);
283
 
284
                    if ( dplyArchiveEntryFile.exists() )
814 mhunt 285
                    {
886 mhunt 286
                      if ( dplyArchiveEntryFile.isDirectory() )
287
                      {
288
                        mLogger.warn("run deleting " + dplyArchiveEntryFile.getName());
289
                        deleteDirectory(dplyArchiveEntryFile);
290
                      }
814 mhunt 291
                    }
292
                  }
886 mhunt 293
 
294
                  Integer rtagId = new Integer(mRtagId);
295
 
296
                  if ( !buildErrorOccurred )
297
                  {
298
                    mLogger.fatal("an error occurred publishing to ClearCase or Release Manager");
908 mhunt 299
                    // force exclusion by default
300
                    int testBuildInstruction = 0;
301
                    try
302
                    {
303
                      testBuildInstruction = Integer.parseInt( mReportingTestBuild );
304
                    }
305
                    catch( NumberFormatException nfe )
306
                    {
307
                    }
308
                    mReleaseManager.excludeFromBuild(mReportingPackageVersionId, null, rtagId.toString(), null, rootCause, null, false, testBuildInstruction);
886 mhunt 309
                    throw new Exception("an error occurred publishing to ClearCase or Release Manager");
310
                  }
898 mhunt 311
 
902 mhunt 312
                  // DEVI 55364
313
                  // Package has not been built on all configured platforms
314
                  // Under normal circumstances, this root cause will be masked by a previously reported error
315
                  // Under abnormal circumstances amidst build activity such as:
316
                  // - slave build machine reboots
317
                  // - slave build machines with a read only file system
318
                  // this root cause is required to keep the end user informed
319
                  // max 50 chars
320
                  String cause = "Buildtool env error occurred. Attempt build again";
908 mhunt 321
                  // force exclusion by default
322
                  int testBuildInstruction = 0;
323
                  try
324
                  {
325
                    testBuildInstruction = Integer.parseInt( mReportingTestBuild );
326
                  }
327
                  catch( NumberFormatException nfe )
328
                  {
329
                  }
330
                  mReleaseManager.excludeFromBuild(mReportingPackageVersionId, mReportingPackageVersion, rtagId.toString(), null, mReportingBuildFailureLogFile == null ? cause : null, mReportingBuildFailureLogFile, false, testBuildInstruction);
814 mhunt 331
                }
332
              }
886 mhunt 333
 
896 mhunt 334
              if ( mUnitTest.compareTo("unit test coordinate slave threads") == 0 )            
886 mhunt 335
              {
336
                throw new ExitException();
337
              }
338
              mLogger.info("run coordinate slave threads returned");
814 mhunt 339
            }
340
 
886 mhunt 341
            // DEVI 51366 allowed to proceed after coordinate slave threads
342
            mLogger.warn("run checking allowedToProceed");
343
            allowedToProceed(true);
344
            mLogger.info("run allowedToProceed returned");
345
 
896 mhunt 346
            if ( mUnitTest.compareTo("unit test allowed to proceed") == 0 )            
886 mhunt 347
            {
348
              throw new ExitException();
349
            }
814 mhunt 350
 
351
            // generate build files
352
            mLogger.warn("run generating build files");
353
            rippleEngine.planRelease();
908 mhunt 354
            rippleEngine.reportChange();
814 mhunt 355
 
356
            // get the build file from the ripple engine
357
            rippleEngine.getFirstBuildFileContent(buildFileContent, addendum);
358
 
359
            if ( addendum.value.compareTo("non generic") == 0 )
360
            {
361
              // publish the build file
362
              mLogger.warn("run publishing build file");
363
              mReleaseManager.publishBuildFile(mRtagId, buildFileContent.value);
364
            }
365
            else
366
            {
367
              // publish a dummy build file for either generic or dummy cases
368
              // this results in the slave not running ant
369
              mLogger.warn("run publishing dummy build file");
370
              mReleaseManager.publishBuildFile(mRtagId, mDummyBuildFileContent);
371
            }
372
          }
373
          mLogger.info("run generated build files");
374
 
868 mhunt 375
          if ( mGbeGatherMetricsOnly != null )
376
          {
377
            // set view up early for metrics gathering to ensure build file is fully written before letting the slave loose
378
            setViewUp(buildFileContent.value, true);            
379
          }
380
 
814 mhunt 381
          // change the run level for all threads in associated with the baseline
382
          mLogger.warn("run change the run level for all threads in associated with the baseline");
383
          mReleaseManager.queryReleaseConfig(mRtagId);
384
          rconId.value = -1;
385
          boolean moreBuildThreadsConfigured = mReleaseManager.getFirstReleaseConfig(rconId);
386
          mRunLevel = RunLevel.ACTIVE;
387
 
388
          do
389
          {
390
            if (moreBuildThreadsConfigured)
391
            {
816 mhunt 392
                mLogger.warn("run changing run level to ACTIVE for rcon_id " + rconId.value);
814 mhunt 393
                mRunLevel.persist(mReleaseManager, rconId.value);
394
                moreBuildThreadsConfigured = mReleaseManager.getNextReleaseConfig(rconId);
395
            }
396
          }
397
          while (moreBuildThreadsConfigured);
398
 
896 mhunt 399
          if ( mUnitTest.compareTo("unit test generate build files") == 0 )
814 mhunt 400
          {
401
            throw new ExitException();
402
          }
403
        }
404
 
405
        mLogger.info("run changed run levels");
406
 
407
        // check environment
408
        mLogger.warn("run checkEnvironment");
409
        checkEnvironment();
410
        mLogger.info("run checkEnvironment returned");
411
 
896 mhunt 412
        if ( mUnitTest.compareTo("unit test check environment") == 0 )
814 mhunt 413
        {
414
          throw new ExitException();
415
        }
416
 
417
        // deliver change to product baseline
418
        mLogger.warn("run deliverChange");
868 mhunt 419
 
420
        if ( mGbeGatherMetricsOnly == null )
421
        {
422
          setViewUp(buildFileContent.value, true);
423
        }
424
 
814 mhunt 425
        deliverChange(null, null, false);
426
        mLogger.info("run deliverChange returned");
886 mhunt 427
 
428
        mSleep = false;
429
        if ( addendum.value.compareTo("dummy") == 0 )
430
        {
431
          // no build requirement, so let things settle
432
          mLogger.warn("run no build requirement, so let things settle");
433
          mSleep = true;
434
        }        
435
 
814 mhunt 436
      }
437
      catch( SQLException e )
438
      {
439
        // oracle connection issues        
440
        mLogger.warn("run oracle connection issues");
886 mhunt 441
        mException = true;
814 mhunt 442
      }
443
      catch( ExitException e )
444
      {
858 mhunt 445
        mLogger.warn("run ExitException");
814 mhunt 446
        exit = true;
447
      }
448
      catch( InterruptedException e )
449
      {
450
        mLogger.warn("run InterruptedException");
451
      }
452
      catch( Exception e )
453
      {
454
        mLogger.error("run indefinitePause");
868 mhunt 455
        String cause = e.getMessage();
456
 
457
        if ( cause != null )
814 mhunt 458
        {
868 mhunt 459
          try
460
          {
461
            // notify first
462
            // many reasons for indefinite pause, including database related, so do database last
896 mhunt 463
            mRecoverable = false;
464
 
465
            if ( cause.compareTo(Package.mRecoverable) == 0 )
466
            {
467
              mRecoverable = true;
468
            }
469
 
868 mhunt 470
            indefinitePause(rippleEngine, cause);
471
            mReleaseManager.indefinitePause();
886 mhunt 472
            // DEVI 51366 force sleep at beginning of while loop
473
            mException = true;
868 mhunt 474
          }
475
          catch( Exception f )
476
          {
477
            mLogger.error("run indefinitePause failed");
478
          }
814 mhunt 479
        }
480
      }
481
    }
482
  }
483
 
484
  /**returns 'M'
485
   */
486
  protected char getMode()
487
  {
488
    mLogger.debug("getMode");
489
    return 'M';
490
  }
491
}