1 11 12 package org.eclipse.osgi.internal.profile; 13 14 import java.io.*; 15 import java.util.*; 16 import org.eclipse.osgi.framework.debug.FrameworkDebugOptions; 17 import org.eclipse.osgi.framework.internal.core.FrameworkProperties; 18 19 public class DefaultProfileLogger implements ProfileLogger { 20 protected static final String DEFAULTPROFILE_PROP = "osgi.defaultprofile."; protected static final String PROP_FILENAME = DEFAULTPROFILE_PROP + "logfilename"; protected static final String PROP_LOGSYNCHRONOUSLY = DEFAULTPROFILE_PROP + "logsynchronously"; protected static final String PROP_BUFFERSIZE = DEFAULTPROFILE_PROP + "buffersize"; 25 protected static final String DEFAULTPROFILE_OPTION = "org.eclipse.osgi/defaultprofile/"; protected static final String OPTION_FILENAME = DEFAULTPROFILE_OPTION + "logfilename"; protected static final String OPTION_LOGSYNCHRONOUSLY = DEFAULTPROFILE_OPTION + "logsynchronously"; protected static final String OPTION_BUFFERSIZE = DEFAULTPROFILE_OPTION + "buffersize"; 30 protected boolean logSynchronously = false; 31 protected long startTime = 0; 32 protected static final int DEFAULT_BUFFER_SIZE = 256; 33 34 protected TimeEntry[] timeLogEntries = null; 35 protected int timeEntriesIndex = 0; 36 protected StringBuffer timelog = null; 37 38 protected long launchTime = -1; 39 protected int bufferSize = DEFAULT_BUFFER_SIZE; 40 protected String logFileName = null; 41 protected File logFile = null; 42 private StringBuffer entryReport = new StringBuffer (120); 43 private StringBuffer padsb = new StringBuffer (16); protected int indent; 45 protected int timePaddingLength; 46 protected Stack scopeStack; 47 protected Map scopeToAccumPerfDataMap; 48 49 public DefaultProfileLogger() { 50 initProps(); 51 52 int size = getBufferSize(); 53 timeLogEntries = new TimeEntry[size]; 54 timelog = new StringBuffer (4096); 55 for (int i = 0; i < size; i++) { 56 timeLogEntries[i] = timeEntryFactory(); 57 } 58 timeEntriesIndex = 0; 59 60 launchTime = getLaunchTime(); 61 if (launchTime == -1) { 62 startTime = getMainStartTime(); 63 } else { 64 startTime = launchTime; 65 } 66 67 long freq = getTimerFrequency(); 68 for (timePaddingLength = 3; freq > 9; timePaddingLength++) { 69 freq /= 10; 70 } 71 72 logInitMessages(); 73 } 74 75 protected void logInitMessages() { 76 int index = 0; 77 if (launchTime != -1L) { 78 logTime(Profile.FLAG_NONE, "DefaultProfileLogger.init()", "launch time initialized", null); timeLogEntries[index++].time = launchTime; 80 } 81 82 logTime(Profile.FLAG_NONE, "DefaultProfileLogger.init()", "start time initialized", null); timeLogEntries[index++].time = getMainStartTime(); 84 } 85 86 protected long getLaunchTime() { 87 String launchTimeString = FrameworkProperties.getProperty("launch.startMillis"); if (launchTimeString != null) { 89 return Long.parseLong(launchTimeString); 90 } 91 return -1L; 92 } 93 94 protected long getMainStartTime() { 95 String timeString = FrameworkProperties.getProperty("eclipse.startTime"); if (timeString != null) 97 return Long.parseLong(timeString); 98 99 return System.currentTimeMillis(); 100 } 101 102 public void initProps() { 103 String prop; 104 FrameworkDebugOptions dbgOptions = null; 105 if (FrameworkProperties.getProperty("osgi.debug") != null) { dbgOptions = FrameworkDebugOptions.getDefault(); 110 if (dbgOptions != null) { 111 logFileName = dbgOptions.getOption(OPTION_FILENAME); 112 logSynchronously = dbgOptions.getBooleanOption(OPTION_LOGSYNCHRONOUSLY, false); 113 int size = dbgOptions.getIntegerOption(OPTION_BUFFERSIZE, 0); 114 if (size > 0) 115 bufferSize = size; 116 } 117 } 118 119 if ((prop = FrameworkProperties.getProperty(PROP_FILENAME)) != null) { 120 logFileName = prop; 121 if (dbgOptions != null) 122 dbgOptions.setOption(OPTION_FILENAME, logFileName); 123 } 124 if ((prop = FrameworkProperties.getProperty(PROP_LOGSYNCHRONOUSLY)) != null) { 125 logSynchronously = Boolean.valueOf(prop).booleanValue(); 126 if (dbgOptions != null) 127 dbgOptions.setOption(OPTION_LOGSYNCHRONOUSLY, new Boolean (logSynchronously).toString()); 128 } 129 if ((prop = FrameworkProperties.getProperty(PROP_BUFFERSIZE)) != null) { 130 try { 131 int value = Integer.parseInt(prop); 132 if (value > 0) { 133 bufferSize = value; 134 if (dbgOptions != null) 135 dbgOptions.setOption(OPTION_BUFFERSIZE, Integer.toString(bufferSize)); 136 } 137 } catch (NumberFormatException e) { 138 } 140 } 141 } 142 143 public synchronized void logTime(int flag, String id, String msg, String description) { 144 if (timeEntriesIndex == timeLogEntries.length) { 145 makeLog(); 146 logTime(Profile.FLAG_NONE, "Profile.logTime()", "log entries rolled", null); } 148 149 TimeEntry entry = timeLogEntries[timeEntriesIndex++]; 150 entry.time = getTime(); 151 entry.id = id; 152 entry.msg = msg; 153 entry.flag = flag; 154 entry.description = description; 155 156 if (logSynchronously) { 157 System.out.print(getProfileLog().substring(2)); 158 } 159 } 160 161 public synchronized String getProfileLog() { 162 String log; 163 log = getProfileLogReport(); 164 writeToProfileLogFile(log); 165 return log; 166 } 167 168 public synchronized void accumLogEnter(String scope) { 169 if (scopeStack == null) 171 scopeStack = new Stack(); 172 if (scopeToAccumPerfDataMap == null) 173 scopeToAccumPerfDataMap = new TreeMap(); 174 175 scopeStack.push(new AccumPerfScope(scope, getTime())); 177 } 178 179 public synchronized void accumLogExit(String scope) { 180 long exit = getTime(); 182 183 if (scopeStack == null) 185 scopeStack = new Stack(); 186 if (scopeToAccumPerfDataMap == null) 187 scopeToAccumPerfDataMap = new TreeMap(); 188 189 AccumPerfScope then = (AccumPerfScope) scopeStack.pop(); 191 if (then == null) 192 System.err.println("ACCUM PERF ERROR: Scope stack empty: " + scope); else { 194 if (!then.scope.equals(scope)) 195 System.err.println("ACCUM PERF ERROR: Scope mismatch: then='" + then.scope + "', now='" + scope + "'"); 197 AccumPerfData now = (AccumPerfData) scopeToAccumPerfDataMap.get(scope); 198 if (now == null) { 199 now = new AccumPerfData(scope); 200 scopeToAccumPerfDataMap.put(scope, now); 201 } 202 203 now.time += exit - then.enter; 204 now.enters++; 205 } 206 } 207 208 protected long getTime() { 209 return System.currentTimeMillis(); 210 } 211 212 protected long getTimerFrequency() { 213 return 1000L; } 215 216 protected TimeEntry findCompareEntry(int index, String id, int flag) { 217 if (index > 0) 218 index--; 219 int prev = index; 220 if (flag != Profile.FLAG_ENTER) { 221 while (index >= 0) { 222 TimeEntry entry = timeLogEntries[index]; 223 if (entry.id.equals(id)) { 224 switch (flag) { 225 case Profile.FLAG_NONE : 226 return entry; 227 case Profile.FLAG_EXIT : 228 if (entry.flag == Profile.FLAG_ENTER) 229 return entry; 230 break; 231 } 232 } 233 index--; 234 } 235 } 236 return timeLogEntries[prev]; 237 } 238 239 protected String entryReport(TimeEntry entry, TimeEntry compareWith) { 240 entryReport.setLength(0); 242 if (entry.flag == Profile.FLAG_ENTER) 243 indent++; 244 long zeroTime = getRelativeTime(getStartTime()); 245 246 entryReport.append('-'); 247 long entryTime = getRelativeTime(entry.time); 248 long diff = entryTime - zeroTime; 249 entryReport.append(pad(Long.toString(diff), timePaddingLength)); 250 entryReport.append(" :"); diff = entry.time - compareWith.time; 252 entryReport.append(pad(Long.toString(diff), timePaddingLength)); 253 entryReport.append(pad("", indent * 2)); 255 if (entry.flag == Profile.FLAG_ENTER) 256 entryReport.append(" >> "); else if (entry.flag == Profile.FLAG_EXIT) 258 entryReport.append(" << "); else if (entry.flag == Profile.FLAG_NONE) 260 entryReport.append(" -- "); 262 entryReport.append(entry.id); 263 entryReport.append(" > "); entryReport.append(entry.msg); 265 if (entry.description != null) { 266 entryReport.append(" :: "); entryReport.append(entry.description); 268 } 269 entryReport.append("\r\n"); 271 if (entry.flag == Profile.FLAG_EXIT) 272 indent -= 1; 273 return entryReport.toString(); 274 } 275 276 protected String accumEntryReport(AccumPerfData d) { 277 return (" " + d.scope + ":enters=" + d.enters + ";time=" + d.time + ";\r\n"); } 279 280 protected void makeLog() { 281 indent = 0; 282 timelog.append("\r\n"); for (int i = 0; i < timeEntriesIndex; i++) { 284 TimeEntry entry = timeLogEntries[i]; 285 TimeEntry cmpEntry = findCompareEntry(i, entry.id, entry.flag); 286 timelog.append(entryReport(entry, cmpEntry)); 287 } 288 timeEntriesIndex = 0; 289 290 if (scopeToAccumPerfDataMap == null || scopeToAccumPerfDataMap.isEmpty()) 291 return; timelog.append("\r\n"); timelog.append("Cumulative Log:\r\n"); Iterator iter = scopeToAccumPerfDataMap.values().iterator(); 295 while (iter.hasNext()) { 296 AccumPerfData d = (AccumPerfData) iter.next(); 297 timelog.append(accumEntryReport(d)); 298 } 299 scopeToAccumPerfDataMap.clear(); 300 } 301 302 protected String pad(String str, int size) { 303 padsb.setLength(0); 304 int len = str.length(); 305 int count = size - len; 306 for (int i = 0; i < count; i++) 307 padsb.append(' '); 308 padsb.append(str); 309 return padsb.toString(); 310 } 311 312 protected String getProfileLogReport() { 313 if (timelog == null) 314 return ""; makeLog(); 316 String log = timelog.toString(); 317 timelog.setLength(0); 318 return log; 319 } 320 321 protected void writeToProfileLogFile(String log) { 322 File profileLog = getProfileLogFile(); 323 if (profileLog == null) 324 return; 325 FileWriter fw = null; 326 try { 327 fw = new FileWriter(profileLog.getAbsolutePath(), true); 328 fw.write(log); 329 } catch (IOException e) { 330 e.printStackTrace(); 331 } finally { 332 if (fw != null) 333 try { 334 fw.close(); 335 } catch (IOException e) { 336 } 338 } 339 } 340 341 protected File getProfileLogFile() { 342 if (logFile == null) 343 if ((logFileName != null) && (logFileName.length() > 0)) 344 logFile = new File(logFileName); 345 return logFile; 346 } 347 348 protected long getStartTime() { 349 return startTime; 350 } 351 352 protected long getRelativeTime(long absoluteTime) { 353 return absoluteTime; 354 } 355 356 protected int getBufferSize() { 357 if (bufferSize < 2) 358 return DEFAULT_BUFFER_SIZE; 359 return bufferSize; 360 } 361 362 protected TimeEntry timeEntryFactory() { 363 return new TimeEntry(); 364 } 365 366 protected class TimeEntry { 367 public long time; 368 public String id; 369 public String msg; 370 public String description; 371 public int flag; 372 } 373 374 protected static class AccumPerfData { 375 public AccumPerfData(String scope) { 376 this.scope = scope; 377 } 378 379 public String scope; 380 public long time; 381 public long enters; 382 } 383 384 protected static class AccumPerfScope { 385 public AccumPerfScope(String scope, long enter) { 386 this.scope = scope; 387 this.enter = enter; 388 } 389 390 public String scope; 391 public long enter; 392 } 393 } 394 | Popular Tags |