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.ripple.Package;
4285 dpurdie 4
import com.erggroup.buildtool.ripple.ReleaseConfig;
814 mhunt 5
import com.erggroup.buildtool.ripple.ReleaseManager;
1350 dpurdie 6
import com.erggroup.buildtool.daemon.NagiosThread;
814 mhunt 7
 
854 mhunt 8
import java.io.File;
1352 dpurdie 9
import java.io.IOException;
814 mhunt 10
import java.net.InetAddress;
11
import java.net.UnknownHostException;
1350 dpurdie 12
import java.net.ServerSocket;
814 mhunt 13
import java.sql.SQLException;
14
import java.util.Iterator;
15
import java.util.Vector;
16
 
17
import org.apache.log4j.Logger;
18
import org.apache.log4j.xml.DOMConfigurator;
19
 
20
/**BuildDaemon sub component and entry point (main BuildDaemon thread)
21
 */
22
public class BuildDaemon
23
{
24
 
25
  /**hostname
26
   * @attribute
27
   */
28
  static String mHostname = new String();
29
 
854 mhunt 30
  /**GBE_LOG
31
   * @attribute
32
   */
33
  static String mGbeLog = new String();
34
 
814 mhunt 35
  /**Logger
36
   * @attribute
37
   */
38
  private static final Logger mLogger = Logger.getLogger(BuildDaemon.class);
39
 
40
  /**Collection of ThreadIdentifier objects.
41
   * @attribute
42
   */
864 mhunt 43
  private Vector<ThreadIdentifier> mThreadCollection = new Vector<ThreadIdentifier>();
814 mhunt 44
 
1350 dpurdie 45
  /**Nagios
46
   * @attribute
47
   */
48
  ServerSocket nagiosSrv;
49
  NagiosThread nagiosChecker;
50
 
814 mhunt 51
  /**mThreadCollection items
52
   */
53
  private class ThreadIdentifier
54
  {
55
    /**rcon_id associated with the thread
56
     * @attribute
57
     */
58
    private final int mRcon_id;
59
 
60
    /**thread identifier
61
     * @attribute
62
     */
1361 dpurdie 63
    private final BuildThread mThread;
814 mhunt 64
 
65
    /**constructor
66
     */
1361 dpurdie 67
    ThreadIdentifier(int rcon_id, BuildThread thread)
814 mhunt 68
    {
69
      mLogger.debug("ThreadIdentifier " + rcon_id);
70
      mRcon_id = rcon_id;
71
      mThread = thread;
72
    }
73
 
74
    /**accessor
75
     */
76
    int get_rcon_id()
77
    {
78
      mLogger.debug("get_rcon_id");
79
      mLogger.info("get_rcon_id returned " + mRcon_id);
80
      return mRcon_id;
81
    }
82
 
83
    /**accessor
84
     */
1361 dpurdie 85
    BuildThread get_thread()
814 mhunt 86
    {
87
      mLogger.debug("get_thread");
88
      return mThread;
89
    }
90
  }
91
 
92
  /**main method for the Build Daemon program
93
   * instantiates a BuildDaemon object
94
   */
95
  public static void main(String[] args)
96
  {
858 mhunt 97
    String abtdXml = System.getenv("ABT_HOME");
98
 
99
    if ( abtdXml != null )
100
    {
101
      abtdXml += System.getProperty( "file.separator" ) + "abtd.xml";
102
    }
103
    else
104
    {
105
      abtdXml = new String("abtd.xml");
106
    }
107
    DOMConfigurator.configure(abtdXml);
108
    mLogger.debug("main");
854 mhunt 109
    String antHome = System.getenv("ANT_HOME");
110
 
111
    if ( antHome == null )
112
    {
113
      mLogger.fatal("main ANT_HOME not set");
114
      System.exit(1);
115
    }
116
 
117
    mGbeLog = System.getenv("GBE_LOG");
118
 
119
    if ( mGbeLog == null )
120
    {
121
      mLogger.fatal("main GBE_LOG not set");
122
      System.exit(1);
123
    }
124
 
125
    File gl = new File( mGbeLog );
126
 
127
    if ( !gl.isDirectory() )
128
    {
129
      mLogger.fatal("main GBE_LOG is not a directory");
130
    }
131
 
132
    String gbeUNC = System.getenv("GBE_UNC");
133
 
134
    if ( gbeUNC == null )
135
    {
136
      mLogger.fatal("main GBE_UNC not set");
137
      System.exit(1);
138
    }
139
 
814 mhunt 140
    String connectionString = System.getenv("GBE_RM_LOCATION");
141
    String username = System.getenv("GBE_RM_USERNAME");
142
    String password = System.getenv("GBE_RM_PASSWORD");
143
 
144
    for (int optind = 0; optind < args.length; optind++)
145
    {
146
      if (args[optind].equals("-c") && optind < (args.length - 1))
147
      {
148
        connectionString = args[++optind];
149
      }
150
      else if (args[optind].equals("-u") && optind < (args.length - 1))
151
      {
152
        username = args[++optind];
153
      }
154
      else if (args[optind].equals("-p") && optind < (args.length - 1))
155
      {
156
        password = args[++optind];
157
      }
158
    }
159
 
854 mhunt 160
    if (connectionString == null ||
161
        connectionString.length() == 0 ||
162
        username == null ||
163
        username.length() == 0 ||
164
        password == null ||
165
        password.length() == 0)
814 mhunt 166
    {
854 mhunt 167
      mLogger.fatal("Usage: java -jar abtdD.jar -c connectionString -u username -p password");
814 mhunt 168
      System.exit(1);
169
    }
1350 dpurdie 170
 
814 mhunt 171
    BuildDaemon buildDaemon = new BuildDaemon(connectionString, username, password);
172
    buildDaemon.cleanUp();
173
 
174
  }
175
 
176
  /**constructor, implements the sequence diagram spawn thread
177
   */
178
  public BuildDaemon(String connectionString, String username, 
179
                     String password)
180
  {
4123 dpurdie 181
    mLogger.warn("BuildDaemon");
4285 dpurdie 182
    ReleaseManager releaseManager = new ReleaseManager(connectionString, username + "[release_manager]", password);
814 mhunt 183
    boolean run = true;
4285 dpurdie 184
    String utf = null;
814 mhunt 185
 
186
    try
187
    {
188
      InetAddress local = InetAddress.getLocalHost();
4285 dpurdie 189
      mHostname = local.getHostName();
814 mhunt 190
      mLogger.info("BuildDaemon set hostname " + mHostname);
191
 
4285 dpurdie 192
      // Flag UTF in progress
193
      if ( connectionString.compareTo("unit test spawn thread") == 0 )
194
      {
195
        utf = connectionString;
196
      }
197
 
924 dpurdie 198
      if ( Package.mGenericMachtype == null )
814 mhunt 199
      {
924 dpurdie 200
        mLogger.fatal("run GBE_MACHTYPE not set");
201
        throw new Exception("run GBE_MACHTYPE not set");
814 mhunt 202
      }
924 dpurdie 203
 
204
      if ( Package.mGbeDpkg == null )
205
      {
206
        mLogger.fatal("run GBE_DPKG not set");
207
        throw new Exception("run GBE_DPKG not set");
208
      }
209
 
4285 dpurdie 210
      //	Set the default handler invoked when a thread abruptly terminates due to an
211
      //	uncaught exception, and no other handler has been defined for that thread.
212
      //
4123 dpurdie 213
      Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler());
214
 
1350 dpurdie 215
      //
216
      //  Start the Nagios Interface Thread
217
      //
1365 dpurdie 218
      if ( connectionString.compareTo("unit test spawn thread") != 0 )
219
      {
220
        try {
221
          nagiosSrv = new ServerSocket(1111);
222
          nagiosChecker = new NagiosThread(nagiosSrv, this);
223
          nagiosChecker.start();
224
        } catch ( IOException e ) {
225
              mLogger.fatal("Failed to start Nagios Service. Port already in use");
226
              throw new Exception("Nagios port in use");
227
        }
1352 dpurdie 228
      }
4285 dpurdie 229
 
230
      //	Discover new build daemons to be started on the current host
231
      //
814 mhunt 232
      while (run)
233
      {
234
        try
235
        {
4285 dpurdie 236
        	// Create a list of all machines that are configured to run on this machine
237
        	//
238
        	releaseManager.queryReleaseConfig(mHostname);
239
 
240
          //
241
          //  Iterate over all the configured machines
242
          //	Start up new build threads for new machines
243
          //
244
          for (Iterator<ReleaseConfig> it = releaseManager.mReleaseConfigCollection.iterator(); it.hasNext(); )
820 mhunt 245
          {
4285 dpurdie 246
            ReleaseConfig rc = it.next();
247
 
248
            if (!isActive(rc.get_rcon_id()))
814 mhunt 249
            {
4285 dpurdie 250
              mLogger.warn("BuildDaemon activating " + rc.get_rtag_id() + " " + rc.get_rcon_id() + " " + rc.get_daemon_mode());
251
 
252
 
253
              // spawn and run the BuildThread
254
              if (rc.get_daemon_mode() == 'M')
814 mhunt 255
              {
4285 dpurdie 256
                MasterThread thread = new MasterThread(rc.get_rtag_id(), rc.get_rcon_id(), utf);
257
                ThreadIdentifier threadIdentifier =  new ThreadIdentifier(rc.get_rcon_id(), thread);
258
                mThreadCollection.add(threadIdentifier);
259
                // begin thread execution and invoke thread.run();
260
                thread.start();
814 mhunt 261
              }
4285 dpurdie 262
              else if (rc.get_daemon_mode() == 'S')
263
              {
264
                SlaveThread thread = new SlaveThread(rc.get_rtag_id(), rc.get_rcon_id(), utf);
265
                ThreadIdentifier threadIdentifier = new ThreadIdentifier(rc.get_rcon_id(), thread);
266
                mThreadCollection.add(threadIdentifier);
267
                // begin thread execution and invoke thread.run();
268
                thread.start();
269
              }
814 mhunt 270
            }
4285 dpurdie 271
 
814 mhunt 272
          }
4285 dpurdie 273
 
274
          //	In UTF mode we only execute the loop once
275
          if ( utf != null )
814 mhunt 276
          {
820 mhunt 277
            run = false;
4285 dpurdie 278
            continue;
814 mhunt 279
          }
4285 dpurdie 280
 
281
          // Wait 10 minutes before we try to discover new machines
814 mhunt 282
 
4285 dpurdie 283
          mLogger.warn("BuildDaemon sleep for 10 mins");
284
          Thread.sleep(600000);
285
          mLogger.info("BuildDaemon sleep returned");
286
 
814 mhunt 287
        }
288
        catch (SQLException e)
289
        {
290
          mLogger.warn("BuildDaemon caught SQLException");
291
        }
292
        catch (InterruptedException e)
293
        {
294
          mLogger.warn("BuildDaemon caught InterruptedException");
295
        }
296
        catch (Exception e)
297
        {
820 mhunt 298
          mLogger.warn("BuildDaemon caught Exception");
814 mhunt 299
        }
300
      }
301
    }
302
    catch( UnknownHostException e )
303
    {
304
      mLogger.fatal("BuildDaemon caught UnknownHostException");
305
    }
306
    catch( Exception e )
307
    {
308
      mLogger.fatal("BuildDaemon caught Exception");
309
    }
310
  }
