Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
6914 dpurdie 1
package com.erggroup.buildtool.ripple;
2
 
3
import org.apache.log4j.Logger;
4
 
5
import com.erggroup.buildtool.smtp.CreateUrls;
6
import com.erggroup.buildtool.smtp.Smtpsend;
7
 
8
import java.sql.SQLException;
9
import java.util.ArrayList;
10
import java.util.Iterator;
11
 
12
/**entity class holding build exclusion data
13
 */
14
public class BuildExclusion
15
{
16
  /**Logger
17
   * @attribute
18
   */
19
  private static final Logger mLogger = Logger.getLogger(BuildExclusion.class);
20
 
21
  /**The pvid of the package being excluded
22
   * @attribute
23
   */
24
  private int mId;
25
 
26
  /**root identifier is the PVID of the package that is causing the exclusion
27
   * A NULL value indicates that this entry(package) is the root cause of the of an exclusion
28
   * @attribute
29
   */
30
  private int mRootId;
31
 
32
  /**root cause
33
   * If not NULL, then this is the reason this package is being excluded
34
   * @attribute
35
   */
36
  private String mRootCause;
37
 
38
  /**test build instruction
39
   * @attribute
40
   */
41
  private int mTestBuildInstruction;
42
 
43
  /**Indicates that the item has been processed
44
   * @attribute
45
   */
46
  private boolean mProcessed = false;
47
 
48
  /**constructor
49
   */
50
  public BuildExclusion(int identifier, int rootIdentifier, String rootCause, int testBuildInstruction )
51
  {
52
    mLogger.debug("BuildExclusion");
53
    mId = identifier;
54
    mRootId = dealWithNullRootPvId(identifier, rootIdentifier);
55
    mRootCause = rootCause;
56
    mTestBuildInstruction = testBuildInstruction;
57
  }
58
 
59
  /**sets mProcessed true
60
   */
61
  void process()
62
  {
63
    mLogger.debug("process " + mId);
64
    mProcessed = true;
65
  }
66
 
67
  /** @returns true if the item has been marked as processed. 
68
   * Appears to be an indication that the entry has been superceeded.
69
   */
70
  boolean isProcessed()
71
  {
72
    mLogger.debug("isProcessed " + mId);
73
    mLogger.info("isProcessed returned " + mProcessed);
74
    return mProcessed;
75
  }
76
 
77
  /**
78
   * Compare this item with parameters
79
   * @param identifier          - Related Package identifier
80
   * @param rootIdentifier      - Package identifier of root cause
81
   * @param  rootCause          - Root cause string. May be null
82
   * @return true if all attributes match
83
   */
84
  boolean compare( int identifier, int rootIdentifier, String rootCause)
85
  {
86
    mLogger.debug("compare " + mId + ", " + identifier + ", " + rootIdentifier + ", " + rootCause);
87
    boolean retVal = false;
88
    rootIdentifier = dealWithNullRootPvId(identifier, rootIdentifier);
89
 
90
    if ( mRootCause == null )
91
    {
92
      if ( mId == identifier && mRootId == rootIdentifier && rootCause == null )
93
      {
94
        retVal = true;
95
      }
96
    }
97
    else
98
    {
99
      if ( mId == identifier && mRootId == rootIdentifier && mRootCause.compareTo(rootCause) == 0 )
100
      {
101
        retVal = true;
102
      }
103
    }
104
 
105
    mLogger.info("compare returned " + retVal);
106
    return retVal;
107
  }
108
 
109
  /**
110
   * @param identifier  - identifier to match
111
   * @return true if mId attribute matches
112
   */
113
  boolean compare( int identifier )
114
  {
115
    mLogger.debug("compare " + mId + ", " + identifier);
116
    boolean retVal = false;
117
 
118
    if ( mId == identifier )
119
    {
120
      retVal = true;
121
    }
122
 
123
    mLogger.info("compare returned " + retVal);
124
    return retVal;
125
  }
126
 
127
  /**runs exclude from build
128
   * Assumes that a connection to RM has been established
129
   * 
130
   * @param rm          Release Manager instance
131
   * @param rtag_id     Rtag Id we are working against
132
   */
133
  void excludeFromBuild( ReleaseManager rm, int rtag_id ) throws SQLException, Exception
134
  {
135
    mLogger.debug("excludeFromBuild " + mId);
136
 
137
    // a null version and log file is passed to oracle
138
    // the planned version is only needed to remove a planned version from the planned version table
139
    // the ripple engine does not get this far ie it excludes pvs before claiming a version
140
    // this is the one instance where an existing build failure must be superseded in the database
141
    rm.excludeFromBuild(true, 
142
                        mId, 
143
                        null, 
144
                        rtag_id, 
145
    		            mRootId == -1 ? null : String.valueOf(mRootId), 
146
    		            mRootCause, 
147
    		            null, 
148
    		            true, (mTestBuildInstruction > 0) );
149
  }
150
 
151
  /**runs include to build
152
   * Include a previously excluded package-version back into the build set
153
   * 
154
   * @param rm          Release Manager instance
155
   * @param rtag_id     Rtag Id we are working against
156
   */
157
  void includeToBuild( ReleaseManager rm, int rtag_id ) throws SQLException, Exception
158
  {
159
    mLogger.debug("includeToBuild " + mId);
160
    rm.includeToBuild(mId, rtag_id);
161
  }
162
 
163
  /**
164
   * Match this items id against that provided
165
   * @param id  - Id to match
166
   * @return true if id matches mId
167
   */
168
    private boolean isRelevant(int id)
169
    {
170
      mLogger.debug("isRelevant " + mId + ", " + id);
171
      boolean retVal = false;
172
 
173
      if ( mId == id )
174
      {
175
        retVal = true;
176
      }
177
 
178
      mLogger.info("isRelevant " + mId +  ", " + id + " returned " + retVal);
179
      return retVal;
180
    }
181
 
182
  /**
183
   * Match this items mRootId against the id's provided in a collection
184
   * ie: Determine if any items in the collection are the root cause of this items
185
   * ie: Used to determine if an entry is for an indirectly excluded package where
186
   *     the root cause of the exclusion has been removed.
187
   *     
188
   * @param buildExclusionCollection - Collection to be processed
189
   * @return false: Indirectly excluded package whose root cause no longer exists
190
   */
191
  boolean isRelevant(ArrayList<BuildExclusion> buildExclusionCollection)
192
  {
193
    mLogger.debug("isRelevant " + mId);
194
    boolean retVal = false;
195
 
196
    if ( mRootId == -1 )     {
197
      retVal = true;
198
 
199
    } else if(mRootId == -2 ) {
200
        // Excluded due to Ripple Stop
201
        // Will be recalculated so its not relevant
202
        retVal = false;
203
 
204
    } else {
205
      for (Iterator<BuildExclusion> it = buildExclusionCollection.iterator(); it.hasNext(); )
206
      {
207
        BuildExclusion buildExclusion = it.next();
208
 
209
        if ( buildExclusion.isRelevant( mRootId ) )
210
        {
211
          retVal = true;
212
          break;
213
        }
214
      }
215
    }
216
 
217
    mLogger.info("isRelevant " + mId + " returned " + retVal);
218
    return retVal;
219
  }
220
 
221
  /**
222
   * @return true if the root_pv_id is null (-1). This indicates that the item is the root case, and is not simply
223
   *         a by product of some other cause.
224
   */
225
  boolean isARootCause()
226
  {
227
    mLogger.debug("isARootCause " + mId);
228
    boolean retVal = false;
229
 
230
    if ( mRootId == -1 )
231
    {
232
      retVal = true;
233
    }
234
 
235
    mLogger.info("isARootCause " + mId + " returned " + retVal);
236
    return retVal;
237
  }
238
 
239
  /**
240
   * Send an email notifying users about a build excluded package
241
   * It is user friendly, in that it does not trigger a storm of emails because a low level package 
242
   * has a build issue. It limits the emails to the low level package
243
   * 
244
   * i.e. only send email if the build exclusion has a null root pv id
245
   * and a non null root cause
246
   * 
247
   * @param    rippleEngine        - Ripple Engine Instance
248
   * @param    packageCollection   - Collection to process
249
   */
250
    public void email(RippleEngine rippleEngine, ArrayList<Package> packageCollection) throws SQLException, Exception
251
    {
252
      mLogger.debug("email " + mId);
253
 
254
      //
255
      //    Only process entries that are direct failures of ripple engine detected failure
256
      //    Do not process entries that are indirectly excluded as this will cause an email storm
257
      //    Direct build failure: 
258
      //        Have no RootId and have a rootCause
259
      //
260
      if ( mRootId == -1 && mRootCause != null )
261
      {
262
        //  Locate the associated package entry
263
        Package pkg= rippleEngine.mReleaseManager.findPackage(mId, packageCollection);
264
 
265
        if ( pkg != ReleaseManager.NULL_PACKAGE )
266
        {
267
 
268
          // Is there anyone to send an email to
269
          String owners = pkg.emailInfoNonAntTask(rippleEngine);
270
 
271
          if ( owners != null )
272
          {
273
 
274
            String body =
275
            "Release: " + rippleEngine.mBaselineName + "<p>" +
276
            "Package: " + pkg.mName + "<p>" + 
277
            "Cause: "   + mRootCause + "<p>"+
278
            "RmRef: "   + CreateUrls.generateRmUrl(rippleEngine.getRtagId(), pkg.mId) +"<p>";
279
 
280
            try
281
            {
282
              Smtpsend.send(
283
              rippleEngine.getMailServer(),                 // mailServer
284
              rippleEngine.getMailSender(),                 // source
285
              owners,                                   // target
286
              null,                                     // cc
287
              null,                                     // bcc
288
              "BUILD FAILURE on package " + pkg.mName,  // subject
289
              body,                                     // body
290
              null                                      // attachment
291
              );
292
            }
293
            catch( Exception e )
294
            {
295
            }
296
          }
297
 
298
          // Having sent the build failure email, complete a test build if applicable.
299
          // This ensures the test build instruction is not processed indefinitely
300
          // as there is no notion of excluding test builds
301
          pkg.completeTestBuild(rippleEngine, false);
302
        }
303
      }
304
    }
305
 
306
    /**
307
     * Hides how a rootPvId is treated
308
     * Only use rootPvId if not equal to the pvid
309
     * 
310
     * If the provided rootPvId matches the pvId, then the rootPvId will be set to null (-1)
311
     * This is to drive a direct build exclusion in the release manager
312
     * 
313
     * @param   pvid        - id
314
     * @param   rootPvId    - rootPvid
315
     * 
316
     * @returns rootPvId unless pvId matches= rootPvId, when it returns a null (-1)
317
    */
318
    private int dealWithNullRootPvId( int pvId, int rootPvId )
319
    {
320
      int retVal = rootPvId;
321
 
322
      if ( pvId == rootPvId )
323
      {
324
        retVal = -1;    // -1 == null entry
325
      }
326
 
327
      return retVal;
328
    }
329
 
330
    /**
331
     * Generate a single text line of info
332
     * Used within the UTF to 
333
     * @return String form of the state of the entry
334
     */
335
    public String info()
336
    {
337
        String rv = "";
338
        rv += "pvid=" + mId + ",RootId=" + mRootId + ",Processed=" + mProcessed + ",TestBuild=" + mTestBuildInstruction + ",RootCause=" + mRootCause;
339
        return rv;
340
    }
341
}