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.List;
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 org.eclipse.jface.preference.IPreferenceStore;
@ -57,7 +63,6 @@ import org.opengis.referencing.FactoryException;
import org.opengis.referencing.operation.TransformException;
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.localization.IPathManager;
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
* FileUpdatedMessage so we can ignore our own changes
* Moved retrieval of combinations file to CombinationsFileUtil.init
* Oct 07, 2015 #4695 dgilling Move loading of combinations file off UI thread.
*
* </pre>
*
@ -233,6 +239,8 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
private AbstractGFENotificationObserver<CombinationsFileChangedNotification> comboChangeListener;
private final ExecutorService asyncExecutor;
private void initPreferences() {
IPreferenceStore prefs = Activator.getDefault().getPreferenceStore();
@ -276,6 +284,8 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
mapRequired = false;
}
this.asyncExecutor = Executors.newCachedThreadPool();
initPreferences();
init();
@ -303,6 +313,7 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
ZoneCombinerComp.this.dataManager.getNotificationRouter()
.removeObserver(
ZoneCombinerComp.this.comboChangeListener);
ZoneCombinerComp.this.asyncExecutor.shutdown();
}
});
@ -954,23 +965,41 @@ public class ZoneCombinerComp extends Composite implements IZoneCombiner {
zoneSelector.updateCombos(comboDict);
}
public Map<String, Integer> loadCombinationsFile(String comboName) {
Map<String, Integer> dict = new HashMap<String, Integer>();
private Map<String, Integer> loadCombinationsFile(final String comboName) {
List<List<String>> combolist = Collections.emptyList();
try {
List<List<String>> combolist = CombinationsFileUtil.init(comboName);
Callable<List<List<String>>> loadTask = new Callable<List<List<String>>>() {
// reformat combinations into combo dictionary
int group = 1;
for (List<String> zonelist : combolist) {
for (String z : zonelist) {
dict.put(z, group);
@Override
public List<List<String>> call() throws Exception {
return CombinationsFileUtil.init(comboName);
}
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) {
statusHandler.handle(Priority.SIGNIFICANT, e.getLocalizedMessage(),
e);
return new HashMap<String, Integer>();
group += 1;
}
currentComboFile = comboName;

View file

@ -21,6 +21,7 @@ package com.raytheon.viz.gfe.textformatter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
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.LocalizationFile;
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.LocalizationOpFailedException;
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
* Implemented retry on error
* 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
* Oct 07, 2015 #4695 dgilling Code cleanup to remove compile warnings.
*
* </pre>
*
@ -166,12 +169,13 @@ public class CombinationsFileUtil {
}
public static void saveComboData(String id, Map<String, Integer> combos)
throws LocalizationException, SerializationException {
throws LocalizationException, SerializationException, IOException {
LocalizationFile lf = idToFile(id);
File file = lf.getFile(false);
ComboData comboData = new ComboData(combos);
jaxb.marshalToXmlFile(comboData, file.getPath());
lf.save();
try (SaveableOutputStream out = lf.openOutputStream()) {
ComboData comboData = new ComboData(combos);
jaxb.marshalToStream(comboData, out);
out.save();
}
}
public static void deleteComboData(String id)
@ -205,18 +209,19 @@ public class CombinationsFileUtil {
}
public static Map<String, Integer> loadComboData(String id)
throws SerializationException {
throws SerializationException, IOException, LocalizationException {
LocalizationFile lf = idToFile(id);
File file = lf.getFile();
ComboData comboData = jaxb.unmarshalFromXmlFile(file);
try (InputStream in = lf.openInputStream()) {
ComboData comboData = (ComboData) jaxb.unmarshalFromInputStream(in);
Map<String, Integer> comboDict = new HashMap<String, Integer>(
comboData.combos.size());
for (Entry entry : comboData.combos) {
comboDict.put(entry.zone, entry.group);
Map<String, Integer> comboDict = new HashMap<String, Integer>(
comboData.combos.size());
for (Entry entry : comboData.combos) {
comboDict.put(entry.zone, entry.group);
}
return comboDict;
}
return comboDict;
}
@SuppressWarnings("unchecked")
@ -262,15 +267,12 @@ public class CombinationsFileUtil {
List<List<String>> combos = null;
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("comboName", comboName);
PythonScript python = null;
for (int retryCount = 0; retryCount < MAX_TRIES; retryCount++) {
try {
python = new PythonScript(scriptPath,
PyUtil.buildJepIncludePath(
GfePyIncludeUtil.getCombinationsIncludePath(),
GfePyIncludeUtil.getCommonPythonIncludePath()),
CombinationsFileUtil.class.getClassLoader());
try (PythonScript python = new PythonScript(scriptPath,
PyUtil.buildJepIncludePath(
GfePyIncludeUtil.getCombinationsIncludePath(),
GfePyIncludeUtil.getCommonPythonIncludePath()),
CombinationsFileUtil.class.getClassLoader())) {
Object com = python.execute("getCombinations", map);
combos = (List<List<String>>) com;
@ -292,10 +294,6 @@ public class CombinationsFileUtil {
throw new GfeException("Error loading combinations file: "
+ comboName, e);
}
} finally {
if (python != null) {
python.dispose();
}
}
}
return combos;