Issue #1096 fix memory leaks in CcfpResource

Change-Id: Icccd4d3811327b9a1dcfdf6a5a2cc714ff92afbc

Former-commit-id: 7439c24618 [formerly 7b62f6ac75] [formerly 73f428e4d5] [formerly 047441f91c [formerly 73f428e4d5 [formerly 5e9d7763442ab91cb8d33c16139eb5bca9b033ea]]]
Former-commit-id: 047441f91c
Former-commit-id: 801d77ec89944e6f04cdd301015c751823cf9554 [formerly 347c13143b]
Former-commit-id: 0cc8e95b0c
This commit is contained in:
Nate Jensen 2012-08-23 18:18:23 -05:00
parent b33e97efd3
commit 132cc792f4
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.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -63,6 +64,7 @@ import com.vividsolutions.jts.geom.Point;
* Date Ticket# Engineer Description * Date Ticket# Engineer Description
* ------------ ---------- ----------- -------------------------- * ------------ ---------- ----------- --------------------------
* Sep 22, 2009 3072 bsteffen Initial creation * Sep 22, 2009 3072 bsteffen Initial creation
* Aug 23, 2012 1096 njensen Fixed memory leaks
* *
* </pre> * </pre>
* *
@ -161,10 +163,12 @@ public class CcfpResource extends
} }
private void disposeFrames() { private void disposeFrames() {
synchronized (frames) {
for (DisplayFrame frame : frames.values()) { for (DisplayFrame frame : frames.values()) {
frame.dispose(); frame.dispose();
} }
} }
}
@Override @Override
public DataTime[] getDataTimes() { public DataTime[] getDataTimes() {
@ -180,11 +184,15 @@ public class CcfpResource extends
@Override @Override
public String inspect(ReferencedCoordinate coord) throws VizException { 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 ""; return "";
} }
StringBuilder res = new StringBuilder(); 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 // Check if we have an area we are rendering
if (isPaintingArea(record)) { if (isPaintingArea(record)) {
try { try {
@ -216,15 +224,20 @@ public class CcfpResource extends
*/ */
private void updateRecords(IGraphicsTarget target, private void updateRecords(IGraphicsTarget target,
PaintProperties paintProps) throws VizException { PaintProperties paintProps) throws VizException {
DisplayFrame frame = frames.get(this.displayedDataTime); DisplayFrame frame = null;
synchronized (frames) {
frame = frames.get(this.displayedDataTime);
if (frame == null) { if (frame == null) {
frame = new DisplayFrame(); frame = new DisplayFrame();
frames.put(this.displayedDataTime, frame); frames.put(this.displayedDataTime, frame);
} }
}
// Add all the new Records // Add all the new Records
Collection<CcfpRecord> newRecords = unprocessedRecords Collection<CcfpRecord> newRecords = null;
.get(this.displayedDataTime); synchronized (unprocessedRecords) {
newRecords = unprocessedRecords.get(this.displayedDataTime);
}
for (CcfpRecord record : newRecords) { for (CcfpRecord record : newRecords) {
// If we need to draw anything for this record then keep it // If we need to draw anything for this record then keep it
if (isPaintingArea(record) || isPaintingMovement(record) if (isPaintingArea(record) || isPaintingMovement(record)
@ -259,14 +272,19 @@ public class CcfpResource extends
this.displayedDataTime = paintProps.getDataTime(); this.displayedDataTime = paintProps.getDataTime();
// First check to see if we need to process new data // First check to see if we need to process new data
Collection<CcfpRecord> unprocessed = unprocessedRecords Collection<CcfpRecord> unprocessed = null;
.get(this.displayedDataTime); synchronized (unprocessedRecords) {
unprocessed = unprocessedRecords.get(this.displayedDataTime);
}
if (unprocessed != null && unprocessed.size() > 0) { if (unprocessed != null && unprocessed.size() > 0) {
updateRecords(target, paintProps); updateRecords(target, paintProps);
} }
// Hopefully we now have some data to display, if not bail // 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) { if (frame == null) {
this.displayedDataTime = null; this.displayedDataTime = null;
return; return;
@ -509,15 +527,25 @@ public class CcfpResource extends
*/ */
protected void addRecord(CcfpRecord obj) { protected void addRecord(CcfpRecord obj) {
DataTime dataTime = obj.getDataTime(); DataTime dataTime = obj.getDataTime();
Collection<CcfpRecord> records = unprocessedRecords.get(dataTime); if (resourceData.durationMatches(dataTime)) {
Collection<CcfpRecord> records = null;
boolean brandNew = false;
synchronized (unprocessedRecords) {
records = unprocessedRecords.get(dataTime);
if (records == null) { if (records == null) {
records = new ArrayList<CcfpRecord>(); records = new HashSet<CcfpRecord>();
unprocessedRecords.put(dataTime, records); unprocessedRecords.put(dataTime, records);
brandNew = true;
}
}
if (brandNew) {
this.dataTimes.add(dataTime); this.dataTimes.add(dataTime);
Collections.sort(this.dataTimes); Collections.sort(this.dataTimes);
} }
records.add(obj); records.add(obj);
} }
}
@Override @Override
public String getName() { public String getName() {
@ -677,6 +705,7 @@ public class CcfpResource extends
@Override @Override
public void project(CoordinateReferenceSystem crs) throws VizException { public void project(CoordinateReferenceSystem crs) throws VizException {
synchronized (frames) {
disposeFrames(); disposeFrames();
// add as unprocessed to make sure frames created // add as unprocessed to make sure frames created
for (DataTime time : frames.keySet()) { for (DataTime time : frames.keySet()) {
@ -684,9 +713,32 @@ public class CcfpResource extends
if (frame != null) { if (frame != null) {
List<CcfpRecord> copyList = new ArrayList<CcfpRecord>( List<CcfpRecord> copyList = new ArrayList<CcfpRecord>(
frame.records); frame.records);
synchronized (unprocessedRecords) {
unprocessedRecords.put(time, copyList); 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;
import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.DataTime; 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.exception.VizException;
import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData; import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource; import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties; import com.raytheon.uf.viz.core.rsc.LoadProperties;
import com.raytheon.uf.viz.core.status.StatusConstants;
/** /**
* *
@ -56,7 +54,8 @@ import com.raytheon.uf.viz.core.status.StatusConstants;
*/ */
@XmlAccessorType(XmlAccessType.NONE) @XmlAccessorType(XmlAccessType.NONE)
public class CcfpResourceData extends AbstractRequestableResourceData { 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 // This flag determnies if we draw lines and polygons
@XmlAttribute @XmlAttribute
@ -74,7 +73,6 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
@XmlAttribute @XmlAttribute
private int coverageFilter = 0; private int coverageFilter = 0;
@XmlAttribute @XmlAttribute
private int validDuration = 0; private int validDuration = 0;
@ -122,7 +120,7 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
DataTime[] originalTimes = super.getAvailableTimes(); DataTime[] originalTimes = super.getAvailableTimes();
ArrayList<DataTime> newTimes = new ArrayList<DataTime>(); ArrayList<DataTime> newTimes = new ArrayList<DataTime>();
for (DataTime time : originalTimes) { for (DataTime time : originalTimes) {
if (time.getValidPeriod().getDuration() == validDuration * 1000) { if (durationMatches(time)) {
newTimes.add(time); newTimes.add(time);
} }
} }
@ -147,6 +145,18 @@ public class CcfpResourceData extends AbstractRequestableResourceData {
return nr; 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() { public boolean isDisplayArea() {
return displayArea; return displayArea;
} }