Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

new command: watch, used to automatically follow changes to variables…

…/fields while debugging
  • Loading branch information...
commit a33ecb28c72d076641229d0c6067bd1658092f5a 1 parent f67ecca
@lmcalpin authored
View
62 sidrat-core/src/main/java/com/sidrat/SidratReplay.java
@@ -5,14 +5,18 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
+import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
import com.sidrat.event.SidratExecutionEvent;
import com.sidrat.event.store.EventReader;
import com.sidrat.event.store.hsqldb.HsqldbEventReader;
+import com.sidrat.event.tracking.ExecutionLocation;
import com.sidrat.event.tracking.TrackedObject;
import com.sidrat.util.Logger;
import com.sidrat.util.Tuple3;
@@ -30,6 +34,8 @@
private boolean continueProcessing = true;
private SidratExecutionEvent event;
private List<String> breakpoints = Lists.newArrayList();
+ private Multimap<ExecutionLocation, String> variableWatches = ArrayListMultimap.create();
+ private Multimap<String, String> fieldWatches = ArrayListMultimap.create();
private List<String> invalidSourceFiles = Lists.newArrayList();
@@ -149,6 +155,28 @@ public boolean execute() {
print(localVariables);
}
break;
+ case "h":
+ // TODO
+ break;
+ case "w": // watch
+ case "watch":
+ {
+ if (parsedLine.length != 2) {
+ out.println("Variable is required.");
+ } else {
+ String variable = parsedLine[1];
+ Map<String, TrackedObject> instanceVariables = eval(this.event.getExecutionContext().getObject());
+ Map<String, TrackedObject> localVariables = locals();
+ if (instanceVariables.get(variable) != null) {
+ fieldWatches.put(this.event.getExecutionContext().getClassName(), variable);
+ } else if (localVariables != null) {
+ variableWatches.put(this.event.getExecutionContext(), variable);
+ } else {
+ out.println("Variable " + variable + " not found");
+ }
+ }
+ }
+ break;
case "q":
case "quit":
continueProcessing = false;
@@ -167,11 +195,15 @@ public boolean execute() {
private void print(Map<String, TrackedObject> vars) {
for (String key : vars.keySet()) {
TrackedObject value = vars.get(key);
- if (value == null) {
- out.println(key + " = null");
- } else {
- out.println(key + ":" + value.getClassName() + " = " + value.getValue());
- }
+ print(key, value);
+ }
+ }
+
+ private void print(String key, TrackedObject value) {
+ if (value == null) {
+ out.println(key + " = null");
+ } else {
+ out.println(key + ":" + value.getClassName() + " = " + value.getValue());
}
}
@@ -235,6 +267,24 @@ public void print(SidratExecutionEvent event) {
String sourceCode = lookupSourceCode(event);
if (sourceCode != null)
out.println(sourceCode);
+ // if we are watching variables, print their current values
+ if (fieldWatches.size() > 0 || variableWatches.size() > 0) {
+ out.println("-- watched variables:");
+ }
+ if (fieldWatches.size() > 0) {
+ Collection<String> variables = fieldWatches.get(this.event.getExecutionContext().getClassName());
+ Map<String, TrackedObject> instanceVariables = eval(this.event.getExecutionContext().getObject());
+ for (String variable : variables) {
+ print(variable, instanceVariables.get(variable));
+ }
+ }
+ if (variableWatches.size() > 0) {
+ Collection<String> variables = variableWatches.get(this.event.getExecutionContext());
+ Map<String, TrackedObject> localVariables = locals();
+ for (String variable : variables) {
+ print(variable, localVariables.get(variable));
+ }
+ }
}
public Tuple3<String, String, Integer> split(String breakpoint) {
@@ -251,7 +301,7 @@ public void print(SidratExecutionEvent event) {
@SuppressWarnings("unchecked")
public String lookupSourceCode(SidratExecutionEvent event) {
- if (sourceDir == null)
+ if (sourceDir == null)
return null;
String rootPath = sourceDir.getAbsolutePath();
if (rootPath.endsWith("/")) {
View
11 sidrat-core/src/main/java/com/sidrat/event/store/EventReader.java
@@ -5,6 +5,7 @@
import com.sidrat.event.SidratExecutionEvent;
import com.sidrat.event.tracking.TrackedObject;
+import com.sidrat.util.Pair;
public interface EventReader {
/**
@@ -41,4 +42,14 @@
* @return a list of SidratEvents where we execute the line of code described by 'loc'
*/
public List<SidratExecutionEvent> executions(String className, String methodName, int lineNumber);
+
+ /**
+ * @return history of assignments to a specified field
+ */
+ public List<Pair<Long,TrackedObject>> fieldHistory(Long fieldID);
+
+ /**
+ * @return history of assignments to a specified local variable
+ */
+ public List<Pair<Long,TrackedObject>> localVariableHistory(Long localVariableID);
}
View
15 sidrat-core/src/main/java/com/sidrat/event/store/hsqldb/HsqldbEventReader.java
@@ -3,6 +3,7 @@
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -18,6 +19,7 @@
import com.sidrat.replay.SystemState;
import com.sidrat.util.Jdbc;
import com.sidrat.util.JdbcConnectionProvider;
+import com.sidrat.util.Pair;
public class HsqldbEventReader implements EventReader, JdbcConnectionProvider {
private String connString;
@@ -118,6 +120,19 @@ public SidratExecutionEvent findPrev(SidratExecutionEvent lastEvent) {
return values;
}
+ // TODO: unfinished!
+ @Override
+ public List<Pair<Long,TrackedObject>> fieldHistory(Long fieldID) {
+ List<Map<String, Object>> updates = jdbcHelper.find("SELECT fu.*, o.clazz FROM field_updates fu LEFT JOIN objects o ON fu.ref = o.id WHERE fu.field_id = ? ORDER BY event_id DESC", fieldID);
+ return new ArrayList();
+ }
+
+ // TODO: unfinished!
+ @Override
+ public List<Pair<Long,TrackedObject>> localVariableHistory(Long localVariableID) {
+ return new ArrayList();
+ }
+
public List<SidratExecutionEvent> executions(String className, String method, int lineNumber) {
List<Map<String, Object>> rows = jdbcHelper.find(EVENTS_QUERY + "WHERE clazz=? AND method=? AND lineNumber=?", className, method, lineNumber);
List<SidratExecutionEvent> events = Lists.newArrayList();
View
43 sidrat-core/src/main/java/com/sidrat/event/tracking/ExecutionLocation.java
@@ -1,7 +1,11 @@
package com.sidrat.event.tracking;
+import java.io.Serializable;
-public class ExecutionLocation {
+
+public class ExecutionLocation implements Serializable {
+ private static final long serialVersionUID = 6558516445801512512L;
+
private final TrackedObject object;
private final String className, methodName;
@@ -22,4 +26,41 @@ public String getClassName() {
public String getMethodName() {
return methodName;
}
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((className == null) ? 0 : className.hashCode());
+ result = prime * result + ((methodName == null) ? 0 : methodName.hashCode());
+ result = prime * result + ((object == null) ? 0 : object.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ ExecutionLocation other = (ExecutionLocation) obj;
+ if (className == null) {
+ if (other.className != null)
+ return false;
+ } else if (!className.equals(other.className))
+ return false;
+ if (methodName == null) {
+ if (other.methodName != null)
+ return false;
+ } else if (!methodName.equals(other.methodName))
+ return false;
+ if (object == null) {
+ if (other.object != null)
+ return false;
+ } else if (!object.equals(other.object))
+ return false;
+ return true;
+ }
}
View
44 sidrat-core/src/main/java/com/sidrat/event/tracking/TrackedObject.java
@@ -1,8 +1,12 @@
package com.sidrat.event.tracking;
+import java.io.Serializable;
+
import com.sidrat.SidratProcessingException;
-public class TrackedObject {
+public class TrackedObject implements Serializable {
+ private static final long serialVersionUID = -6154638687577620218L;
+
private String className;
private String value;
private Long uniqueID;
@@ -38,5 +42,41 @@ public String toString() {
}
throw new SidratProcessingException("TrackedObject corrupt: " + uniqueID);
}
-
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((className == null) ? 0 : className.hashCode());
+ result = prime * result + ((uniqueID == null) ? 0 : uniqueID.hashCode());
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ TrackedObject other = (TrackedObject) obj;
+ if (className == null) {
+ if (other.className != null)
+ return false;
+ } else if (!className.equals(other.className))
+ return false;
+ if (uniqueID == null) {
+ if (other.uniqueID != null)
+ return false;
+ } else if (!uniqueID.equals(other.uniqueID))
+ return false;
+ if (value == null) {
+ if (other.value != null)
+ return false;
+ } else if (!value.equals(other.value))
+ return false;
+ return true;
+ }
}
View
3  sidrat-core/src/main/java/com/sidrat/event/tracking/TrackedVariable.java
@@ -1,8 +1,5 @@
package com.sidrat.event.tracking;
-import bytecodeparser.analysis.LocalVariable;
-import javassist.CtBehavior;
-
import com.sidrat.util.Pair;
public class TrackedVariable {
Please sign in to comment.
Something went wrong with that request. Please try again.