311
 
312
  /**calls isAlive on the Thread object associated with the rcon_id
313
   */
314
  public boolean isActive(final int rcon_id)
315
  {
316
    mLogger.debug("isActive " + rcon_id);
317
    boolean retVal = false;
4123 dpurdie 318
    boolean found = false;
814 mhunt 319
 
864 mhunt 320
    for (Iterator<ThreadIdentifier> it = mThreadCollection.iterator(); it.hasNext(); )
814 mhunt 321
    {
864 mhunt 322
      ThreadIdentifier threadIdentifier = it.next();
814 mhunt 323
 
324
      if (threadIdentifier.get_rcon_id() == rcon_id)
325
      {
4123 dpurdie 326
        found = true;
814 mhunt 327
        if (threadIdentifier.get_thread().isAlive())
328
        {
329
          retVal = true;
844 dpurdie 330
          break;
814 mhunt 331
        }
844 dpurdie 332
        else
333
        {
334
            mLogger.warn("isActive found dead thread " + rcon_id );
335
        }
814 mhunt 336
      }
337
    }
4123 dpurdie 338
 
339
    if ( !found )
340
    {
341
        mLogger.warn("isActive thread not found " + rcon_id);
342
    }
343
 
344
    mLogger.warn("isActive returned " + retVal);
814 mhunt 345
    return retVal;
346
  }
