return and cache event stripes at the DB layer

This commit is contained in:
jmillman 2015-11-12 15:37:39 -05:00
parent aed99b647f
commit b82d0a2e9c
9 changed files with 98 additions and 75 deletions

View File

@ -83,6 +83,22 @@ public final class EventStripe implements EventBundle<EventCluster> {
*/
private final Set<Long> hashHits = new HashSet<>();
public EventStripe withParent(EventCluster parent) {
EventStripe eventStripe = new EventStripe(parent, this.type, this.description, this.lod);
eventStripe.clusters.addAll(clusters);
eventStripe.eventIDs.addAll(eventIDs);
eventStripe.tagged.addAll(tagged);
eventStripe.hashHits.addAll(hashHits);
return eventStripe;
}
private EventStripe(EventCluster parent, EventType type, String description, DescriptionLoD lod) {
this.parent = parent;
this.type = type;
this.description = description;
this.lod = lod;
}
public EventStripe(EventCluster cluster, EventCluster parent) {
clusters.add(cluster);
@ -158,4 +174,5 @@ public final class EventStripe implements EventBundle<EventCluster> {
public SortedSet< EventCluster> getClusters() {
return Collections.unmodifiableSortedSet(clusters);
}
}

View File

@ -327,7 +327,7 @@ public final class FilteredEventsModel {
* @return a list of event clusters at the requested zoom levels that are
* within the requested time range and pass the requested filter
*/
public List<EventCluster> getEventClusters() {
public List<EventStripe> getEventClusters() {
final Interval range;
final RootFilter filter;
final EventTypeZoomLevel zoom;
@ -348,7 +348,7 @@ public final class FilteredEventsModel {
* range and pass the requested filter, using the given aggregation
* to control the grouping of events
*/
public List<EventCluster> getEventClusters(ZoomParams params) {
public List<EventStripe> getEventClusters(ZoomParams params) {
return repo.getEventClusters(params);
}

View File

@ -48,6 +48,7 @@ import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.joda.time.DateTimeZone;
import org.joda.time.Interval;
import org.joda.time.Period;
@ -55,6 +56,7 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.datamodel.EventCluster;
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.BaseTypes;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
@ -1062,7 +1064,7 @@ public class EventDB {
* the supplied filter, aggregated according to the given event type
* and description zoom levels
*/
List<EventCluster> getClusteredEvents(ZoomParams params) {
List<EventStripe> getClusteredEvents(ZoomParams params) {
//unpack params
Interval timeRange = params.getTimeRange();
RootFilter filter = params.getFilter();
@ -1105,7 +1107,6 @@ public class EventDB {
try (Statement createStatement = con.createStatement();
ResultSet rs = createStatement.executeQuery(query)) {
while (rs.next()) {
events.add(eventClusterHelper(rs, useSubTypes, descriptionLOD, filter.getTagsFilter()));
}
} catch (SQLException ex) {
@ -1114,7 +1115,17 @@ public class EventDB {
DBLock.unlock();
}
return mergeEventClusters(rangeInfo.getPeriodSize().getPeriod(), events);
List<EventCluster> mergeEventClusters = mergeEventClusters(rangeInfo.getPeriodSize().getPeriod(), events);
//merge clusters to stripes
Map<ImmutablePair<EventType, String>, EventStripe> stripeDescMap = new HashMap<>();
for (EventCluster eventCluster : mergeEventClusters) {
stripeDescMap.merge(ImmutablePair.of(eventCluster.getEventType(), eventCluster.getDescription()),
new EventStripe(eventCluster, null), EventStripe::merge);
}
return stripeDescMap.values().stream().sorted(Comparator.comparing(EventStripe::getStartMillis)).collect(Collectors.toList());
}
/**

View File

@ -53,10 +53,8 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.timeline.CancellationProgressTask;
import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.datamodel.EventCluster;
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
import org.sleuthkit.autopsy.timeline.datamodel.TimeLineEvent;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.ArtifactEventType;
@ -106,7 +104,7 @@ public class EventsRepository {
private final LoadingCache<Object, Long> minCache;
private final LoadingCache<Long, TimeLineEvent> idToEventCache;
private final LoadingCache<ZoomParams, Map<EventType, Long>> eventCountsCache;
private final LoadingCache<ZoomParams, List<EventCluster>> eventClusterCache;
private final LoadingCache<ZoomParams, List<EventStripe>> eventClusterCache;
private final ObservableMap<Long, String> datasourcesMap = FXCollections.observableHashMap();
private final ObservableMap<Long, String> hashSetMap = FXCollections.observableHashMap();
@ -213,7 +211,7 @@ public class EventsRepository {
}
synchronized public List<EventCluster> getEventClusters(ZoomParams params) {
synchronized public List<EventStripe> getEventClusters(ZoomParams params) {
return eventClusterCache.getUnchecked(params);
}

View File

@ -252,7 +252,7 @@ public abstract class AbstractVisualizationPane<X, Y, N, C extends XYChart<X, Y>
}
});
update();
// update();
}
@Subscribe

View File

@ -66,7 +66,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.timeline.FXMLConstructor;
import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.datamodel.EventBundle;
import org.sleuthkit.autopsy.timeline.datamodel.EventCluster;
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
import org.sleuthkit.autopsy.timeline.ui.AbstractVisualizationPane;
@ -85,7 +85,7 @@ import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
* EventTypeMap, and dataSets is all linked directly to the ClusterChart which
* must only be manipulated on the JavaFx thread.
*/
public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventCluster, EventBundleNodeBase<?, ?, ?>, EventDetailsChart> {
public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventStripe, EventBundleNodeBase<?, ?, ?>, EventDetailsChart> {
private final static Logger LOGGER = Logger.getLogger(DetailViewPane.class.getName());
@ -93,7 +93,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
private static final double PAGE_SCROLL_PERCENTAGE = .70;
private final DateAxis dateAxis = new DateAxis();
private final Axis<EventCluster> verticalAxis = new EventAxis();
private final Axis<EventStripe> verticalAxis = new EventAxis();
private final ScrollBar vertScrollBar = new ScrollBar();
private final Region scrollBarSpacer = new Region();
@ -101,7 +101,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
private final ObservableList<EventBundleNodeBase<?, ?, ?>> highlightedNodes = FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
//private access to barchart data
private final Map<EventType, XYChart.Series<DateTime, EventCluster>> eventTypeToSeriesMap = new ConcurrentHashMap<>();
private final Map<EventType, XYChart.Series<DateTime, EventStripe>> eventTypeToSeriesMap = new ConcurrentHashMap<>();
public ObservableList<EventBundle<?>> getEventBundles() {
return chart.getEventBundles();
@ -224,7 +224,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
}
@Override
protected Axis<EventCluster> getYAxis() {
protected Axis<EventStripe> getYAxis() {
return verticalAxis;
}
@ -253,9 +253,9 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
* EventType
*/
// @ThreadConfined(type = ThreadConfined.ThreadType.JFX)
private XYChart.Series<DateTime, EventCluster> getSeries(final EventType et) {
private XYChart.Series<DateTime, EventStripe> getSeries(final EventType et) {
return eventTypeToSeriesMap.computeIfAbsent(et, (EventType t) -> {
XYChart.Series<DateTime, EventCluster> series = new XYChart.Series<>();
XYChart.Series<DateTime, EventStripe> series = new XYChart.Series<>();
series.setName(et.getDisplayName());
// Platform.runLater(() -> {
dataSeries.add(series);
@ -310,7 +310,7 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
}
});
List<EventCluster> eventClusters = filteredEvents.getEventClusters();
List<EventStripe> eventClusters = filteredEvents.getEventClusters();
final int size = eventClusters.size();
updateMessage(NbBundle.getMessage(this.getClass(), "DetailViewPane.loggedTask.updateUI"));
@ -318,9 +318,9 @@ public class DetailViewPane extends AbstractVisualizationPane<DateTime, EventClu
if (isCancelled()) {
break;
}
final EventCluster cluster = eventClusters.get(i);
final EventStripe cluster = eventClusters.get(i);
updateProgress(i, size);
final XYChart.Data<DateTime, EventCluster> xyData = new BarChart.Data<>(new DateTime(cluster.getStartMillis()), cluster);
final XYChart.Data<DateTime, EventStripe> xyData = new BarChart.Data<>(new DateTime(cluster.getStartMillis()), cluster);
// Platform.runLater(() -> {
getSeries(cluster.getEventType()).getData().add(xyData);

View File

@ -22,21 +22,21 @@ import java.util.Collections;
import java.util.List;
import javafx.scene.chart.Axis;
import javafx.scene.chart.XYChart;
import org.sleuthkit.autopsy.timeline.datamodel.EventCluster;
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
/**
* No-Op axis that doesn't do anything usefull but is necessary to pass
* AggregateEvent as the second member of {@link XYChart.Data} objects
*/
class EventAxis extends Axis<EventCluster> {
class EventAxis extends Axis<EventStripe> {
@Override
public double getDisplayPosition(EventCluster value) {
public double getDisplayPosition(EventStripe value) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public EventCluster getValueForDisplay(double displayPosition) {
public EventStripe getValueForDisplay(double displayPosition) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@ -46,17 +46,17 @@ class EventAxis extends Axis<EventCluster> {
}
@Override
public boolean isValueOnAxis(EventCluster value) {
public boolean isValueOnAxis(EventStripe value) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public double toNumericValue(EventCluster value) {
public double toNumericValue(EventStripe value) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public EventCluster toRealValue(double value) {
public EventStripe toRealValue(double value) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@ -66,7 +66,7 @@ class EventAxis extends Axis<EventCluster> {
}
@Override
protected List<EventCluster> calculateTickValues(double length, Object range) {
protected List<EventStripe> calculateTickValues(double length, Object range) {
return Collections.emptyList();
}
@ -76,7 +76,7 @@ class EventAxis extends Axis<EventCluster> {
}
@Override
protected String getTickMarkLabel(EventCluster value) {
protected String getTickMarkLabel(EventStripe value) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

View File

@ -169,7 +169,7 @@ final public class EventClusterNode extends EventBundleNodeBase<EventCluster, Ev
@Override
protected Collection<EventStripe> call() throws Exception {
Collection<EventStripe> bundles;
Collection<EventStripe> bundles = null;
DescriptionLoD next = loadedDescriptionLoD;
do {
loadedDescriptionLoD = next;
@ -177,8 +177,8 @@ final public class EventClusterNode extends EventBundleNodeBase<EventCluster, Ev
return Collections.emptySet();
}
bundles = eventsModel.getEventClusters(zoomParams.withDescrLOD(loadedDescriptionLoD)).stream()
.collect(Collectors.toMap(EventCluster::getDescription, //key
(eventCluster) -> new EventStripe(eventCluster, getEventCluster()), //value
.collect(Collectors.toMap(EventStripe::getDescription, //key
eventStripe -> eventStripe.withParent(getEventCluster()), //value
EventStripe::merge) //merge method
).values();
next = loadedDescriptionLoD.withRelativeDetail(relativeDetail);

View File

@ -59,7 +59,6 @@ import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.shape.Line;
import javafx.scene.shape.StrokeLineCap;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.controlsfx.control.action.Action;
import org.controlsfx.control.action.ActionUtils;
import org.joda.time.DateTime;
@ -71,7 +70,6 @@ import org.sleuthkit.autopsy.timeline.datamodel.EventBundle;
import org.sleuthkit.autopsy.timeline.datamodel.EventCluster;
import org.sleuthkit.autopsy.timeline.datamodel.EventStripe;
import org.sleuthkit.autopsy.timeline.datamodel.FilteredEventsModel;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
import org.sleuthkit.autopsy.timeline.filters.AbstractFilter;
import org.sleuthkit.autopsy.timeline.filters.DescriptionFilter;
import org.sleuthkit.autopsy.timeline.ui.AbstractVisualizationPane;
@ -93,7 +91,7 @@ import org.sleuthkit.autopsy.timeline.zooming.DescriptionLoD;
*
* //TODO: refactor the projected lines to a separate class. -jm
*/
public final class EventDetailsChart extends XYChart<DateTime, EventCluster> implements TimeLineChart<DateTime> {
public final class EventDetailsChart extends XYChart<DateTime, EventStripe> implements TimeLineChart<DateTime> {
private static final String styleSheet = GuideLine.class.getResource("EventsDetailsChart.css").toExternalForm();
private static final Image HIDE = new Image("/org/sleuthkit/autopsy/timeline/images/eye--minus.png"); // NON-NLS
@ -145,7 +143,7 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
*/
private final Group nodeGroup = new Group();
private final ObservableList<EventBundle<?>> bundles = FXCollections.observableArrayList();
private final Map<ImmutablePair<EventType, String>, EventStripe> stripeDescMap = new ConcurrentHashMap<>();
// private final Map<ImmutablePair<EventType, String>, EventStripe> stripeDescMap = new ConcurrentHashMap<>();
private final Map<EventStripe, EventStripeNode> stripeNodeMap = new ConcurrentHashMap<>();
private final Map<EventCluster, Line> projectionMap = new ConcurrentHashMap<>();
@ -181,7 +179,7 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
*/
final SimpleDoubleProperty truncateWidth = new SimpleDoubleProperty(200.0);
EventDetailsChart(TimeLineController controller, DateAxis dateAxis, final Axis<EventCluster> verticalAxis, ObservableList<EventBundleNodeBase<?, ?, ?>> selectedNodes) {
EventDetailsChart(TimeLineController controller, DateAxis dateAxis, final Axis<EventStripe> verticalAxis, ObservableList<EventBundleNodeBase<?, ?, ?>> selectedNodes) {
super(dateAxis, verticalAxis);
this.controller = controller;
@ -321,55 +319,56 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
}
@Override
protected synchronized void dataItemAdded(Series<DateTime, EventCluster> series, int i, Data<DateTime, EventCluster> data) {
final EventCluster eventCluster = data.getYValue();
EventStripe eventStripe = stripeDescMap.merge(ImmutablePair.of(eventCluster.getEventType(), eventCluster.getDescription()),
new EventStripe(eventCluster, null),
(EventStripe u, EventStripe v) -> {
EventStripeNode removeU = stripeNodeMap.remove(u);
EventStripeNode removeV = stripeNodeMap.remove(v);
Platform.runLater(() -> {
nodeGroup.getChildren().remove(removeU);
nodeGroup.getChildren().remove(removeV);
});
return EventStripe.merge(u, v);
}
);
protected synchronized void dataItemAdded(Series<DateTime, EventStripe> series, int i, Data<DateTime, EventStripe> data) {
final EventStripe eventStripe = data.getYValue();
//
// EventStripe eventStripe = stripeDescMap.put(ImmutablePair.of(eventCluster.getEventType(), eventCluster.getDescription()), eventCluster);
//// new EventStripe(eventCluster, null),
//// (EventStripe u, EventStripe v) -> {
//// EventStripeNode removeU = stripeNodeMap.remove(u);
//// EventStripeNode removeV = stripeNodeMap.remove(v);
//// Platform.runLater(() -> {
//// nodeGroup.getChildren().remove(removeU);
//// nodeGroup.getChildren().remove(removeV);
//// });
//// return EventStripe.merge(u, v);
//// }
//// );
EventStripeNode stripeNode = new EventStripeNode(EventDetailsChart.this, eventStripe, null);
stripeNodeMap.put(eventStripe, stripeNode);
Platform.runLater(() -> {
bundles.add(eventCluster);
bundles.add(eventStripe);
nodeGroup.getChildren().add(stripeNode);
data.setNode(stripeNode);
});
}
@Override
protected void dataItemChanged(Data<DateTime, EventCluster> data) {
protected void dataItemChanged(Data<DateTime, EventStripe> data) {
//TODO: can we use this to help with local detail level adjustment -jm
throw new UnsupportedOperationException("Not supported yet."); // NON-NLS //To change body of generated methods, choose Tools | Templates.
}
@Override
protected void dataItemRemoved(Data<DateTime, EventCluster> data, Series<DateTime, EventCluster> series) {
EventCluster eventCluster = data.getYValue();
Platform.runLater(() -> {
bundles.removeAll(eventCluster);
});
protected synchronized void dataItemRemoved(Data<DateTime, EventStripe> data, Series<DateTime, EventStripe> series) {
EventStripe removedStripe = data.getYValue();
// Platform.runLater(() -> {
// bundles.removeAll(removedStripe);
// });
EventStripe removedStripe = stripeDescMap.remove(ImmutablePair.of(eventCluster.getEventType(), eventCluster.getDescription()));
if (removedStripe != null) {
EventStripeNode removedNode = stripeNodeMap.remove(removedStripe);
Platform.runLater(() -> {
nodeGroup.getChildren().remove(removedNode);
data.setNode(null);
});
}
// EventStripe removedStripe = stripeDescMap.remove(ImmutablePair.of(eventCluster.getEventType(), eventCluster.getDescription()));
// if (removedStripe != null) {
EventStripeNode removedNode = stripeNodeMap.remove(removedStripe);
Platform.runLater(() -> {
bundles.removeAll(removedStripe);
nodeGroup.getChildren().remove(removedNode);
data.setNode(null);
});
// }
}
@Override
protected void layoutPlotChildren() {
protected synchronized void layoutPlotChildren() {
setCursor(Cursor.WAIT);
maxY.set(0);
if (bandByType.get()) {
@ -393,16 +392,16 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
}
@Override
protected void seriesAdded(Series<DateTime, EventCluster> series, int i) {
protected void seriesAdded(Series<DateTime, EventStripe> series, int i) {
for (int j = 0; j < series.getData().size(); j++) {
dataItemAdded(series, j, series.getData().get(j));
}
}
@Override
protected void seriesRemoved(Series<DateTime, EventCluster> series) {
for (int j = 0; j < series.getData().size(); j++) {
dataItemRemoved(series.getData().get(j), series);
protected void seriesRemoved(Series<DateTime, EventStripe> series) {
for (Data<DateTime, EventStripe> data : series.getData()) {
dataItemRemoved(data, series);
}
}
@ -413,7 +412,7 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
/**
* @return all the nodes that pass the given predicate
*/
Iterable<EventBundleNodeBase<?, ?, ?>> getNodes(Predicate<EventBundleNodeBase<?, ?, ?>> p) {
synchronized Iterable<EventBundleNodeBase<?, ?, ?>> getNodes(Predicate<EventBundleNodeBase<?, ?, ?>> p) {
//use this recursive function to flatten the tree of nodes into an iterable.
Function<EventBundleNodeBase<?, ?, ?>, Stream<EventBundleNodeBase<?, ?, ?>>> stripeFlattener =
new Function<EventBundleNodeBase<?, ?, ?>, Stream<EventBundleNodeBase<?, ?, ?>>>() {
@ -535,8 +534,6 @@ public final class EventDetailsChart extends XYChart<DateTime, EventCluster> imp
return localMax; //return new max
}
private void bundleLayoutHelper(final EventBundleNodeBase<?, ?, ?> bundleNode) {
//make sure it is shown
bundleNode.setVisible(true);