Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
6914 dpurdie 1
package com.erggroup.buildtool.ripple;
2
 
3
import java.sql.Array;
4
import java.sql.CallableStatement;
5
import java.sql.Clob;
6
import java.sql.Connection;
7
import java.sql.DriverManager;
8
import java.sql.PreparedStatement;
9
import java.sql.ResultSet;
10
import java.sql.SQLException;
11
import java.sql.Timestamp;
12
import java.sql.Types;
13
import java.util.ArrayList;
14
import java.util.Arrays;
15
import java.util.Calendar;
16
import java.util.Date;
17
import java.util.GregorianCalendar;
18
import java.util.Iterator;
19
import java.util.List;
20
import java.util.ListIterator;
21
import java.util.concurrent.locks.ReentrantLock;
22
 
23
import oracle.sql.ArrayDescriptor;
24
 
25
import org.apache.log4j.Logger;
26
 
27
import com.erggroup.buildtool.ripple.RunLevel.BuildState;
28
import com.erggroup.buildtool.utilities.MutableDate;
29
import com.erggroup.buildtool.utilities.MutableInt;
30
import com.erggroup.buildtool.utilities.MutableString;
31
 
32
/**Release Manager schema abstraction
33
 */
34
public class ReleaseManager implements Cloneable
35
{
36
    /**Unit test hook.
37
     * Prevents Oracle interaction when false.
38
     * @attribute
39
     */
40
    public static boolean mUseDatabase = true;
41
 
42
    /**Debug Support.
43
     * Set to false if EnvVar GBE_BUILDTOOL_DEBUG exists
44
     * Value of GBE_BUILDTOOL_DEBUG is expected to be an email if greater than
45
     * one character.
46
     *
47
     * When set to false will:
48
     *    Prevents use of Oracle Mutex and potential lockout during debug sessions.
49
     *    Prevent the initiation of an indefinite pause.
50
     *    Force abt_usetestarchive, Add -testArchive to the assemble_dpkg command
51
     * @attribute
52
     */
53
    private static boolean mUseMutex = true;
54
 
55
    /** 
56
     * Reasons for building a package
57
     * The character code is inserted directly into the Release Manager Database
58
     * 
59
     */
60
    public enum BuildReason {
61
 
62
        Ripple('R'),
63
        Test('T'),
64
        NewVersion('N'),
65
        Restore('P');
66
 
67
        private char reason;
68
        private BuildReason(char reason) { this.reason = reason; }
69
        @Override
70
        public  String toString() { return String.valueOf(reason); }
71
        public static BuildReason fromValue(String value) {  
72
            if (value != null) {  
73
              for (BuildReason vReason : values()) {  
74
                if (vReason.reason == value.charAt(0) ) {  
75
                  return vReason;  
76
                }  
77
              }  
78
            }
79
            return null;  
80
        }
81
    }
82
 
83
    /**
84
     * The build result : Error, Complete ...
85
     * The character code is inserted directly into the Release Manager Database
86
     */
87
    public enum BuildResult {
88
 
89
        Building('B'),
90
        BuildError('E'),
91
        Complete('C'),
92
        SystemError('S');
93
 
94
        private char state;
95
        private BuildResult(char state) { this.state = state; }
96
        @Override
97
        public  String toString() { return String.valueOf(state); }
98
//        public static BuildResult fromValue(String value) {  
99
//            if (value != null) {  
100
//              for (BuildResult vState : values()) {  
101
//                if (vState.state == value.charAt(0) ) {  
102
//                  return vState;  
103
//                }  
104
//              }  
105
//            }
106
//            return null;  
107
//        }
108
    }
109
 
110
    /**package object of no consequence
111
     * @attribute
112
     */
113
    public static final Package NULL_PACKAGE = new Package();
114
 
115
    /**Logger
116
     * @attribute
117
     */
118
    private static final Logger mLogger = Logger.getLogger(ReleaseManager.class);
119
 
120
    /** Class to contain a lock and a connection as a single entity
121
     * 
122
     */
123
    static class RmConnection {
124
    	/**
125
    	 *  Connection to the database
126
    	 */
127
    	public Connection mConnection = null;
128
 
129
    	/**
130
    	 *  Lock used to control access to the connection
131
    	 */
132
    	public final ReentrantLock mSession = new ReentrantLock();
133
 
134
    	/** 
135
    	 * Close the connection on disconnect
136
    	 */
137
    	public boolean mCloseOnDisconnect = false;
138
 
139
    	public RmConnection ( boolean closeMe)
140
    	{
141
    		mCloseOnDisconnect = closeMe;
142
    	}
143
 
144
    	/**
145
    	 *  Close the connection - do not throw an error
146
    	 */
147
    	void closeConnection()
148
    	{
149
    		closeConnection(mConnection);
150
    	}
151
 
152
    	/**
153
    	 *  Close the specified connection - do not throw an error.
154
    	 *  To be used for general error handling
155
    	 * @param connection
156
    	 */
157
    	static void closeConnection( Connection connection )
158
    	{
159
            try {
160
                if (connection != null)
161
                	connection.close();
162
            }
163
            catch (SQLException e)
164
            {
165
                mLogger.fatal("SQL Exception closing connection:" + e.getMessage());
166
            }
167
    	}
168
    }
169
 
170
    /**database connection for use when not planning a build
171
     * @attribute
172
     */
173
    private static RmConnection mNonPlanningConnection = new RmConnection(false);
174
 
175
    /**database session handle for use when planning a build
176
     * @attribute
177
     */
178
    private static RmConnection mPlanningConnection = new RmConnection(true);
179
 
180
    /**database session handle
181
     * note this handle is only ever set to mNonPlanningConnection or mPlanningConnection
182
     * @attribute
183
     */
184
    private Connection mConnection = null;
185
    private boolean    mIsConnected = false;
186
 
187
    /**thread synchronization governing database connection request queuing
188
     * this lock is used by master threads with a low priority planning requirement
189
     * use the fairness parameter to grant access to the longest waiting thread
190
     * @attribute
191
     */
192
    private static final ReentrantLock mLowPriorityQueue = new ReentrantLock(true);
193
 
194
    /**collection of ReleaseConfig objects
195
     * @attribute
196
     */
197
    public ReleaseConfigData mReleaseConfigCollection = new ReleaseConfigData();
198
 
199
    /**database connection string
200
     * @attribute
201
     */
202
    public String mConnectionString = "";
203
 
204
    /**database username
205
     * @attribute
206
     */
207
    private String mUsername = "";
208
 
209
    /**database password
210
     * @attribute
211
     */
212
    private String mPassword = "";
213
 
214
    /**collection of RunLevel objects
215
     * @attribute
216
     */
217
    public List<RunLevelData> mRunLevelCollection = new ArrayList<RunLevelData>();
218
 
219
    /**set in claimVersion, cleared in discardVersion
220
     * @attribute
221
     */
222
    private String mPlannedPkgId = null;
223
 
224
    /**set in claimVersion, cleared in discardVersion
225
     * @attribute
226
     */
227
 
228
    private String mPlannedPkgVersion = null;
229
 
230
    /**prevents inadvertently attempting a commit which releases record locks in between claimMutex and releaseMutex
231
     * @attribute
232
     */
233
    private boolean mDoNotCommit = false;
234
 
235
     /**
236
     * Controls the data collection mode.
237
     * True : daemon Mode (default)
238
     * False: escrow Mode
239
     */
240
    public boolean mDaemon = true;
241
 
242
    /**
243
     * Indication of the state of the RM mutex
244
     * Used only for reporting
245
     */
246
    public String mMutexState = "";
247
 
248
    /**
249
     *  The number of seconds to postpone a shut down of a daemon set
250
     *  after the thread has started. 
251
     *  
252
     *  This will prevent a daemon from being automatically disabled as soon
253
     *  as it is restarted
254
     *  
255
     *  Set to four hours
256
     */
257
    private static final long mPostponeShutdown = 4L * 60L * 60L;
258
 
259
 
260
    /**constructor
261
     * @param connectionString
262
     * @param username
263
     * @param password
264
     */
265
    public ReleaseManager(final String connectionString, final String username, final String password)
266
    {
267
        mLogger.debug("ReleaseManager " + connectionString);
268
        mConnectionString = connectionString;
269
        mUsername = username;
270
        mPassword = password;
271
 
272
        String gbeBtDebug = System.getenv("GBE_BUILDTOOL_DEBUG");
273
        if ( gbeBtDebug != null )
274
        {
275
            mLogger.fatal("GBE_BUILDTOOL_DEBUG set - Use of database mutex supressed");
276
            setNoMutex();
277
        }
278
    }
279
 
280
    /**
281
     * Clone an instance of this class
282
     */
283
    @Override
284
    public Object clone() throws CloneNotSupportedException {
285
 
286
        //  Clone myself - using Java's build in stuff
287
        ReleaseManager clonedObj = (ReleaseManager) super.clone();
288
 
289
        //  Fix up several members
290
        //
291
        clonedObj.mConnection = null;
292
        clonedObj.mReleaseConfigCollection = new ReleaseConfigData();
293
        clonedObj.mRunLevelCollection = new ArrayList<RunLevelData>();
294
        clonedObj.mPlannedPkgId = null;
295
        clonedObj.mDoNotCommit = false;
296
        clonedObj.mPlannedPkgVersion = null;
297
 
298
        return clonedObj;
299
    }
300
 
301
 
302
    /**constructor used when schema information is unknown eg location, username, password
303
     */
304
    public ReleaseManager()
305
    {
306
        // inherit mConnectionString, mUsername, mPassword
307
        mLogger.debug("ReleaseManager");
308
    }
309
 
310
    /**
311
     * Set the mode of operation to be either escrow mode or daemon mode
312
     * 
313
     * @param isDaemon True: Daemon Mode
314
     *               False: Escrow Mode
315
     */
316
    public void setDaemonMode(boolean isDaemon)
317
    {
318
        mDaemon = isDaemon;
319
        mLogger.debug("DaemonMode:" + mDaemon);
320
    }
321
 
322
    /**
323
     * Clear mUseMutex
324
     * Used only in test mode to prevent the use of a mutex 
325
     */
326
    public static void setNoMutex()
327
    {
328
        mUseMutex = false;
329
    }
330
 
331
    /**
332
     * Return the state of mUseMutex
333
     * True indicates that the system must use a Mutex to access data
334
     */
335
    public static boolean getUseMutex()
336
    {
337
        return mUseMutex;
338
    }
339
 
340
    /** Returns the current time
341
     * 
342
     *  Overridden in ReleaseManagerUtf
343
     */
344
    public long currentTimeMillis()
345
    {
346
        return System.currentTimeMillis();
347
    }
348
 
349
    /** Returns the applications major version number
350
     *  Used to stamp the generated XML files to ensure that producer and consumer match 
351
     * 
352
     * Overridden in ReleaseManagerUtf
353
     */
354
    public String getMajorVersionNumber()
355
    {
356
        return this.getClass().getPackage().getSpecificationVersion();
357
    }
358
 
359
    /**connect to oracle - in a non planning mode 
360
     * Overridden in ReleaseManagerUtf 
361
     */
362
    public void connect() throws SQLException
363
    {
364
        mLogger.debug("connect");
365
        mNonPlanningConnection = connect( mNonPlanningConnection );
366
    }
367
 
368
    /**connect to oracle - to plan a build
369
     * @param   priority - true: Connect with a high priority (last planning session resulted in a build)
370
     */
371
    public void connectForPlanning( boolean priority ) throws SQLException
372
    {
373
        mLogger.debug("connectForPlanning");
374
 
375
        if ( !priority )
376
        {
377
            // limit only one thread with a low priority build requirement to connect
378
            if ( mLowPriorityQueue.isHeldByCurrentThread() )
379
            {
380
                // by design a thread must NOT connect multiple times
381
                // this is to ensure the lock is claimed only once
382
                mLogger.error("connectForPlanning thread already has the lock");
383
            }
384
            else
385
            {
386
                mLogger.debug("connectForPlanning calling lock");
387
                mLowPriorityQueue.lock();
388
                mLogger.debug("connectForPlanning called lock");
389
            }
390
        }
391
 
392
        // threads with a high priority build requirement are not subject to the mLowPriorityQueue
393
        mPlanningConnection = connect( mPlanningConnection );    
394
    }
395
 
396
    /**Connect to oracle - finally
397
     *  @param  session         - Lock item to use
398
     *  @param  connection      - Connection to use 
399
     */
400
    private RmConnection connect( RmConnection rmc ) throws SQLException
401
    {
402
        mLogger.debug("connect");
403
 
404
        try
405
        {
406
            if ( rmc.mSession.isHeldByCurrentThread() )
407
            {
408
                // by design a thread must NOT connect multiple times
409
                // this is to ensure the lock is claimed only once
410
                mLogger.error("connect thread already has the lock");
411
            }
412
            else
413
            {
414
                mLogger.debug("connect calling lock");
415
                rmc.mSession.lock();
416
                mLogger.debug("connect called lock");
417
            }
418
 
419
            if ( !mUseDatabase )
420
            {
421
                mLogger.info("connect !mUseDatabase");
422
            }
423
            else
424
            {
425
                // DEVI 46868
426
                // loop indefinitely until a connection attempt succeeds
427
                // unless the failure is on the first attempt
428
                boolean problemConnecting;
429
 
430
                do
431
                {
432
                    mLogger.debug("connect check connection");
433
                    problemConnecting = false;
434
 
435
                    try
436
                    {
437
                        if ( rmc.mConnection == null || ( rmc.mConnection != null && !rmc.mConnection.isValid(10) ) )
438
                        {
439
                            mLogger.warn("connect calling getConnection");
440
                            rmc.mConnection = DriverManager.getConnection(mConnectionString, mUsername, mPassword);
441
                            // when connection to the database is established, the connection, by default, is in auto-commit mode
442
                            // to adhere to the design in the use of select for update, it is crucial to turn auto-commit off
443
                            // this also improves performance
444
                            rmc.mConnection.setAutoCommit(false);
445
                        }
446
                    }
447
                    catch(SQLException e)
448
                    {
449
                        mLogger.warn("connect determined problem connecting");
450
                        problemConnecting = true;
451
                        try
452
                        {
453
                            // sleep 30 secs
454
                            mLogger.warn("connect getConnection failed. sleep 30secs");
455
                            Thread.sleep(30000);
456
                        }
457
                        catch (InterruptedException f)
458
                        {
459
                            mLogger.warn("connect caught InterruptedException");
460
                            Thread.currentThread().interrupt();
461
                        }
462
 
463
                        if ( rmc.mConnection == null )
464
                        {
465
                            // failed on first connection attempt - unlikely due to database loading - likely bad connection parameters
466
                            throw new SQLException();
467
                        }
468
                    }
469
                } while ( problemConnecting );
470
                mLogger.debug("connect checked connection");
471
            }
472
        }
473
        finally
474
        {
475
            mConnection = rmc.mConnection;
476
            mIsConnected = true;
477
            mLogger.debug("connect finally connection");
478
        }
479
        return rmc;
480
 
481
    }
482
 
483
    /**Disconnect from oracle Database 
484
     * <br>Is overridden in ReleaseManagerUtf for test purposes 
485
     */
486
    public void disconnect()
487
    {
488
        mLogger.debug("disconnect");
489
 
490
        disconnect( mNonPlanningConnection );
491
    }
492
 
493
    /**Disconnect from oracle
494
     * @param   priority    - True: High priority planning thread
495
     */
496
    public void disconnectForPlanning( boolean priority )
497
    {
498
        mLogger.debug("disconnectForPlanning");
499
 
500
        if ( !priority )
501
        {
502
            // allow another low priority thread to connect
503
            try {
504
                mLowPriorityQueue.unlock();
505
            }
506
            catch( IllegalMonitorStateException e ) {
507
                mLogger.fatal("disconnectForPlanning. IllegalMonitorStateException exception");
508
            }
509
        }
510
 
511
        disconnect( mPlanningConnection );
512
    }
513
 
514
    /**Disconnect from oracle
515
     * Internal oracle disconnection method. Wrapped by publicly available disconnection methods
516
     * @param   session. Session Lock
517
     */
518
    private void disconnect( RmConnection connection )
519
    {
520
        mLogger.debug("disconnect");
521
 
522
        // The planning connection is flagged to close on disconnect
523
        // This is an attempt to prevent database deadlocks - which have been seen
524
        // under unknown conditions.
525
        // Done before the lock is released
526
        if (connection.mCloseOnDisconnect)
527
        {
528
            mLogger.debug("disconnect close on disconnect");
529
        	connection.closeConnection();
530
        }
531
 
532
        // by design, a thread may call disconnect multiple times
533
        // this is a technique used in finally blocks
534
        // it is to ensure the lock is released in all cases
535
        // only unlock if it is held by this thread
536
        // when unlock is called on a ReentrantLock held by this thread
537
        // the hold count is decremented
538
        // connect should only let the hold count be incremented to 1
539
        // when the hold count is 0 the lock is released
540
        // and the ReentrantLock is no longer held by this thread
541
        // only call unlock when the lock is held by this thread
542
        if ( connection.mSession.isHeldByCurrentThread() )
543
        {
544
            mLogger.debug("disconnect calling unlock");
545
            try {
546
                connection.mSession.unlock();
547
            }
548
            catch (IllegalMonitorStateException e) {
549
                mLogger.fatal("disconnect. IllegalMonitorStateException exception");
550
            }
551
            mLogger.debug("disconnect called unlock");
552
        }
553
 
554
        mIsConnected = false;
555
    }
556
 
557
    /** Common processing SQL Exceptions
558
     *  If it is a connection error then a new SQLException will be thrown otherwise
559
     *  its an error with the SQL itself and a normal Exception will be thrown.
560
     *  
561
     * @param e                 - Exception being thrown
562
     * @param instanceId        - Method suffix to differentiate multiple methods of the same name
563
     * 
564
     * @throws SQLException
565
     * @throws Exception
566
     */
567
    void handleSQLException(SQLException e, String instanceId ) throws SQLException, Exception
568
    {
569
        String callingMethodName = Thread.currentThread().getStackTrace()[2].getMethodName() + instanceId ;
570
        mLogger.fatal(callingMethodName + " sql exception:" + e.getMessage());
571
 
572
        if ( mConnection == null || !mConnection.isValid(10) )
573
        {
574
            mLogger.error(callingMethodName + " database access error only");
575
            RmConnection.closeConnection(mConnection);
576
            throw new SQLException(e);
577
        }
578
        else
579
        {
580
            mLogger.fatal(callingMethodName + " show stopper");
581
            throw new Exception(callingMethodName + " show stopper");
582
        }
583
    }
584
 
585
    /** Claim the Build System Planning Lock
586
     * Essentially locks the row in the BUILD_SERVICE_CONFIG table with a service of MUTEX
587
     * for the duration of the transaction this prevents other MasterThreads from 
588
     * generating build files in parallel and hence prevents planned version numbering contention 
589
     */
590
    public void claimMutex() throws SQLException, Exception
591
    {
592
        mLogger.debug("claimMutex");
593
        mMutexState = "Claiming Mutex";
594
        if ( mUseDatabase && mUseMutex )
595
        {
596
            try
597
            {
598
                CallableStatement stmt = mConnection.prepareCall("select CONFIG from release_manager.BUILD_SERVICE_CONFIG WHERE SERVICE='MUTEX' FOR UPDATE");
599
                mLogger.fatal("claimMutex calling stmt.executeUpdate");
600
                stmt.executeUpdate();
601
                mLogger.fatal("claimMutex called stmt.executeUpdate");
602
                stmt.close();
603
                mDoNotCommit = true;
604
                mMutexState = "Holding Mutex";
605
            }
606
            catch ( SQLException e )
607
            {
608
                mMutexState = "Mutex Claim Exception";
609
                handleSQLException(e, "");
610
            }
611
 
612
            // about to start the planning process again, discard previous
613
            discardVersions();
614
        }
615
    }
616
 
617
    /** Release the Build System Planning Lock 
618
     *  Essentially unlocks the row in the BUILD_SERVICE_CONFIG table with a service of MUTEX
619
     */
620
    public void releaseMutex() throws SQLException, Exception
621
    {
622
        mLogger.debug("releaseMutex");
623
        mMutexState = "Releasing Mutex";
624
        if ( mUseDatabase )
625
        {
626
            try
627
            {
628
                mDoNotCommit = false;
629
                mLogger.fatal("releaseMutex calling commit");
630
                commit();
631
                mLogger.fatal("releaseMutex called commit");
632
                mMutexState = "Released Mutex";
633
            }
634
            catch ( SQLException e )
635
            {
636
                mMutexState = "Mutex Release Exception";
637
                handleSQLException(e, "");
638
            }
639
        }
640
    }
641
 
642
    /**central commit protection
643
     */
644
    private void commit() throws SQLException, Exception
645
    {
646
        mLogger.debug("commit");
647
        if ( mUseDatabase )
648
        {
649
            if ( mDoNotCommit )
650
            {
651
                mLogger.error("commit attempted commit with mDoNotCommit set, this is a programming error");
652
            }
653
            else
654
            {
655
                mConnection.commit();
656
            }
657
        }
658
    }
659
 
660
    /**Flag a Build System Pause in the database
661
     * This is aimed at stopping ALL daemons dead in the water
662
     * 
663
     * Used when handling an unsupported exception case in either the main or slave daemons
664
     * typically an SQLException other than a database connection related on
665
     *
666
     * @param mRecoverable  True: Recoverable pause wait until recovery is detected
667
     *                  <br>False: Unrecoverable pause. Wait for 20 minutes 
668
     */
669
    public void indefinitePause(boolean mRecoverable)
670
    {
671
        mLogger.debug("indefinitePause");
672
        if ( mUseDatabase )
673
        {
674
            String sqlStr;
675
            if ( mRecoverable) {
676
                sqlStr = "begin PK_BUILDAPI.set_infinite_pause(); end;";
677
            }
678
            else {
679
                sqlStr = "begin PK_BUILDAPI.set_finite_pause(20); end;";
680
            }
681
            try
682
            {
683
                connect();
684
                CallableStatement stmt = mConnection.prepareCall( sqlStr );
685
                stmt.executeUpdate();
686
                stmt.close();
687
                commit();
688
            }
689
            catch( SQLException e )
690
            {
691
                // do not throw Exception
692
                // this is part of Exception handling
693
                mLogger.fatal( "indefinitePause caught SQLException " + e.getMessage() );
694
                RmConnection.closeConnection(mConnection);
695
            }
696
            catch( Exception e )
697
            {
698
                mLogger.fatal( "indefinitePause caught Exception " + e.getMessage() );
699
            }
700
            finally
701
            {
702
                // this block is executed regardless of what happens in the try block
703
                // even if an exception is thrown
704
                // ensure disconnect
705
                try
706
                {
707
                    disconnect();
708
                }
709
                catch( Exception e )
710
                {
711
                    // do not throw Exception
712
                    // this is part of Exception handling
713
                    mLogger.fatal( "indefinitePause2 caught Exception " + e.getMessage() );
714
                    RmConnection.closeConnection(mConnection);
715
                }
716
            }
717
        }
718
    }
719
 
720
    /**ensures a run_level_schedule row with a non null indefinite_pause column does not exist
721
     * this is aimed at resuming all daemons
722
     * 
723
     * Assumes connection to database has been established
724
     */
725
    public void resumeIndefinitePause() throws SQLException, Exception
726
    {
727
        mLogger.debug("resume");
728
        if ( mUseDatabase )
729
        {
730
            try
731
            {
732
                CallableStatement stmt = mConnection.prepareCall( "begin PK_BUILDAPI.SET_RESUME(); end;" );
733
                stmt.executeUpdate();
734
                stmt.close();
735
                commit();
736
            }
737
            catch ( SQLException e )
738
            {
739
                handleSQLException(e, "");
740
            }
741
        }
742
    }
743
 
744
 
745
    /**
746
     *  Only used in daemon mode
747
     *  Update the Database information to show the package being built
748
     * 
749
     * @param pkgId  Identify the package (name) being built
750
     * 
751
     * @param pkgVersion
752
     *                The version at which the package is being built
753
     * 
754
     * @param rtagId The release Id in which the package is being built
755
     * 
756
     * @exception SQLException
757
     * @exception Exception
758
     */
759
    void claimVersion(int pkgId, String pkgVersion, int rtagId) throws SQLException, Exception
760
    {
761
        mLogger.debug("claimVersion " + pkgId + " " + pkgVersion);
762
        if ( mUseDatabase )
763
        {
764
            CallableStatement stmt1 = null;
765
            try
766
            {
767
                if (isRtagIdConfigured( rtagId ))
768
                {
769
                    stmt1 = mConnection.prepareCall(
770
                            "insert into release_manager.planned_versions (pkg_id, pkg_version, planned_time) values (?,?, sysdate)");
771
                    stmt1.setInt(1, pkgId);
772
                    stmt1.setString(2, pkgVersion);
773
                    stmt1.executeUpdate();
774
 
775
                    mPlannedPkgId = String.valueOf(pkgId);
776
                    mPlannedPkgVersion = pkgVersion;
777
                }
778
            }
779
            catch ( SQLException e )
780
            {
781
                handleSQLException(e, "");
782
            }
783
            finally {
784
                if (stmt1 != null)
785
                    stmt1.close();
786
            }
787
        }
788
    }
789
 
790
    /**Only used in daemon mode
791
     * <br>Delete planned package package information from the last planned build
792
     * <p>
793
     * Note: There is an aging process to cleanup entries that are left around due to
794
     *       unforeseen errors.
795
     * <p>      
796
     * Resets mPlannedPkgId and mPlannedPkgVersion to null
797
     * 
798
     * @exception   SQLException
799
     * @exception   Exception
800
     */
801
    public void discardVersion() throws SQLException, Exception
802
    {
803
        mLogger.fatal("discardVersion");
804
 
805
        if ( mPlannedPkgId != null && mPlannedPkgVersion != null )
806
        {
807
            try
808
            {
809
                connect();
810
                CallableStatement stmt = mConnection.prepareCall(
811
                    "delete from release_manager.planned_versions" +
812
                    " where pkg_id=" + mPlannedPkgId + 
813
                    "   and pkg_version='" + mPlannedPkgVersion + "'");
814
                stmt.executeUpdate();
815
                stmt.close();
816
                commit();
817
                mPlannedPkgId = null;
818
                mPlannedPkgVersion = null;
819
            }
820
            catch ( SQLException e )
821
            {
822
                handleSQLException(e, "");
823
            }
824
            finally
825
            {
826
                disconnect();
827
            }
828
        }
829
    }
830
 
831
    /** Delete planned versions over 24 hours old (rounded to the nearest hour that is) 
832
     *  Only used in daemon mode 
833
     */
834
    private void discardVersions() throws SQLException, Exception
835
    {
836
        mLogger.debug("discardVersions");
837
        try
838
        {
839
            // housekeeping whilst the daemon has the mutex
840
            // trunc(sysdate, 'hh') returns the time now rounded to the nearest hour
841
            // trunc(sysdate, 'hh') - 1 returns the time 24 hours ago rounded to the nearest hour
842
            // this statement does not return any rows when planned_time is null, though this should never be the case
843
            CallableStatement stmt = mConnection.prepareCall("delete from release_manager.planned_versions where planned_time < trunc(sysdate, 'hh') - 1");
844
            stmt.executeUpdate();
845
            stmt.close();
846
        }
847
        catch ( SQLException e )
848
        {
849
            handleSQLException(e, "");
850
        }
851
    }
852
 
853
    /**Update the Database information to show that a package is being built 
854
     * Only used in daemon mode
855
     * 
856
     *  @param rconId - Identifies the Release Config table entry
857
     *  @param pkgId - Identifies the name of the package being built
858
     *  @param pkgPvId - Identifies the packageVersion the build is based upon
859
     */
860
    public void setCurrentPackageBeingBuilt(int rconId, int pkgId, int pkgPvId) throws SQLException, Exception
861
    {
862
        mLogger.fatal("setCurrentPackageBeingBuilt " + rconId);
863
        if ( mUseDatabase )
864
        {
865
            CallableStatement stmt = null;
866
            try
867
            {
868
                connect();
869
 
870
                stmt = mConnection.prepareCall(
871
                        "update release_manager.run_level rl"+
872
                        " set current_pkg_id_being_built=?"+
873
                        "    ,current_pv_id=?" +
874
                        "    ,last_build=sysdate" +
875
                        " where rl.rcon_id=?" 
876
                        );
877
                stmt.setInt(1, pkgId);
878
                stmt.setInt(2, pkgPvId);
879
                stmt.setInt(3, rconId);                    
880
                stmt.executeUpdate();
881
 
882
                commit();
883
            }
884
            catch ( SQLException e )
885
            {
886
                handleSQLException(e, "");
887
            }
888
            finally
889
            {
890
                // this block is executed regardless of what happens in the try block
891
                // even if an exception is thrown
892
                // ensure disconnect
893
                if (stmt != null)
894
                    stmt.close();
895
                disconnect();
896
            }
897
        }
898
    }
899
 
900
 
901
    /**Update the Database information to show that no package is being built 
902
     * Only used in daemon mode
903
     * 
904
     *  @param rconId - Identifies the Release Config table entry
905
     */
906
    public void clearCurrentPackageBeingBuilt(int rconId) throws SQLException, Exception
907
    {
908
        mLogger.fatal("clearCurrentPackageBeingBuilt " + rconId);
909
        if ( mUseDatabase )
910
        {
911
            try
912
            {
913
                connect();
914
 
915
                CallableStatement stmt4 = mConnection.prepareCall(
916
                        "update release_manager.run_level" +
917
                        " set current_pkg_id_being_built=NULL,"+
918
                        "     current_pv_id=NULL," +
919
                        "     current_build_files=NULL" +
920
                        " where rcon_id=" + rconId
921
                         );
922
                stmt4.executeUpdate();
923
                stmt4.close();
924
                commit();
925
            }
926
            catch ( SQLException e )
927
            {
928
                handleSQLException(e, "");
929
            }
930
            finally
931
            {
932
                // this block is executed regardless of what happens in the try block
933
                // even if an exception is thrown
934
                // ensure disconnect
935
                disconnect();
936
            }
937
        }
938
    }
939
 
940
    /**
941
     * Executes the AutoMakeRelease stored procedure with the passed parameters
942
     *          Handles database connection/disconnection
943
     * 
944
     * @param mReporting
945
     * 
946
     * @return A publishing error
947
     *         True: A publishing error that only affect the current package
948
     *         False: No publishing error
949
     * @exception SQLException
950
     * @exception Exception A publishing error that affects the entire build system.
951
     *                      This will cause an 'indefinite pause'
952
     */
953
    public boolean autoMakeRelease(ReportingData mReporting) throws SQLException, Exception
954
    {
955
 
956
        mReporting.errMsg = null;
957
        mLogger.debug("autoMakeRelease " + mReporting.packageName);
958
        if ( mUseDatabase )
959
        {
960
            try
961
            {
962
                //  Create an array of dependencies
963
                //  Convert the string mReporting.packageDepends into an array
964
                //      mReporting.packageDepends is of the form 'PackageName','PackageVersion';'PackageName2','PackageVersion2'
965
                String [] depArrayData = mReporting.packageDepends.split(";"); 
966
                ArrayDescriptor desc = ArrayDescriptor.createDescriptor("RELEASE_MANAGER" + "." + "RELMGR_VARCHAR2_TAB_T", mConnection);
967
                Array depArray = new oracle.sql.ARRAY(desc, mConnection, depArrayData);                
968
 
969
                connect();
970
                CallableStatement stmt = mConnection.prepareCall( "begin ? := PK_RMAPI.AUTO_MAKE_VCSRELEASE2(?,?,?,?,?,?,?,?); end;" );
971
                stmt.registerOutParameter( 1, Types.INTEGER);
972
                stmt.setLong( 2, mReporting.rtagId );
973
                stmt.setString( 3, mReporting.packageName );
974
                stmt.setString( 4, mReporting.packageExtension );
975
                stmt.setString( 5, mReporting.packageVersion );
976
                stmt.setString( 6, mReporting.newVcsTag );
977
                stmt.setArray ( 7, depArray );
978
                stmt.setInt   ( 8, mReporting.isRipple ? 1 : 0 );
979
                stmt.setString( 9, "buildadm" );
980
                stmt.executeUpdate();
981
                int result = stmt.getInt( 1 );
982
 
983
                //
984
                //  Return values
985
                //      >0 PVID of package
986
                //      -1 Package not found in pending table
987
                //      -2 Package already exists
988
                //      -3 Not approved for auto build
989
                //      -4 Package Migrated to SVN being built from CC tag
990
                //      -5 Rippled Package: Source path changed
991
                //  Sql Application Errors cause an SQLException
992
                //         Rtagid is NULL
993
                //         No Package Name
994
                //         No Package Version
995
                //         No Package VCS
996
                //         Bad IsRipple value
997
                //         No User Name
998
                //         Malformed VCS Tag
999
                //         Database missing VCS tag
1000
                //         Invalid UserName
1001
                //
1002
 
1003
                //
1004
                //  Report per-package errors directly
1005
                //  Exceptions are for errors that need to halt the entire system
1006
                //
1007
                if ( result <= 0 )
1008
                {
1009
                    mLogger.fatal("autoMakeRelease PK_RMAPI.AUTO_MAKE_VCSRELEASE failed, returned " + result);
1010
                    if ( result == -4 ) {
1011
                        mReporting.errMsg = "Package migrated to SVN being built from CC tag";
1012
                    } else if ( result == -3 ) {
1013
                        mReporting.errMsg = "Package not approved for autobuild";
1014
                    } else if ( result == -2 ) {
1015
                        // This is OK
1016
                    }  else if ( result == -1 ) {
1017
                        mReporting.errMsg = "Package Version no longer pending";
1018
                    }  else if ( result == -5 ) {
1019
                        mReporting.errMsg = "VCS Source path changed in ripple build";
1020
                    } else {
1021
                        // Don't know this error - so its fatal
1022
                        throw new Exception("autoMakeRelease show stopper PK_RMAPI.AUTO_MAKE_VCSRELEASE failed, returned " + result);
1023
                    }
1024
                }
1025
                else
1026
                {
1027
 
1028
                    //  Now that the package-version has been created in the database, we have the pv_id of the
1029
                    //  new package. Use this in the reporting process.
1030
                    mReporting.packageVersionId = result;
1031
                }
1032
 
1033
                stmt.close();
1034
                commit();
1035
            }
1036
            catch ( SQLException e )
1037
            {
1038
                handleSQLException(e, "");
1039
            }
1040
            finally
1041
            {
1042
                // this block is executed regardless of what happens in the try block
1043
                // even if an exception is thrown
1044
                // ensure disconnect
1045
                disconnect();
1046
            }
1047
        }
1048
        return (mReporting.errMsg != null);
1049
    }
1050
 
1051
    /** Executes the insertPackageMetrics stored procedure with the passed parameters
1052
     *  Handles database connection/disconnection
1053
     */
1054
    public void insertPackageMetrics(int mRtagId, String packageName, 
1055
            String packageExtension, String metrics) throws SQLException, Exception
1056
    {
1057
        mLogger.debug("insertPackageMetrics " + packageName);
1058
        if ( mUseDatabase )
1059
        {
1060
            try
1061
            {
1062
                connect();
1063
                CallableStatement stmt = mConnection.prepareCall( "begin ? := PK_RMAPI.INSERT_PACKAGE_METRICS(?,?,?,?); end;" );
1064
                stmt.registerOutParameter( 1, Types.INTEGER);
1065
                stmt.setInt   ( 2, mRtagId );
1066
                stmt.setString( 3, packageName );
1067
                stmt.setString( 4, packageExtension );
1068
                stmt.setString( 5, metrics );
1069
                stmt.executeUpdate();
1070
                int result = stmt.getInt( 1 );
1071
 
1072
                if ( result != 0 )
1073
                {
1074
                    // flag build failure
1075
                    mLogger.fatal("insertPackageMetrics show stopper PK_RMAPI.INSERT_PACKAGE_METRICS failed, returned" + result);
1076
                    throw new Exception("insertPackageMetrics show stopper PK_RMAPI.INSERT_PACKAGE_METRICS failed, returned" + result);
1077
                }
1078
                stmt.close();
1079
                commit();
1080
            }
1081
            catch ( SQLException e )
1082
            {
1083
                handleSQLException(e, "");
1084
            }
1085
            finally
1086
            {
1087
                // this block is executed regardless of what happens in the try block
1088
                // even if an exception is thrown
1089
                // ensure disconnect
1090
                disconnect();
1091
            }
1092
        }
1093
    }
1094
 
1095
    /**
1096
     * Add entry to the Build_Instance table
1097
     * Returns the build instance number. This will be used to cross reference unit tests results
1098
     * 
1099
     * @throws throws SQLException, Exception 
1100
     * 
1101
     */
1102
    public int createBuildInstance(int rtagId, int pvId, BuildReason reason) throws SQLException, Exception
1103
    {
1104
        int buildId = 0;
1105
 
1106
        mLogger.debug("createBuildInstance " + rtagId + ":" + pvId);
1107
        if ( mUseDatabase )
1108
        {
1109
            try
1110
            {
1111
                connect();
1112
 
1113
                CallableStatement stmt = mConnection.prepareCall("begin ? := PK_RMAPI.new_build_instance(?,?,?); end;");
1114
                stmt.registerOutParameter( 1, Types.INTEGER);
1115
                stmt.setLong( 2,rtagId );
1116
                stmt.setLong( 3,pvId );
1117
                stmt.setString( 4,reason.toString() );
1118
                stmt.executeUpdate();
1119
                buildId = stmt.getInt( 1 );
1120
 
1121
                mLogger.warn("createBuildInstance: Build Instance ID: " + buildId);
1122
 
1123
                stmt.close();
1124
                commit();
1125
            }
1126
            catch ( SQLException e )
1127
            {
1128
                handleSQLException(e, "");
1129
            }
1130
            finally
1131
            {
1132
                // this block is executed regardless of what happens in the try block
1133
                //      even if an exception is thrown
1134
                //      ensure disconnect
1135
                disconnect();
1136
            }
1137
        }
1138
        return buildId;
1139
    }
1140
 
1141
    /**
1142
     * Update the Build_Instance table.
1143
     * <br>Record the state of the current build in the database
1144
     * 
1145
     * @param buildId  - Build ID of build
1146
     * @param pvId     - PV_ID of the build
1147
     * @param result   - Outcome  of the build
1148
     * 
1149
     * Returns the internal error code. <0 == error
1150
     * 
1151
     * @throws throws SQLException, Exception 
1152
     * 
1153
     */
1154
    public int updateBuildInstance(int buildID, int pvId, BuildResult result) throws SQLException, Exception
1155
    {
1156
        int rv = 0;
1157
 
1158
        mLogger.debug("updateBuildInstance " + buildID + ":" + pvId + ":" + result);
1159
        if ( mUseDatabase )
1160
        {
1161
            try
1162
            {
1163
                connect();
1164
 
1165
                String sql = "begin ? := PK_RMAPI.update_build_instance(?,?,?); end;";
1166
 
1167
                CallableStatement stmt = mConnection.prepareCall(sql);
1168
                stmt.registerOutParameter( 1, Types.INTEGER);
1169
                stmt.setLong( 2,buildID );
1170
                stmt.setLong( 3,pvId );
1171
                stmt.setString( 4,result.toString() );
1172
                stmt.executeUpdate();
1173
                rv = stmt.getInt( 1 );
1174
 
1175
                mLogger.warn("updateBuildInstance: Result: " + rv);
1176
 
1177
                stmt.close();
1178
                commit();
1179
            }
1180
            catch ( SQLException e )
1181
            {
1182
                handleSQLException(e, "");
1183
            }
1184
            finally
1185
            {
1186
                // this block is executed regardless of what happens in the try block
1187
                //      even if an exception is thrown
1188
                //      ensure disconnect
1189
                disconnect();
1190
            }
1191
        }
1192
        return rv;
1193
    }
1194
 
1195
    /**
1196
     * Insert Test Results into Release Manager
1197
     * Manage connection and disconnection
1198
     * 
1199
     * @param buildId
1200
     * @param btr
1201
     * @throws Exception, SQLException 
1202
     */
1203
    public void insertTestResults(int buildId, BuildTestResults btr) throws Exception, SQLException
1204
    {
1205
        if (buildId <= 0)
1206
        {
1207
            mLogger.warn("insertTestResults: Invalid build Id");
1208
            return;
1209
        }
1210
 
1211
        if ( !mUseDatabase || !btr.mResultsFound )
1212
        {
1213
            return;
1214
        }
1215
 
1216
        mLogger.warn("insertTestResults: " + buildId + ", Number:" + btr.mTestResults.size() );
1217
        try
1218
        {
1219
            connect();
1220
            String sql = "BEGIN ? := PK_RMAPI.insert_test_run(?, ?, ?, ?, ?, ?, ?);end;";
1221
            CallableStatement stmt = mConnection.prepareCall(sql);
1222
            stmt.registerOutParameter( 1, Types.INTEGER);
1223
            stmt.setLong(2, buildId);
1224
            Clob myClob = mConnection.createClob();
1225
 
1226
            for (int ii = 0; ii < btr.mTestResults.size(); ii++)
1227
            {
1228
                //System.out.println("Data: " +data.testResults.get(ii).toString());
1229
 
1230
                BuildTestResults.testResultData td = btr.mTestResults.get(ii);
1231
                if (td.platform != null)
1232
                {
1233
                    stmt.setString(3, td.testName);
1234
                    stmt.setString(4, td.outcome);
1235
                    stmt.setString(5, td.platform);
1236
                    stmt.setString(6, td.type);
1237
                    if (td.duration ==  null) {
1238
                        stmt.setNull(7, Types.NUMERIC);
1239
                    } else {
1240
                        stmt.setLong  (7, td.duration);
1241
                    }
1242
 
1243
                    // Insert CLOB data, or a null
1244
                    if (td.message == null)
1245
                    {
1246
                        stmt.setNull(8,Types.CLOB);
1247
                    }
1248
                    else
1249
                    {
1250
                        myClob.truncate(0);
1251
                        myClob.setString(1, td.message);
1252
                        stmt.setClob(8, myClob);
1253
                    }
1254
 
1255
                    stmt.execute();
1256
                    int rv = stmt.getInt( 1 );
1257
 
1258
                    if (rv != 1)
1259
                    {
1260
                        mLogger.fatal("insertTestResults show stopper. Insert error");
1261
                        throw new Exception("insertTestResults show stopper. Insert error");
1262
                    }
1263
                }
1264
            }
1265
            stmt.close();
1266
 
1267
        }
1268
        catch ( SQLException e )
1269
        {
1270
            handleSQLException(e, "");
1271
        }
1272
        finally
1273
        {
1274
            // this block is executed regardless of what happens in the try block
1275
            // even if an exception is thrown
1276
            // ensure disconnect
1277
            disconnect();
1278
        }
1279
    }
1280
 
1281
    /**executes the get_daemon_inst function with the passed parameters
1282
     * @param   rtagId          - Release to examine
1283
     * @param   opCode          - Type of instruction to process
1284
     * @param   instruction     - In/Out daemon instruction identifier Start scan from this instruction
1285
     * @param   pvId            - Returns Pvid from instruction
1286
     * @param   userId          - Returns userId of creator
1287
     * @param   userEmail       - Returns email address of userId
1288
     * @return  true if an instruction exists - for use in a while loop
1289
     */
1290
    private boolean getDaemonInst(final int rtagId, final int opCode, 
1291
            MutableInt instruction, MutableInt pvId, MutableInt userId, MutableString userEmail ) throws SQLException, Exception
1292
    {
1293
        mLogger.debug("getDaemonInst " + instruction);
1294
        boolean retVal = false;
1295
 
1296
        if ( mUseDatabase )
1297
        {
1298
            try
1299
            {
1300
                CallableStatement stmt = mConnection.prepareCall( "begin ? := PK_BUILDAPI.GET_DAEMON_INST(?,?,?,?,?,?); end;" );
1301
                stmt.registerOutParameter(1, Types.INTEGER);
1302
                stmt.registerOutParameter(3, Types.INTEGER);
1303
                stmt.registerOutParameter(4, Types.INTEGER);
1304
                stmt.registerOutParameter(5, Types.INTEGER);
1305
                stmt.registerOutParameter(6, Types.INTEGER);
1306
                stmt.registerOutParameter(7, Types.INTEGER);
1307
                stmt.setInt(2, rtagId );
1308
                stmt.setInt( 3, instruction.value );
1309
                stmt.setInt( 4, opCode );
1310
                stmt.execute();
1311
                int result = stmt.getInt( 1 );
1312
 
1313
                if ( result == 1 )
1314
                {
1315
                    retVal = true;
1316
                    instruction.value = stmt.getInt( 3 );
1317
                    pvId.value = stmt.getInt( 5 );
1318
                    userId.value = stmt.getInt( 6 );
1319
 
1320
                    //
1321
                    //  Convert userId into an email address
1322
                    //
1323
                    CallableStatement stmt1 = mConnection.prepareCall(
1324
                            "select user_email from release_manager.users where user_id=" + userId.value);
1325
                    ResultSet rset1 = stmt1.executeQuery();
1326
 
1327
                    while( rset1.next() )
1328
                    {
1329
                        userEmail.value = rset1.getString("user_email");
1330
                        if (rset1.wasNull())
1331
                        {
1332
                            userEmail.value = "";
1333
                        }
1334
                    }
1335
 
1336
                    rset1.close();
1337
                    stmt1.close();
1338
 
1339
                }
1340
 
1341
                stmt.close();
1342
 
1343
            }
1344
            catch ( SQLException e )
1345
            {
1346
                handleSQLException(e, "");
1347
            }
1348
        }
1349
        return retVal;
1350
    }
1351
 
1352
    /** Mark a Daemon Instruction as in-progress
1353
     *  Assumes that a database connection has been established
1354
     *  Assumes that the connection is within a Mutex session and the database commit will be done elsewhere
1355
     *  
1356
     *  @param  instruction - PVID of the daemon instruction to process
1357
     */
1358
    public void markDaemonInstInProgress(final int instruction) throws SQLException, Exception
1359
    {
1360
        mLogger.debug("markDaemonInstInProgress " + instruction);
1361
 
1362
        if ( mUseDatabase )
1363
        {
1364
            try
1365
            {
1366
                CallableStatement stmt = mConnection.prepareCall( "call PK_BUILDAPI.MARK_DAEMON_INST_IN_PROGRESS(?)" );
1367
                stmt.setInt( 1, instruction );
1368
                stmt.executeUpdate();
1369
                stmt.close();
1370
            }
1371
            catch ( SQLException e )
1372
            {
1373
                handleSQLException(e, "");
1374
            }
1375
        }
1376
    }
1377
 
1378
    /** Mark a Daemon Instruction as completed
1379
     *  Will establish (and release) a database connection if non is currently open
1380
     *  Will commit the change - unless commits have been disabled within a Mutex session
1381
     *  
1382
     *  @param  instruction - PVID of Daemon Instruction to process
1383
     */
1384
    public void markDaemonInstCompleted(final int instruction) throws SQLException, Exception
1385
    {
1386
        mLogger.debug("markDaemonInstCompletedConnect " + instruction);
1387
        boolean connectionCreated = false;
1388
 
1389
        try
1390
        {
1391
            if (! mIsConnected)
1392
            {
1393
                connect();
1394
                connectionCreated = true;
1395
            }
1396
 
1397
            if ( mUseDatabase )
1398
            {
1399
                try
1400
                {
1401
                    CallableStatement stmt = mConnection.prepareCall( "call PK_BUILDAPI.MARK_DAEMON_INST_COMPLETED(?)" );
1402
                    stmt.setInt( 1, instruction );
1403
                    stmt.executeUpdate();
1404
                    stmt.close();
1405
                }
1406
                catch ( SQLException e )
1407
                {
1408
                    handleSQLException(e, "");
1409
                }
1410
            }
1411
 
1412
            if ( ! mDoNotCommit )
1413
            {
1414
                commit();
1415
            }
1416
        }
1417
        catch ( SQLException e )
1418
        {
1419
            handleSQLException(e, "");
1420
        }
1421
        finally
1422
        {
1423
            // this block is executed regardless of what happens in the try block
1424
            // even if an exception is thrown
1425
            // ensure disconnect
1426
            if (connectionCreated)
1427
            {
1428
                disconnect();
1429
            }
1430
        }
1431
    }
1432
 
1433
    /**
1434
     * Determine the RTAG_ID associated with a given SBOM
1435
     * Sets up mRtagId and mSbomId 
1436
     *  
1437
     * Overridden in ReleaseManagerUtf
1438
     * 
1439
     * @param sbom_id An sbom_id to process
1440
     * 
1441
     * @return The SBOM's RTAG_ID, or zero if none was found
1442
     * @exception SQLException
1443
     */
1444
    public int queryRtagIdForSbom(int sbom_id) throws SQLException
1445
    {
1446
        int rtagId = 0;
1447
 
1448
        CallableStatement stmt = mConnection.prepareCall("select b.rtag_id_fk from deployment_manager.boms b where b.bom_id=" + sbom_id);
1449
        ResultSet rset = stmt.executeQuery();
1450
        while( rset.next() )
1451
        {
1452
            rtagId = rset.getInt("rtag_id_fk");
1453
        }
1454
        rset.close();
1455
        stmt.close();
1456
 
1457
        return rtagId;
1458
     }
1459
 
1460
 
1461
    /**In daemon mode
1462
     * Returns a concatenation of the proj_name and rtag_name 
1463
     *  
1464
     * In escrow mode
1465
     * Returns a concatenation of the proj_name, branch_name, bom_version and bom_lifecycle 
1466
     *  
1467
     * Overridden in ReleaseManagerUtf 
1468
     */
1469
    public String queryBaselineName(int baseline) throws SQLException, Exception
1470
    {
1471
        mLogger.debug("queryBaselineName " + mDaemon);
1472
        StringBuilder retVal = new StringBuilder();
1473
 
1474
        String sql = "";
1475
 
1476
        if ( mDaemon )
1477
        {
1478
            sql = "select p.proj_name, rt.rtag_name" +
1479
                  " from release_manager.projects p, release_manager.release_tags rt" +
1480
                  " where rt.rtag_id=" + baseline + " and p.proj_id=rt.proj_id";
1481
        }
1482
        else
1483
        {
1484
            sql = "select dp.proj_name, br.branch_name, b.bom_version, b.bom_lifecycle" +
1485
                  " from deployment_manager.dm_projects dp, deployment_manager.branches br, deployment_manager.boms b" +
1486
                  " where b.bom_id=" + baseline + " and br.branch_id=b.branch_id and dp.proj_id=br.proj_id";
1487
        }
1488
 
1489
        try
1490
        {
1491
            CallableStatement stmt = mConnection.prepareCall(sql);
1492
            ResultSet rset = stmt.executeQuery();
1493
 
1494
            while( rset.next() )
1495
            {
1496
                String proj_name = rset.getString("proj_name");
1497
 
1498
                if ( proj_name != null )
1499
                {
1500
                    retVal.append(proj_name);
1501
                }
1502
 
1503
                if ( mDaemon )
1504
                {
1505
                    String rtag_name = rset.getString("rtag_name");
1506
 
1507
                    if ( rtag_name != null )
1508
                    {
1509
                        retVal.append(" > ").append(rtag_name);
1510
                    }
1511
                }
1512
                else
1513
                {
1514
                    String branch_name = rset.getString("branch_name");
1515
 
1516
                    if ( branch_name != null )
1517
                    {
1518
                        retVal.append(" > ").append(branch_name);
1519
                    }
1520
 
1521
                    String bom_version = rset.getString("bom_version");
1522
 
1523
                    if ( bom_version != null )
1524
                    {
1525
                        retVal.append(" ").append(bom_version);
1526
                    }
1527
 
1528
                    String bom_lifecycle = rset.getString("bom_lifecycle");
1529
 
1530
                    if ( bom_lifecycle != null )
1531
                    {
1532
                        retVal.append(".").append(bom_lifecycle);
1533
                    }
1534
                }
1535
            }
1536
 
1537
            rset.close();
1538
            stmt.close();
1539
        }
1540
        catch ( SQLException e )
1541
        {
1542
            handleSQLException(e, "");
1543
        }
1544
 
1545
        mLogger.info("queryBaselineName returned " + retVal);
1546
        return retVal.toString();
1547
    }
1548
 
1549
    /**only used in daemon mode
1550
     *   select config from release_manager.build_service_config where service='MAIL SERVER';
1551
     * returns the configured service 
1552
     *  
1553
     * Overridden in ReleaseManagerUtf 
1554
     *  
1555
     */
1556
    public String queryMailServer() throws SQLException, Exception
1557
    {
1558
        mLogger.debug("queryMailServer");
1559
        String retVal = "";
1560
 
1561
 
1562
        try
1563
        {
1564
            CallableStatement stmt = mConnection.prepareCall("select config from release_manager.build_service_config where service='MAIL SERVER'");
1565
            ResultSet rset = stmt.executeQuery();
1566
 
1567
            while( rset.next() )
1568
            {
1569
                String config = rset.getString("config");
1570
 
1571
                if ( config != null )
1572
                {
1573
                    retVal = config;
1574
                    break;
1575
                }
1576
            }
1577
 
1578
            rset.close();
1579
            stmt.close();
1580
        }
1581
        catch ( SQLException e )
1582
        {
1583
            handleSQLException(e, "");
1584
        }
1585
 
1586
 
1587
        mLogger.info("queryMailServer returned " + retVal);
1588
        return retVal;
1589
    }
1590
 
1591
    /**only used in daemon mode
1592
     * returns the configured service 
1593
     *  
1594
     * Overridden in ReleaseManagerUtf 
1595
     *  
1596
     */
1597
    public String queryMailSender() throws SQLException, Exception
1598
    {
1599
        mLogger.debug("queryMailSender");
1600
        String retVal = "";
1601
 
1602
        try
1603
        {
1604
            CallableStatement stmt = mConnection.prepareCall("select config from release_manager.build_service_config where service='BUILD FAILURE MAIL SENDER'");
1605
            ResultSet rset = stmt.executeQuery();
1606
 
1607
            while( rset.next() )
1608
            {
1609
                String config = rset.getString("config");
1610
 
1611
                if ( config != null )
1612
                {
1613
                    retVal = config;
1614
                    break;
1615
                }
1616
            }
1617
 
1618
            rset.close();
1619
            stmt.close();
1620
        }
1621
        catch ( SQLException e )
1622
        {
1623
            handleSQLException(e, "");
1624
        }
1625
 
1626
        mLogger.debug("queryMailSender returned " + retVal);
1627
        return retVal;
1628
    }
1629
 
1630
    /**only used in daemon mode
1631
     * returns the configured global email addresses 
1632
     *  
1633
     * Overridden in ReleaseManagerUtf 
1634
     */
1635
    public String queryGlobalAddresses() throws SQLException, Exception
1636
    {
1637
        mLogger.debug("queryGlobalAddresses");
1638
        String retVal = "";
1639
 
1640
        try
1641
        {
1642
            CallableStatement stmt = mConnection.prepareCall(
1643
                    "select u.user_email from release_manager.build_service_config bsc, release_manager.users u " +
1644
                            "where bsc.service='GLOBAL EMAIL ADDRESS LIST' and u.full_name=bsc.config"
1645
                    );
1646
            ResultSet rset = stmt.executeQuery();
1647
 
1648
            while( rset.next() )
1649
            {
1650
                String email = rset.getString("user_email");
1651
 
1652
                if ( email != null )
1653
                {
1654
                    retVal = email;
1655
                    break;
1656
                }
1657
            }
1658
 
1659
            rset.close();
1660
            stmt.close();
1661
        }
1662
        catch ( SQLException e )
1663
        {
1664
            handleSQLException(e, "");
1665
        }
1666
 
1667
 
1668
        mLogger.debug("queryGlobalAddresses returned " + retVal);
1669
        return retVal;
1670
    }
1671
 
1672
    /**
1673
     * Determine a list of global, project wide and release email recipients
1674
     * All emails will be sent to people on this list
1675
     * @param baseline - an rtag_id
1676
     * @throws SQLException
1677
     * @returns String vector of email addresses
1678
     */
1679
    public List<String> queryProjectEmail(int baseline) throws SQLException
1680
    {
1681
        //
1682
        //  Get Global and Project Wide email information
1683
        //
1684
        mLogger.debug("queryGlobalandProjectEmail");
1685
        ArrayList<String> emailCollection = new ArrayList<String>();
1686
 
1687
        CallableStatement stmt0 = mConnection.prepareCall(
1688
                "select u.user_email " +
1689
                        "from release_manager.autobuild_failure af, " + 
1690
                        "release_manager.members_group mg, " + 
1691
                        "release_manager.users u, " + 
1692
                        "release_manager.views v, " + 
1693
                        "release_manager.release_tags rt " +
1694
                        "where rt.rtag_id=" + baseline + " " +
1695
                        "and v.view_name='PROJECT WIDE' " +
1696
                        "and af.proj_id=rt.proj_id " +
1697
                        "and af.view_id=v.view_id " +
1698
                        "and mg.group_email_id=af.group_email_id " +
1699
                        "and u.user_id=mg.user_id"
1700
                );
1701
        ResultSet rset0 = stmt0.executeQuery();
1702
        while( rset0.next() )
1703
        {
1704
            String email = rset0.getString("user_email");
1705
 
1706
            if ( email != null )
1707
            {
1708
                email = email.trim();
1709
                emailCollection.addAll( Arrays.asList(email.split("\\s*[,\\s]+\\s*")));
1710
            }
1711
        }
1712
 
1713
        rset0.close();
1714
        stmt0.close();
1715
 
1716
        //  Fetch the Release Specific email address
1717
        //  It may be comma separated
1718
        CallableStatement stmt1 = mConnection.prepareCall(
1719
                "select owner_email from release_manager.release_tags rt where rt.rtag_id = " + baseline
1720
                );
1721
        ResultSet rset1 = stmt1.executeQuery();
1722
 
1723
        while( rset1.next() )
1724
        {
1725
            String email = rset1.getString("owner_email");
1726
 
1727
            if ( email != null )
1728
            {
1729
                email = email.trim();
1730
                emailCollection.addAll( Arrays.asList(email.split("\\s*[,\\s]+\\s*")));
1731
            }
1732
        }
1733
 
1734
        rset1.close();
1735
        stmt1.close();
1736
 
1737
        return emailCollection;
1738
    }
1739
 
1740
    /**	Clears the database entry of the build file
1741
     *  <br>The assumption is that the file has been collected from the database and stored for use
1742
     *  
1743
     *  <p>sets CURRENT_BUILD_FILES to NULL for the rcon_id
1744
     */
1745
    public void clearBuildFile(int rcon_id) throws SQLException, Exception
1746
    {
1747
        mLogger.debug("clearBuildFile");
1748
 
1749
        try
1750
        {
1751
            connect();
1752
 
1753
            CallableStatement stmt = mConnection.prepareCall(
1754
                    "update release_manager.run_level" +
1755
                    " set current_build_files=NULL" +
1756
                    " where rcon_id=" + rcon_id
1757
                    );
1758
            stmt.executeUpdate();
1759
            stmt.close();
1760
            commit();
1761
        }
1762
        catch ( SQLException e )
1763
        {
1764
            handleSQLException(e, "");
1765
        }
1766
        finally
1767
        {
1768
            // this block is executed regardless of what happens in the try block
1769
            // even if an exception is thrown
1770
            // ensure disconnect
1771
            disconnect();
1772
        }
1773
    }
1774
 
1775
    /** Stores a buildfile in the database so that all daemons can collect it
1776
     * updates the CURRENT_BUILD_FILES for the rtag_id
1777
     *      This will trigger the slave build cycle
1778
     * Also sets the pkg_id and pvId of the package being built
1779
     *      This is only used for display purposes in Release manager
1780
     * 
1781
     * @param rtag_id   - Target Release
1782
     * @param buildFile - buildfile content to be saved
1783
     */
1784
    public void publishBuildFile(int rtag_id, BuildFile buildFile) throws SQLException, Exception
1785
    {
1786
        mLogger.debug("publishBuildFile publishing a build file of length " + buildFile.content.length());
1787
        mLogger.debug("publishBuildFile publishing pkgId: " + buildFile.mPkgId + " pvid: " + buildFile.mPvId);
1788
 
1789
        try
1790
        {
1791
            connect();
1792
 
1793
            if ( isRtagIdConfigured( rtag_id ) )
1794
            {
1795
                PreparedStatement stmt = mConnection.prepareStatement(
1796
                        "update release_manager.run_level " +
1797
                                "    set current_build_files=?,  " +
1798
                                "        current_pkg_id_being_built=?,"+
1799
                                "        current_pv_id=?," +
1800
                                "       last_build=sysdate" +
1801
                                "    WHERE rcon_id in (  " +
1802
                                "        select rl.rcon_id from release_manager.release_config rc,  " +
1803
                                "               release_manager.run_level rl  " +
1804
                                "        where rc.rtag_id=? and rl.rcon_id=rc.rcon_id )" );
1805
                stmt.setString(1, buildFile.content);
1806
 
1807
                if (buildFile.mPkgId ==  0) {
1808
                    stmt.setNull(2, Types.NUMERIC);
1809
                } else {
1810
                    stmt.setInt  (2, buildFile.mPkgId);
1811
                }
1812
 
1813
                if (buildFile.mPvId ==  0) {
1814
                    stmt.setNull(3, Types.NUMERIC);
1815
                } else {
1816
                    stmt.setInt  (3, buildFile.mPvId);
1817
                }
1818
 
1819
                stmt.setInt(4, rtag_id);
1820
 
1821
                stmt.executeUpdate();
1822
                stmt.close();
1823
                commit();
1824
            }
1825
        }
1826
        catch ( SQLException e )
1827
        {
1828
            handleSQLException(e, "");
1829
        }
1830
        catch ( Exception e )
1831
        {
1832
            // this catch and rethrow is historical
1833
            // problems were found using CallableStatement when updating a CLOB column with data > 4000 bytes
1834
            mLogger.fatal("publishBuildFile caught Exception " + e.getMessage());
1835
            throw new Exception("publishBuildFile caught Exception " + e.getMessage());
1836
        }
1837
        finally
1838
        {
1839
            // this block is executed regardless of what happens in the try block
1840
            // even if an exception is thrown
1841
            // ensure disconnect
1842
            disconnect();
1843
        }
1844
    }
1845
 
1846
    /**only used in daemon mode
1847
     * <br>Query the Release Sequence Number for the specified Release, while ensuing that the machine
1848
     * is still a part of the current build set
1849
     * 
1850
     * @param   rtagId      Release Identifier
1851
     * @return  <0  - No longer a part of the Build Set
1852
     * <br>     >=0 - Release Sequence Number
1853
     * 
1854
     */
1855
    public int queryReleaseSeqNum(int rtagId, int rcon_id, String machine_hostname) throws SQLException, Exception
1856
    {
1857
        mLogger.debug("queryReleaseSeqNum");
1858
        int retVal = 0;
1859
 
1860
        if ( mUseDatabase )
1861
        {
1862
            try
1863
            {
1864
                connect();
1865
                mLogger.info("queryReleaseSeqNum queryReleaseSeqNum");
1866
                CallableStatement stmt = mConnection.prepareCall(
1867
                        "SELECT NVL(rl.pause,0) AS pause, " + 
1868
                                "(select seqnum from release_modified where rtag_id = "+ rtagId +") as seqnum" +
1869
                                " FROM run_level rl," +
1870
                                "  release_config rc," +
1871
                                "  BUILD_MACHINE_CONFIG bmc" +
1872
                                " WHERE rl.rcon_id = " + rcon_id +
1873
                                " AND rl.RCON_ID   = rc.RCON_ID" +
1874
                                " AND rc.BMCON_ID IS NOT NULL" +
1875
                                " AND rc.BMCON_ID = bmc.BMCON_ID" +
1876
                                " AND rc.DAEMON_MODE = 'M'" +
1877
                                " AND UPPER(bmc.MACHINE_HOSTNAME) = UPPER('"+machine_hostname+"')"
1878
                                );
1879
 
1880
                ResultSet rset = stmt.executeQuery();
1881
                if( rset.next() )
1882
                {
1883
                    int pause = rset.getInt("pause");
1884
                    if (pause > 1)
1885
                        retVal = -2;
1886
                    else
1887
                        retVal = rset.getInt("seqnum");                        
1888
                }
1889
                else
1890
                {
1891
                    retVal = -1;
1892
                }
1893
 
1894
                rset.close();
1895
                stmt.close();
1896
            }
1897
            catch ( SQLException e )
1898
            {
1899
                handleSQLException(e, "");
1900
            }
1901
            finally
1902
            {
1903
                disconnect();
1904
            }
1905
        }
1906
 
1907
        mLogger.warn("queryReleaseSeqNum returned " + retVal);
1908
        return retVal;
1909
    }
1910
 
1911
    /**
1912
     * Disable all the daemons for a specific release
1913
     *      Should only be done by the master
1914
     *      Used when master thread discovers that no build has occurred for a long time
1915
     *      
1916
     * @param rtag_id
1917
     * @throws SQLException
1918
     * @throws Exception
1919
     */
1920
    private void disableDaemons(final int rtag_id) throws SQLException, Exception
1921
    {
1922
        mLogger.fatal("disableDaemons: " + rtag_id );
1923
 
1924
        try
1925
        {
1926
            CallableStatement stmt1 = mConnection.prepareCall( "call PK_BUILDAPI.set_daemon_states(?,2)" );
1927
            stmt1.setInt( 1, rtag_id );
1928
            stmt1.executeUpdate();
1929
            stmt1.close();
1930
            commit();
1931
        }
1932
        catch ( SQLException e )
1933
        {
1934
            handleSQLException(e, "");
1935
        }
1936
    }
1937
 
1938
    /**Checks the existence of any valid daemon configuration for the Release
1939
     * 
1940
     * A valid configuration record has a release_config entry that is linked to
1941
     * a machine_configuration entry. ie: unlinked entries are not part of a configured set.
1942
     * 
1943
     * @param   rtag_id - Release Tag to test
1944
     * @return  True if the Release still has a configuration entry
1945
     */
1946
    private boolean isRtagIdConfigured(final int rtag_id) throws SQLException, Exception
1947
    {
1948
        mLogger.debug("isRtagIdConfigured");
1949
        boolean retVal = false;
1950
 
1951
        try
1952
        {
1953
            // check if the rcon_id is still configured
1954
            CallableStatement stmt = mConnection.prepareCall(
1955
                    "select rtag_id"
1956
                    + " from release_manager.release_config"
1957
                    + " where rtag_id=" + rtag_id
1958
                    + " AND bmcon_id is not NULL");
1959
            ResultSet rset = stmt.executeQuery();
1960
 
1961
            while( rset.next() )
1962
            {
1963
                retVal = true;
1964
            }
1965
 
1966
            rset.close();
1967
            stmt.close();
1968
        }
1969
        catch ( SQLException e )
1970
        {
1971
            handleSQLException(e, "");
1972
        }
1973
        mLogger.info("isRtagIdConfigured returning " + retVal);
1974
        return retVal;
1975
    }
1976
 
1977
    /**queries the RUN_LEVEL table for daemon to determine if the daemon has been paused
1978
     * or disabled.
1979
     * 
1980
     * Used as a part of allowedToProceed()
1981
     * 
1982
     * Handles the following conditions
1983
     *  Daemon has be de-configured - Returns TRUE
1984
     *  Daemon has been paused - Returns FALSE
1985
     *  Daemon has been disabled - Returns TRUE
1986
     *  Daemon has been set to run - Returns TRUE 
1987
     * 
1988
     * @param   rcon_id Connection identifier
1989
     * @returns False: Build agent has been commanded to PAUSE
1990
     *      <br>True: All other conditions
1991
     * 
1992
     * @exception SQLException
1993
     * @exception Exception
1994
     */
1995
    public boolean queryDirectedRunLevel(final int rcon_id) throws SQLException, Exception
1996
    {
1997
        mLogger.debug("queryDirectedRunLevel " + rcon_id);
1998
        boolean retVal = true;
1999
 
2000
        if ( mUseDatabase )
2001
        {
2002
            try
2003
            {
2004
                CallableStatement stmt = mConnection.prepareCall(
2005
                        "select NVL(rl.pause,0) as pause" +
2006
                        " from release_manager.run_level rl, release_manager.release_config rc "+
2007
                        " where rl.rcon_id=" + rcon_id +
2008
                        " and rl.RCON_ID = rc.RCON_ID" +
2009
                        " and rc.BMCON_ID is not NULL"
2010
                        );
2011
                ResultSet rset = stmt.executeQuery();
2012
                int rsetSize = 0;
2013
 
2014
                while( rset.next() )
2015
                {
2016
                    rsetSize++;
2017
 
2018
                    //
2019
                    //  Pause: null -> 0 == Run
2020
                    //         1         == Pause
2021
                    //         2         == Disabled
2022
                    //
2023
                    int pause = rset.getInt("pause");
2024
                    if ( pause == 1) {
2025
                        retVal = false;
2026
                    }
2027
                }
2028
 
2029
                rset.close();
2030
                stmt.close();
2031
 
2032
                if ( rsetSize > 1 )
2033
                {
2034
                    mLogger.fatal("queryDirectedRunLevel rsetSize > 1");
2035
                    // show stopper
2036
                    throw new Exception("queryDirectedRunLevel rsetSize > 1");
2037
                }
2038
            }
2039
            catch ( SQLException e )
2040
            {
2041
                handleSQLException(e, "");
2042
            }
2043
        }
2044
 
2045
        mLogger.info("queryDirectedRunLevel returning " + retVal);
2046
        return retVal;
2047
    }
2048
 
2049
    /**
2050
     * queries the RELEASE_CONFIG and BUILD_MACHINE_CONFIG tables using the rcon_id primary key, rtag_id, machine_hostname, daemon_mode
2051
     * <p>Return true if the query contains a result set containing one row
2052
     *  (indicating the rcon_id is still configured and its configuration is unchanged, aside from the gbe_buildfilter)
2053
     *  the gbe_buildfilter is queried prior to usage
2054
     * 
2055
     *  <p>Used to determine if this daemon should be allowed to continue running
2056
     *  or if it should be terminated
2057
     *  
2058
     * <br>Overridden in ReleaseManagerUtf 
2059
     * 
2060
     * @param rtag_id          The rtag_id of the machine to examine
2061
     * @param rcon_id          The rcond_id of the machine to examine
2062
     * @param machine_hostname The hostname of the machine to examine
2063
     * @param daemon_mode      The daemon mode of the machine to examine
2064
     * @param threadStartTime  The time that the thread started
2065
     * 
2066
     * @return True: The machine is a part of the current build set
2067
     *         False: The machine is not a part of the current build set
2068
     * @exception SQLException
2069
     * @exception Exception
2070
     */
2071
    public boolean queryReleaseConfig(final int rtag_id, final int rcon_id,final String machine_hostname, final char daemon_mode, final long threadStartTime) throws SQLException, Exception
2072
    {
2073
        mLogger.debug("queryReleaseConfig 1");
2074
        boolean retVal = false;
2075
 
2076
        try
2077
        {
2078
            String sql = 
2079
                    "select rl.pause," +
2080
                    "       rt.build_age," +
2081
                    "       TRUNC((SYSDATE-rl.last_build) ) as last_build_days" +
2082
                    "   from release_manager.release_config rc," +
2083
                    "        release_manager.release_tags rt," +
2084
                    "        release_manager.run_level rl," +
2085
                    "        release_manager.build_machine_config bc" +
2086
                    "   where rc.rtag_id=?" +
2087
                    "     and rc.rcon_id=?" +
2088
                    "     and rc.bmcon_id is not NULL" +
2089
                    "     and rc.bmcon_id = bc.bmcon_id" +
2090
                    "     and bc.machine_hostname=?" +
2091
                    "     and rc.daemon_mode=?" +
2092
                    "     and rl.rcon_id=rc.rcon_id" +
2093
                    "     and rt.rtag_id=rc.rtag_id" +
2094
                    "     and (rt.official = 'N' or rt.official='R' or rt.official='C')";
2095
 
2096
            CallableStatement stmt = mConnection.prepareCall( sql );
2097
            stmt.setFetchSize(10);
2098
            stmt.setInt(1, rtag_id);
2099
            stmt.setInt(2, rcon_id);
2100
            stmt.setString(3, machine_hostname);
2101
            stmt.setString(4, Character.toString(daemon_mode));
2102
            ResultSet rset = stmt.executeQuery();
2103
            int rsetSize = 0;
2104
 
2105
            while( rset.next() )
2106
            {
2107
                rsetSize++;
2108
 
2109
                //
2110
                //  Pause: null -> 0 == Run
2111
                //         1         == Pause
2112
                //         2         == Disabled
2113
                //
2114
                int pause = rset.getInt("pause");
2115
                if ( rset.wasNull() )
2116
                {
2117
                    pause = 0;
2118
                }
2119
 
2120
                //
2121
                //  build_age
2122
                //
2123
                int build_age = rset.getInt("build_age");
2124
                if ( rset.wasNull() )
2125
                {
2126
                    build_age = 0;
2127
                }
2128
 
2129
                //
2130
                // days since last build
2131
                //
2132
                int days_since_last_build = rset.getInt("last_build_days");
2133
                if ( rset.wasNull() )
2134
                {
2135
                    days_since_last_build = 0;
2136
                }
2137
 
2138
                //
2139
                //  Determine if we should disable the daemons on this release because they have not been
2140
                //  used in a long while.
2141
                //
2142
                //  Only Master makes the decision
2143
                //  If build_age is zero - then the daemon does not get aged out
2144
                //  If the days since last build > build_age, then we will shut down
2145
                //      Allow one days grace - will show up IN RM for a day
2146
                //  Allow the thread to run for x hours before shutting it down
2147
                //      Handles case where daemon has just been started/restarted
2148
                //
2149
                if ( daemon_mode == 'M' &&  build_age > 0 && days_since_last_build > (build_age + 1) )
2150
                {
2151
                    long upTimeSecs = (System.currentTimeMillis() - threadStartTime)/1000;
2152
                    mLogger.fatal("queryReleaseConfig 1: " + rtag_id + ", " + rcon_id + ", "+ daemon_mode + ", " + pause + ", " + build_age + ", " + days_since_last_build + ", " + upTimeSecs );
2153
                    if ( upTimeSecs > mPostponeShutdown)
2154
                    {
2155
                        disableDaemons(rtag_id);
2156
                        pause = 2;
2157
                    }
2158
                    else
2159
                    {
2160
                        mLogger.fatal("queryReleaseConfig 1: Shutdown Postponed"  );    
2161
                    }
2162
                }
2163
 
2164
                mLogger.info("queryReleaseConfig 1: " + rtag_id + ", " + rcon_id + ", "+ daemon_mode + ", " + pause + ", " + build_age + ", " + days_since_last_build );
2165
 
2166
                if ( pause <= 1 )
2167
                {
2168
                    retVal = true;
2169
                }
2170
            }
2171
 
2172
            rset.close();
2173
            stmt.close();
2174
 
2175
            if ( rsetSize > 1 )
2176
            {
2177
                mLogger.fatal("queryReleaseConfig 1 rsetSize > 1");
2178
                // show stopper
2179
                throw new Exception("queryReleaseConfig 1 rsetSize > 1");
2180
            }
2181
        }
2182
        catch ( SQLException e )
2183
        {
2184
            handleSQLException(e, ":1");
2185
        }
2186
 
2187
        mLogger.info("queryReleaseConfig 1 returning " + retVal);
2188
        return retVal;
2189
    }
2190
 
2191
    /**removes all elements from the mReleaseConfigCollection
2192
     * handles database connection and disconnection
2193
     * queries the RELEASE_CONFIG and BUILD_MACHINE_CONFIG tables using the rtag_id 
2194
     *  
2195
     * populates the mReleaseConfigCollection with the query result set
2196
     * partially implements the sequence diagrams coordinate slave threads generate build files 
2197
     *  
2198
     * Used by Master Thread to determine the build machines that will be a part 
2199
     * of the Slave-Sync process.
2200
     * 
2201
     *  Only called when a database connection has been established
2202
     */
2203
    public void queryReleaseConfig(final int rtag_id) throws SQLException, Exception
2204
    {
2205
        mLogger.debug("queryReleaseConfig 2");
2206
        mReleaseConfigCollection.resetData();
2207
 
2208
        try
2209
        {
2210
            //connect();
2211
 
2212
            CallableStatement stmt = mConnection.prepareCall(
2213
                    " select rc.rcon_id,"+
2214
                    "        rc.daemon_mode,"+
2215
                    "        rl.pause,"+
2216
                    "        bc.machine_hostname,"+
2217
                    "        rc.gbe_buildfilter,"+
2218
                    "        mt.gbe_value,"+
2219
                    "        bm.bm_name" +
2220
                    "    from release_manager.release_config rc, " +
2221
                    "         release_manager.run_level rl, " +
2222
                    "         release_manager.build_machine_config bc, " +
2223
                    "         release_manager.gbe_machtype mt," +
2224
                    "         release_manager.build_machines bm" +
2225
                    "    where   rc.rtag_id=?" +
2226
                    "        and rl.rcon_id=rc.rcon_id " +
2227
                    "        and rc.bmcon_id is not NULL" +
2228
                    "        and rc.bmcon_id = bc.bmcon_id" +
2229
                    "        and mt.gbe_id=bc.gbe_id" +
2230
                    "        and mt.bm_id=bm.bm_id"
2231
                    );
2232
            stmt.setFetchSize(10);
2233
            stmt.setInt(1, rtag_id);
2234
            ResultSet rset = stmt.executeQuery();
2235
 
2236
            while( rset.next() )
2237
            {
2238
                int rcon_id = rset.getInt("rcon_id");
2239
 
2240
                if ( rset.wasNull() )
2241
                {
2242
                    mLogger.fatal("queryReleaseConfig 2 null rcon_id " + rtag_id);
2243
                    // show stopper
2244
                    throw new Exception("queryReleaseConfig 2 null rcon_id " + rtag_id);
2245
                }
2246
 
2247
                char dm = 'S';          
2248
                String daemon_mode = rset.getString("daemon_mode");
2249
 
2250
                if ( daemon_mode != null )
2251
                {
2252
                    mLogger.info("queryReleaseConfig 2 daemon_mode " + daemon_mode + ".");
2253
 
2254
                    if ( daemon_mode.compareTo("M") == 0 )
2255
                    {
2256
                        dm = 'M';
2257
                    }
2258
                }
2259
 
2260
                String machine_hostname = rset.getString("machine_hostname");
2261
                if (machine_hostname == null)
2262
                {
2263
                    mLogger.fatal("queryReleaseConfig 2 null machine_hostname " + rtag_id);
2264
                    throw new Exception("queryReleaseConfig 2 null machine_hostname " + rtag_id);
2265
                }
2266
 
2267
                String gbe_buildfilter = rset.getString("gbe_buildfilter");
2268
 
2269
                String gbe_machtype = rset.getString("gbe_value");
2270
                if (gbe_machtype == null)
2271
                {
2272
                    mLogger.fatal("queryReleaseConfig 2 null gbe_value " + rtag_id);
2273
                    throw new Exception("queryReleaseConfig 2 null gbe_value " + rtag_id);
2274
                }
2275
 
2276
                String gbe_machclass = rset.getString("bm_name");
2277
                if (gbe_machclass == null)
2278
                {
2279
                    mLogger.fatal("queryReleaseConfig 2 null bm_name " + rtag_id);
2280
                    throw new Exception("queryReleaseConfig 2 null bm_name " + rtag_id);
2281
                }
2282
 
2283
                //
2284
                //  Pause: null -> 0 == Run
2285
                //         1         == Pause
2286
                //         2         == Disabled
2287
                //
2288
                int pause = rset.getInt("pause");
2289
                if ( rset.wasNull() )
2290
                {
2291
                    pause = 0;
2292
                }
2293
                mLogger.info("queryReleaseConfig 2: " + rtag_id + ", " + rcon_id + ", "+ dm + ", " + pause + 
2294
                        ", " + machine_hostname + ", " + gbe_buildfilter + ", " + gbe_machtype + ", + " + gbe_machclass );
2295
 
2296
                //
2297
                // Daemon Mode : Do not include build daemons that are disabled
2298
                // Escrow Mode : Include all machines
2299
                //
2300
                if ( pause <= 1 ||  ! mDaemon )
2301
                {
2302
                    ReleaseConfig releaseConfig = new ReleaseConfig( rtag_id, rcon_id, dm, machine_hostname, gbe_buildfilter, gbe_machtype, gbe_machclass);
2303
                    mReleaseConfigCollection.add(releaseConfig);
2304
                }
2305
            }
2306
 
2307
 
2308
            rset.close();
2309
            stmt.close();
2310
        }
2311
        catch ( SQLException e )
2312
        {
2313
            handleSQLException(e, ":2");
2314
        }
2315
        finally
2316
        {
2317
            // this block is executed regardless of what happens in the try block
2318
            // even if an exception is thrown
2319
            // ensure disconnect
2320
            //disconnect();
2321
        }
2322
    }
2323
 
2324
    /**removes all elements from the mReleaseConfigCollection
2325
     * handles database connection and disconnection
2326
     * queries the RELEASE_CONFIG and BUILD_MACHINE_CONFIG table using the machine_hostname
2327
     * populates the mReleaseConfigCollection with the query result set
2328
     * partially implements the sequence diagram spawn thread 
2329
     *  
2330
     * Used by the BuildDaemon thread to determine daemons to start and stop
2331
     */
2332
    public void queryReleaseConfig(final String hostname) throws SQLException, Exception
2333
    {
2334
        mLogger.debug("queryReleaseConfig 3 " + hostname);
2335
        mReleaseConfigCollection.resetData();
2336
 
2337
        try
2338
        {
2339
            connect();
2340
            CallableStatement stmt = mConnection.prepareCall(
2341
                    "select rc.rtag_id,"+
2342
                    "       rc.rcon_id,"+
2343
                    "       rc.daemon_mode,"+
2344
                    "       rl.pause,"+
2345
                    "       bc.machine_hostname,"+
2346
                    "       rc.gbe_buildfilter,"+
2347
                    "       mt.gbe_value,"+
2348
                    "       bm.bm_name" +
2349
                    "  from release_manager.release_config rc," +
2350
                    "       release_manager.release_tags rt," +
2351
                    "       release_manager.run_level rl," +
2352
                    "       release_manager.build_machine_config bc," +
2353
                    "       release_manager.gbe_machtype mt," +
2354
                    "       release_manager.build_machines bm " +
2355
                    "    where bc.machine_hostname=?" +
2356
                    "      and rt.rtag_id=rc.rtag_id" +
2357
                    "      and rl.rcon_id=rc.rcon_id" +
2358
                    "      and rc.bmcon_id is not NULL" +
2359
                    "      and bc.bmcon_id=rc.bmcon_id" +
2360
                    "      and mt.gbe_id=bc.gbe_id" +
2361
                    "      and mt.bm_id=bm.bm_id" +
2362
                    "      and (rt.official = 'N' or rt.official='R' or rt.official='C')"
2363
                    );
2364
 
2365
            stmt.setFetchSize(20);
2366
            stmt.setString(1, hostname);
2367
            ResultSet rset = stmt.executeQuery();
2368
 
2369
            while( rset.next() )
2370
            {
2371
                int rtag_id = rset.getInt("rtag_id");
2372
 
2373
                if ( rset.wasNull() )
2374
                {
2375
                    mLogger.fatal("queryReleaseConfig 3 null rtag_id");
2376
                    // show stopper
2377
                    throw new Exception("queryReleaseConfig 3 null rtag_id");
2378
                }
2379
 
2380
                int rcon_id = rset.getInt("rcon_id");
2381
 
2382
                if ( rset.wasNull() )
2383
                {
2384
                    mLogger.fatal("queryReleaseConfig 3 null rcon_id");
2385
                    throw new Exception("queryReleaseConfig 3 null rcon_id");
2386
                }
2387
 
2388
                char dm = 'S';          
2389
                String daemon_mode = rset.getString("daemon_mode");
2390
 
2391
                if ( daemon_mode != null )
2392
                {
2393
                    mLogger.info("queryReleaseConfig 3 daemon_mode " + daemon_mode + ".");
2394
 
2395
                    if ( daemon_mode.compareTo("M") == 0 )
2396
                    {
2397
                        dm = 'M';
2398
                    }
2399
                }
2400
 
2401
                String machine_hostname = rset.getString("machine_hostname");
2402
                if (machine_hostname == null)
2403
                {
2404
                    mLogger.fatal("queryReleaseConfig 3 null machine_hostname " + rtag_id);
2405
                    throw new Exception("queryReleaseConfig 3 null machine_hostname " + rtag_id);
2406
                }
2407
 
2408
                String gbe_buildfilter = rset.getString("gbe_buildfilter");
2409
 
2410
                String gbe_machtype = rset.getString("gbe_value");
2411
                if (gbe_machtype == null)
2412
                {
2413
                    mLogger.fatal("queryReleaseConfig 3 null gbe_value " + rtag_id);
2414
                    throw new Exception("queryReleaseConfig 3 null gbe_value " + rtag_id);
2415
                }
2416
 
2417
                String gbe_machclass = rset.getString("bm_name");
2418
                if (gbe_machclass == null)
2419
                {
2420
                    mLogger.fatal("queryReleaseConfig 3 null bm_name " + rtag_id);
2421
                    throw new Exception("queryReleaseConfig 3 null bm_name " + rtag_id);
2422
                }
2423
 
2424
                //
2425
                //  Pause: null -> 0 == Run
2426
                //         1         == Pause
2427
                //         2         == Disabled
2428
                //
2429
                int pause = rset.getInt("pause");
2430
                if ( rset.wasNull() )
2431
                {
2432
                    pause = 0;
2433
                }
2434
 
2435
                mLogger.info("queryReleaseConfig 3: " + rtag_id + ", " + rcon_id + ", "+ dm + ", " + pause + 
2436
                        ", " + machine_hostname + ", " + gbe_buildfilter + ", " + gbe_machtype + ", + " + gbe_machclass );
2437
 
2438
                //
2439
                // Do not include build daemons that are disabled
2440
                // Only those that are running or paused
2441
                //
2442
                if ( pause <= 1 )
2443
                {
2444
                    ReleaseConfig releaseConfig = new ReleaseConfig( rtag_id, rcon_id, dm, machine_hostname, gbe_buildfilter, gbe_machtype, gbe_machclass);
2445
                    mReleaseConfigCollection.add(releaseConfig);
2446
                }
2447
            }
2448
 
2449
            rset.close();
2450
            stmt.close();
2451
        }
2452
        catch ( SQLException e )
2453
        {
2454
            handleSQLException(e, ":3");
2455
        }
2456
        finally
2457
        {
2458
            // this block is executed regardless of what happens in the try block
2459
            // even if an exception is thrown
2460
            // ensure disconnect
2461
            disconnect();
2462
        }
2463
 
2464
    }
2465
 
2466
    /** Check that the build set has exactly one master
2467
     *  
2468
     *  Ignores entries that are disabled
2469
     *  Ignore entries that have been 'unlinked' - they have no active machine configuration
2470
     *
2471
     *   @param rtag_id - Release Tag
2472
     *  
2473
     *  Used by the Master and Slave Daemons 
2474
     *  Overridden in ReleaseManagerUtf 
2475
     */
2476
    public int queryMasterCount(final int rtag_id) throws SQLException, Exception
2477
    {
2478
        mLogger.debug("queryMasterCount rtag_id " + rtag_id);
2479
 
2480
        int masterCount = 0;
2481
        try
2482
        {
2483
            connect();
2484
            CallableStatement stmt = mConnection.prepareCall(
2485
                            "SELECT COUNT (rc.daemon_mode) as masterCount" +
2486
                            " FROM release_manager.release_config rc, release_manager.run_level rl" +
2487
                            " WHERE rc.rtag_id =" + rtag_id +
2488
                            " AND rl.RCON_ID = rc.RCON_ID" +
2489
                            " AND   rc.bmcon_id is not NULL" +
2490
                            " AND NVL(rl.PAUSE,0) != 2" +
2491
                            " GROUP BY rc.daemon_mode" +
2492
                            " HAVING rc.daemon_mode = 'M'" );
2493
 
2494
            ResultSet rset = stmt.executeQuery();
2495
 
2496
            if ( rset.next() )
2497
            {
2498
                masterCount = rset.getInt("masterCount");
2499
            }
2500
 
2501
            rset.close();
2502
            stmt.close();
2503
        }
2504
        catch ( SQLException e )
2505
        {
2506
            handleSQLException(e, "");
2507
        }
2508
        finally
2509
        {
2510
            // this block is executed regardless of what happens in the try block
2511
            // even if an exception is thrown
2512
            // ensure disconnect
2513
            disconnect();
2514
        }
2515
 
2516
        return masterCount;
2517
    }
2518
 
2519
    /**
2520
     * Determine an array of machines for which there are active build requests
2521
     * Used to notify slave machines of a pending build request
2522
     * 
2523
     *  
2524
     * @param mHostname - Identifies the build machine
2525
     * @param rconIdList - Comma separated list of RCON_IDs that we are interested in
2526
     * @return An array of Integers, each being the rcon_id of a machine that has an active build
2527
     * @throws Exception 
2528
     */
2529
    public ArrayList<Integer> queryActivatedBuilds(String mHostname, String rconIdList) throws Exception {
2530
 
2531
        ArrayList<Integer> rv = new ArrayList<Integer>();
2532
        try
2533
        {
2534
            connect();
2535
            PreparedStatement stmt = mConnection.prepareStatement(
2536
                    "SELECT rl.rcon_id, rc.RTAG_ID" +
2537
                    " FROM run_level rl, release_config rc, release_tags rt" +
2538
                    " WHERE  rt.rtag_id = rc.RTAG_ID" +
2539
                    " AND UPPER(rc.daemon_hostname) = UPPER('"+mHostname+"')" +
2540
                    " AND rc.DAEMON_MODE != 'M'" +
2541
                    " AND rc.RCON_ID = rl.rcon_id" +
2542
                    " AND CURRENT_BUILD_FILES IS NOT NULL" +
2543
                    " AND rl.pause is null" +
2544
                    " AND rl.rcon_id in ("+rconIdList+")"
2545
                    );
2546
 
2547
            ResultSet rset = stmt.executeQuery();
2548
 
2549
            while (rset.next()) {
2550
                Integer ii = rset.getInt("rcon_id");
2551
                rv.add(ii);
2552
            }
2553
 
2554
            rset.close();
2555
            stmt.close();
2556
        }
2557
        catch ( SQLException e )
2558
        {
2559
            handleSQLException(e, "");
2560
        }
2561
        finally
2562
        {
2563
            // this block is executed regardless of what happens in the try block
2564
            // even if an exception is thrown
2565
            // ensure disconnect
2566
            disconnect();
2567
        }
2568
        return rv;
2569
    }
2570
 
2571
    /**in daemon mode
2572
     *  1 get planned package info
2573
     *     select pl.pv_id, p.pkg_id, p.pkg_name, pv.v_ext, pv.pkg_vcs_tag, pv.change_type
2574
     *     from release_manager.planned pl, release_manager.package_versions pv, release_manager.packages p
2575
     *     where pl.rtag_id=<mBaseline> and pv.build_type='A' and pv.dlocked='A'
2576
     *     and pv.pv_id=pl.pv_id and p.pkg_id=pv.pkg_id
2577
     *     order by pl.pv_id;
2578
     *  2 get planned package dependency info
2579
     *     select pl.pv_id, p.pkg_name, dpv.v_ext
2580
     *     from release_manager.planned pl, release_manager.package_versions pv, release_manager.package_dependencies pd, release_manager.package_versions dpv, release_manager.packages p
2581
     *     where pl.rtag_id=<mBaseline> and pv.build_type='A' and pv.dlocked='A'
2582
     *     and pv.pv_id = pl.pv_id and pd.pv_id=pl.pv_id and dpv.pv_id=pd.dpv_id and p.pkg_id=dpv.pkg_id
2583
     *     order by pl.pv_id;
2584
     *  3 get planned package build info
2585
     *     select pl.pv_id, bm.bm_name, bsa.bsa_name
2586
     *     from release_manager.planned pl, release_manager.package_versions pv, release_manager.package_build_info pbi, release_manager.build_machines bm, release_manager.build_standards_addendum bsa
2587
     *     where pl.rtag_id=<mBaseline> and pv.build_type='A' and pv.dlocked='A'
2588
     *     and pv.pv_id = pl.pv_id and pbi.pv_id=pv.pv_id and bm.bm_id=pbi.bm_id and bsa.bsa_id=pbi.bsa_id
2589
     *     order by pl.pv_id;
2590
     *  4 get planned package unit test info
2591
     *     select pl.pv_id, tt.test_type_name
2592
     *     from release_manager.planned pl, release_manager.package_versions pv, release_manager.unit_tests ut, release_manager.test_types tt
2593
     *     where pl.rtag_id=<mBaseline> and pv.build_type='A' and pv.dlocked='A'
2594
     *     and pv.pv_id = pl.pv_id and ut.pv_id=pv.pv_id and tt.test_type_id=ut.test_types_fk
2595
     *     order by pl.pv_id;
2596
     *  5 get planned package build failure info
2597
     *     select pl.pv_id, u.user_email
2598
     *     from release_manager.planned pl, release_manager.release_tags rt, release_manager.package_versions pv, release_manager.autobuild_failure af, release_manager.members_group mg, release_manager.users u
2599
     *     where pl.rtag_id=<mBaseline> and rt.rtag_id=pl.rtag_id and pv.build_type='A' and pv.dlocked='A'
2600
     *     and pv.pv_id = pl.pv_id and af.view_id=pl.view_id and mg.group_email_id=af.group_email_id and u.user_id=mg.user_id and af.proj_id=rt.proj_id
2601
     *     order by pl.pv_id;
2602
     *  6 get planned package do not ripple info
2603
     *     select pl.pv_id
2604
     *     from release_manager.planned pl, release_manager.package_versions pv, release_manager.do_not_ripple dnr
2605
     *     where pl.rtag_id=<mBaseline> and pv.build_type='A' and pv.dlocked='A'
2606
     *     and pv.pv_id = pl.pv_id and dnr.rtag_id=pl.rtag_id and dnr.pv_id=pl.pv_id
2607
     *     order by pl.pv_id;
2608
     *  7 get planned package advisory ripple info
2609
     *     select pl.pv_id
2610
     *     from release_manager.planned pl, release_manager.package_versions pv, release_manager.advisory_ripple ar
2611
     *     where pl.rtag_id=<mBaseline> and pv.build_type='A' and pv.dlocked='A'
2612
     *     and pv.pv_id = pl.pv_id and ar.rtag_id=pl.rtag_id and ar.pv_id=pl.pv_id
2613
     *     order by pl.pv_id;
2614
     *  8 get released package info
2615
     *     select rc.pv_id, p.pkg_id, p.pkg_name, pv.pkg_version, pv.v_ext, pv.pkg_vcs_tag, pv.ripple_field
2616
     *     pv.major_limit, pv.minor_limit, pv.patch_limit, pv.build_number_limit
2617
     *     from release_manager.release_content rc, release_manager.package_versions pv, release_manager.packages p
2618
     *     where rc.rtag_id=<mBaseline>
2619
     *     and pv.pv_id = rc.pv_id and p.pkg_id = pv.pkg_id
2620
     *     order by rc.pv_id;
2621
     *  9 get released package dependency info
2622
     *     select rc.pv_id, dpv.pv_id, p.pkg_name, dpv.v_ext
2623
     *     from release_manager.release_content rc, release_manager.package_versions pv, release_manager.package_dependencies pd, release_manager.package_versions dpv, release_manager.packages p
2624
     *     where rc.rtag_id=<mBaseline>
2625
     *     and pv.pv_id = rc.pv_id and pd.pv_id=pv.pv_id and dpv.pv_id=pd.dpv_id and p.pkg_id=dpv.pkg_id
2626
     *     order by rc.pv_id;
2627
     * 10 get released package build info
2628
     *     select rc.pv_id, bm.bm_name, bsa.bsa_name
2629
     *     from release_manager.release_content rc, release_manager.package_versions pv, release_manager.package_build_info pbi, release_manager.build_machines bm, release_manager.build_standards_addendum bsa
2630
     *     where rc.rtag_id=<mBaseline>
2631
     *     and pv.pv_id = rc.pv_id and pbi.pv_id=pv.pv_id and bm.bm_id=pbi.bm_id and bsa.bsa_id=pbi.bsa_id
2632
     *     order by rc.pv_id;
2633
     * 11 get released package unit test info
2634
     *     select rc.pv_id, tt.test_type_name
2635
     *     from release_manager.release_content rc, release_manager.package_versions pv, release_manager.unit_tests ut, release_manager.test_types tt
2636
     *     where rc.rtag_id=<mBaseline>
2637
     *     and pv.pv_id = rc.pv_id and ut.pv_id=pv.pv_id and tt.test_type_id=ut.test_types_fk
2638
     *     order by rc.pv_id;
2639
     * 12 get released package build failure email info
2640
     *     select rc.pv_id, u.user_email
2641
     *     from release_manager.release_content rc, release_manager.release_tags rt, release_manager.package_versions pv, release_manager.autobuild_failure af, release_manager.members_group mg, release_manager.users u
2642
     *     where rc.rtag_id=<mBaseline> and rt.rtag_id=rc.rtag_id
2643
     *     and pv.pv_id = rc.pv_id and af.view_id=rc.base_view_id and mg.group_email_id=af.group_email_id and u.user_id=mg.user_id and af.proj_id=rt.proj_id
2644
     *     order by rc.pv_id;
2645
     * 13 get released package do not ripple info
2646
     *     select rc.pv_id
2647
     *     from release_manager.release_content rc, release_manager.package_versions pv, release_manager.do_not_ripple dnr
2648
     *     where rc.rtag_id=<mBaseline>
2649
     *     and pv.pv_id = rc.pv_id and dnr.rtag_id=rc.rtag_id and dnr.pv_id=rc.pv_id
2650
     *     order by rc.pv_id;
2651
     * 14 get released advisory ripple info
2652
     *     select rc.pv_id
2653
     *     from release_manager.release_content rc, release_manager.package_versions pv, release_manager.advisory_ripple ar
2654
     *     where rc.rtag_id=<mBaseline>
2655
     *     and pv.pv_id = rc.pv_id and ar.rtag_id=rc.rtag_id and ar.pv_id=rc.pv_id
2656
     *     order by rc.pv_id;
2657
     *     
2658
     * in escrow mode
2659
     *  1 get released product info
2660
     *     select oc.prod_id, p.pkg_name, pv.pkg_version, pv.v_ext, pv.pkg_vcs_tag
2661
     *     from deployment_manager.bom_contents bc, deployment_manager.operating_systems os, deployment_manager.os_contents oc, release_manager.package_versions pv, release_manager.packages p
2662
     *     where bc.bom_id=<mBaseline> and os.node_id=bc.node_id and oc.os_id=os.os_id and pv.pv_id=oc.prod_id and p.pkg_id=pv.pkg_id
2663
     *     order by oc.prod_id;
2664
     *    this will generate a list of pv_ids associated with products
2665
     *    many in the list will reference cots products outside the scope of a escrow build
2666
     *  2 for each <pv_id>, call traverseDependencies( packageCollection, pv_id, false ) to traverse its set of dependencies
2667
     *  3 for each Package, call queryBuildInfo to get released package build info
2668
     *  
2669
     * Supports
2670
     *    test_type_name="Autobuild UTF"
2671
     *    bm_name="Generic"|"Linux"|"Solaris"|"Win32"
2672
     *    bsa_name="Debug"|"Production"|"Production and Debug"|"Java 1.4"|"Java 1.5"|"Java 1.6"
2673
     *  
2674
     * Overridden in ReleaseManagerUtf
2675
     *  
2676
     */
2677
    protected void queryPackageVersions(
2678
            RippleEngine rippleEngine, 
2679
            ArrayList<Package> packageCollection, 
2680
            int baseline) throws SQLException, Exception
2681
    {
2682
        Phase phase = new Phase("rmData");
2683
        mLogger.debug("queryPackageVersions " + mDaemon);
2684
 
2685
        try
2686
        {
2687
            if (mDaemon)
2688
            {
2689
                // Get planned package info
2690
                // Support multiple WIPS on the same package and build in the order they were released
2691
                // These are packages that are marked as pending build
2692
                //
2693
                mLogger.debug("queryPackageVersions: stmt1");
2694
                phase.setPhase("getPlannedPkgs1");
2695
                PreparedStatement stmt1 = mConnection.prepareStatement(
2696
                        "select pl.pv_id, p.pkg_id, p.pkg_name, pv.pkg_version, " +
2697
                                " pv.v_ext, pv.change_type, pv.ripple_field," +
2698
                                " pv.major_limit, pv.minor_limit, pv.patch_limit, pv.build_number_limit," +
2699
                                " pv.modified_stamp," +
2700
                                " release_manager.PK_RMAPI.return_vcs_tag(pl.pv_id) AS vcsTag" +
2701
                                " from release_manager.planned pl," +
2702
                                "      release_manager.package_versions pv," +
2703
                                "      release_manager.packages p" +
2704
                                " where pl.rtag_id=" + baseline +
2705
                                "   and pv.build_type='A' and pv.dlocked='A'" +
2706
                                "   and pv.pv_id=pl.pv_id and p.pkg_id=pv.pkg_id" +
2707
                                " order by pv.modified_stamp"
2708
                        );
2709
                stmt1.setFetchSize(500);
2710
                ResultSet rset1 = stmt1.executeQuery();
2711
 
2712
                while( rset1.next() )
2713
                {
2714
                    int pv_id = rset1.getInt("pv_id");
2715
 
2716
                    if ( rset1.wasNull() )
2717
                    {
2718
                        mLogger.fatal("queryPackageVersions rset1 null pv_id");
2719
                        // show stopper
2720
                        throw new Exception("queryPackageVersions rset1 null pv_id");
2721
                    }
2722
 
2723
                    int pkg_id = rset1.getInt("pkg_id");
2724
 
2725
                    if ( rset1.wasNull() )
2726
                    {
2727
                        mLogger.fatal("queryPackageVersions rset1 null pkg_id " + pv_id);
2728
                        // show stopper
2729
                        throw new Exception("queryPackageVersions rset1 null pkg_id " + pv_id);
2730
                    }
2731
 
2732
                    String pkg_name = rset1.getString("pkg_name");
2733
 
2734
                    if ( pkg_name == null )
2735
                    {
2736
                        mLogger.fatal("queryPackageVersions rset1 null pkg_name " + pv_id);
2737
                        // show stopper
2738
                        throw new Exception("queryPackageVersions rset1 null pkg_name " + pv_id);
2739
                    }
2740
 
2741
                    String pkg_version = rset1.getString("pkg_version");
2742
                    if (pkg_version == null) 
2743
                    {
2744
                        mLogger.fatal("queryPackageVersions rset1 null pkg_version " + pv_id);
2745
                        // show stopper
2746
                        throw new Exception("queryPackageVersions rset1 null pkg_version " + pv_id);
2747
                    }
2748
 
2749
                    // Previous Version of this package, without the project suffix
2750
                    String pkg_prevVersion = getBaseVersionNumber(pv_id);
2751
                    if ( pkg_prevVersion == null)
2752
                    {
2753
                        mLogger.fatal("queryPackageVersions. No Previous version" + pv_id);
2754
                        // show stopper
2755
                        throw new Exception("queryPackageVersions. No Previous version" + pv_id);
2756
                    }
2757
 
2758
                    String v_ext = rset1.getString("v_ext");
2759
 
2760
                    if ( v_ext == null )
2761
                    {
2762
                        v_ext = "";
2763
                    }
2764
 
2765
                    String change_type = rset1.getString("change_type");
2766
 
2767
                    if ( change_type == null )
2768
                    {
2769
                        change_type = "P";
2770
                    }
2771
 
2772
                    char ct = 'x';
2773
 
2774
                    if ( change_type.compareTo("M") == 0 )
2775
                    {
2776
                        ct = 'M';
2777
                    }
2778
                    else if ( change_type.compareTo("N") == 0 )
2779
                    {
2780
                        ct = 'N';
2781
                    }
2782
                    else if ( change_type.compareTo("P") == 0 )
2783
                    {
2784
                        ct = 'P';
2785
                    }
2786
                    else if ( change_type.compareTo("F") == 0 )
2787
                    {
2788
                        ct = 'F';
2789
                    }
2790
 
2791
                    if ( ct != 'x' )
2792
                    {
2793
                        String ripple_field = rset1.getString("ripple_field");
2794
 
2795
                        if ( ripple_field == null ||  ripple_field.length() == 0 )
2796
                        {
2797
                            ripple_field = "b";
2798
                        }
2799
 
2800
                        int major_limit = rset1.getInt("major_limit");
2801
 
2802
                        if ( rset1.wasNull() )
2803
                        {
2804
                            major_limit = 0;
2805
                        }
2806
 
2807
                        int minor_limit = rset1.getInt("minor_limit");
2808
 
2809
                        if ( rset1.wasNull() )
2810
                        {
2811
                            minor_limit = 0;
2812
                        }
2813
 
2814
                        int patch_limit = rset1.getInt("patch_limit");
2815
 
2816
                        if ( rset1.wasNull() )
2817
                        {
2818
                            patch_limit = 0;
2819
                        }
2820
 
2821
                        int build_number_limit = rset1.getInt("build_number_limit");
2822
 
2823
                        if ( rset1.wasNull() )
2824
                        {
2825
                            build_number_limit = 0;
2826
                        }
2827
 
2828
                        String vcs_tag = rset1.getString("vcsTag");
2829
                        if ( vcs_tag == null )
2830
                        {
2831
                            vcs_tag = "";
2832
                        }
2833
 
2834
                        Package p = new Package(pkg_id, pv_id, pkg_name, pkg_version, v_ext, pkg_name + v_ext, vcs_tag, ripple_field.charAt(0), ct);
2835
                        p.mDirectlyPlanned = true;
2836
                        p.mBuildReason = BuildReason.NewVersion;
2837
                        p.mMajorLimit = major_limit;
2838
                        p.mMinorLimit = minor_limit;
2839
                        p.mPatchLimit = patch_limit;
2840
                        p.mBuildLimit = build_number_limit;
2841
                        p.mPrevVersion = pkg_prevVersion;
2842
 
2843
                        Package prevPlannedPackage = findPackage(p.mAlias, packageCollection);
2844
 
2845
                        // If there are multiple packages with the same Alias, then only the first one
2846
                        // will be placed in the build set. The will be the oldest, the first one released
2847
                        // to be built
2848
                        if ( prevPlannedPackage == NULL_PACKAGE )
2849
                        {
2850
                            mLogger.info("queryPackageVersions rset1 no previous planned package " + pv_id);
2851
                            packageCollection.add(p);
2852
                        }
2853
                    }
2854
                }
2855
 
2856
                rset1.close();
2857
                stmt1.close();
2858
 
2859
                // get planned package dependency info
2860
                mLogger.debug("queryPackageVersions: stmt2");
2861
                phase.setPhase("getPlannedPkgs2");
2862
                PreparedStatement stmt2 = mConnection.prepareStatement(
2863
                        "select pl.pv_id, p.pkg_name, dpv.v_ext, pv.modified_stamp " +
2864
                                "from release_manager.planned pl,"+
2865
                                "     release_manager.package_versions pv,"+
2866
                                "     release_manager.package_dependencies pd," +
2867
                                "     release_manager.package_versions dpv,"+
2868
                                "     release_manager.packages p " +
2869
                                " where pl.rtag_id=" + baseline + 
2870
                                "  and pv.build_type='A'"+
2871
                                "  and pv.dlocked='A' " +
2872
                                "  and pv.pv_id = pl.pv_id"+
2873
                                "  and pd.pv_id=pl.pv_id"+
2874
                                "  and dpv.pv_id=pd.dpv_id"+
2875
                                "  and p.pkg_id=dpv.pkg_id " +
2876
                                " order by pv.modified_stamp"
2877
                        );
2878
                stmt2.setFetchSize(500);
2879
                ResultSet rset2 = stmt2.executeQuery();
2880
 
2881
                while( rset2.next() )
2882
                {
2883
                    boolean ignore = false;
2884
 
2885
                    int pv_id = rset2.getInt("pv_id");
2886
 
2887
                    if ( rset2.wasNull() )
2888
                    {
2889
                        mLogger.fatal("queryPackageVersions rset2 null pv_id");
2890
                        // show stopper
2891
                        throw new Exception("queryPackageVersions rset2 null pv_id");
2892
                    }
2893
 
2894
                    Package p = findPackage(pv_id, packageCollection);
2895
 
2896
                    if ( p == NULL_PACKAGE )
2897
                    {
2898
                        mLogger.info("queryPackageVersions rset2 package superceded by planned " + pv_id);
2899
                        ignore = true;
2900
                    }
2901
 
2902
                    String pkg_name = rset2.getString("pkg_name");
2903
 
2904
                    if ( pkg_name == null )
2905
                    {
2906
                        mLogger.fatal("queryPackageVersions rset2 null pkg_name " + pv_id);
2907
                        // show stopper
2908
                        throw new Exception("queryPackageVersions rset2 null pkg_name " + pv_id);
2909
                    }
2910
 
2911
                    String v_ext = rset2.getString("v_ext");
2912
 
2913
                    if ( v_ext == null )
2914
                    {
2915
                        v_ext = "";
2916
                    }
2917
 
2918
                    if ( !ignore )
2919
                    {
2920
                        p.mDependencyCollection.add(pkg_name + v_ext);
2921
                        p.mDependencyIDCollection.add(-1);
2922
                    }
2923
                }
2924
 
2925
                rset2.close();
2926
                stmt2.close();
2927
 
2928
                // get planned package build info
2929
                mLogger.debug("queryPackageVersions: stmt3");
2930
                phase.setPhase("getPlannedPkgs3");
2931
                PreparedStatement stmt3 = mConnection.prepareStatement(
2932
                        "select pl.pv_id, bm.bm_name, bsa.bsa_name, pv.modified_stamp " +
2933
                                "from release_manager.planned pl," +
2934
                                "     release_manager.package_versions pv," +
2935
                                "     release_manager.package_build_info pbi," +
2936
                                "     release_manager.build_machines bm," +
2937
                                "     release_manager.build_standards_addendum bsa " +
2938
                                "where pl.rtag_id=" + baseline + 
2939
                                "     and pv.build_type='A' and pv.dlocked='A' " +
2940
                                "     and pv.pv_id = pl.pv_id" +
2941
                                "     and pbi.pv_id=pv.pv_id" +
2942
                                "     and bm.bm_id=pbi.bm_id" +
2943
                                "     and bsa.bsa_id=pbi.bsa_id " +
2944
                                "order by pv.modified_stamp"
2945
                        );
2946
                stmt3.setFetchSize(500);
2947
                ResultSet rset3 = stmt3.executeQuery();
2948
 
2949
                while( rset3.next() )
2950
                {
2951
                    boolean ignore = false;
2952
                    int pv_id = rset3.getInt("pv_id");
2953
 
2954
                    if ( rset3.wasNull() )
2955
                    {
2956
                        mLogger.fatal("queryPackageVersions rset3 null pv_id");
2957
                        // show stopper
2958
                        throw new Exception("queryPackageVersions rset3 null pv_id");
2959
                    }
2960
 
2961
                    Package p = findPackage(pv_id, packageCollection);
2962
 
2963
                    if ( p == NULL_PACKAGE )
2964
                    {
2965
                        mLogger.info("queryPackageVersions rset3 package superceded by planned " + pv_id);
2966
                        ignore = true;
2967
                    }
2968
 
2969
                    String bm_name = rset3.getString("bm_name");
2970
 
2971
                    if ( bm_name == null )
2972
                    {
2973
                        mLogger.fatal("queryPackageVersions rset3 null bm_name " + pv_id);
2974
                        // show stopper
2975
                        throw new Exception("queryPackageVersions rset3 null bm_name " + pv_id);
2976
                    }
2977
 
2978
                    String bsa_name = rset3.getString("bsa_name");
2979
 
2980
                    if ( bsa_name == null )
2981
                    {
2982
                        mLogger.fatal("queryPackageVersions rset3 null bsa_name " + pv_id);
2983
                        // show stopper
2984
                        throw new Exception("queryPackageVersions rset3 null bsa_name " + pv_id);
2985
                    }
2986
 
2987
                    if ( !ignore )
2988
                    {
2989
                        BuildStandard bs = new BuildStandard(rippleEngine, bm_name, bsa_name);
2990
 
2991
                        if ( bs.supportedBuildStandard() )
2992
                        {
2993
                            p.mBuildStandardCollection.add(bs);
2994
                        }
2995
                    }
2996
                }
2997
 
2998
                rset3.close();
2999
                stmt3.close();
3000
 
3001
                // get planned package unit test info
3002
                mLogger.debug("queryPackageVersions: stmt4");
3003
                phase.setPhase("getPlannedPkgs4");
3004
                PreparedStatement stmt4 = mConnection.prepareStatement(
3005
                        "select pl.pv_id, tt.test_type_name, pv.modified_stamp" +
3006
                        "  from release_manager.planned pl,"+
3007
                        "       release_manager.package_versions pv,"+
3008
                        "       release_manager.unit_tests ut," +
3009
                        "       release_manager.test_types tt" +
3010
                        " where pl.rtag_id=" + baseline + 
3011
                        "   and pv.build_type='A'" +
3012
                        "   and pv.dlocked='A'" +
3013
                        "  and pv.pv_id = pl.pv_id" +
3014
                        "  and ut.pv_id=pv.pv_id" +
3015
                        "  and tt.test_type_id=ut.test_types_fk" +
3016
                        " order by pv.modified_stamp"
3017
                        );
3018
                stmt4.setFetchSize(500);
3019
                ResultSet rset4 = stmt4.executeQuery();
3020
 
3021
                while( rset4.next() )
3022
                {
3023
                    boolean ignore = false;
3024
 
3025
                    int pv_id = rset4.getInt("pv_id");
3026
 
3027
                    if ( rset4.wasNull() )
3028
                    {
3029
                        mLogger.fatal("queryPackageVersions rset4 null pv_id");
3030
                        // show stopper
3031
                        throw new Exception("queryPackageVersions rset4 null pv_id");
3032
                    }
3033
 
3034
                    Package p = findPackage(pv_id, packageCollection);
3035
 
3036
                    if ( p == NULL_PACKAGE )
3037
                    {
3038
                        mLogger.info("queryPackageVersions rset4 package superceded by planned " + pv_id);
3039
                        ignore = true;
3040
                    }
3041
 
3042
                    String test_type_name = rset4.getString("test_type_name");
3043
 
3044
                    if ( test_type_name == null )
3045
                    {
3046
                        mLogger.fatal("queryPackageVersions rset4 null test_type_name " + pv_id);
3047
                        // show stopper
3048
                        throw new Exception("queryPackageVersions rset4 null test_type_name " + pv_id);
3049
                    }
3050
 
3051
                    if ( !ignore )
3052
                    {
3053
                        if ( test_type_name.compareTo("Autobuild UTF") == 0 )
3054
                        {
3055
                            p.mHasAutomatedUnitTests = true;
3056
                        }
3057
                    }
3058
                }
3059
 
3060
                rset4.close();
3061
                stmt4.close();
3062
 
3063
                // get planned package build failure info...
3064
                //      view based
3065
                mLogger.debug("queryPackageVersions: stmt5");
3066
                phase.setPhase("getPlannedPkgs6");
3067
                PreparedStatement stmt5 = mConnection.prepareStatement(
3068
                        "select pl.pv_id, u.user_email, pv.modified_stamp " +
3069
                                " from release_manager.planned pl, " +
3070
                                "      release_manager.release_tags rt, " +
3071
                                "      release_manager.package_versions pv, " +
3072
                                "      release_manager.autobuild_failure af, " +
3073
                                "      release_manager.members_group mg, " +
3074
                                "      release_manager.users u " +
3075
                                " where pl.rtag_id=" + baseline + 
3076
                                "      and rt.rtag_id=pl.rtag_id" +
3077
                                "      and pv.build_type='A' and pv.dlocked='A' " +
3078
                                "      and pv.pv_id = pl.pv_id " +
3079
                                "      and af.view_id=pl.view_id " +
3080
                                "      and mg.group_email_id=af.group_email_id " +
3081
                                "      and u.user_id=mg.user_id " +
3082
                                "      and af.proj_id=rt.proj_id " +
3083
                                " order by pv.modified_stamp"
3084
                        );
3085
                stmt5.setFetchSize(500);
3086
                ResultSet rset5 = stmt5.executeQuery();
3087
 
3088
                while( rset5.next() )
3089
                {
3090
                    int pv_id = rset5.getInt("pv_id");
3091
 
3092
                    if ( rset5.wasNull() )
3093
                    {
3094
                        mLogger.fatal("queryPackageVersions rset5 null pv_id");
3095
                        // show stopper
3096
                        throw new Exception("queryPackageVersions rset5 null pv_id");
3097
                    }
3098
 
3099
                    Package p = findPackage(pv_id, packageCollection);
3100
 
3101
                    if ( p == NULL_PACKAGE )
3102
                    {
3103
                        mLogger.info("queryPackageVersions rset5 package superceded by planned " + pv_id);
3104
                    }
3105
                    else
3106
                    {
3107
                        String user_email = rset5.getString("user_email");
3108
 
3109
                        if ( user_email != null )
3110
                        {
3111
                            p.addEmail(user_email);
3112
                        }
3113
                    }
3114
                }
3115
 
3116
                rset5.close();
3117
                stmt5.close();
3118
 
3119
                // get planned package build failure info...
3120
                // package version
3121
                mLogger.debug("queryPackageVersions: stmt51");
3122
                phase.setPhase("getPlannedPkgs7");
3123
                PreparedStatement stmt51 = mConnection.prepareStatement(
3124
                        "select pl.pv_id, u1.user_email, u2.user_email, u3.user_email, pv.modified_stamp" +
3125
                        " from release_manager.planned pl," +
3126
                        "      release_manager.release_tags rt," +
3127
                        "      release_manager.package_versions pv," +
3128
                        "      release_manager.users u1," +
3129
                        "      release_manager.users u2," +
3130
                        "      release_manager.users u3 " +
3131
                        " where pl.rtag_id=" + baseline + 
3132
                        "   and rt.rtag_id=pl.rtag_id" +
3133
                        "   and pv.build_type='A'" +
3134
                        "   and pv.dlocked='A' " +
3135
                        "   and pv.pv_id = pl.pv_id" +
3136
                        "   and u1.user_id=pv.creator_id" +
3137
                        "   and u2.user_id=pv.owner_id" +
3138
                        "   and u3.user_id=pv.modifier_id" +
3139
                        "   order by pv.modified_stamp"
3140
                        );
3141
                stmt51.setFetchSize(500);
3142
                ResultSet rset51 = stmt51.executeQuery();
3143
 
3144
                while( rset51.next() )
3145
                {
3146
                    int pv_id = rset51.getInt("pv_id");
3147
 
3148
                    if ( rset51.wasNull() )
3149
                    {
3150
                        mLogger.fatal("queryPackageVersions rset51 null pv_id");
3151
                        // show stopper
3152
                        throw new Exception("queryPackageVersions rset51 null pv_id");
3153
                    }
3154
 
3155
                    Package p = findPackage(pv_id, packageCollection);
3156
 
3157
                    if ( p == NULL_PACKAGE )
3158
                    {
3159
                        mLogger.info("queryPackageVersions rset51 package superceded by planned " + pv_id);
3160
                    }
3161
                    else
3162
                    {
3163
 
3164
                        // walk the 3 columns of user_email in the resultset
3165
                        // columns 2, 3 and 4, all of the same name, respectively
3166
                        for(int column=2; column<5; column++ )
3167
                        {
3168
                            String user_email = rset51.getString(column);
3169
 
3170
                            if ( user_email != null )
3171
                            {
3172
                                p.addEmail(user_email);
3173
                            }
3174
                        }
3175
                    }
3176
                }
3177
 
3178
                rset51.close();
3179
                stmt51.close();
3180
 
3181
                // get planned package advisory ripple info
3182
                mLogger.debug("queryPackageVersions: stmt7");
3183
                phase.setPhase("getPlannedPkgs8");
3184
                PreparedStatement stmt7 = mConnection.prepareStatement(
3185
                        "select pl.pv_id, pv.modified_stamp " +
3186
                        " from release_manager.planned pl," +
3187
                        "      release_manager.package_versions pv," +
3188
                        "      release_manager.advisory_ripple ar " +
3189
                        " where pl.rtag_id=" + baseline + 
3190
                        "   and pv.build_type='A'" +
3191
                        "    and pv.dlocked='A' " +
3192
                        "    and pv.pv_id = pl.pv_id" +
3193
                        "    and ar.rtag_id=pl.rtag_id" +
3194
                        "    and ar.pv_id=pl.pv_id " +
3195
                        " order by pv.modified_stamp"
3196
                        );
3197
                stmt7.setFetchSize(500);
3198
                ResultSet rset7 = stmt7.executeQuery();
3199
 
3200
                while( rset7.next() )
3201
                {
3202
                    boolean ignore = false;
3203
 
3204
                    int pv_id = rset7.getInt("pv_id");
3205
 
3206
                    if ( rset7.wasNull() )
3207
                    {
3208
                        mLogger.fatal("queryPackageVersions rset7 null pv_id");
3209
                        // show stopper
3210
                        throw new Exception("queryPackageVersions rset7 null pv_id");
3211
                    }
3212
 
3213
                    Package p = findPackage(pv_id, packageCollection);
3214
 
3215
                    if ( p == NULL_PACKAGE )
3216
                    {
3217
                        mLogger.info("queryPackageVersions rset7 package superceded by planned " + pv_id);
3218
                        ignore = true;
3219
                    }
3220
 
3221
                    if ( !ignore )
3222
                    {
3223
                        p.mAdvisoryRipple = true;
3224
                    }
3225
                }
3226
 
3227
                rset7.close();
3228
                stmt7.close();
3229
 
3230
                // get released package info
3231
                //    Get package information on ALL released packages within the release of interest
3232
                //
3233
                mLogger.debug("queryPackageVersions: stmt8");
3234
                phase.setPhase("getAllPkgs1");
3235
                PreparedStatement stmt8 = mConnection.prepareStatement(
3236
                        "SELECT rc.pv_id," +
3237
                                "  p.pkg_id," +
3238
                                "  p.pkg_name," +
3239
                                "  pv.pkg_version," +
3240
                                "  pv.v_ext," +
3241
                                "  pv.ripple_field," +
3242
                                "  pv.major_limit," +
3243
                                "  pv.minor_limit," +
3244
                                "  pv.patch_limit," +
3245
                                "  pv.build_number_limit," +
3246
                                "  pv.build_type," +
3247
                                "  rc.sdktag_id," +
3248
                                "  rc.ripple_stop," +
3249
                                "  peg.pv_id as pegged," +
3250
                                "  release_manager.PK_RMAPI.return_vcs_tag(rc.pv_id) AS vcsTag" +
3251
                                " FROM release_manager.release_content rc," +
3252
                                "  release_manager.package_versions pv," +
3253
                                "  release_manager.packages p," +
3254
                                "  release_manager.pegged_versions peg" +
3255
                                " WHERE rc.rtag_id= " + baseline +
3256
                                " AND pv.pv_id    = rc.pv_id" +
3257
                                " AND p.pkg_id    = pv.pkg_id" +
3258
                                " AND peg.rtag_id(+) = rc.rtag_id" +
3259
                                " AND peg.pv_id(+) = rc.pv_id" +
3260
                                " ORDER BY rc.pv_id"
3261
                        );
3262
                mLogger.debug("queryPackageVersions: stmt8 Prepared");
3263
                stmt8.setFetchSize(1000);
3264
                ResultSet rset8 = stmt8.executeQuery();
3265
                mLogger.debug("queryPackageVersions: stmt8 Query Done");
3266
 
3267
                while( rset8.next() )
3268
                {
3269
                    int pv_id = rset8.getInt("pv_id");
3270
 
3271
                    if ( rset8.wasNull() )
3272
                    {
3273
                        mLogger.fatal("queryPackageVersions rset8 null pv_id");
3274
                        // show stopper
3275
                        throw new Exception("queryPackageVersions rset8 null pv_id");
3276
                    }
3277
 
3278
                    int pkg_id = rset8.getInt("pkg_id");
3279
 
3280
                    if ( rset8.wasNull() )
3281
                    {
3282
                        mLogger.fatal("queryPackageVersions rset8 null pkg_id " + pv_id);
3283
                        // show stopper
3284
                        throw new Exception("queryPackageVersions rset8 null pkg_id " + pv_id);
3285
                    }
3286
 
3287
                    String pkg_name = rset8.getString("pkg_name");
3288
 
3289
                    if ( pkg_name == null )
3290
                    {
3291
                        mLogger.fatal("queryPackageVersions rset8 null pkg_name " + pv_id);
3292
                        // show stopper
3293
                        throw new Exception("queryPackageVersions rset8 null pkg_name " + pv_id);
3294
                    }
3295
 
3296
                    String pkg_version = rset8.getString("pkg_version");
3297
 
3298
                    if ( pkg_version == null )
3299
                    {
3300
                        mLogger.fatal("queryPackageVersions rset8 null pkg_version " + pv_id);
3301
                        // show stopper
3302
                        throw new Exception("queryPackageVersions rset8 null pkg_version " + pv_id);
3303
                    }
3304
 
3305
                    String v_ext = rset8.getString("v_ext");
3306
 
3307
                    if ( v_ext == null )
3308
                    {
3309
                        v_ext = "";
3310
                    }
3311
 
3312
                    String ripple_field = rset8.getString("ripple_field");
3313
 
3314
                    if ( ripple_field == null || ripple_field.length() == 0 )
3315
                    {
3316
                        ripple_field = "b";
3317
                    }
3318
 
3319
                    int major_limit = rset8.getInt("major_limit");
3320
 
3321
                    if ( rset8.wasNull() )
3322
                    {
3323
                        major_limit = 0;
3324
                    }
3325
 
3326
                    int minor_limit = rset8.getInt("minor_limit");
3327
 
3328
                    if ( rset8.wasNull() )
3329
                    {
3330
                        minor_limit = 0;
3331
                    }
3332
 
3333
                    int patch_limit = rset8.getInt("patch_limit");
3334
 
3335
                    if ( rset8.wasNull() )
3336
                    {
3337
                        patch_limit = 0;
3338
                    }
3339
 
3340
                    int build_number_limit = rset8.getInt("build_number_limit");
3341
 
3342
                    if ( rset8.wasNull() )
3343
                    {
3344
                        build_number_limit = 0;
3345
                    }
3346
 
3347
                    String vcs_tag = rset8.getString("vcsTag");
3348
                    if ( vcs_tag == null )
3349
                    {
3350
                        vcs_tag = "";
3351
                    }
3352
 
3353
                    int isAnSdk = rset8.getInt("sdktag_id"); 
3354
                    if ( rset8.wasNull() )
3355
                    {
3356
                        isAnSdk = 0;
3357
                    }
3358
 
3359
                    int isPegged = rset8.getInt("pegged");
3360
                    if ( rset8.wasNull() )
3361
                    {
3362
                        isPegged = 0;
3363
                    }
3364
 
3365
                    String buildType = rset8.getString("build_type");
3366
                    boolean isBuildable = ( buildType != null ) && (buildType.equals("A") || buildType.equals("Y") );
3367
 
3368
 
3369
                    String rippleStopData = rset8.getString("ripple_stop");
3370
                    char rippleStop = 'n';
3371
                    if ( ! rset8.wasNull() ) {
3372
                        rippleStop =  rippleStopData.charAt(0);
3373
                    }
3374
 
3375
                    Package p = new Package(pkg_id, pv_id, pkg_name, pkg_version, v_ext, pkg_name + v_ext, vcs_tag, ripple_field.charAt(0));
3376
                    p.mMajorLimit = major_limit;
3377
                    p.mMinorLimit = minor_limit;
3378
                    p.mPatchLimit = patch_limit;
3379
                    p.mBuildLimit = build_number_limit;
3380
                    p.mIsSdk = isAnSdk > 0;
3381
                    p.mIsPegged = isPegged > 0;
3382
                    p.mIsBuildable = isBuildable;
3383
                    p.mRippleStop = rippleStop;
3384
 
3385
                    Integer ipv_id = Integer.valueOf(pv_id);
3386
                    rippleEngine.mReleasedPvIDCollection.add(ipv_id);
3387
 
3388
                    //  If this package is to be replaced by a planned package then
3389
                    //  insert some of the current packages attributes
3390
                    //  Otherwise, add the the package to the package collection
3391
                    //
3392
                    Package plannedPackage = findPackage(p.mAlias, packageCollection);
3393
                    if ( plannedPackage == NULL_PACKAGE )
3394
                    {
3395
                        mLogger.info("queryPackageVersions rset8 no planned package " + pv_id);
3396
                        packageCollection.add(p);
3397
                    }
3398
                    else
3399
                    {
3400
                        //  Copy these flags from the package that will be replaced
3401
                        //      Should not be able to replace a package provided by an SDK
3402
                        plannedPackage.mIsSdk = p.mIsSdk;
3403
 
3404
                        // A pegged package can be replaced with a directly built package
3405
                        // plannedPackage.mIsPegged = p.mIsPegged;
3406
                    }
3407
                }
3408
 
3409
                mLogger.debug("queryPackageVersions: stmt8 processing complete");
3410
                rset8.close();
3411
                stmt8.close();
3412
 
3413
                // get released package dependency info
3414
                // 
3415
                mLogger.debug("queryPackageVersions: stmt9");
3416
                phase.setPhase("getAllPkgs2");
3417
                PreparedStatement stmt9 = mConnection.prepareStatement(
3418
                        "select rc.pv_id, dpv.pv_id, p.pkg_name, dpv.v_ext" +
3419
                                " from release_manager.release_content rc," +
3420
                                "      release_manager.package_versions pv," + 
3421
                                "      release_manager.package_dependencies pd,"+
3422
                                "      release_manager.package_versions dpv,"+
3423
                                "      release_manager.packages p" +
3424
                                " where rc.rtag_id=" + baseline +
3425
                                "  and pv.pv_id = rc.pv_id" +
3426
                                "  and pd.pv_id=pv.pv_id" +
3427
                                "  and dpv.pv_id=pd.dpv_id" +
3428
                                "  and p.pkg_id=dpv.pkg_id" +
3429
                                " order by rc.pv_id"
3430
                        );
3431
                mLogger.debug("queryPackageVersions: stmt9 prepared");
3432
                stmt9.setFetchSize(1000);
3433
                ResultSet rset9 = stmt9.executeQuery();
3434
                mLogger.debug("queryPackageVersions: stmt9 query done");
3435
 
3436
                while( rset9.next() )
3437
                {
3438
                    boolean ignore = false;
3439
 
3440
                    int pv_id = rset9.getInt(1);
3441
 
3442
                    if ( rset9.wasNull() )
3443
                    {
3444
                        mLogger.fatal("queryPackageVersions rset9 null pv_id");
3445
                        // show stopper
3446
                        throw new Exception("queryPackageVersions rset9 null pv_id");
3447
                    }
3448
 
3449
                    int dpv_id = rset9.getInt(2);
3450
 
3451
                    if ( rset9.wasNull() )
3452
                    {
3453
                        mLogger.fatal("queryPackageVersions rset9 null dpv_id " + pv_id);
3454
                        // show stopper
3455
                        throw new Exception("queryPackageVersions rset9 null dpv_id " + pv_id);
3456
                    }
3457
 
3458
                    Package p = findPackage(pv_id, packageCollection);
3459
 
3460
                    if ( p == NULL_PACKAGE )
3461
                    {
3462
                        mLogger.info("queryPackageVersions rset9 package superceded by planned " + pv_id);
3463
                        ignore = true;
3464
                    }
3465
 
3466
                    String pkg_name = rset9.getString("pkg_name");
3467
 
3468
                    if ( pkg_name == null )
3469
                    {
3470
                        mLogger.fatal("queryPackageVersions rset9 null pkg_name " + pv_id);
3471
                        // show stopper
3472
                        throw new Exception("queryPackageVersions rset9 null pkg_name " + pv_id);
3473
                    }
3474
 
3475
                    String v_ext = rset9.getString("v_ext");
3476
 
3477
                    if ( v_ext == null )
3478
                    {
3479
                        v_ext = "";
3480
                    }
3481
 
3482
                    if ( !ignore )
3483
                    {
3484
                        p.mDependencyCollection.add(pkg_name + v_ext);
3485
                        p.mDependencyIDCollection.add(dpv_id);
3486
                    }
3487
                }
3488
                mLogger.debug("queryPackageVersions: stmt9 processing complete");
3489
 
3490
                rset9.close();
3491
                stmt9.close();
3492
 
3493
                // get released package build info
3494
                mLogger.debug("queryPackageVersions: stmt10");
3495
                phase.setPhase("getAllPkgs3");
3496
                PreparedStatement stmt10 = mConnection.prepareStatement(
3497
                        "select rc.pv_id, bm.bm_name, bsa.bsa_name " +
3498
                                "from release_manager.release_content rc," +
3499
                                "     release_manager.package_versions pv," +
3500
                                "     release_manager.package_build_info pbi," +
3501
                                "     release_manager.build_machines bm," +
3502
                                "     release_manager.build_standards_addendum bsa " +
3503
                                "where rc.rtag_id=?" + 
3504
                                "     and pv.pv_id = rc.pv_id" +
3505
                                "     and pbi.pv_id=pv.pv_id" +
3506
                                "     and bm.bm_id=pbi.bm_id" +
3507
                                "     and bsa.bsa_id=pbi.bsa_id " +
3508
                                "order by rc.pv_id"
3509
                        );
3510
                stmt10.setFetchSize(1000);
3511
                stmt10.setInt(1, baseline);
3512
                ResultSet rset10 = stmt10.executeQuery();
3513
 
3514
                while( rset10.next() )
3515
                {
3516
                    boolean ignore = false;
3517
                    int pv_id = rset10.getInt("pv_id");
3518
 
3519
                    if ( rset10.wasNull() )
3520
                    {
3521
                        mLogger.fatal("queryPackageVersions rset10 null pv_id");
3522
                        // show stopper
3523
                        throw new Exception("queryPackageVersions rset10 null pv_id");
3524
                    }
3525
 
3526
                    Package p = findPackage(pv_id, packageCollection);
3527
 
3528
                    if ( p == NULL_PACKAGE )
3529
                    {
3530
                        mLogger.info("queryPackageVersions rset10 package superceded by planned " + pv_id);
3531
                        ignore = true;
3532
                    }
3533
 
3534
                    String bm_name = rset10.getString("bm_name");
3535
 
3536
                    if ( bm_name == null )
3537
                    {
3538
                        mLogger.fatal("queryPackageVersions rset10 null bm_name " + pv_id);
3539
                        // show stopper
3540
                        throw new Exception("queryPackageVersions rset10 null bm_name " + pv_id);
3541
                    }
3542
 
3543
                    String bsa_name = rset10.getString("bsa_name");
3544
 
3545
                    if ( bsa_name == null )
3546
                    {
3547
                        mLogger.fatal("queryPackageVersions rset10 null bsa_name " + pv_id);
3548
                        // show stopper
3549
                        throw new Exception("queryPackageVersions rset10 null bsa_name " + pv_id);
3550
                    }
3551
 
3552
                    if ( !ignore )
3553
                    {
3554
                        BuildStandard bs = new BuildStandard(rippleEngine, bm_name, bsa_name);
3555
 
3556
                        if ( bs.supportedBuildStandard() )
3557
                        {
3558
                            p.mBuildStandardCollection.add(bs);
3559
                        }
3560
                    }
3561
                }
3562
 
3563
                rset10.close();
3564
                stmt10.close();
3565
 
3566
                // get released package unit test info
3567
                mLogger.debug("queryPackageVersions: stmt11");
3568
                phase.setPhase("getAllPkgs4");
3569
                PreparedStatement stmt11 = mConnection.prepareStatement(
3570
                        "select rc.pv_id, tt.test_type_name " +
3571
                                "from release_manager.release_content rc, release_manager.package_versions pv, release_manager.unit_tests ut, release_manager.test_types tt " +
3572
                                "where rc.rtag_id=" + baseline +
3573
                                " and pv.pv_id = rc.pv_id and ut.pv_id=pv.pv_id and tt.test_type_id=ut.test_types_fk " +
3574
                                "order by rc.pv_id"
3575
                        );
3576
                stmt11.setFetchSize(1000);
3577
                ResultSet rset11 = stmt11.executeQuery();
3578
 
3579
                while( rset11.next() )
3580
                {
3581
                    boolean ignore = false;
3582
 
3583
                    int pv_id = rset11.getInt("pv_id");
3584
 
3585
                    if ( rset11.wasNull() )
3586
                    {
3587
                        mLogger.fatal("queryPackageVersions rset11 null pv_id");
3588
                        // show stopper
3589
                        throw new Exception("queryPackageVersions rset11 null pv_id");
3590
                    }
3591
 
3592
                    Package p = findPackage(pv_id, packageCollection);
3593
 
3594
                    if ( p == NULL_PACKAGE )
3595
                    {
3596
                        mLogger.info("queryPackageVersions rset11 package superceded by planned " + pv_id);
3597
                        ignore = true;
3598
                    }
3599
 
3600
                    String test_type_name = rset11.getString("test_type_name");
3601
 
3602
                    if ( test_type_name == null )
3603
                    {
3604
                        mLogger.fatal("queryPackageVersions rset11 null test_type_name " + pv_id);
3605
                        // show stopper
3606
                        throw new Exception("queryPackageVersions rset11 null test_type_name " + pv_id);
3607
                    }
3608
 
3609
                    if ( !ignore )
3610
                    {
3611
                        if ( test_type_name.compareTo("Autobuild UTF") == 0 )
3612
                        {
3613
                            p.mHasAutomatedUnitTests = true;
3614
                        }
3615
                    }
3616
                }
3617
 
3618
                rset11.close();
3619
                stmt11.close();
3620
 
3621
                // get released package build failure info...
3622
                // view based
3623
                mLogger.debug("queryPackageVersions: stmt12");
3624
                phase.setPhase("getAllPkgs5");
3625
                PreparedStatement stmt12 = mConnection.prepareStatement(
3626
                        "SELECT rc.pv_id," +
3627
                        "  u.user_email" +
3628
                        " FROM release_manager.release_content rc," +
3629
                        "  release_manager.release_tags rt," +
3630
                        "  release_manager.package_versions pv," +
3631
                        "  release_manager.autobuild_failure af," +
3632
                        "  release_manager.members_group mg," +
3633
                        "  release_manager.users u" +
3634
                        " WHERE rc.rtag_id     = " + baseline +
3635
                        " AND rt.rtag_id       = rc.rtag_id" +
3636
                        " AND pv.pv_id         = rc.pv_id" +
3637
                        " AND af.view_id       = rc.base_view_id" +
3638
                        " AND mg.group_email_id= af.group_email_id" +
3639
                        " AND u.user_id        = mg.user_id" +
3640
                        " AND af.proj_id       = rt.proj_id" +
3641
                        " ORDER BY rc.pv_id"
3642
                        );
3643
                stmt12.setFetchSize(1000);
3644
                ResultSet rset12 = stmt12.executeQuery();
3645
 
3646
                while( rset12.next() )
3647
                {
3648
                    int pv_id = rset12.getInt("pv_id");
3649
 
3650
                    if ( rset12.wasNull() )
3651
                    {
3652
                        mLogger.fatal("queryPackageVersions rset12 null pv_id");
3653
                        // show stopper
3654
                        throw new Exception("queryPackageVersions rset12 null pv_id");
3655
                    }
3656
 
3657
                    Package p = findPackage(pv_id, packageCollection);
3658
 
3659
                    if ( p == NULL_PACKAGE )
3660
                    {
3661
                        mLogger.info("queryPackageVersions rset12 package superceded by planned " + pv_id);
3662
                    }
3663
                    else
3664
                    {
3665
                        String user_email = rset12.getString("user_email");
3666
 
3667
                        if ( user_email != null )
3668
                        {
3669
                            p.addEmail(user_email);
3670
                        }
3671
                    }
3672
                }
3673
 
3674
                rset12.close();
3675
                stmt12.close();
3676
 
3677
                // get released advisory ripple info
3678
                mLogger.debug("queryPackageVersions: stmt14");
3679
                phase.setPhase("getAllPkgs6");
3680
                PreparedStatement stmt14 = mConnection.prepareStatement(
3681
                        "select rc.pv_id " +
3682
                                "from release_manager.release_content rc, release_manager.package_versions pv, release_manager.advisory_ripple ar " +
3683
                                "where rc.rtag_id=" + baseline +
3684
                                " and pv.pv_id = rc.pv_id and ar.rtag_id=rc.rtag_id and ar.pv_id=rc.pv_id " +
3685
                                "order by rc.pv_id"
3686
                        );
3687
                stmt14.setFetchSize(1000);
3688
                ResultSet rset14 = stmt14.executeQuery();
3689
 
3690
                while( rset14.next() )
3691
                {
3692
                    boolean ignore = false;
3693
 
3694
                    int pv_id = rset14.getInt("pv_id");
3695
 
3696
                    if ( rset14.wasNull() )
3697
                    {
3698
                        mLogger.fatal("queryPackageVersions rset14 null pv_id");
3699
                        // show stopper
3700
                        throw new Exception("queryPackageVersions rset14 null pv_id");
3701
                    }
3702
 
3703
                    Package p = findPackage(pv_id, packageCollection);
3704
 
3705
                    if ( p == NULL_PACKAGE )
3706
                    {
3707
                        mLogger.info("queryPackageVersions rset14 package superceded by planned " + pv_id);
3708
                        ignore = true;
3709
                    }
3710
 
3711
                    if ( !ignore )
3712
                    {
3713
                        p.mAdvisoryRipple = true;
3714
                    }
3715
                }
3716
 
3717
                rset14.close();
3718
                stmt14.close();
3719
 
3720
                // Daemon Instruction: Force Package Ripple
3721
                //  An op code of 0 means force ripple
3722
                MutableInt instruction = new MutableInt(0);
3723
                MutableInt pvid = new MutableInt(0);
3724
                MutableInt userid = new MutableInt(0);
3725
                MutableString userEmail = new MutableString();
3726
                phase.setPhase("getDaemonInstructions1");
3727
                while ( getDaemonInst( baseline, 0, instruction, pvid, userid, userEmail ) )
3728
                {
3729
                    Package p = findPackage(pvid.value, packageCollection);
3730
 
3731
                    if ( p != NULL_PACKAGE )
3732
                    {
3733
                        mLogger.info("queryPackageVersions forced ripple data " + pvid.value);
3734
                        p.mForcedRippleInstruction = instruction.value;
3735
                        p.mTestBuildEmail = userEmail.value;
3736
                    }
3737
                    else
3738
                    {
3739
                        // discard
3740
                        markDaemonInstCompleted( instruction.value );
3741
                    }
3742
                }
3743
 
3744
                // Daemon Instruction: Test Build Package
3745
                //  An op code of 1 means test build
3746
                //
3747
                // bare minimal data collection - last thing needed is more data to collect
3748
                // the approach...
3749
                // query all test build instructions for this baseline
3750
                // for each, query its build information
3751
                // store them in "mTestBuild" Package attributes as follows:
3752
                // - mTestBuildInstruction (default 0)
3753
                // - mTestBuildEmail (default "null")
3754
                // - mTestBuildVcsTag (default "null")
3755
                // - mTestBuildStandardCollection
3756
                // - mTestBuildDependencyCollection
3757
                // additionally, trust nothing - these are mostly wips that at any time may have:
3758
                // - no build location
3759
                // - no build label
3760
                // - an empty build standard collection
3761
                // proceed with defaults above if necessary (the build will subsequently fail)
3762
                // in all cases, build a meaningful email body to inform the user
3763
                // of the snapshot of build information that applied to the build and store in:
3764
                // - mTestBuildEmailBody
3765
 
3766
                mLogger.debug("queryPackageVersions: stmt141");
3767
                phase.setPhase("getTestBuild1");
3768
                instruction.value = 0;
3769
                while ( getDaemonInst( baseline, 1, instruction, pvid, userid, userEmail ) )
3770
                {
3771
                    // can only do one test build at a time - others will be discarded until future cycle
3772
                    mLogger.info("queryPackageVersions test build data " + pvid.value);
3773
                    int testBuildPvId = pvid.value;
3774
                    int testBuildInstruction = instruction.value;
3775
                    String testBuildEmail = userEmail.value; 
3776
 
3777
                    String pkg_name = "";
3778
                    String pkg_ext = "";
3779
                    String testBuildVcsTag = "null";
3780
                    int pkg_id = 0;
3781
 
3782
                    // get package info for test build package
3783
                    mLogger.debug("queryPackageVersions: stmt15");
3784
                    PreparedStatement stmt15 = mConnection.prepareStatement(
3785
                            "select p.pkg_name, p.pkg_id, pv.v_ext, release_manager.PK_RMAPI.return_vcs_tag(pv.pv_id) AS vcsTag " +
3786
                                    " from release_manager.package_versions pv," +
3787
                                    "release_manager.packages p" +
3788
                                    " where pv.pv_id=" + testBuildPvId +
3789
                                    " and p.pkg_id=pv.pkg_id "
3790
                            );
3791
                    stmt15.setFetchSize(10);
3792
                    ResultSet rset15 = stmt15.executeQuery();
3793
 
3794
                    int rsetSize = 0;
3795
 
3796
                    while( rset15.next() )
3797
                    {
3798
                        rsetSize++;
3799
                        pkg_name = rset15.getString("pkg_name");
3800
 
3801
                        if ( pkg_name == null )
3802
                        {
3803
                            mLogger.fatal("queryPackageVersions rset15 null pkg_name " + testBuildPvId);
3804
                            // show stopper
3805
                            throw new Exception("queryPackageVersions rset15 null pkg_name " + testBuildPvId);
3806
                        }
3807
 
3808
                        pkg_id = rset15.getInt("pkg_id");
3809
 
3810
                        if ( rset15.wasNull() )
3811
                        {
3812
                            mLogger.fatal("queryPackageVersions rset15 null pkg_id " + testBuildPvId);
3813
                            // show stopper
3814
                            throw new Exception("queryPackageVersions rset15 null pkg_id " + testBuildPvId);
3815
                        }
3816
 
3817
                        pkg_ext = rset15.getString("v_ext");
3818
 
3819
                        if ( pkg_ext == null )
3820
                        {
3821
                            pkg_ext = "";
3822
                        }
3823
 
3824
                        testBuildVcsTag = rset15.getString("vcsTag");
3825
                        if ( testBuildVcsTag == null )
3826
                        {
3827
                            testBuildVcsTag = "null";
3828
                        }
3829
                    }
3830
 
3831
                    rset15.close();
3832
                    stmt15.close();
3833
 
3834
                    mLogger.debug("queryPackageVersions: stmt16");
3835
                    if ( rsetSize == 0 )
3836
                    {
3837
                        mLogger.error("queryPackageVersions rset15 no data found " + instruction.value);
3838
                        markDaemonInstCompleted( instruction.value );
3839
                    }
3840
                    else
3841
                    {
3842
                        Package q = findPackage(pkg_name + pkg_ext, packageCollection);
3843
 
3844
                        if ( q == NULL_PACKAGE )
3845
                        {
3846
                            // Package alias does not exist in this release (planned or released packages)
3847
                            q = new Package(pkg_id, testBuildPvId, pkg_name, pkg_ext, pkg_name + pkg_ext, testBuildVcsTag, testBuildInstruction, testBuildEmail);
3848
                            packageCollection.add(q);
3849
                        }
3850
                        else
3851
                        {
3852
                            // Avoid interaction with real versions
3853
                        	// Flag as not pegged - so that we test build
3854
                            q.mVersion = "0.0.0000";
3855
                            q.mTestBuildVcsTag = testBuildVcsTag;
3856
                            q.mTestBuildInstruction = testBuildInstruction;
3857
                            q.mTestBuildEmail = testBuildEmail;
3858
                            q.mTestBuildPvId = testBuildPvId;
3859
                            q.mTestBuildHasAutomatedUnitTests = false;
3860
                            q.mIsPegged = false;
3861
                        }
3862
 
3863
                        // get test build package dependency info
3864
                        PreparedStatement stmt16 = mConnection.prepareStatement(
3865
                                "select p.pkg_name, dpv.v_ext " +
3866
                                        " from release_manager.package_versions pv," +
3867
                                        "   release_manager.package_dependencies pd,"+
3868
                                        "   release_manager.package_versions dpv,"+
3869
                                        "   release_manager.packages p" +
3870
                                        " where pv.pv_id=" + testBuildPvId +
3871
                                        "   and pd.pv_id=" + testBuildPvId +
3872
                                        "   and dpv.pv_id=pd.dpv_id"+
3873
                                        "   and p.pkg_id=dpv.pkg_id"
3874
                                );
3875
                        stmt16.setFetchSize(1000);
3876
                        ResultSet rset16 = stmt16.executeQuery();
3877
 
3878
                        while( rset16.next() )
3879
                        {
3880
                            String dpkg_name = rset16.getString("pkg_name");
3881
 
3882
                            if ( dpkg_name == null )
3883
                            {
3884
                                mLogger.fatal("queryPackageVersions rset16 null pkg_name " + testBuildPvId);
3885
                                // show stopper
3886
                                throw new Exception("queryPackageVersions rset16 null pkg_name " + testBuildPvId);
3887
                            }
3888
 
3889
                            String v_ext = rset16.getString("v_ext");
3890
 
3891
                            if ( v_ext == null )
3892
                            {
3893
                                v_ext = "";
3894
                            }
3895
 
3896
                            q.mTestBuildDependencyCollection.add(dpkg_name + v_ext);
3897
                        }
3898
 
3899
                        rset16.close();
3900
                        stmt16.close();
3901
 
3902
                        // get test build package build info
3903
                        mLogger.debug("queryPackageVersions: stmt17");
3904
                        PreparedStatement stmt17 = mConnection.prepareStatement(
3905
                                "select bm.bm_name, bsa.bsa_name " +
3906
                                        "from release_manager.package_versions pv," +
3907
                                        "     release_manager.package_build_info pbi," +
3908
                                        "     release_manager.build_machines bm," +
3909
                                        "     release_manager.build_standards_addendum bsa " +
3910
                                        "where pv.pv_id=" + testBuildPvId +
3911
                                        "   and pbi.pv_id=pv.pv_id" +
3912
                                        "   and bm.bm_id=pbi.bm_id" +
3913
                                        "   and bsa.bsa_id=pbi.bsa_id"
3914
                                );
3915
                        ResultSet rset17 = stmt17.executeQuery();
3916
 
3917
                        while( rset17.next() )
3918
                        {
3919
                            String bm_name = rset17.getString("bm_name");
3920
 
3921
                            if ( bm_name == null )
3922
                            {
3923
                                mLogger.fatal("queryPackageVersions rset17 null bm_name " + testBuildPvId);
3924
                                // show stopper
3925
                                throw new Exception("queryPackageVersions rset17 null bm_name " + testBuildPvId);
3926
                            }
3927
 
3928
                            String bsa_name = rset17.getString("bsa_name");
3929
 
3930
                            if ( bsa_name == null )
3931
                            {
3932
                                mLogger.fatal("queryPackageVersions rset17 null bsa_name " + testBuildPvId);
3933
                                // show stopper
3934
                                throw new Exception("queryPackageVersions rset17 null bsa_name " + testBuildPvId);
3935
                            }
3936
 
3937
                            BuildStandard bs = new BuildStandard(rippleEngine, bm_name, bsa_name);
3938
 
3939
                            if ( bs.supportedBuildStandard() )
3940
                            {
3941
                                q.mTestBuildStandardCollection.add(bs);
3942
                            }
3943
                        }
3944
 
3945
                        rset17.close();
3946
                        stmt17.close();
3947
 
3948
                        // get test build package unit test info
3949
                        mLogger.debug("queryPackageVersions: stmt4");
3950
                        PreparedStatement stmt18 = mConnection.prepareStatement(
3951
                                "select tt.test_type_name" +
3952
                                "  from release_manager.unit_tests ut," +
3953
                                "       release_manager.test_types tt" +
3954
                                " where ut.pv_id=" + testBuildPvId +
3955
                                "  and tt.test_type_id=ut.test_types_fk" 
3956
                                );
3957
                        ResultSet rset18 = stmt18.executeQuery();
3958
 
3959
                        while( rset18.next() )
3960
                        {
3961
                            boolean ignore = false;
3962
 
3963
                            String test_type_name = rset18.getString("test_type_name");
3964
 
3965
                            if ( test_type_name == null )
3966
                            {
3967
                                mLogger.fatal("queryPackageVersions rset18 null test_type_name " + testBuildPvId);
3968
                                // show stopper
3969
                                throw new Exception("queryPackageVersions rset18 null test_type_name " + testBuildPvId);
3970
                            }
3971
 
3972
                            if ( !ignore )
3973
                            {
3974
                                if ( test_type_name.compareTo("Autobuild UTF") == 0 )
3975
                                {
3976
                                	q.mTestBuildHasAutomatedUnitTests = true;
3977
                                }
3978
                            }
3979
                        }
3980
 
3981
                        rset18.close();
3982
                        stmt18.close();
3983
 
3984
                    }
3985
                }
3986
            }
3987
            else
3988
            {
3989
                // Escrow Mode
3990
                // get released product info
3991
                mLogger.debug("queryPackageVersions: stmt18");
3992
                PreparedStatement stmt = mConnection.prepareStatement(
3993
                        "select oc.prod_id, p.pkg_name, pv.pkg_version, pv.v_ext," +
3994
                                "release_manager.PK_RMAPI.return_vcs_tag(pv.pv_id) AS vcsTag" +
3995
                                " from deployment_manager.bom_contents bc," +
3996
                                "deployment_manager.operating_systems os," +
3997
                                "deployment_manager.os_contents oc," +
3998
                                "release_manager.package_versions pv," +
3999
                                "release_manager.packages p" +
4000
                                " where bc.bom_id=" + baseline +
4001
                                " and os.node_id=bc.node_id" +
4002
                                " and oc.os_id=os.os_id" +
4003
                                " and pv.pv_id=oc.prod_id" +
4004
                                " and p.pkg_id=pv.pkg_id" +
4005
                                " order by oc.prod_id"
4006
                        );
4007
                stmt.setFetchSize(1000);
4008
                ResultSet rset = stmt.executeQuery();
4009
 
4010
                while( rset.next() )
4011
                {
4012
                    int pv_id = rset.getInt("prod_id");
4013
 
4014
                    if ( rset.wasNull() )
4015
                    {
4016
                        mLogger.fatal("queryPackageVersions rset null prod_id");
4017
                        // show stopper
4018
                        throw new Exception("queryPackageVersions rset null prod_id");
4019
                    }
4020
 
4021
                    String pkg_name = rset.getString("pkg_name");
4022
 
4023
                    if ( pkg_name == null )
4024
                    {
4025
                        mLogger.fatal("queryPackageVersions rset null pkg_name " + pv_id);
4026
                        // show stopper
4027
                        throw new Exception("queryPackageVersions rset null pkg_name " + pv_id);
4028
                    }
4029
 
4030
                    String pkg_version = rset.getString("pkg_version");
4031
 
4032
                    if ( pkg_version == null )
4033
                    {
4034
                        mLogger.fatal("queryPackageVersions rset null pkg_version " + pv_id);
4035
                        // show stopper
4036
                        throw new Exception("queryPackageVersions rset null pkg_version " + pv_id);
4037
                    }
4038
 
4039
                    String v_ext = rset.getString("v_ext");
4040
 
4041
                    if ( v_ext == null )
4042
                    {
4043
                        v_ext = "";
4044
                    }
4045
 
4046
                    String vcs_tag = rset.getString("vcsTag");
4047
                    if ( vcs_tag == null )
4048
                    {
4049
                        vcs_tag = "";
4050
                    }
4051
 
4052
                    Package p = findPackage(pv_id, packageCollection);
4053
 
4054
                    if ( p == NULL_PACKAGE )
4055
                    {
4056
                        Package q = new Package(0, pv_id, pkg_name, pkg_version, v_ext, pkg_name + "." + pkg_version, vcs_tag, 'x');
4057
                        packageCollection.add(q);
4058
                    }
4059
                }
4060
 
4061
                rset.close();
4062
                stmt.close();
4063
            }
4064
        }
4065
        catch ( SQLException e )
4066
        {
4067
            handleSQLException(e, "");
4068
        }
4069
 
4070
        if (!mDaemon)
4071
        {
4072
            // use a ListIterator as it allows traverseDependencies to modify the packageCollection
4073
            for (ListIterator<Package> it = packageCollection.listIterator(); it.hasNext(); )
4074
            {
4075
                Package p = it.next();
4076
                traverseDependencies(packageCollection, p, false, it);
4077
            }
4078
 
4079
            for (Iterator<Package> it = packageCollection.iterator(); it.hasNext(); )
4080
            {
4081
                Package p = it.next();
4082
                queryBuildInfo(rippleEngine, p);
4083
            }
4084
        }
4085
        phase.setPhase("End");
4086
    }
4087
 
4088
 
4089
   /**	Determine the version number of the base package
4090
    *   Used in a ripple build to determine the base for calculating the next version number
4091
    *   Assumes that a database connection has been established
4092
    *   Used in Daemon Mode Only
4093
    *   
4094
    *   History: Used to determine the last non-rippled package, but this had issues [JATS-402]
4095
    *   This version will located the last release version with a check that it is not a WIP ( ie start with a '(' )
4096
    *   
4097
    *   @param pv_id	- The PVID of the package to process
4098
    *   @return         - The version number without a project suffix. Null on error. 0.0.0000 if no previous
4099
    *   @throws SQLException 
4100
    */
4101
    public String getBaseVersionNumber(int pv_id)
4102
    {
4103
    	String baseVersion = "0.0.0000";
4104
 
4105
    	try {
4106
    		CallableStatement stmt;
4107
			stmt = mConnection.prepareCall(
4108
					"SELECT pv_id,last_pv_id,pkg_version,v_ext,build_type, DLOCKED " +
4109
					" FROM " +
4110
					"  (SELECT build_type,last_pv_id,pv_id,pkg_version,v_ext, DLOCKED " +
4111
					"  FROM " +
4112
					"    (SELECT pv.build_type,pv.last_pv_id AS raw_last_pvid ,pv_id,pv.pkg_version,pv.v_ext,DECODE(pv.pv_id, pv.last_pv_id, NULL, pv.last_pv_id) AS last_pv_id, DLOCKED " +
4113
					"    FROM release_manager.package_versions pv " +
4114
					"    WHERE pv.PKG_ID IN " +
4115
					"      (SELECT pkg_id " +
4116
					"      FROM release_manager.package_versions pv " +
4117
					"      WHERE pv.pv_id = " + pv_id +
4118
					"      ) " +
4119
					"    ) " +
4120
					"    START WITH pv_id = " + pv_id +
4121
					"    CONNECT BY nocycle prior last_pv_id = pv_id " +
4122
					"  ) " +
4123
					" WHERE DLOCKED = 'Y' and pkg_version not like '(%' AND pv_id != " + pv_id
4124
	                   //" WHERE build_type != 'Y' and pv_id != " + pv_id
4125
			        );
4126
 
4127
			ResultSet rset = stmt.executeQuery();
4128
 
4129
			while( rset.next() )
4130
			{
4131
				// Previous Version of this package, without the project suffix
4132
				String pkg_prevVersion = rset.getString("pkg_version");
4133
				if (pkg_prevVersion != null) 
4134
				{
4135
					String pkg_prevVext = rset.getString("v_ext");
4136
					if (pkg_prevVext != null) 
4137
					{
4138
						int endindex = pkg_prevVersion.length() - pkg_prevVext.length();
4139
						if ( endindex > 0 )
4140
						{
4141
							baseVersion = pkg_prevVersion.substring(0, endindex);
4142
						}
4143
					}
4144
				}
4145
 
4146
				// Only want the first entry
4147
				break;
4148
			}
4149
 
4150
			rset.close();
4151
			stmt.close();
4152
 
4153
    	} catch (SQLException e) {
4154
    		baseVersion = null;
4155
    		mLogger.fatal("Exception for getBaseVersionNumber " + pv_id);
4156
		}
4157
        return baseVersion;
4158
    }
4159
 
4160
    /**called only in escrow mode
4161
     * if checkCollection is true, checks the pv_id is in the packageCollection
4162
     * if checkCollection is false, or the pv_id is not in the collection
4163
     * 1 traverses the pv_id package dependencies
4164
     *   select dpv.pv_id, p.pkg_name, dpv.pkg_version, dpv.v_ext
4165
     *   from release_manager.package_versions pv, release_manager.package_dependencies pd, release_manager.package_versions dpv, release_manager.packages p
4166
     *   where pv.pv_id = <pv_id> and pd.pv_id=pv.pv_id and dpv.pv_id=pd.dpv_id and p.pkg_id=dpv.pkg_id
4167
     *   order by pv.pv_id;
4168
     * 2 for each dpv.pv_id in the resultset
4169
     *     call traverseDependencies( packageCollection, dpv.pv_id, true )
4170
     *     if the pv_id is not in the collection, add it
4171
     *   
4172
     */
4173
    private void traverseDependencies(ArrayList<Package> packageCollection, Package pkg, 
4174
            boolean checkCollection, 
4175
            ListIterator<Package> listIterator) throws SQLException, Exception
4176
            {
4177
        mLogger.debug("traverseDependencies " + checkCollection);
4178
        boolean pvIdInCollection = false;
4179
 
4180
        if ( checkCollection )
4181
        {
4182
            for (Iterator<Package> it = packageCollection.iterator(); it.hasNext(); )
4183
            {
4184
                Package p = it.next();
4185
 
4186
                if ( p.mId == pkg.mId )
4187
                {
4188
                    pvIdInCollection = true;
4189
                    break;
4190
                }
4191
            }
4192
        }
4193
 
4194
        if ( !pvIdInCollection )
4195
        {
4196
            ArrayList<Package> resultset = new ArrayList<Package>();
4197
 
4198
            try
4199
            {
4200
                PreparedStatement stmt = mConnection.prepareStatement(
4201
                        "select dpv.pv_id," +
4202
                                "p.pkg_name," + 
4203
                                "dpv.pkg_version," +
4204
                                "dpv.v_ext," + 
4205
                                "release_manager.PK_RMAPI.return_vcs_tag(dpv.pv_id) AS vcsTag" + 
4206
                                " from release_manager.package_versions pv," + 
4207
                                "release_manager.package_dependencies pd," + 
4208
                                "release_manager.package_versions dpv," + 
4209
                                "release_manager.packages p" + 
4210
                                " where pv.pv_id=" + pkg.mId + 
4211
                                "   and pd.pv_id=pv.pv_id" +
4212
                                "   and dpv.pv_id=pd.dpv_id" + 
4213
                                "   and p.pkg_id=dpv.pkg_id" + 
4214
                        " order by pv.pv_id");
4215
                stmt.setFetchSize(1000);
4216
                ResultSet rset = stmt.executeQuery();
4217
 
4218
                while (rset.next())
4219
                {
4220
                    int pv_id = rset.getInt("pv_id");
4221
 
4222
                    if (rset.wasNull())
4223
                    {
4224
                        mLogger.fatal("traverseDependencies null pv_id");
4225
                        // show stopper
4226
                        throw new Exception("traverseDependencies null pv_id");
4227
                    }
4228
 
4229
                    String pkg_name = rset.getString("pkg_name");
4230
 
4231
                    if (pkg_name == null)
4232
                    {
4233
                        mLogger.fatal("traverseDependencies null pkg_name " + pv_id);
4234
                        // show stopper
4235
                        throw new Exception("traverseDependencies null pkg_name " + pv_id);
4236
                    }
4237
 
4238
                    String pkg_version = rset.getString("pkg_version");
4239
 
4240
                    if (pkg_version == null)
4241
                    {
4242
                        mLogger.fatal("traverseDependencies null pkg_version " + pv_id);
4243
                        // show stopper
4244
                        throw new Exception("traverseDependencies null pkg_version " + pv_id);
4245
                    }
4246
 
4247
                    String v_ext = rset.getString("v_ext");
4248
 
4249
                    if (v_ext == null)
4250
                    {
4251
                        v_ext = "";
4252
                    }
4253
 
4254
                    String vcs_tag = rset.getString("vcsTag");
4255
                    if (vcs_tag == null)
4256
                    {
4257
                        vcs_tag = "";
4258
                    }
4259
 
4260
                    Package p = new Package(0, pv_id, pkg_name, pkg_version, v_ext, pkg_name + "." + pkg_version, vcs_tag, 'x');
4261
                    resultset.add(p);
4262
                    pkg.mDependencyCollection.add(p.mAlias);
4263
                }
4264
 
4265
                rset.close();
4266
                stmt.close();
4267
            }
4268
            catch ( SQLException e )
4269
            {
4270
                handleSQLException(e, "");
4271
            }
4272
 
4273
            for (Iterator<Package> it = resultset.iterator(); it.hasNext();)
4274
            {
4275
                Package r = it.next();
4276
                traverseDependencies(packageCollection, r, true, listIterator);
4277
 
4278
                pvIdInCollection = false;
4279
 
4280
                for (Iterator<Package> it2 = packageCollection.iterator(); it2.hasNext();)
4281
                {
4282
                    Package p = it2.next();
4283
 
4284
                    if (p.mId == r.mId)
4285
                    {
4286
                        pvIdInCollection = true;
4287
                        break;
4288
                    }
4289
                }
4290
 
4291
                if (!pvIdInCollection)
4292
                {
4293
                    // insert the Package immediately before the next Package returned by next
4294
                    // this does not change the next Package (if any) to be returned by next
4295
                    listIterator.add(r);
4296
                }
4297
 
4298
            }
4299
        }
4300
            }
4301
 
4302
    /**called only in escrow mode to add build info to the Package
4303
     * select bm.bm_name, bsa.bsa_name
4304
     * from release_manager.package_versions pv, release_manager.package_build_info pbi, release_manager.build_machines bm, release_manager.build_standards_addendum bsa
4305
     * where pv.pv_id = <p.pv_id> and pbi.pv_id=pv.pv_id and bm.bm_id=pbi.bm_id and bsa.bsa_id=pbi.bsa_id
4306
     * order by pv.pv_id;
4307
     */
4308
    private void queryBuildInfo(RippleEngine rippleEngine, Package p) throws SQLException, Exception
4309
    {
4310
        mLogger.debug("queryBuildInfo");
4311
 
4312
        try
4313
        {
4314
            CallableStatement stmt = mConnection.prepareCall("select bm.bm_name, bsa.bsa_name "
4315
                    + "from release_manager.package_versions pv," 
4316
                    + "     release_manager.package_build_info pbi,"
4317
                    + "     release_manager.build_machines bm," 
4318
                    + "     release_manager.build_standards_addendum bsa "
4319
                    + "where pv.pv_id=" + p.mId 
4320
                    + "   and pbi.pv_id=pv.pv_id" 
4321
                    + "   and bm.bm_id=pbi.bm_id"
4322
                    + "   and bsa.bsa_id=pbi.bsa_id " 
4323
                    + "order by pv.pv_id");
4324
            ResultSet rset = stmt.executeQuery();
4325
 
4326
            while (rset.next())
4327
            {
4328
                String bm_name = rset.getString("bm_name");
4329
 
4330
                if (bm_name == null)
4331
                {
4332
                    mLogger.fatal("queryBuildInfo null bm_name " + p.mId);
4333
                    // show stopper
4334
                    throw new Exception("queryBuildInfo null bm_name " + p.mId);
4335
                }
4336
 
4337
                String bsa_name = rset.getString("bsa_name");
4338
 
4339
                if (bsa_name == null)
4340
                {
4341
                    mLogger.fatal("queryBuildInfo null bsa_name " + p.mId);
4342
                    // show stopper
4343
                    throw new Exception("queryBuildInfo null bsa_name " + p.mId);
4344
                }
4345
 
4346
                BuildStandard bs = new BuildStandard(rippleEngine, bm_name, bsa_name);
4347
 
4348
                if (bs.supportedBuildStandard())
4349
                {
4350
                    p.mBuildStandardCollection.add(bs);
4351
                }
4352
            }
4353
 
4354
            rset.close();
4355
            stmt.close();
4356
        }
4357
        catch ( SQLException e )
4358
        {
4359
            handleSQLException(e, "");
4360
        }
4361
 
4362
    }
4363
 
4364
    /**
4365
     * Find Package by pvid
4366
     * @param   id                  - pvid of package to locate
4367
     * @param   packageCollection   - Collection to scan
4368
     * @return  Package with the matching mID or NULL_PACKAGE if no package has the mID
4369
     */
4370
    protected Package findPackage(int id, ArrayList<Package> packageCollection)
4371
    {
4372
        mLogger.debug("findPackage 1 id " + id);
4373
        Package retVal = NULL_PACKAGE;
4374
 
4375
        for (Iterator<Package> it = packageCollection.iterator(); it.hasNext(); )
4376
        {
4377
            Package p = it.next();
4378
 
4379
            if ( p.mId == id )
4380
            {
4381
                retVal = p;
4382
                break;
4383
            }
4384
        }
4385
 
4386
        mLogger.debug("findPackage 1 returned " + retVal.mName);
4387
        return retVal;
4388
    }
4389
 
4390
    /**
4391
     * Find Package by package alias
4392
     * @param   alias               - alias of package to locate
4393
     * @param   packageCollection   - Collection to scan
4394
     * @return  Package with the matching mAlias or NULL_PACKAGE if no package has the mAlias
4395
     */
4396
    protected Package findPackage(String alias, ArrayList<Package> packageCollection)
4397
    {
4398
        mLogger.debug("findPackage 2 alias " + alias);
4399
        Package retVal = NULL_PACKAGE;
4400
 
4401
        for (Iterator<Package> it = packageCollection.iterator(); it.hasNext(); )
4402
        {
4403
            Package p = it.next();
4404
 
4405
            if ( p.mAlias.compareTo( alias ) == 0 )
4406
            {
4407
                retVal = p;
4408
                break;
4409
            }
4410
        }
4411
 
4412
        mLogger.info("findPackage 2 returned " + retVal.mName);
4413
        return retVal;
4414
    }
4415
 
4416
    /**only used in daemon mode to determine version existence in the database
4417
     *  1 select pkg_id from release_manager.package_versions where pkg_id=<pkg_id> and pkg_version=<pkg_version>;
4418
     *  2 select pkg_id from release_manager.planned_versions where pkg_id=<pkg_id> and pkg_version=<pkg_version>;
4419
     * returns true if either resultset contains one record to indicate it already exists
4420
     */
4421
    boolean queryPackageVersions(int pkg_id, String pkg_version) throws SQLException, Exception
4422
    {
4423
        mLogger.debug("queryPackageVersions");
4424
        boolean retVal = false;
4425
 
4426
        if ( mUseDatabase )
4427
        {
4428
            try
4429
            {
4430
                mLogger.info("queryPackageVersions release_manager.package_versions");
4431
                CallableStatement stmt1 = mConnection.prepareCall(
4432
                    "select pkg_id" +
4433
                    " from release_manager.package_versions" +
4434
                    " where pkg_id=" + pkg_id + 
4435
                    " and pkg_version='" + pkg_version + "'");
4436
 
4437
                ResultSet rset1 = stmt1.executeQuery();
4438
                int rsetSize = 0;
4439
 
4440
                while( rset1.next() )
4441
                {
4442
                    rsetSize++;
4443
                }
4444
 
4445
                rset1.close();
4446
                stmt1.close();
4447
 
4448
                if ( rsetSize > 1 )
4449
                {
4450
                    mLogger.fatal("queryPackageVersions rsetSize > 1 " + pkg_id + " " + pkg_version);
4451
                    // show stopper
4452
                    throw new Exception("queryPackageVersions rsetSize > 1 " + pkg_id + " " + pkg_version);
4453
                }
4454
 
4455
                if ( rsetSize == 1 )
4456
                {
4457
                    retVal = true;
4458
                }
4459
                else
4460
                {
4461
                    mLogger.info("queryPackageVersions release_manager.planned_versions");
4462
                    CallableStatement stmt2 = mConnection.prepareCall(
4463
                        "select pkg_id" +
4464
                        " from release_manager.planned_versions" +
4465
                        " where pkg_id=" + pkg_id + 
4466
                        " and pkg_version='" + pkg_version + "'");
4467
                    ResultSet rset2 = stmt2.executeQuery();
4468
                    rsetSize = 0;
4469
 
4470
                    while( rset2.next() )
4471
                    {
4472
                        rsetSize++;
4473
                    }
4474
 
4475
                    rset2.close();
4476
                    stmt2.close();
4477
 
4478
                    if ( rsetSize > 1 )
4479
                    {
4480
                        mLogger.fatal("queryPackageVersions rsetSize > 1 " + pkg_id + " " + pkg_version);
4481
                        // show stopper
4482
                        throw new Exception("queryPackageVersions rsetSize > 1 " + pkg_id + " " + pkg_version);
4483
                    }
4484
 
4485
                    if ( rsetSize == 1 )
4486
                    {
4487
                        retVal = true;
4488
                    }
4489
                }
4490
            }
4491
            catch ( SQLException e )
4492
            {
4493
                handleSQLException(e, "");
4494
            }
4495
        }
4496
 
4497
        mLogger.info("queryPackageVersions returned " + retVal);
4498
        return retVal;
4499
    }
4500
 
4501
    /**
4502
     * Determine the set of packages that have been excluded from the build 
4503
     * These are packages that have been marked as do_not_ripple 
4504
     *  
4505
     * Overridden in ReleaseManagerUtf
4506
     * 
4507
     * @param buildExclusionCollection
4508
     * @param baseline The rtag_id of the release to examine
4509
     * 
4510
     * @exception SQLException
4511
     * @exception Exception
4512
     */
4513
    public void queryBuildExclusions(List<BuildExclusion> buildExclusionCollection, int baseline) throws SQLException, Exception
4514
    {
4515
        mLogger.debug("queryBuildExclusions " + baseline);
4516
 
4517
        try
4518
        {
4519
            PreparedStatement stmt = mConnection.prepareStatement(
4520
                    "select pv_id, root_pv_id, root_cause" +
4521
                    " from release_manager.do_not_ripple" + 
4522
                    " where rtag_id=" + baseline);
4523
            stmt.setFetchSize(1000);
4524
            ResultSet rset = stmt.executeQuery();
4525
 
4526
            while( rset.next() )
4527
            {
4528
                int pvId = rset.getInt("pv_id");
4529
                if ( rset.wasNull() )
4530
                {
4531
                    // show stopper
4532
                    mLogger.fatal("queryBuildExclusions rset null pv_id");
4533
                    throw new Exception("queryBuildExclusions rset null pv_id");
4534
                }
4535
 
4536
                int rootPvId = rset.getInt("root_pv_id");
4537
                if ( rset.wasNull() )
4538
                {
4539
                    // quite acceptable
4540
                    rootPvId = -1;
4541
                }
4542
 
4543
                // again, a null root_cause is quite acceptable
4544
                String rootCause = rset.getString("root_cause");
4545
 
4546
                // force email notification by using a zero test build instruction
4547
                BuildExclusion buildExclusion = new BuildExclusion(pvId, rootPvId, rootCause, 0);
4548
                buildExclusionCollection.add(buildExclusion);
4549
            }
4550
 
4551
            rset.close();
4552
            stmt.close();
4553
        }
4554
        catch ( SQLException e )
4555
        {
4556
            handleSQLException(e, "");
4557
        }
4558
    }
4559
 
4560
    /**
4561
     * attempts to execute the Exclude_Indirect_From_Build stored procedure
4562
     *  Note: Execute_Indirect_From_Build will delete matching do_not_ripple
4563
     *        rows prior to an insertion - this is crucial!!
4564
     * @param hasConnection        IN True. Use existing connection and will not commit the operation
4565
     * @param packageVersionId     IN passed to Exclude_Indirect_From_Build
4566
     * @param packageVersion       IN passed to Exclude_Indirect_From_Build
4567
     * @param rtagId               IN passed to Exclude_Indirect_From_Build
4568
     * @param rootPvId             IN passed to Exclude_Indirect_From_Build
4569
     * @param rootCause            IN passed to Exclude_Indirect_From_Build
4570
     * @param rootFile             IN passed to Exclude_Indirect_From_Build
4571
     * @param supercede            IN checks for a row with a matching packageVersionId and rtagId when false
4572
     *                                such a row will prevent the execution of Exclude_Indirect_From_Build
4573
     * @param testBuildInstruction IN will prevent the execution of Exclude_Indirect_From_Build true
4574
     * 
4575
     * @exception SQLException
4576
     * @exception Exception
4577
     */
4578
    public void excludeFromBuild(
4579
            boolean hasConnection, 
4580
            int packageVersionId, 
4581
            String packageVersion, 
4582
            int rtagId,
4583
            String rootPvId, 
4584
            String rootCause,
4585
            String rootFile,
4586
            boolean supercede, Boolean testBuildInstruction) throws SQLException, Exception
4587
    {
4588
        mLogger.debug("excludeFromBuild " + packageVersionId);
4589
 
4590
        //  If a Test Build, then don't excluded package
4591
        if ( testBuildInstruction )
4592
        {
4593
            return;
4594
        }
4595
 
4596
        if ( mUseDatabase )
4597
        {
4598
            try
4599
            {
4600
                if (!hasConnection)
4601
                    connect();
4602
 
4603
                boolean exist = false;
4604
 
4605
                if ( !supercede )
4606
                {
4607
                    // do not exclude a package already excluded ie let the first build failure count
4608
                    // there is a window of opportunity here, but it is worth doing
4609
                    // scenario 1
4610
                    //      1 this query indicates no build failure exists on this version
4611
                    //      2 another build machine reports a build failure on this version
4612
                    //      3 this is then overridden by this thread
4613
                    // does not matter
4614
                    // doing this works well for the following
4615
                    // scenario 2
4616
                    //      1 this query (run by a slave) indicates no build failure exists on this version
4617
                    //      2 build failure is reported
4618
                    //      3 master build machine detects slave in state waiting
4619
                    //      4 master daemon discovers slave did not deliver artifacts
4620
                    //      5 master daemon is prevented from overriding the build failure
4621
                    CallableStatement stmt = mConnection.prepareCall("select pv_id from release_manager.do_not_ripple where pv_id=" + packageVersionId + "and rtag_id=" + rtagId);
4622
                    ResultSet rset = stmt.executeQuery();
4623
 
4624
                    while( rset.next() )
4625
                    {
4626
                        exist = true;
4627
                        break;
4628
                    }
4629
 
4630
                    rset.close();
4631
                    stmt.close();
4632
                }
4633
 
4634
                if ( !exist )
4635
                {
4636
                    CallableStatement stmt = mConnection.prepareCall( "begin ? := PK_RMAPI.EXCLUDE_INDIRECT_FROM_BUILD(?,?,?,?,?,?,?); end;" );
4637
                    stmt.registerOutParameter( 1, Types.INTEGER);
4638
                    stmt.setInt    ( 2, packageVersionId );
4639
                    stmt.setString ( 3, packageVersion );
4640
                    stmt.setInt    ( 4, rtagId );
4641
                    stmt.setString ( 5, "buildadm" );
4642
                    stmt.setString ( 6, rootPvId);
4643
                    stmt.setString ( 7, rootCause);
4644
                    stmt.setString ( 8, rootFile);
4645
                    stmt.executeUpdate();
4646
                    int result = stmt.getInt( 1 );
4647
 
4648
                    if ( result != 0 )
4649
                    {
4650
                        // flag build failure
4651
                        mLogger.fatal( "excludeFromBuild show stopper PK_RMAPI.EXCLUDE_INDIRECT_FROM_BUILD failed, returned " + result );
4652
                        throw new Exception("excludeFromBuild show stopper PK_RMAPI.EXCLUDE_INDIRECT_FROM_BUILD failed, returned " + result);
4653
                    }
4654
                    stmt.close();
4655
                    if (!hasConnection )
4656
                        commit();
4657
                }
4658
            }
4659
            catch ( SQLException e )
4660
            {
4661
                handleSQLException(e, "");
4662
            }
4663
            finally
4664
            {
4665
                // this block is executed regardless of what happens in the try block
4666
                // even if an exception is thrown
4667
                // ensure disconnect
4668
                if (!hasConnection )
4669
                    disconnect();
4670
            }
4671
        }
4672
    }
4673
 
4674
    /**
4675
     * Removes an excluded package from the do_not_ripple table, thereby including the package back into the build set.
4676
     * The method does not remove packages that were manually added to the DNR table, as those
4677
     * packages are not in the domain of the buildtool.
4678
     * 
4679
     * @param packageVersionId Packages PVID
4680
     * @param rtagId           The RTAG id of the release to consider
4681
     * 
4682
     * @exception SQLException
4683
     * @exception Exception
4684
     */
4685
 
4686
    public void includeToBuild(int packageVersionId, int rtagId) throws SQLException, Exception
4687
    {
4688
        mLogger.debug("includeToBuild " + packageVersionId);
4689
        if ( mUseDatabase )
4690
        {
4691
            try
4692
            {
4693
                CallableStatement stmt = mConnection.prepareCall(
4694
                    "delete from release_manager.do_not_ripple " +
4695
                    "  where rtag_id=" + rtagId + 
4696
                    "  and pv_id=" + packageVersionId +
4697
                    "  and (root_pv_id is not NULL or root_cause is not NULL or root_file is not NULL)"
4698
                    );
4699
                stmt.executeUpdate();
4700
                stmt.close();
4701
            }
4702
            catch ( SQLException e )
4703
            {
4704
                handleSQLException(e, "");
4705
            }
4706
        }
4707
    }
4708
 
4709
 
4710
 
4711
 
4712
    /**queries the RUN_LEVEL table using the rcon_id primary key
4713
     * handles database connection and disconnection
4714
     * returns the current_build_files
4715
     * implements the sequence diagram consume build files 
4716
     *  
4717
     * Used by the Slave Daemon
4718
     * 
4719
     *  @param rcon_id - My release config id
4720
     *  @return The buildFile content. Will be null if none is found
4721
     */
4722
    public String queryBuildFile(int rcon_id) throws SQLException, Exception
4723
    {
4724
        String buildFile = null;
4725
 
4726
        mLogger.debug("queryRunLevel 1 rcon_id " + rcon_id);
4727
        if ( !mUseDatabase )
4728
        {
4729
            mLogger.info("queryRunLevel 1 !mUseDatabase");
4730
            buildFile = "unit test build file content";
4731
        }
4732
        else
4733
        {
4734
            try
4735
            {
4736
                connect();
4737
                CallableStatement stmt = mConnection.prepareCall("select current_build_files from release_manager.run_level where rcon_id=" + rcon_id);
4738
                ResultSet rset = stmt.executeQuery();
4739
                int rsetSize = 0;
4740
 
4741
                while( rset.next() )
4742
                {
4743
                    rsetSize++;
4744
                    buildFile = rset.getString("current_build_files");
4745
                }
4746
 
4747
                if ( rsetSize > 1 )
4748
                {
4749
                    mLogger.fatal("queryRunLevel 1 rsetSize > 1");
4750
                    // show stopper
4751
                    throw new Exception("queryRunLevel 1 rsetSize > 1");
4752
                }
4753
 
4754
                rset.close();
4755
                stmt.close();
4756
            }
4757
            catch ( SQLException e )
4758
            {
4759
                handleSQLException(e, "");
4760
            }
4761
            finally
4762
            {
4763
                // this block is executed regardless of what happens in the try block
4764
                // even if an exception is thrown
4765
                // ensure disconnect
4766
                disconnect();
4767
            }
4768
        }
4769
 
4770
        return buildFile;
4771
    }
4772
 
4773
    /** Updates mRunLevelCollection
4774
     *  Removes all elements from mRunLevelCollection, then queries the Database
4775
     *  and re-populates the structure.
4776
     *  
4777
     *  Used to determine which slave daemons the master needs to wait upon.
4778
     *  
4779
     *  Ignores entries that are disabled
4780
     *  Ignore entries that have been 'unlinked' - they have no active machine configuration
4781
     *
4782
     *   @param	rtag_id	- Release Tag
4783
     *  
4784
     *	Used by the Master Daemon 
4785
     * 	Overridden in ReleaseManagerUtf 
4786
     */
4787
    public void queryRunLevel(final int rtag_id) throws SQLException, Exception
4788
    {
4789
        mLogger.debug("queryRunLevel 2 rtag_id " + rtag_id);
4790
 
4791
        mRunLevelCollection.clear();
4792
 
4793
        try
4794
        {
4795
            connect();
4796
            CallableStatement stmt = mConnection.prepareCall(
4797
                    "SELECT rl.rcon_id," +
4798
                    "  rl.current_run_level," +
4799
                    "  NVL(rl.pause,0) as pause," +
4800
                    "  rc.daemon_mode," +
4801
                    "  NVL2(rl.CURRENT_BUILD_FILES, 1 , 0) as bfPresent" +
4802
                    " FROM release_manager.release_config rc," +
4803
                    "     release_manager.run_level rl" +
4804
                    " WHERE rc.rtag_id = " + rtag_id +
4805
                    " AND   rl.rcon_id = rc.rcon_id" +
4806
                    " AND   rc.bmcon_id is not NULL");
4807
            stmt.setFetchSize(20);
4808
            ResultSet rset = stmt.executeQuery();
4809
            int rcon_id = 0;
4810
            int current_run_level = 0;
4811
            String modeString;
4812
            char mode;
4813
            int pause = 0;
4814
            int buildFilePresent = 0;
4815
 
4816
            while( rset.next() )
4817
            {
4818
                rcon_id = rset.getInt("rcon_id");
4819
                if ( rset.wasNull() )
4820
                {
4821
                    mLogger.fatal("queryRunLevel 2 null rcon_id");
4822
                    // show stopper
4823
                    throw new Exception("queryRunLevel 2 null rcon_id");
4824
                }
4825
 
4826
                modeString = rset.getString("daemon_mode");
4827
                if ( rset.wasNull() )
4828
                {
4829
                    mLogger.fatal("queryRunLevel 2 null rcon_id");
4830
                    // show stopper
4831
                    throw new Exception("queryRunLevel 2 null rcon_id");
4832
                }
4833
                mode = modeString.charAt(0);
4834
 
4835
                buildFilePresent = rset.getInt("bfPresent");
4836
 
4837
                current_run_level = rset.getInt("current_run_level");
4838
                if ( rset.wasNull() )
4839
                {
4840
                    // slave may never have started to insert run level
4841
                    // use idle
4842
                    current_run_level = BuildState.DB_IDLE.toValue();
4843
                }
4844
 
4845
                //
4846
                //  Pause: null -> 0 == Run
4847
                //         1         == Pause
4848
                //         2         == Disabled
4849
                //
4850
                pause = rset.getInt("pause");
4851
 
4852
                //  Ignore disabled entries
4853
                if ( pause <= 1 )
4854
                {
4855
                    RunLevelData runLevel = new RunLevelData(rcon_id, current_run_level, mode, buildFilePresent);
4856
                    mRunLevelCollection.add(runLevel);
4857
                }
4858
            }
4859
 
4860
            rset.close();
4861
            stmt.close();
4862
        }
4863
        catch ( SQLException e )
4864
        {
4865
            handleSQLException(e, "");
4866
        }
4867
        finally
4868
        {
4869
            // this block is executed regardless of what happens in the try block
4870
            // even if an exception is thrown
4871
            // ensure disconnect
4872
            disconnect();
4873
        }
4874
    }
4875
 
4876
    /**
4877
     * Removes all elements and then re-populates mRunLevelCollection
4878
     * 
4879
     * Queries the RM database to determine the run_level of the current daemon.
4880
     * Populates the mRunLevelCollection with the query result set 
4881
     *  
4882
     * Used to determine if the (Slave) thread should still be running
4883
     *  
4884
     * Used by the Slave Daemon 
4885
     * Overridden in ReleaseManagerUtf 
4886
     * 
4887
     * @param rcon_id     Identify the Release_Config table entry for the daemon
4888
     * @param hostname    Name of the host machine
4889
     * @param daemon_mode Specifies the current daemon type
4890
     * 
4891
     * @exception SQLException
4892
     *                      Database connection errors
4893
     *                      Bad SQL statement
4894
     * @exception Exception Too many rows extracted from the database
4895
     *                      Empty(NULL) data in database
4896
     */
4897
    public void querySingleRunLevel(final int rcon_id, String hostname, char daemon_mode) throws SQLException, Exception
4898
    {
4899
        mLogger.debug("querySingleRunLevel rcon_id " + rcon_id);
4900
        mRunLevelCollection.clear();
4901
 
4902
        try
4903
        {
4904
            connect();
4905
 
4906
            CallableStatement stmt = mConnection.prepareCall(
4907
                    "select rl.rcon_id, "+
4908
                    "  rl.current_run_level,"+
4909
                    "  NVL(rl.pause,0) as pause," +
4910
                    "  NVL2(rl.CURRENT_BUILD_FILES, 1 , 0) as bfPresent" +
4911
                    " from release_manager.run_level rl,"+
4912
                    "   release_manager.release_config rc" +
4913
                    " where rl.rcon_id = rc.rcon_id" +
4914
                    "   AND rc.rcon_id=" + rcon_id +
4915
                    "   AND rc.bmcon_id is not NULL" +
4916
                    "   AND rc.daemon_mode='" + daemon_mode + "'" +
4917
                    "   AND UPPER(rc.daemon_hostname)=UPPER('" + hostname + "')"
4918
                    );
4919
            ResultSet rset = stmt.executeQuery();
4920
            int rsetSize = 0;
4921
            int current_run_level = 0;
4922
            int pause = 0;
4923
            int buildFilePresent = 0;
4924
 
4925
            while( rset.next() )
4926
            {
4927
                rsetSize++;
4928
                current_run_level = rset.getInt("current_run_level");
4929
 
4930
                if ( rset.wasNull() )
4931
                {
4932
                    mLogger.fatal("querySingleRunLevel null current_run_level");
4933
                    // show stopper
4934
                    throw new Exception("querySingleRunLevel null current_run_level");
4935
                }
4936
 
4937
                buildFilePresent = rset.getInt("bfPresent");
4938
 
4939
                //
4940
                //  Pause: null -> 0 == Run
4941
                //         1         == Pause
4942
                //         2         == Disabled
4943
                //
4944
                pause = rset.getInt("pause");
4945
 
4946
                //  Ignore disabled daemons
4947
                if ( pause <= 1)
4948
                {
4949
                    RunLevelData runLevel = new RunLevelData(rcon_id, current_run_level, daemon_mode, buildFilePresent);
4950
                    mRunLevelCollection.add(runLevel);
4951
                }
4952
            }
4953
 
4954
            rset.close();
4955
            stmt.close();
4956
 
4957
            //  Must have no more than one record
4958
            //  Will have none if this daemon is no longer a part of the build set
4959
            //
4960
            if ( rsetSize > 1 )
4961
            {
4962
                //  show stopper
4963
                //  More rows than expected returned from the database
4964
                mLogger.fatal("querySingleRunLevel rsetSize > 1");
4965
                throw new Exception("querySingleRunLevel rsetSize > 1");
4966
            }
4967
        }
4968
        catch ( SQLException e )
4969
        {
4970
            handleSQLException(e, "");
4971
        }
4972
        finally
4973
        {
4974
            // this block is executed regardless of what happens in the try block
4975
            // even if an exception is thrown
4976
            // ensure disconnect
4977
            disconnect();
4978
        }
4979
    }
4980
 
4981
    /**Queries the RUN_LEVEL_SCHEDULE table to determine if we can proceed
4982
     * <br>Will not proceed if:
4983
     *      <br>- Inside a scheduled downtime
4984
     *      <br>- Indefinite pause present
4985
     * 
4986
     * <br>Should delete rows with a non NULL indefinite pause (but doesn't appear too)
4987
     *  
4988
     * <br>Assumes connection to database has been established
4989
     * 
4990
     * @param   resumeTime.value  Returns date-time when daemon can run again 
4991
     * 
4992
     * @return  False: if a row in the query result set indicates build service downtime is scheduled
4993
     *      <br>False: if a row in the query result set has a non NULL indefinite_pause
4994
     */
4995
    public boolean queryRunLevelSchedule(MutableDate resumeTime) throws SQLException, Exception
4996
    {
4997
        mLogger.debug("queryRunLevelSchedule");
4998
        boolean retVal = true;
4999
 
5000
        if ( mUseDatabase )
5001
        {
5002
            //
5003
            //  Clean up the run_level_schedule table by deleting out of date entries
5004
            //
5005
            try
5006
            {
5007
                CallableStatement stmt = mConnection.prepareCall( "BEGIN PK_BUILDAPI.DELETE_OUT_OF_DATE_SCHEDULE;   END;" );
5008
                stmt.executeUpdate();
5009
                stmt.close();
5010
                commit();
5011
            }
5012
            catch ( SQLException e )
5013
            {
5014
                handleSQLException(e, ":1");
5015
            }
5016
 
5017
            try
5018
            {
5019
                //  Extract info from the database
5020
                //
5021
                CallableStatement stmt = mConnection.prepareCall(
5022
                        "select scheduled_pause, scheduled_resume, repeat, indefinite_pause" + 
5023
                        " from release_manager.run_level_schedule");
5024
                ResultSet rset = stmt.executeQuery();
5025
                Date now = new Date();
5026
 
5027
                //
5028
                //  Scan the database information and determine if there is any reason
5029
                //  to pause. Terminate the loop on the first excuse to pause
5030
                //  as indefinite pause may have multiple (lots) of entries in the data
5031
                //  base.
5032
                //
5033
                while( retVal && rset.next() )
5034
                {
5035
                    //
5036
                    //  Examine the current row from the data base
5037
                    //  Expect one of two forms:
5038
                    //    1) scheduled_pause
5039
                    //       Must also have a scheduled_resume and a repeat
5040
                    //    2) indefinite_pause
5041
                    //
5042
 
5043
                    //  Look for scheduled_pause style of entry
5044
                    //
5045
                    Timestamp sp = rset.getTimestamp("scheduled_pause");
5046
                    if ( sp != null )
5047
                    {
5048
                        Date scheduledPause = new Date( sp.getTime() );
5049
                        Timestamp sr = rset.getTimestamp("scheduled_resume");
5050
 
5051
                        if ( sr != null )
5052
                        {
5053
                            Date scheduledResume = new Date( sr.getTime() );
5054
                            int repeat = rset.getInt("repeat");
5055
                            mLogger.info("queryRunLevelSchedule repeat " + repeat);
5056
 
5057
                            //
5058
                            //  Have scheduled_pause and scheduled_resume
5059
                            //  Examine the repeat field and determine how these are used
5060
                            //  Supported repeat:
5061
                            //      0:Once Only
5062
                            //      1:Daily           Year, Month and Day information is ignored
5063
                            //      7:Weekly          Only day of week is utilized
5064
                            //
5065
                            if ( !rset.wasNull() )
5066
                            {
5067
                                GregorianCalendar startOfDowntime = new GregorianCalendar();
5068
                                GregorianCalendar endOfDowntime = new GregorianCalendar();
5069
                                GregorianCalendar clock = new GregorianCalendar();
5070
 
5071
                                switch( repeat )
5072
                                {
5073
                                    case 0:
5074
                                        // Once Only
5075
                                        // Simple check between start and end date-times
5076
                                        if ( scheduledPause.before(now) && scheduledResume.after(now) )
5077
                                        {
5078
                                            mLogger.warn("queryRunLevelSchedule one off scheduled downtime");
5079
                                            resumeTime.value = scheduledResume;
5080
                                            retVal = false;
5081
                                        }
5082
                                        break;
5083
 
5084
                                    case 1:
5085
 
5086
                                        //  Daily
5087
                                        //  Create start and end times, then massage some fields
5088
                                        //  to reflect todays date.
5089
                                        //  Use start and end times from scheduled_pause and scheduled_resume
5090
                                        //
5091
 
5092
                                        startOfDowntime.setTime(scheduledPause);
5093
                                        endOfDowntime.setTime(scheduledResume);
5094
                                        clock.setTime(now);
5095
 
5096
                                        // Force date fields to todays date
5097
                                        endOfDowntime.set  ( clock.get(Calendar.YEAR), clock.get(Calendar.MONTH), clock.get(Calendar.DAY_OF_MONTH) );
5098
                                        startOfDowntime.set( clock.get(Calendar.YEAR), clock.get(Calendar.MONTH), clock.get(Calendar.DAY_OF_MONTH) );
5099
 
5100
                                        if ( startOfDowntime.before(clock) && endOfDowntime.after(clock) )
5101
                                        {
5102
                                            mLogger.warn("queryRunLevelSchedule daily scheduled downtime");
5103
                                            resumeTime.value.setTime(endOfDowntime.getTimeInMillis());
5104
                                            retVal = false;
5105
                                        }
5106
                                        break;
5107
 
5108
                                    case 7:
5109
 
5110
                                        // Weekly
5111
                                        // Create start and end times, then massage some fields
5112
                                        // to reflect todays date.
5113
                                        // Use DayOfWeek and time from scheduled_pause
5114
                                        // Use time from scheduled_resume
5115
                                        //
5116
                                        startOfDowntime.setTime(scheduledPause);
5117
                                        endOfDowntime.setTime(scheduledResume);
5118
                                        clock.setTime(now);
5119
 
5120
                                        // Only interested in one day of the week
5121
                                        if ( startOfDowntime.get(Calendar.DAY_OF_WEEK) == clock.get(Calendar.DAY_OF_WEEK) )
5122
                                        {
5123
                                            endOfDowntime.set  ( clock.get(Calendar.YEAR), clock.get(Calendar.MONTH), clock.get(Calendar.DAY_OF_MONTH) );
5124
                                            startOfDowntime.set( clock.get(Calendar.YEAR), clock.get(Calendar.MONTH), clock.get(Calendar.DAY_OF_MONTH) );
5125
 
5126
                                            if ( startOfDowntime.before(clock) && endOfDowntime.after(clock) )
5127
                                            {
5128
                                                mLogger.warn("queryRunLevelSchedule weekly scheduled downtime");
5129
                                                resumeTime.value.setTime(endOfDowntime.getTimeInMillis());
5130
                                                retVal = false;
5131
                                            }
5132
                                        }
5133
                                        break;
5134
 
5135
                                   default:
5136
                                       //
5137
                                       //   Unexpected value
5138
                                       break;
5139
                                }
5140
                            }
5141
                        }
5142
                    }
5143
 
5144
                    //
5145
                    //  Look for indefinite_pause style of entry
5146
                    //  Note: due to an implementation error there may be many
5147
                    //        rows that match. We only need one. The scan will
5148
                    //        be terminated if we find any
5149
                    //  
5150
                    //
5151
                    String ip = rset.getString("indefinite_pause");
5152
                    if ( ip != null )
5153
                    {
5154
                        // indefinite pause is non null
5155
                        mLogger.warn("queryRunLevelSchedule indefinite pause");
5156
                        GregorianCalendar clock = new GregorianCalendar();
5157
                        clock.setTime(now);
5158
                        // wait a minute
5159
                        resumeTime.value.setTime(clock.getTimeInMillis() + 60000);
5160
                        retVal = false;
5161
                    }
5162
                }
5163
 
5164
                rset.close();
5165
                stmt.close();
5166
            }
5167
            catch ( SQLException e )
5168
            {
5169
                handleSQLException(e, ":2");
5170
            }
5171
        }
5172
 
5173
        mLogger.info("queryRunLevelSchedule returning " + retVal);
5174
        return retVal;
5175
    }
5176
 
5177
    /**persists the runLevel in the RUN_LEVEL table for the rcon_id primary key
5178
     * 
5179
     * Overridden in the UTF
5180
     * 
5181
     * @param   rcon_id         Identifies the Release Connection (daemon)
5182
     * @param   runLevel        The run level to set
5183
     * 
5184
     */
5185
    public void updateCurrentRunLevel(final int rcon_id, final int runLevel) throws SQLException, Exception
5186
    {
5187
        mLogger.debug("updateCurrentRunLevel");
5188
 
5189
        try
5190
        {
5191
            connect();
5192
 
5193
            mLogger.warn("updateCurrentRunLevel: Set Runlevel:" + runLevel + ", rcon_id: " + rcon_id);
5194
            PreparedStatement stmt = mConnection.prepareCall("update release_manager.run_level set current_run_level=" + runLevel + ", keep_alive=SYSDATE where rcon_id=" + rcon_id);
5195
            stmt.executeUpdate();
5196
            stmt.close();
5197
 
5198
            mLogger.info("updateCurrentRunLevel: committing");
5199
            commit();
5200
            mLogger.info("updateCurrentRunLevel: committed");
5201
        }
5202
        catch ( SQLException e )
5203
        {
5204
            handleSQLException(e, "");
5205
        }
5206
        finally
5207
        {
5208
            // this block is executed regardless of what happens in the try block
5209
            // even if an exception is thrown
5210
            // ensure disconnect
5211
            disconnect();
5212
        }
5213
 
5214
    }
5215
 
5216
    /** Report the current build plan
5217
     *  This is only for display purposes
5218
     *  Assume a connection has been established. Will not commit if the operation is covered by the Mutex
5219
     *  
5220
     * @param mRtagId - Release we are building
5221
     * @param mBuildOrder - Ordered list of PackageVersions that we plan to build
5222
     * @throws Exception 
5223
     * @throws SQLException 
5224
     */
5225
    public void reportPlan(int mRtagId, List<Package> mBuildOrder) throws SQLException, Exception {
5226
        mLogger.debug("reportPlan " + mRtagId);
5227
 
5228
        if ( mUseDatabase )
5229
        {
5230
            try
5231
            {
5232
                Iterator<Package> it = mBuildOrder.iterator();
5233
                int fragment = 0;
5234
                CallableStatement stmt = mConnection.prepareCall( "call PK_BUILDAPI.set_build_plan(?,?,?)" );
5235
 
5236
                do {
5237
                    //
5238
                    // Generate a comma separated list of PVIDs
5239
                    // Limit the length of the string since we can only pump 4000 chars into a string
5240
                    // Allow 10 chars per PV_ID
5241
                    //
5242
                    StringBuilder pvList = new StringBuilder();
5243
                    String joiner = "";
5244
 
5245
                    while ( pvList.length() < 3000  && it.hasNext() )
5246
                    {
5247
                        Package p = it.next();
5248
                        pvList.append(joiner);
5249
                        pvList.append(p.mId);
5250
                        joiner = ",";
5251
                    }
5252
 
5253
                    //  Terminate if we have nothing to add and its not the first pass
5254
                    if (pvList.length() <= 0 && fragment != 0)
5255
                    {
5256
                        break;
5257
                    }
5258
 
5259
                    //
5260
                    //  Insert data - one fragment at a time
5261
                    //
5262
                    stmt.setInt    ( 1, mRtagId );
5263
                    stmt.setInt    ( 2, fragment );
5264
                    stmt.setString ( 3, pvList.toString() );
5265
                    stmt.executeUpdate();
5266
                    fragment++;
5267
 
5268
                } while(true);
5269
 
5270
                stmt.close();
5271
 
5272
                //  Commit only if not covered by the Mutex
5273
                if ( ! mDoNotCommit )
5274
                    commit();
5275
            }
5276
            catch ( SQLException e )
5277
            {
5278
                handleSQLException(e, "");
5279
            }
5280
            finally
5281
            {
5282
                // this block is executed regardless of what happens in the try block
5283
                // even if an exception is thrown
5284
            }
5285
        }
5286
    }
5287
 
5288
    public void updateBuildDuration(int pvId, int duration) throws Exception {
5289
        mLogger.debug("updateBuildDuration " + pvId + ":" + duration);
5290
        if ( mUseDatabase )
5291
        {
5292
            try
5293
            {
5294
                connect();
5295
 
5296
                String sql = "update release_manager.package_versions set BUILD_TIME = ? where pv_id = ?";
5297
 
5298
                PreparedStatement stmt = mConnection.prepareStatement(sql);
5299
                stmt.setLong( 1,duration );
5300
                stmt.setLong( 2,pvId );
5301
                stmt.executeUpdate();
5302
                stmt.close();
5303
                commit();
5304
            }
5305
            catch ( SQLException e )
5306
            {
5307
                handleSQLException(e, "");
5308
            }
5309
            finally
5310
            {
5311
                disconnect();
5312
            }
5313
        }
5314
    }
5315
 
5316
    /**  Set RippleStop flag to 'w' for waiting
5317
     *  Indicated that the build system will Ripple the package, when the user confirms that it can be done
5318
     *  Assume database connection has been established
5319
     * @param mRtagId 
5320
     * 
5321
     * @param pkg - Package being processed
5322
     * @throws Exception 
5323
     */
5324
    public void setRippleStopWait(int mRtagId, Package pkg) throws Exception {
5325
 
5326
        // Use a stored procedure as it will also do logging
5327
        mLogger.debug("setRippleStopWait");
5328
        if ( mUseDatabase )
5329
        {
5330
            try
5331
            {
5332
                // "BEGIN  PK_PACKAGE.Set_Ripple_Stop( :PV_ID, :RTAG_ID, :USER_ID, :RSTATE );  END;"
5333
 
5334
                CallableStatement stmt = mConnection.prepareCall( "BEGIN  PK_PACKAGE.Set_Ripple_Stop( ?, ?, ?, 'w' );  END;" );
5335
                stmt.setInt(1, pkg.mId);        // PVID
5336
                stmt.setInt(2, mRtagId);        // RTAG ID 
5337
                stmt.setInt(3, 3768);           // USER ID - buildadm ( Yes I know its ugly )
5338
                stmt.executeUpdate();
5339
                stmt.close();
5340
            }
5341
            catch ( SQLException e )
5342
            {
5343
                handleSQLException(e, "");
5344
            }
5345
        }
5346
 
5347
    }
5348
 
5349
}
5350