Issue #924 fix some concurrency issues for GridResource

Former-commit-id: 78491d6318 [formerly e18782687c] [formerly de742a4b8c [formerly 312361f3bacf9ed935ee7cd69be90192af34b3fd]]
Former-commit-id: de742a4b8c
Former-commit-id: 3e9abe8682
This commit is contained in:
Ben Steffensmeier 2012-07-25 17:32:51 -05:00
parent a307242aea
commit bcea00c92b

View file

@ -23,7 +23,6 @@ import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
@ -196,6 +195,14 @@ public class GridResource extends
private StyleRule styleRule; private StyleRule styleRule;
/**
* The great protector of all things related to dataTimes, do not modify or
* iterate over pdosToParse, dataTimes, or tileSet unless you sync on this
* or else...
*
*/
protected Object timeLock = new Object();
/** /**
* Extends the MemoryBasedTileSet class so that we can have direct access to * Extends the MemoryBasedTileSet class so that we can have direct access to
* the loadedData * the loadedData
@ -575,12 +582,14 @@ public class GridResource extends
GribRecord[] records = resourceData.getRecords(); GribRecord[] records = resourceData.getRecords();
GribRecord emptyRecord = new GribRecord(); GribRecord emptyRecord = new GribRecord();
for (int i = 0; i < records.length; i++) { synchronized (timeLock) {
if (emptyRecord.equals(records[i])) { for (int i = 0; i < records.length; i++) {
// Don't add empty records if (emptyRecord.equals(records[i])) {
continue; // Don't add empty records
continue;
}
pdosToParse.add(records[i]);
} }
pdosToParse.add(records[i]);
} }
if (resourceData.getNameGenerator() == null) { if (resourceData.getNameGenerator() == null) {
@ -650,14 +659,16 @@ public class GridResource extends
mbts = createTileSet(record, lvlSet, levelConverter); mbts = createTileSet(record, lvlSet, levelConverter);
mbts.setMapDescriptor(descriptor); mbts.setMapDescriptor(descriptor);
Set<DataTime> dateSet = tileSet.keySet(); synchronized (timeLock) {
dataTimes.clear(); Set<DataTime> dateSet = tileSet.keySet();
Iterator<DataTime> dateIterator = dateSet.iterator(); dataTimes.clear();
while (dateIterator.hasNext()) { Iterator<DataTime> dateIterator = dateSet.iterator();
dataTimes.add(dateIterator.next()); while (dateIterator.hasNext()) {
} dataTimes.add(dateIterator.next());
}
Collections.sort(dataTimes); Collections.sort(dataTimes);
}
levels = new SingleLevel[lvlSet.size()]; levels = new SingleLevel[lvlSet.size()];
Iterator<SingleLevel> lvlIterator = lvlSet.iterator(); Iterator<SingleLevel> lvlIterator = lvlSet.iterator();
@ -675,12 +686,14 @@ public class GridResource extends
Set<SingleLevel> lvlSet, UnitConverter levelConverter) Set<SingleLevel> lvlSet, UnitConverter levelConverter)
throws VizException { throws VizException {
DataTime dataTime = record.getDataTime(); DataTime dataTime = record.getDataTime();
Map<Float, GridMemoryBasedTileSet> tilemap = tileSet.get(dataTime); Map<Float, GridMemoryBasedTileSet> tilemap = null;
if (tilemap == null) { synchronized (timeLock) {
tilemap = new HashMap<Float, GridMemoryBasedTileSet>(); tilemap = tileSet.get(dataTime);
tileSet.put(dataTime, tilemap); if (tilemap == null) {
tilemap = new HashMap<Float, GridMemoryBasedTileSet>();
tileSet.put(dataTime, tilemap);
}
} }
float convertedLevel = (float) levelConverter.convert(record float convertedLevel = (float) levelConverter.convert(record
.getModelInfo().getLevelOneValue()); .getModelInfo().getLevelOneValue());
@ -766,116 +779,109 @@ public class GridResource extends
*/ */
@Override @Override
protected void disposeInternal() { protected void disposeInternal() {
synchronized (timeLock) {
for (Map.Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> set : tileSet for (Map.Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> set : tileSet
.entrySet()) {
for (Map.Entry<Float, GridMemoryBasedTileSet> tile : set.getValue()
.entrySet()) { .entrySet()) {
tile.getValue().dispose(); for (Map.Entry<Float, GridMemoryBasedTileSet> tile : set
.getValue().entrySet()) {
tile.getValue().dispose();
}
} }
} }
} }
@Override @Override
protected void initInternal(IGraphicsTarget target) throws VizException { protected void initInternal(IGraphicsTarget target) throws VizException {
this.target = target; synchronized (timeLock) {
this.target = target;
synchronized (pdosToParse) {
if (pdosToParse.size() > 0) { if (pdosToParse.size() > 0) {
for (PluginDataObject pdo : pdosToParse) { for (PluginDataObject pdo : pdosToParse) {
createTile(pdo); createTile(pdo);
} }
pdosToParse.clear(); pdosToParse.clear();
} }
}
boolean combineResources = combineOperation != CombineOperation.NONE; boolean combineResources = combineOperation != CombineOperation.NONE;
viewType = target.getViewType(); viewType = target.getViewType();
Map<DataTime, Map<Float, GridMemoryBasedTileSet>> combinedSet = new HashMap<DataTime, Map<Float, GridMemoryBasedTileSet>>(); Map<DataTime, Map<Float, GridMemoryBasedTileSet>> combinedSet = new HashMap<DataTime, Map<Float, GridMemoryBasedTileSet>>();
for (Map.Entry<Integer, GridMemoryBasedTileSet> baseTileEntry : baseTiles for (Map.Entry<Integer, GridMemoryBasedTileSet> baseTileEntry : baseTiles
.entrySet()) { .entrySet()) {
GridMemoryBasedTileSet baseTile = baseTileEntry.getValue(); GridMemoryBasedTileSet baseTile = baseTileEntry.getValue();
baseTile.setMapDescriptor(descriptor); baseTile.setMapDescriptor(descriptor);
baseTile.init(target); baseTile.init(target);
if (combineResources && !baseTile.isCombined()) { if (combineResources && !baseTile.isCombined()) {
Entry<Float, GridMemoryBasedTileSet> tileSetRef = null; Entry<Float, GridMemoryBasedTileSet> tileSetRef = null;
// Need to find the reference in order to update the object when // Need to find the reference in order to update the object
// it comes back as a new combined object // when
for (Map.Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> set : tileSet // it comes back as a new combined object
.entrySet()) { for (Map.Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> set : tileSet
for (Map.Entry<Float, GridMemoryBasedTileSet> tile : set .entrySet()) {
.getValue().entrySet()) { for (Map.Entry<Float, GridMemoryBasedTileSet> tile : set
if (tile.getValue().getDataTime() .getValue().entrySet()) {
.equals(baseTile.getDataTime())) { if (tile.getValue().getDataTime()
tileSetRef = tile; .equals(baseTile.getDataTime())) {
tileSetRef = tile;
break;
}
}
if (tileSetRef != null) {
break; break;
} }
} }
GridMemoryBasedTileSet combinedResourceData = combineResourceData(baseTile);
if (tileSetRef != null) { if (tileSetRef != null) {
break; tileSetRef.setValue(combinedResourceData);
} }
}
GridMemoryBasedTileSet combinedResourceData = combineResourceData(baseTile); baseTileEntry.setValue(combinedResourceData);
if (tileSetRef != null) {
tileSetRef.setValue(combinedResourceData);
} }
baseTileEntry.setValue(combinedResourceData);
} }
} DataTime[] primaryDataTimes = descriptor.getTimeMatchingMap().get(
DataTime[] primaryDataTimes = descriptor.getTimeMatchingMap().get(this); this);
for (int i = 0; i < primaryDataTimes.length; i++) { for (int i = 0; i < primaryDataTimes.length; i++) {
Map<Float, GridMemoryBasedTileSet> map = tileSet Map<Float, GridMemoryBasedTileSet> map = tileSet
.get(primaryDataTimes[i]); .get(primaryDataTimes[i]);
if (map != null) { if (map != null) {
for (Map.Entry<Float, GridMemoryBasedTileSet> tile : map for (Map.Entry<Float, GridMemoryBasedTileSet> tile : map
.entrySet()) { .entrySet()) {
if (baseTiles.values().contains(tile.getValue())) { if (baseTiles.values().contains(tile.getValue())) {
if (combineResources) { if (combineResources) {
Map<Float, GridMemoryBasedTileSet> map2 = new HashMap<Float, GridResource.GridMemoryBasedTileSet>();
map2.put(tile.getKey(), tile.getValue());
combinedSet.put(primaryDataTimes[i], map2);
}
continue;
}
tile.getValue().init(target);
if (!tile.getValue().isCombined()) {
GridMemoryBasedTileSet combinedResourceData = combineResourceData(tile
.getValue());
Map<Float, GridMemoryBasedTileSet> map2 = new HashMap<Float, GridResource.GridMemoryBasedTileSet>(); Map<Float, GridMemoryBasedTileSet> map2 = new HashMap<Float, GridResource.GridMemoryBasedTileSet>();
map2.put(tile.getKey(), tile.getValue()); map2.put(tile.getKey(), combinedResourceData);
combinedSet.put(primaryDataTimes[i], map2); combinedSet.put(primaryDataTimes[i], map2);
} }
continue;
}
tile.getValue().init(target);
if (!tile.getValue().isCombined()) {
GridMemoryBasedTileSet combinedResourceData = combineResourceData(tile
.getValue());
Map<Float, GridMemoryBasedTileSet> map2 = new HashMap<Float, GridResource.GridMemoryBasedTileSet>();
map2.put(tile.getKey(), combinedResourceData);
combinedSet.put(primaryDataTimes[i], map2);
} }
} }
} }
} if (!combinedSet.isEmpty()) {
if (!combinedSet.isEmpty()) { tileSet = combinedSet;
tileSet = combinedSet; List<DataTime> newDataTimes = new ArrayList<DataTime>();
List<DataTime> newDataTimes = new ArrayList<DataTime>();
for (Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> entry : combinedSet for (Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> entry : combinedSet
.entrySet()) { .entrySet()) {
newDataTimes.add(entry.getKey()); newDataTimes.add(entry.getKey());
}
Collections.sort(newDataTimes);
dataTimes = newDataTimes;
} }
Collections.sort(newDataTimes, dataTime);
dataTimes = newDataTimes;
} }
} }
/**
* DataTime Comparator
*/
private static Comparator<DataTime> dataTime = new Comparator<DataTime>() {
@Override
public int compare(DataTime arg0, DataTime arg1) {
return arg0.compareTo(arg1);
}
};
/** /**
* Combine the given tiles sets * Combine the given tiles sets
* *
@ -1217,11 +1223,13 @@ public class GridResource extends
@Override @Override
public void setDescriptor(MapDescriptor descriptor) { public void setDescriptor(MapDescriptor descriptor) {
this.descriptor = descriptor; this.descriptor = descriptor;
for (Map.Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> set : tileSet synchronized (timeLock) {
.entrySet()) { for (Map.Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> set : tileSet
for (Map.Entry<Float, GridMemoryBasedTileSet> tile : set.getValue()
.entrySet()) { .entrySet()) {
tile.getValue().setMapDescriptor(this.descriptor); for (Map.Entry<Float, GridMemoryBasedTileSet> tile : set
.getValue().entrySet()) {
tile.getValue().setMapDescriptor(this.descriptor);
}
} }
} }
} }
@ -1238,22 +1246,24 @@ public class GridResource extends
} }
} }
if (reproject) { if (reproject) {
// If we are reprojecting to screen space, clear all tiles synchronized (timeLock) {
for (Map.Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> set : tileSet // If we are reprojecting to screen space, clear all tiles
.entrySet()) { for (Map.Entry<DataTime, Map<Float, GridMemoryBasedTileSet>> set : tileSet
for (Map.Entry<Float, GridMemoryBasedTileSet> tile : set .entrySet()) {
.getValue().entrySet()) { for (Map.Entry<Float, GridMemoryBasedTileSet> tile : set
tile.getValue().dispose(); .getValue().entrySet()) {
pdosToParse.add(tile.getValue().getPluginDataObject()); tile.getValue().dispose();
pdosToParse.add(tile.getValue().getPluginDataObject());
}
} }
} tileSet.clear();
tileSet.clear(); baseTiles.clear();
baseTiles.clear(); if (pdosToParse.size() > 0) {
if (pdosToParse.size() > 0) { for (PluginDataObject pdo : pdosToParse) {
for (PluginDataObject pdo : pdosToParse) { createTile(pdo);
createTile(pdo); }
pdosToParse.clear();
} }
pdosToParse.clear();
} }
} else { } else {
for (GridMemoryBasedTileSet tile : baseTiles.values()) { for (GridMemoryBasedTileSet tile : baseTiles.values()) {
@ -1453,41 +1463,44 @@ public class GridResource extends
@Override @Override
public void remove(DataTime dataTime) { public void remove(DataTime dataTime) {
Map<Float, GridMemoryBasedTileSet> ts = tileSet.remove(dataTime); synchronized (timeLock) {
if (ts == null) { Map<Float, GridMemoryBasedTileSet> ts = tileSet.remove(dataTime);
return; if (ts == null) {
} return;
}
for (Map.Entry<Float, GridMemoryBasedTileSet> tile : ts.entrySet()) { for (Map.Entry<Float, GridMemoryBasedTileSet> tile : ts.entrySet()) {
tile.getValue().dispose(); tile.getValue().dispose();
} }
Set<DataTime> dateSet = tileSet.keySet(); Set<DataTime> dateSet = tileSet.keySet();
dataTimes.clear(); dataTimes.clear();
Iterator<DataTime> dateIterator = dateSet.iterator(); Iterator<DataTime> dateIterator = dateSet.iterator();
while (dateIterator.hasNext()) { while (dateIterator.hasNext()) {
dataTimes.add(dateIterator.next()); dataTimes.add(dateIterator.next());
} }
Collections.sort(dataTimes);
Collections.sort(dataTimes);
}
} }
@Override @Override
public void resourceChanged(ChangeType type, Object object) { public void resourceChanged(ChangeType type, Object object) {
if (type.equals(ChangeType.DATA_UPDATE)) { if (type.equals(ChangeType.DATA_UPDATE)) {
PluginDataObject[] pdos = (PluginDataObject[]) object; PluginDataObject[] pdos = (PluginDataObject[]) object;
synchronized (timeLock) {
for (PluginDataObject pdo : pdos) {
for (PluginDataObject pdo : pdos) { if (pdo != null) {
if (CombineOperation.DIFFERENCE
if (pdo != null) { .equals(combineOperation)
if (CombineOperation.DIFFERENCE.equals(combineOperation) && !(pdo instanceof CombinedGribRecord)) {
&& !(pdo instanceof CombinedGribRecord)) { // Do nothing, timematcher will take care of it.
// Do nothing, timematcher will take care of it.
} else {
if (target != null) {
createTile(pdo);
} else { } else {
pdosToParse.add(pdo); if (target != null) {
createTile(pdo);
} else {
pdosToParse.add(pdo);
}
} }
} }
} }