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