Merge "Issue #1096 fix memory leaks in CcfpResource" into development

Former-commit-id: 94b7f40d1d [formerly 94b7f40d1d [formerly 0f98c3bfbf041cd46311517f2819ca2d81b1cd34]]
Former-commit-id: 168bee4bd7
Former-commit-id: a2f594e354
This commit is contained in:
Nate Jensen 2012-08-27 09:21:50 -05:00 committed by Gerrit Code Review
commit 22b6406fe4
2 changed files with 105 additions and 43 deletions

View file

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@ -63,6 +64,7 @@ import com.vividsolutions.jts.geom.Point;
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Sep 22, 2009 3072 bsteffen Initial creation
* Aug 23, 2012 1096 njensen Fixed memory leaks
*
* </pre>
*
@ -161,8 +163,10 @@ public class CcfpResource extends
}
private void disposeFrames() {
for (DisplayFrame frame : frames.values()) {
frame.dispose();
synchronized (frames) {
for (DisplayFrame frame : frames.values()) {
frame.dispose();
}
}
}
@ -180,11 +184,15 @@ public class CcfpResource extends
@Override
public String inspect(ReferencedCoordinate coord) throws VizException {
if (frames.get(this.displayedDataTime) == null) {
DisplayFrame frame = null;
synchronized (frames) {
frame = frames.get(this.displayedDataTime);
}
if (frame == null) {
return "";
}
StringBuilder res = new StringBuilder();
for (CcfpRecord record : frames.get(this.displayedDataTime).records) {
for (CcfpRecord record : frame.records) {
// Check if we have an area we are rendering
if (isPaintingArea(record)) {
try {
@ -216,15 +224,20 @@ public class CcfpResource extends
*/
private void updateRecords(IGraphicsTarget target,
PaintProperties paintProps) throws VizException {
DisplayFrame frame = frames.get(this.displayedDataTime);
if (frame == null) {
frame = new DisplayFrame();
frames.put(this.displayedDataTime, frame);
DisplayFrame frame = null;
synchronized (frames) {
frame = frames.get(this.displayedDataTime);
if (frame == null) {
frame = new DisplayFrame();
frames.put(this.displayedDataTime, frame);
}
}
// Add all the new Records
Collection<CcfpRecord> newRecords = unprocessedRecords
.get(this.displayedDataTime);
Collection<CcfpRecord> newRecords = null;
synchronized (unprocessedRecords) {
newRecords = unprocessedRecords.get(this.displayedDataTime);
}
for (CcfpRecord record : newRecords) {
// If we need to draw anything for this record then keep it
if (isPaintingArea(record) || isPaintingMovement(record)
@ -259,14 +272,19 @@ public class CcfpResource extends
this.displayedDataTime = paintProps.getDataTime();
// First check to see if we need to process new data
Collection<CcfpRecord> unprocessed = unprocessedRecords
.get(this.displayedDataTime);
Collection<CcfpRecord> unprocessed = null;
synchronized (unprocessedRecords) {
unprocessed = unprocessedRecords.get(this.displayedDataTime);
}
if (unprocessed != null && unprocessed.size() > 0) {
updateRecords(target, paintProps);
}
// Hopefully we now have some data to display, if not bail
DisplayFrame frame = frames.get(this.displayedDataTime);
DisplayFrame frame = null;
synchronized (frames) {
frame = frames.get(this.displayedDataTime);
}
if (frame == null) {
this.displayedDataTime = null;
return;
@ -509,14 +527,24 @@ public class CcfpResource extends
*/
protected void addRecord(CcfpRecord obj) {
DataTime dataTime = obj.getDataTime();
Collection<CcfpRecord> records = unprocessedRecords.get(dataTime);
if (records == null) {
records = new ArrayList<CcfpRecord>();
unprocessedRecords.put(dataTime, records);
this.dataTimes.add(dataTime);
Collections.sort(this.dataTimes);
if (resourceData.durationMatches(dataTime)) {
Collection<CcfpRecord> records = null;
boolean brandNew = false;
synchronized (unprocessedRecords) {
records = unprocessedRecords.get(dataTime);
if (records == null) {
records = new HashSet<CcfpRecord>();
unprocessedRecords.put(dataTime, records);
brandNew = true;
}
}
if (brandNew) {
this.dataTimes.add(dataTime);
Collections.sort(this.dataTimes);
}
records.add(obj);
}
records.add(obj);
}
@Override
@ -677,16 +705,40 @@ public class CcfpResource extends
@Override
public void project(CoordinateReferenceSystem crs) throws VizException {
disposeFrames();
// add as unprocessed to make sure frames created
for (DataTime time : frames.keySet()) {
DisplayFrame frame = frames.get(time);
if (frame != null) {
List<CcfpRecord> copyList = new ArrayList<CcfpRecord>(
frame.records);
unprocessedRecords.put(time, copyList);
synchronized (frames) {
disposeFrames();
// add as unprocessed to make sure frames created
for (DataTime time : frames.keySet()) {
DisplayFrame frame = frames.get(time);
if (frame != null) {
List<CcfpRecord> copyList = new ArrayList<CcfpRecord>(
frame.records);
synchronized (unprocessedRecords) {
unprocessedRecords.put(time, copyList);
}
}
}
}
}
@Override
public void remove(DataTime time) {
super.remove(time);
Collection<CcfpRecord> notNeeded = null;
synchronized (unprocessedRecords) {
notNeeded = unprocessedRecords.remove(time);
}
if (notNeeded != null) {
notNeeded.clear();
}
DisplayFrame frame = null;
synchronized (frames) {
frame = frames.remove(time);
}
if (frame != null) {
frame.dispose();
}
}
}

View file

@ -31,12 +31,10 @@ import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.ccfp.Activator;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.status.StatusConstants;
/**
*
@ -56,8 +54,9 @@ import com.raytheon.uf.viz.core.status.StatusConstants;
*/
@XmlAccessorType(XmlAccessType.NONE)
public class CcfpResourceData extends AbstractRequestableResourceData {
private static final transient IUFStatusHandler statusHandler = UFStatus.getHandler(CcfpResourceData.class);
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(CcfpResourceData.class);
// This flag determnies if we draw lines and polygons
@XmlAttribute
private boolean displayArea = true;
@ -69,35 +68,34 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
// This flag determines if we display text boxes
@XmlAttribute
private boolean displayText = true;
// Filter by coverage
@XmlAttribute
private int coverageFilter = 0;
@XmlAttribute
private int validDuration = 0;
@Override
public boolean equals(Object obj) {
if (!super.equals(obj)) {
return false;
}
if (obj instanceof CcfpResourceData == false) {
return false;
}
CcfpResourceData other = (CcfpResourceData) obj;
if (other.coverageFilter != this.coverageFilter) {
return false;
}
if (other.validDuration != this.validDuration) {
return false;
}
if (other.displayText != this.displayText) {
return false;
}
@ -109,7 +107,7 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
if (other.displayMovement != this.displayMovement) {
return false;
}
return true;
}
@ -122,7 +120,7 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
DataTime[] originalTimes = super.getAvailableTimes();
ArrayList<DataTime> newTimes = new ArrayList<DataTime>();
for (DataTime time : originalTimes) {
if (time.getValidPeriod().getDuration() == validDuration * 1000) {
if (durationMatches(time)) {
newTimes.add(time);
}
}
@ -147,6 +145,18 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
return nr;
}
/**
* Checks if a DataTime's valid period matches the duration of the resource
* data
*
* @param time
* the time to check
* @return true if the durations are equal, otherwise false
*/
protected boolean durationMatches(DataTime time) {
return time.getValidPeriod().getDuration() == validDuration * 1000;
}
public boolean isDisplayArea() {
return displayArea;
}
@ -185,6 +195,6 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
public void setValidDuration(int validDuration) {
this.validDuration = validDuration;
}
}
}