Subversion Repositories DevTools

Rev

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