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
 
16
import java.io.FileReader;
17
 
18
import java.io.IOException;
19
 
20
import java.sql.SQLException;
21
 
22
import java.util.Iterator;
23
 
24
import java.util.Vector;
25
 
26
import org.apache.log4j.Logger;
27
import org.apache.tools.ant.taskdefs.Execute;
28
 
29
/**Master Thread sub component
30
 */
31
public class MasterThread
32
  extends BuildThread
33
{
34
 
35
  /**Logger
36
   * @attribute
37
   */
38
  private static final Logger mLogger = Logger.getLogger(MasterThread.class);
39
 
40
  /**
41
   * @attribute
42
   */
43
  private String[] command = new String[100];
44
 
45
  /**
46
   * @attribute
47
   */
48
  private int commandIndex = 0;
49
 
50
  /**
51
   * @attribute
52
   */
53
  private Execute thread = new Execute();
54
 
55
  /**constructor
56
   */
57
  public MasterThread(int rtag_id, int rcon_id, String gbebuildfilter)
58
  {
818 mhunt 59
    mLogger.warn("MasterThread rtag_id " + rtag_id + " rcon_id " + rcon_id);
814 mhunt 60
    mRtagId = rtag_id;
61
    mRconId = rcon_id;
62
    mGbebuildfilter = gbebuildfilter;
63
  }
64
 
65
  /**implements the sequence diagrams coordinate slave threads, generate build files, allowed to proceed, check environment
66
   */
67
  public void run()
68
  {
69
    Integer id = new Integer(mRtagId);
70
    setName(id.toString());
71
    mLogger.debug("run");
72
    boolean exit = false;
73
    RippleEngine rippleEngine = new RippleEngine(mReleaseManager, mRtagId, true);
74
    MutableInt rconId = new MutableInt();
75
    MutableInt current_run_level = new MutableInt();
76
    MutableString addendum = new MutableString();
77
 
78
    while(!exit)
79
    {
80
      try
81
      {
82
        if ( Thread.currentThread().isInterrupted() )
83
        {
84
          mLogger.warn("run is interrupted");
85
          // unit test technique
86
          throw new ExitException();
87
        }
88
 
89
        if ( mGbebuildfilter.compareTo("unit test spawn thread") == 0)
90
        {
91
          throw new Exception();
92
        }
93
 
94
        // allowed to proceed
95
        MutableString buildFileContent = new MutableString();
96
 
97
        if ( mGbebuildfilter.compareTo("unit test check environment") != 0)
98
        {
99
          if ( mGbebuildfilter.compareTo("unit test generate build files") != 0)
100
          {
101
            if ( mGbebuildfilter.compareTo("unit test coordinate slave threads") != 0 )
102
            {
103
              mLogger.warn("run checking allowedToProceed");
104
              allowedToProceed();
105
              mLogger.info("run allowedToProceed returned");
106
 
107
              if ( mGbebuildfilter.compareTo("unit test allowed to proceed") == 0 )            
108
              {
109
                throw new ExitException();
110
              }
111
            }
112
 
113
            // coordinate slave threads
114
            mLogger.warn("run coordinate slave threads");
115
            boolean allSlaveThreadsWaiting = false;
816 mhunt 116
            boolean logWarning = true;
820 mhunt 117
            boolean logWarning2 = true;
814 mhunt 118
 
119
            while ( !allSlaveThreadsWaiting )
120
            {
121
              mReleaseManager.queryRunLevel(mRtagId);
122
 
123
              // anything but WAITING
124
              current_run_level.value = ReleaseManager.DB_IDLE;
125
              boolean moreRunLevelsConfigured = mReleaseManager.getFirstRunLevel(rconId, current_run_level);
126
 
127
              // attempt to exit loop
128
              allSlaveThreadsWaiting = true;
129
 
130
              do
131
              {
132
                if (moreRunLevelsConfigured)
133
                {
134
                  if (current_run_level.value != ReleaseManager.DB_WAITING)
135
                  {
816 mhunt 136
                    if ( logWarning )
137
                    {
138
                      mLogger.warn("run waiting for rcon id " + rconId.value);
139
                      logWarning = false;
140
                    }
141
                    else
142
                    {
143
                      mLogger.info("run waiting for rcon id " + rconId.value);                      
144
                    }
814 mhunt 145
                    allSlaveThreadsWaiting = false;
146
                  }
147
                  else
148
                  {
149
                    moreRunLevelsConfigured = mReleaseManager.getNextRunLevel(rconId, current_run_level);
150
                  }
151
                }
152
              }
153
              while (moreRunLevelsConfigured && allSlaveThreadsWaiting);
154
 
155
              if ( !allSlaveThreadsWaiting )
156
              {
157
                // to do, sleep for periodicMs
158
                if ( mGbebuildfilter.compareTo("unit test coordinate slave threads") == 0 )
159
                {
160
                  Thread.currentThread().interrupt();
161
                }
162
                else
163
                {
820 mhunt 164
                  if ( logWarning2 )
165
                  {
166
                    mLogger.warn("run sleeping 3 secs waiting for slave threads");
167
                    logWarning2 = false;
168
                  }
169
                  else
170
                  {
171
                    mLogger.info("run sleeping 3 secs waiting for slave threads");
172
                  }
814 mhunt 173
                  Thread.sleep(3000);
174
                  mLogger.info("run sleep returned");
175
                }
176
              }
177
            }
178
 
179
            if ( mGbebuildfilter.compareTo("unit test coordinate slave threads") == 0 )
180
            {
181
              throw new ExitException();
182
            }
183
 
184
            deliverChange(null, "AbtPublish", false);
185
 
186
            // Publishing is done outside ant by design
187
            // The preference is to do all release manager work outside ant
188
            MutableString packageName = new MutableString();
189
            MutableString packageExtension = new MutableString();
190
            MutableString packageVersion = new MutableString();
191
            MutableString packageDepends = new MutableString();
192
            MutableString isRipple = new MutableString();
193
            MutableString packageVersionId = new MutableString();
194
            MutableString fullyPublished = new MutableString();
195
            MutableString newLabel = new MutableString();
852 mhunt 196
            MutableString doesNotRequireSourceControlInteraction = new MutableString();
854 mhunt 197
            boolean buildOccurred = false;
198
 
199
            try
200
            {
201
              buildOccurred = retrieveLastPackage(mRtagId,
202
                                                  packageName, 
203
                                                  packageExtension, 
204
                                                  packageVersion, 
205
                                                  packageDepends, 
206
                                                  isRipple,
207
                                                  packageVersionId, 
208
                                                  fullyPublished,
209
                                                  newLabel,
210
                                                  doesNotRequireSourceControlInteraction);
211
            }
212
            catch( IOException e )
213
            {
214
              // this is caught here to ensure an exception cannot circumvent the deletion of the build file below
215
              mLogger.warn("run IOException");
216
            }
217
 
814 mhunt 218
            if ( buildOccurred )
219
            {
816 mhunt 220
              // buildOccurred simply means a dummy build file did not apply ie the build file had attempted a build
221
              // by now it has been labelled
222
              tearViewDown();
223
 
854 mhunt 224
              // DEVI 47395 delete the build file now
225
              // this will prevent any chance of multiply publishing a package version
226
              File buildFile = new File(mRtagId + "build.xml");
227
 
228
              if ( buildFile.exists() )
229
              {
230
                buildFile.delete();
231
              }
232
 
814 mhunt 233
              boolean buildErrorOccurred = true;
234
              try
235
              {
236
 
237
                if ( fullyPublished.value.compareTo("yes") == 0 )
238
                {
239
                  buildErrorOccurred = false;
240
 
241
                  if ( newLabel.value.length() > 0 )
242
                  {
243
                    Integer rtagId = new Integer(mRtagId);
852 mhunt 244
 
245
                    if ( doesNotRequireSourceControlInteraction.value.length() == 0 )
246
                    {
247
                      // requires source control interaction ie labelled in ClearCase
248
                      // publish to release manager
249
                      mReleaseManager.autoMakeRelease(rtagId.toString(), packageName.value, packageExtension.value, packageVersion.value, newLabel.value, packageDepends.value, isRipple.value);
250
                    }
251
                    else
252
                    {
253
                      // trigger release note generation and on_make_official.wsf, which changes ownership and write access in the archive
254
                      // this should not be through autoMakeRelease (sledgehammer, the package is already official in release manager in this scenario)
255
                      // at the time of writing, calling autoMakeRelease does not help if the package was 'released' more than 24 hours ago
256
                      // this seems to be a business rule in the generate_release_notes package
257
                      // the buildtool has no option but to call autoMakeRelease at present
258
                      mReleaseManager.autoMakeRelease(rtagId.toString(), packageName.value, packageExtension.value, packageVersion.value, newLabel.value, packageDepends.value, isRipple.value);
259
                    }
834 mhunt 260
 
261
                    FileInputStream abtmetrics = new FileInputStream( rtagId.toString() + "abtmetrics.txt" );
262
                    DataInputStream din = new DataInputStream( abtmetrics );
263
                    InputStreamReader isr = new InputStreamReader( din );
264
                    BufferedReader br = new BufferedReader( isr );
265
                    String metrics = br.readLine();
266
                    mLogger.warn( "execute read metrics string " + metrics );
267
                    br.close();
268
                    isr.close();
269
                    din.close();
270
 
271
                    mReleaseManager.insertPackageMetrics(rtagId.toString(), packageName.value, packageExtension.value, metrics );
814 mhunt 272
                  }
273
                  else
274
                  {
275
                    mLogger.info("run package not labelled in ClearCase on " + packageName.value + packageVersion.value);
276
                    throw new Exception();
277
                  }
278
                }
816 mhunt 279
                else
814 mhunt 280
                {
281
                  mLogger.info("run build error occurred on " + packageName.value + packageVersion.value);
282
                  throw new Exception();
283
                }
284
 
285
              }
286
              catch( Exception e)
287
              {
288
                // an error occurred publishing to ClearCase or Release Manager
289
                // take out the archive entry first
290
                String fs = System.getProperty( "file.separator" );
291
                String dpkgArchiveEntry = new String(Package.mGbeDpkg + fs + packageName.value + fs + packageVersion.value);
292
                File dpkgArchiveEntryFile = new File(dpkgArchiveEntry);
293
                mLogger.info("run checking existence of " + dpkgArchiveEntry);
294
 
295
                if ( dpkgArchiveEntryFile.exists() )
296
                {
297
                  if ( dpkgArchiveEntryFile.isDirectory() )
298
                  {
299
                    mLogger.warn("run deleting " + dpkgArchiveEntryFile.getName());
300
                    deleteDirectory(dpkgArchiveEntryFile);
301
                  }
302
                }
303
                else
304
                {
305
                  String dplyArchiveEntry = new String(Package.mGbeDply + fs + packageName.value + fs + packageVersion.value);
306
                  File dplyArchiveEntryFile = new File(dplyArchiveEntry);
307
                  mLogger.info("run checking existence of " + dplyArchiveEntry);
308
 
309
                  if ( dplyArchiveEntryFile.exists() )
310
                  {
311
                    if ( dplyArchiveEntryFile.isDirectory() )
312
                    {
313
                      mLogger.warn("run deleting " + dplyArchiveEntryFile.getName());
314
                      deleteDirectory(dplyArchiveEntryFile);
315
                    }
316
                  }
317
                }
318
 
820 mhunt 319
                Integer rtagId = new Integer(mRtagId);
320
                mReleaseManager.excludeFromBuild(packageVersionId.value, packageVersion.value, rtagId.toString());
321
 
322
                if ( !buildErrorOccurred )
814 mhunt 323
                {
324
                  mLogger.fatal("an error occurred publishing to ClearCase or Release Manager");
325
                  throw new Exception();
326
                }
327
              }
328
            }
329
 
330
            mLogger.info("run coordinate slave threads returned");
331
 
332
            // generate build files
333
            mLogger.warn("run generating build files");
334
            rippleEngine.planRelease();
335
 
336
            // get the build file from the ripple engine
337
            rippleEngine.getFirstBuildFileContent(buildFileContent, addendum);
338
 
339
            if ( addendum.value.compareTo("non generic") == 0 )
340
            {
341
              // publish the build file
342
              mLogger.warn("run publishing build file");
343
              mReleaseManager.publishBuildFile(mRtagId, buildFileContent.value);
344
            }
345
            else
346
            {
347
              // publish a dummy build file for either generic or dummy cases
348
              // this results in the slave not running ant
349
              mLogger.warn("run publishing dummy build file");
350
              mReleaseManager.publishBuildFile(mRtagId, mDummyBuildFileContent);
351
            }
352
          }
353
          mLogger.info("run generated build files");
354
 
355
          // change the run level for all threads in associated with the baseline
356
          mLogger.warn("run change the run level for all threads in associated with the baseline");
357
          mReleaseManager.queryReleaseConfig(mRtagId);
358
          rconId.value = -1;
359
          boolean moreBuildThreadsConfigured = mReleaseManager.getFirstReleaseConfig(rconId);
360
          mRunLevel = RunLevel.ACTIVE;
361
 
362
          do
363
          {
364
            if (moreBuildThreadsConfigured)
365
            {
816 mhunt 366
                mLogger.warn("run changing run level to ACTIVE for rcon_id " + rconId.value);
814 mhunt 367
                mRunLevel.persist(mReleaseManager, rconId.value);
368
                moreBuildThreadsConfigured = mReleaseManager.getNextReleaseConfig(rconId);
369
            }
370
          }
371
          while (moreBuildThreadsConfigured);
372
 
373
          if ( mGbebuildfilter.compareTo("unit test generate build files") == 0 )
374
          {
375
            throw new ExitException();
376
          }
377
        }
378
 
379
        mLogger.info("run changed run levels");
380
 
381
        // check environment
382
        mLogger.warn("run checkEnvironment");
383
        checkEnvironment();
384
        mLogger.info("run checkEnvironment returned");
385
 
386
        if ( mGbebuildfilter.compareTo("unit test check environment") == 0 )
387
        {
388
          throw new ExitException();
389
        }
390
 
391
        // deliver change to product baseline
392
        mLogger.warn("run deliverChange");
393
        setViewUp(buildFileContent.value, true);
394
        deliverChange(null, null, false);
395
        mLogger.info("run deliverChange returned");
396
      }
397
      catch( SQLException e )
398
      {
399
        // oracle connection issues        
400
        mLogger.warn("run oracle connection issues");
820 mhunt 401
        mSleep = true;
814 mhunt 402
      }
403
      catch( ExitException e )
404
      {
858 mhunt 405
        mLogger.warn("run ExitException");
814 mhunt 406
        exit = true;
407
      }
408
      catch( InterruptedException e )
409
      {
410
        mLogger.warn("run InterruptedException");
411
      }
412
      catch( Exception e )
413
      {
414
        mLogger.error("run indefinitePause");
415
        try
416
        {
417
          mReleaseManager.indefinitePause();
418
        }
419
        catch( Exception f )
420
        {
421
          mLogger.error("run indefinitePause failed");
422
        }
423
      }
424
 
425
      mSleep = false;
426
      if ( addendum.value.compareTo("dummy") == 0 )
427
      {
428
        // no build requirement, so let things settle
429
        mLogger.warn("run no build requirement, so let things settle");
430
        mSleep = true;
431
      }
432
    }
433
  }
434
 
435
  /**returns 'M'
436
   */
437
  protected char getMode()
438
  {
439
    mLogger.debug("getMode");
440
    return 'M';
441
  }
442
 
443
  /**retrieves details concerning the last package built for an rtag_id
444
   * isRipple = "0" (a WIP or direct change) or "1"
445
   * generic = "generic" or not
446
   * buildStandard = "JATS" or "ANT"
447
   */
448
  boolean retrieveLastPackage(int rtagId, MutableString packageName, 
449
                              MutableString packageExtension, 
450
                              MutableString packageVersion, 
451
                              MutableString packageDepends, 
452
                              MutableString isRipple, 
453
                              MutableString packageVersionId, 
454
                              MutableString fullyPublished,
852 mhunt 455
                              MutableString newLabel,
456
                              MutableString doesNotRequireSourceControlInteraction) throws IOException
814 mhunt 457
  {
458
    mLogger.debug("retrieveLastPackage");
459
    boolean retVal = false;
460
    Integer rtag = new Integer(rtagId);
461
    File rtagIdOfficial = new File(rtag + "official");
462
 
463
    if ( rtagIdOfficial.exists() )
464
    {
465
      // read <rtagId>offical
466
      FileReader rtagIdOfficialFileReader = new FileReader(rtagIdOfficial);
467
      BufferedReader rtagIdOfficialBufferedReader = new BufferedReader(rtagIdOfficialFileReader);
468
      String line;
469
 
470
      while( ( line = rtagIdOfficialBufferedReader.readLine() ) != null)
471
      {
472
        String []keyVal = line.split("=", 2);
852 mhunt 473
 
474
        if ( keyVal.length == 2 )
814 mhunt 475
        {
852 mhunt 476
          if (keyVal[0].compareTo("packageName") == 0)
477
          {
478
            packageName.value = keyVal[1];
479
            mLogger.info("retrieveLastPackage packageName " + packageName.value);
480
          }
481
          else
482
          if (keyVal[0].compareTo("packageExtension") == 0)
483
          {
484
            packageExtension.value = keyVal[1];
485
            mLogger.info("retrieveLastPackage packageExtension " + packageExtension.value);
486
          }
487
          else
488
          if (keyVal[0].compareTo("packageVersion") == 0)
489
          {
490
            packageVersion.value = keyVal[1];
491
            mLogger.info("retrieveLastPackage packageVersion " + packageVersion.value);
492
          }
493
          else
494
          if (keyVal[0].compareTo("packageDepends") == 0)
495
          {
496
            packageDepends.value = keyVal[1];
497
            mLogger.info("retrieveLastPackage packageDepends " + packageDepends.value);
498
          }
499
          else
500
          if (keyVal[0].compareTo("packageRipple") == 0)
501
          {
502
            isRipple.value = keyVal[1];
503
            mLogger.info("retrieveLastPackage packageRipple " + isRipple.value);
504
          }
505
          else
506
          if (keyVal[0].compareTo("packageVersionID") == 0)
507
          {
508
            packageVersionId.value = keyVal[1];
509
            mLogger.info("retrieveLastPackage packageVersionID " + packageVersionId.value);
510
          }
511
          else
512
          if (keyVal[0].compareTo("fullyPublished") == 0)
513
          {
514
            fullyPublished.value = keyVal[1];
515
            mLogger.info("retrieveLastPackage fullyPublished " + fullyPublished.value);
516
          }
517
          else
518
          if (keyVal[0].compareTo("newLabel") == 0)
519
          {
520
            newLabel.value = keyVal[1];
521
            mLogger.info("retrieveLastPackage newLabel " + newLabel.value);
522
          }
523
          else
524
          if (keyVal[0].compareTo("doesNotRequireSourceControlInteraction") == 0)
525
          {
526
            doesNotRequireSourceControlInteraction.value = keyVal[1];
527
            mLogger.info("retrieveLastPackage doesNotRequireSourceControlInteraction " + doesNotRequireSourceControlInteraction.value);
528
          }
814 mhunt 529
        }
530
      }
531
      rtagIdOfficialBufferedReader.close();
826 mhunt 532
      rtagIdOfficialFileReader.close();
533
 
534
      boolean del = rtagIdOfficial.delete();
535
 
536
      if ( !del )
537
      {
538
        // the delete failed
539
        // some literature suggests a forced garbage collection may free up resources associated with file handles
540
        // nothing to lose since the file "must" be deleted
541
        System.gc();
542
        del = rtagIdOfficial.delete();
543
 
544
        if ( !del )
545
        {
546
          mLogger.fatal("rtagIdOfficial.delete() returned " + del);
547
        }
548
      }
814 mhunt 549
      retVal = true;
550
    }
551
 
552
 
553
    mLogger.info("retrieveLastPackage returned " + retVal);
554
    return retVal;
555
  }
556
}