347
 
1361 dpurdie 348
    /**
349
     *  Nagios interface
350
     *      Returns true if ALL the thread looks OK
351
     *      Must have one active thread
352
    */
353
    boolean checkThreads()
354
    {
355
      boolean retVal = false;
356
        mLogger.info("checkThreads called");
357
      for (Iterator<ThreadIdentifier> it = mThreadCollection.iterator(); it.hasNext(); )
358
      {
359
        ThreadIdentifier threadIdentifier = it.next();
360
 
361
        if (threadIdentifier.get_thread().checkThread())
362
        {
363
          retVal = true;
364
        }
365
        else
366
        {
367
          retVal = false;
368
          break;
369
        }
370
      }
371
 
372
      mLogger.info("checkThreads returned " + retVal);
373
      return retVal;
374
    }
375
 
376
 
814 mhunt 377
  /**terminates all BuildThreads
378
   */
379
  public void cleanUp()
380
  {
4123 dpurdie 381
    mLogger.warn("cleanUp");
1354 dpurdie 382
    if ( nagiosChecker != null )
383
    {
384
        nagiosChecker.terminate();
385
    }
1350 dpurdie 386
 
864 mhunt 387
    for (Iterator<ThreadIdentifier> it = mThreadCollection.iterator(); it.hasNext(); )
814 mhunt 388
    {
864 mhunt 389
      ThreadIdentifier threadIdentifier = it.next();
814 mhunt 390
 
391
      if (threadIdentifier.get_thread().isAlive())
392
      {
393
        try
394
        {
395
          threadIdentifier.get_thread().interrupt();
396
          threadIdentifier.get_thread().join();
397
        }
398
        catch( InterruptedException e )
399
        {
400
        }
401
      }
402
    }
403
  }
404
}
1361 dpurdie 405
 
4123 dpurdie 406
class UncaughtExceptionHandler implements Thread.UncaughtExceptionHandler
407
{
408
    private static final Logger mLogger = Logger.getLogger(UncaughtExceptionHandler.class);
409
 
410
    //Implements Thread.UncaughtExceptionHandler.uncaughtException()
411
    public void uncaughtException(Thread th, Throwable ex)
412
    {
413
        System.out.println("You crashed thread " + th.getName());
414
        System.out.println("Exception was: " + ex.toString());
415
 
416
        mLogger.fatal("UncaughtException ThreadName: " + th.getName());
417
        mLogger.fatal("UncaughtException was: " + ex.toString());
418
    }
419
}