1 16 package scriptella.execution; 17 18 import scriptella.spi.Connection; 19 20 import java.text.DecimalFormat ; 21 import java.text.Format ; 22 import java.text.NumberFormat ; 23 import java.util.Collection ; 24 import java.util.Date ; 25 import java.util.HashMap ; 26 import java.util.Iterator ; 27 import java.util.LinkedHashMap ; 28 import java.util.Map ; 29 30 31 38 public class ExecutionStatistics { 39 int statements; 40 Map <String , ElementInfo> elements = new LinkedHashMap <String , ElementInfo>(); 41 private Date started; 42 private Date finished; 43 private static final int MINUTE_MILLIS = 60 * 1000; 44 private static final int HOUR_MILLIS = 60 * MINUTE_MILLIS; 45 private static final int DAY_MILLIS = 24 * HOUR_MILLIS; 46 static final String DOUBLE_FORMAT_PTR = "0.##"; 47 48 49 52 public int getExecutedStatementsCount() { 53 return statements; 54 } 55 56 public Collection <ElementInfo> getElements() { 57 return elements.values(); 58 } 59 60 67 public Map <String , Integer > getCategoriesStatistics() { 68 Map <String , Integer > res = new HashMap <String , Integer >(); 69 for (String xpath : elements.keySet()) { 70 String elementName = getElementName(xpath); 71 Integer cnt = res.get(elementName); 72 if (cnt == null) { 73 cnt = 0; 74 } 75 res.put(elementName, ++cnt); } 77 return res; 78 } 79 80 public String toString() { 81 final Collection <ElementInfo> elements = getElements(); 82 if (elements.isEmpty()) { 83 return "No elements executed"; 84 } 85 StringBuilder sb = new StringBuilder (1024); 86 NumberFormat doubleFormat = new DecimalFormat (DOUBLE_FORMAT_PTR); 87 sb.append("Executed "); 88 89 Map <String , Integer > cats = getCategoriesStatistics(); 90 for (Iterator <Map.Entry <String , Integer >> it = cats.entrySet().iterator(); it.hasNext();) { 91 Map.Entry <String , Integer > category = it.next(); 92 appendPlural(sb, category.getValue(), category.getKey()); 93 if (it.hasNext()) { 94 sb.append(", "); 95 } 96 } 97 if (statements > 0) { 98 sb.append(", "); 99 appendPlural(sb, statements, "statement"); 100 } 101 102 sb.append('\n'); 103 104 for (ElementInfo ei : elements) { 105 sb.append(ei.id).append(":"); 106 107 if (ei.okCount > 0) { 108 sb.append(" Element successfully executed"); 109 if (ei.okCount > 1) { 110 sb.append(' '); 111 appendPlural(sb, ei.okCount, "time"); 112 } 113 if (ei.statements > 0) { 114 sb.append(" ("); 115 appendPlural(sb, ei.statements, "statement").append(')'); 116 } 117 sb.append('.'); 118 } 119 120 if (ei.failedCount > 0) { 121 sb.append(" Element failed "); 122 appendPlural(sb, ei.failedCount, "time"); 123 sb.append('.'); 124 } 125 sb.append(" Working time ").append(ei.workingTime / 1000000).append(" milliseconds."); 126 double throughput = ei.getThroughput(); 128 if (throughput >= 0) { 129 sb.append(" Avg throughput: ").append(doubleFormat.format(throughput)).append(" statements/sec."); 130 } 131 sb.append('\n'); 132 133 } 134 long totalTime = getTotalTime(); 135 if (totalTime >= 0) { 136 sb.append("Total working time:"); 137 appendTotalTimeDuration(totalTime, sb, doubleFormat); 138 } 139 return sb.toString(); 140 } 141 142 148 private static String getElementName(String xpath) { 149 int slash = xpath.lastIndexOf('/'); 150 int br = xpath.lastIndexOf('['); 151 return xpath.substring(slash + 1, br); 152 } 153 154 private static StringBuilder appendPlural(final StringBuilder sb, final long num, final String singularNoun) { 155 sb.append(num).append(' '); 156 if (num > 1) { if ("query".equals(singularNoun)) { sb.append("queries"); 159 } else { sb.append(singularNoun).append('s'); 161 } 162 } else { 163 sb.append(singularNoun); } 165 return sb; 166 } 167 168 177 static StringBuilder appendTotalTimeDuration(final long timeMillis, StringBuilder sb, Format doubleFormat) { 178 long time = timeMillis; 179 long days = time / DAY_MILLIS; 180 if (days > 0) { 181 time = time % DAY_MILLIS; 182 sb.append(' '); 183 appendPlural(sb, days, "day"); 184 } 185 long hours = time / HOUR_MILLIS; 186 if (hours > 0) { 187 time = time % HOUR_MILLIS; 188 sb.append(' '); 189 appendPlural(sb, hours, "hour"); 190 } 191 long minutes = time / MINUTE_MILLIS; 192 if (minutes > 0) { 193 time = time % MINUTE_MILLIS; 194 sb.append(' '); 195 appendPlural(sb, minutes, "minute"); 196 } 197 double seconds = time / 1000d; 198 if (seconds > 0) { 199 sb.append(' '); 200 sb.append(doubleFormat.format(seconds)).append(" second"); 201 if (seconds > 1) { sb.append('s'); 203 } 204 } 205 return sb; 206 } 207 208 213 public long getTotalTime() { 214 return finished != null && started != null ? finished.getTime() - started.getTime() : -1; 215 } 216 217 222 public Date getStartDate() { 223 return started == null ? null : (Date ) started.clone(); 224 } 225 226 void setStarted(Date started) { 227 this.started = started; 228 } 229 230 235 public Date getFinishDate() { 236 return finished == null ? null : (Date ) finished.clone(); 237 } 238 239 void setFinished(Date finished) { 240 this.finished = finished; 241 } 242 243 244 public static class ElementInfo { 245 int okCount; 246 Connection connection; 247 long statementsOnStart; 248 long statements; 249 int failedCount; 250 long started; 251 long workingTime; 252 String id; 253 254 public int getSuccessfulExecutionCount() { 255 return okCount; 256 } 257 258 public int getFailedExecutionCount() { 259 return failedCount; 260 } 261 262 269 public long getStatementsCount() { 270 return statements; 271 } 272 273 278 public long getWorkingTime() { 279 return workingTime; 280 } 281 282 288 public double getThroughput() { 289 return statements <= 0 || workingTime <= 0 ? -1 : 1000000000d * statements / workingTime; 290 } 291 292 public String getId() { 293 return id; 294 } 295 } 296 } 297 | Popular Tags |