1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2  *
3  * This program and the accompanying materials are made available under
4  * the terms of the Common Public License v1.0 which accompanies this distribution,
5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
6  *
7  * $Id: CoverageData.java,v 1.1.1.1 2004/05/09 16:57:31 vlad_r Exp $
8  */
9 package com.vladium.emma.data;
10 
11 import java.io.DataInput;
12 import java.io.DataOutput;
13 import java.io.IOException;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.Map;
17 
18 import com.vladium.util.asserts.$assert;
19 
20 // ----------------------------------------------------------------------------
21 /**
22  * @author Vlad Roubtsov, (C) 2003
23  */
24 final class CoverageData implements ICoverageData, Cloneable
25 {
26     // public: ................................................................
27 
28     // TODO: duplicate issue
29 
lock()30     public Object lock ()
31     {
32         return m_coverageMap;
33     }
34 
shallowCopy()35     public ICoverageData shallowCopy ()
36     {
37         final CoverageData _clone;
38         try
39         {
40             _clone = (CoverageData) super.clone ();
41         }
42         catch (CloneNotSupportedException cnse)
43         {
44             throw new Error (cnse.toString ());
45         }
46 
47         final HashMap _coverageMap;
48 
49         synchronized (lock ())
50         {
51             _coverageMap = (HashMap) m_coverageMap.clone ();
52         }
53 
54         _clone.m_coverageMap = _coverageMap;
55 
56         return _clone;
57     }
58 
size()59     public int size ()
60     {
61         return m_coverageMap.size ();
62     }
63 
getCoverage(final ClassDescriptor cls)64     public DataHolder getCoverage (final ClassDescriptor cls)
65     {
66         if (cls == null) throw new IllegalArgumentException ("null input: cls");
67 
68         return (DataHolder) m_coverageMap.get (cls.getClassVMName ());
69     }
70 
addClass(final boolean [][] coverage, final String classVMName, final long stamp)71     public void addClass (final boolean [][] coverage, final String classVMName, final long stamp)
72     {
73         m_coverageMap.put (classVMName, new DataHolder (coverage, stamp));
74     }
75 
76     // IMergeable:
77 
isEmpty()78     public boolean isEmpty ()
79     {
80         return m_coverageMap.isEmpty ();
81     }
82 
83     /*
84      * This method is not MT-safe wrt addClass() etc.
85      *
86      * note: rhs entries override current entries if they have different stamps;
87      * otherwise, the data is merged
88      */
merge(final IMergeable rhs)89     public IMergeable merge (final IMergeable rhs)
90     {
91         if ((rhs == null) || rhs.isEmpty () || (rhs == this))
92             return this;
93         else
94         {
95             final CoverageData rhscdata = (CoverageData) rhs; // TODO: redesign so that the cast is not necessary
96             final Map rhscoverageData = rhscdata.m_coverageMap;
97 
98             for (Iterator entries = rhscoverageData.entrySet ().iterator (); entries.hasNext (); )
99             {
100                 final Map.Entry entry = (Map.Entry) entries.next ();
101                 final String classVMName = (String) entry.getKey ();
102 
103                 final DataHolder rhsdata = (DataHolder) entry.getValue ();
104                 // [assertion: rhsdata != null]
105 
106                 final DataHolder data = (DataHolder) m_coverageMap.get (classVMName);
107 
108                 if (data == null)
109                     m_coverageMap.put (classVMName, rhsdata);
110                 else
111                 {
112                     if (rhsdata.m_stamp != data.m_stamp)
113                         m_coverageMap.put (classVMName, rhsdata);
114                     else // merge two runtime profiles
115                     {
116                         final boolean [][] rhscoverage = rhsdata.m_coverage;
117                         final boolean [][] coverage = data.m_coverage;
118 
119                         // [assertion: both coverage and rhscoverage aren't null]
120 
121                         if ($assert.ENABLED) $assert.ASSERT (coverage.length == rhscoverage.length, "coverage.length [" + coverage.length + "] != rhscoverage.length [" + rhscoverage.length + "]");
122                         for (int m = 0, mLimit = coverage.length; m < mLimit; ++ m)
123                         {
124                             final boolean [] rhsmcoverage = rhscoverage [m];
125                             final boolean [] mcoverage = coverage [m];
126 
127                             if (mcoverage == null)
128                             {
129                                 if ($assert.ENABLED) $assert.ASSERT (rhsmcoverage == null, "mcoverage == null but rhsmcoverage != null");
130 
131                                 // [nothing to merge]
132                             }
133                             else
134                             {
135                                 if ($assert.ENABLED) $assert.ASSERT (rhsmcoverage != null, "mcoverage != null but rhsmcoverage == null");
136                                 if ($assert.ENABLED) $assert.ASSERT (mcoverage.length == rhsmcoverage.length, "mcoverage.length [" + mcoverage.length + "] != rhsmcoverage.length [" + rhsmcoverage.length + "]");
137 
138                                 for (int b = 0, bLimit = mcoverage.length; b < bLimit; ++ b)
139                                 {
140                                     if (rhsmcoverage [b]) mcoverage [b] = true;
141                                 }
142                             }
143                         }
144                     }
145                 }
146             }
147 
148             return this;
149         }
150     }
151 
152     // protected: .............................................................
153 
154     // package: ...............................................................
155 
156 
CoverageData()157     CoverageData ()
158     {
159         m_coverageMap = new HashMap ();
160     }
161 
162 
readExternal(final DataInput in)163     static CoverageData readExternal (final DataInput in)
164         throws IOException
165     {
166         final int size = in.readInt ();
167         final HashMap coverageMap = new HashMap (size);
168 
169         for (int i = 0; i < size; ++ i)
170         {
171             final String classVMName = in.readUTF ();
172             final long stamp = in.readLong ();
173 
174             final int length = in.readInt ();
175             final boolean [][] coverage = new boolean [length][];
176             for (int c = 0; c < length; ++ c)
177             {
178                 coverage [c] = DataFactory.readBooleanArray (in);
179             }
180 
181             coverageMap.put (classVMName, new DataHolder (coverage, stamp));
182         }
183 
184         return new CoverageData (coverageMap);
185     }
186 
writeExternal(final CoverageData cdata, final DataOutput out)187     static void writeExternal (final CoverageData cdata, final DataOutput out)
188         throws IOException
189     {
190         final Map coverageMap = cdata.m_coverageMap;
191 
192         final int size = coverageMap.size ();
193         out.writeInt (size);
194 
195         final Iterator entries = coverageMap.entrySet ().iterator ();
196         for (int i = 0; i < size; ++ i)
197         {
198             final Map.Entry entry = (Map.Entry) entries.next ();
199 
200             final String classVMName = (String) entry.getKey ();
201             final DataHolder data = (DataHolder) entry.getValue ();
202 
203             final boolean [][] coverage = data.m_coverage;
204 
205             out.writeUTF (classVMName);
206             out.writeLong (data.m_stamp);
207 
208             final int length = coverage.length;
209             out.writeInt (length);
210             for (int c = 0; c < length; ++ c)
211             {
212                 DataFactory.writeBooleanArray (coverage [c], out);
213             }
214         }
215     }
216 
217     // private: ...............................................................
218 
219 
CoverageData(final HashMap coverageMap)220     private CoverageData (final HashMap coverageMap)
221     {
222         if ($assert.ENABLED) $assert.ASSERT (coverageMap != null, "coverageMap is null");
223         m_coverageMap = coverageMap;
224     }
225 
226 
227     private /*final*/ HashMap /* String(classVMName) -> DataHolder */ m_coverageMap; // never null
228 
229 } // end of class
230 // ----------------------------------------------------------------------------