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 // ----------------------------------------------------------------------------