Omaha #4695: GFE formatter launcher loads combinations files off UI thread.

Change-Id: Idbad6704ecb184e72c6b1aac43ea1a67bf0f0d61

Former-commit-id: ff984b39a128690a211802678b4815995f742565
This commit is contained in:
David Gillingham 2015-10-06 16:52:56 -05:00
parent 820bc1450d
commit a7da1f6724
2 changed files with 68 additions and 41 deletions

View file

@ -28,6 +28,12 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.IPreferenceStore;
@ -57,7 +63,6 @@ import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.TransformException; import org.opengis.referencing.operation.TransformException;
import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GridLocation;
import com.raytheon.uf.common.dataplugin.gfe.exception.GfeException;
import com.raytheon.uf.common.dataplugin.gfe.server.notify.CombinationsFileChangedNotification; import com.raytheon.uf.common.dataplugin.gfe.server.notify.CombinationsFileChangedNotification;
import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext; import com.raytheon.uf.common.localization.LocalizationContext;
@ -106,6 +111,7 @@ import com.raytheon.viz.gfe.ui.zoneselector.ZoneSelector;
* Changed to use CombinationsFileChangedNotification instead of * Changed to use CombinationsFileChangedNotification instead of
* FileUpdatedMessage so we can ignore our own changes * FileUpdatedMessage so we can ignore our own changes
* Moved retrieval of combinations file to CombinationsFileUtil.init * Moved retrieval of combinations file to CombinationsFileUtil.init
* Oct 07, 2015 #4695 dgilling Move loading of combinations file off UI thread.
* *
* </pre> * </pre>
* *
@ -233,6 +239,8 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
private AbstractGFENotificationObserver<CombinationsFileChangedNotification> comboChangeListener; private AbstractGFENotificationObserver<CombinationsFileChangedNotification> comboChangeListener;
private final ExecutorService asyncExecutor;
private void initPreferences() { private void initPreferences() {
IPreferenceStore prefs = Activator.getDefault().getPreferenceStore(); IPreferenceStore prefs = Activator.getDefault().getPreferenceStore();
@ -276,6 +284,8 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
mapRequired = false; mapRequired = false;
} }
this.asyncExecutor = Executors.newCachedThreadPool();
initPreferences(); initPreferences();
init(); init();
@ -303,6 +313,7 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
ZoneCombinerComp.this.dataManager.getNotificationRouter() ZoneCombinerComp.this.dataManager.getNotificationRouter()
.removeObserver( .removeObserver(
ZoneCombinerComp.this.comboChangeListener); ZoneCombinerComp.this.comboChangeListener);
ZoneCombinerComp.this.asyncExecutor.shutdown();
} }
}); });
@ -954,23 +965,41 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
zoneSelector.updateCombos(comboDict); zoneSelector.updateCombos(comboDict);
} }
public Map<String, Integer> loadCombinationsFile(String comboName) { private Map<String, Integer> loadCombinationsFile(final String comboName) {
Map<String, Integer> dict = new HashMap<String, Integer>(); List<List<String>> combolist = Collections.emptyList();
try { try {
List<List<String>> combolist = CombinationsFileUtil.init(comboName); Callable<List<List<String>>> loadTask = new Callable<List<List<String>>>() {
// reformat combinations into combo dictionary @Override
int group = 1; public List<List<String>> call() throws Exception {
for (List<String> zonelist : combolist) { return CombinationsFileUtil.init(comboName);
for (String z : zonelist) {
dict.put(z, group);
} }
group += 1; };
Future<List<List<String>>> taskResult = asyncExecutor
.submit(loadTask);
combolist = taskResult.get();
} catch (ExecutionException e) {
statusHandler.handle(Priority.SIGNIFICANT,
"Could not load combinations file " + comboName, e);
return Collections.emptyMap();
} catch (InterruptedException | RejectedExecutionException e) {
/*
* We should only ever fall into this block if the Composite is
* disposing and the ExecutorService has been shutdown. Probably not
* worth logging.
*/
return Collections.emptyMap();
}
Map<String, Integer> dict = new HashMap<String, Integer>();
// reformat combinations into combo dictionary
int group = 1;
for (List<String> zonelist : combolist) {
for (String z : zonelist) {
dict.put(z, group);
} }
} catch (GfeException e) { group += 1;
statusHandler.handle(Priority.SIGNIFICANT, e.getLocalizedMessage(),
e);
return new HashMap<String, Integer>();
} }
currentComboFile = comboName; currentComboFile = comboName;

View file

@ -21,6 +21,7 @@ package com.raytheon.viz.gfe.textformatter;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -44,6 +45,7 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.SaveableOutputStream;
import com.raytheon.uf.common.localization.exception.LocalizationException; import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException; import com.raytheon.uf.common.localization.exception.LocalizationOpFailedException;
import com.raytheon.uf.common.python.PyUtil; import com.raytheon.uf.common.python.PyUtil;
@ -73,8 +75,9 @@ import com.raytheon.viz.gfe.textformatter.CombinationsFileUtil.ComboData.Entry;
* Feb 05, 2014 #2591 randerso Forced retrieval of combinations file * Feb 05, 2014 #2591 randerso Forced retrieval of combinations file
* Implemented retry on error * Implemented retry on error
* Aug 27, 2014 #3561 randerso Yet another attempt to fix combinations file updating * Aug 27, 2014 #3561 randerso Yet another attempt to fix combinations file updating
* Sep 08, 2104 #3592 randerso Changed to use only list site level files as all * Sep 08, 2014 #3592 randerso Changed to use only list site level files as all
* combo files are saved to the site level * combo files are saved to the site level
* Oct 07, 2015 #4695 dgilling Code cleanup to remove compile warnings.
* *
* </pre> * </pre>
* *
@ -166,12 +169,13 @@ public class CombinationsFileUtil {
} }
public static void saveComboData(String id, Map<String, Integer> combos) public static void saveComboData(String id, Map<String, Integer> combos)
throws LocalizationException, SerializationException { throws LocalizationException, SerializationException, IOException {
LocalizationFile lf = idToFile(id); LocalizationFile lf = idToFile(id);
File file = lf.getFile(false); try (SaveableOutputStream out = lf.openOutputStream()) {
ComboData comboData = new ComboData(combos); ComboData comboData = new ComboData(combos);
jaxb.marshalToXmlFile(comboData, file.getPath()); jaxb.marshalToStream(comboData, out);
lf.save(); out.save();
}
} }
public static void deleteComboData(String id) public static void deleteComboData(String id)
@ -205,18 +209,19 @@ public class CombinationsFileUtil {
} }
public static Map<String, Integer> loadComboData(String id) public static Map<String, Integer> loadComboData(String id)
throws SerializationException { throws SerializationException, IOException, LocalizationException {
LocalizationFile lf = idToFile(id); LocalizationFile lf = idToFile(id);
File file = lf.getFile(); try (InputStream in = lf.openInputStream()) {
ComboData comboData = jaxb.unmarshalFromXmlFile(file); ComboData comboData = (ComboData) jaxb.unmarshalFromInputStream(in);
Map<String, Integer> comboDict = new HashMap<String, Integer>( Map<String, Integer> comboDict = new HashMap<String, Integer>(
comboData.combos.size()); comboData.combos.size());
for (Entry entry : comboData.combos) { for (Entry entry : comboData.combos) {
comboDict.put(entry.zone, entry.group); comboDict.put(entry.zone, entry.group);
}
return comboDict;
} }
return comboDict;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -262,15 +267,12 @@ public class CombinationsFileUtil {
List<List<String>> combos = null; List<List<String>> combos = null;
HashMap<String, Object> map = new HashMap<String, Object>(); HashMap<String, Object> map = new HashMap<String, Object>();
map.put("comboName", comboName); map.put("comboName", comboName);
PythonScript python = null;
for (int retryCount = 0; retryCount < MAX_TRIES; retryCount++) { for (int retryCount = 0; retryCount < MAX_TRIES; retryCount++) {
try { try (PythonScript python = new PythonScript(scriptPath,
python = new PythonScript(scriptPath, PyUtil.buildJepIncludePath(
PyUtil.buildJepIncludePath( GfePyIncludeUtil.getCombinationsIncludePath(),
GfePyIncludeUtil.getCombinationsIncludePath(), GfePyIncludeUtil.getCommonPythonIncludePath()),
GfePyIncludeUtil.getCommonPythonIncludePath()), CombinationsFileUtil.class.getClassLoader())) {
CombinationsFileUtil.class.getClassLoader());
Object com = python.execute("getCombinations", map); Object com = python.execute("getCombinations", map);
combos = (List<List<String>>) com; combos = (List<List<String>>) com;
@ -292,10 +294,6 @@ public class CombinationsFileUtil {
throw new GfeException("Error loading combinations file: " throw new GfeException("Error loading combinations file: "
+ comboName, e); + comboName, e);
} }
} finally {
if (python != null) {
python.dispose();
}
} }
} }
return combos; return combos;