mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-09 14:08:03 -05:00
GP-6073 - FID - Implemented delayed DB loading to improve tool startup.
This commit is contained in:
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -114,19 +114,25 @@ public class FidAnalyzer extends AbstractAnalyzer {
|
||||
|
||||
@Override
|
||||
public boolean getDefaultEnablement(Program program) {
|
||||
return service.canProcess(program.getLanguage());
|
||||
// Loading Fid db files can be slow. For now, signal that we can analyze and check later.
|
||||
return true;
|
||||
//return service.canProcess(program.getLanguage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAnalyze(Program program) {
|
||||
return service.canProcess(program.getLanguage());
|
||||
// Loading Fid db files can be slow. For now, signal that we can analyze and check later.
|
||||
return true;
|
||||
//return service.canProcess(program.getLanguage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean added(Program program, AddressSetView set, TaskMonitor monitor, MessageLog log)
|
||||
throws CancelledException {
|
||||
|
||||
if (!service.canProcess(program.getLanguage())) {
|
||||
Msg.warn(this, "No FID Libraries apply for language " + program.getLanguageID());
|
||||
// This can now happen, since we no longer check in canAnalyze()
|
||||
Msg.debug(this, "No FID Libraries apply for language " + program.getLanguageID());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,14 +27,18 @@ import generic.util.Path;
|
||||
import ghidra.framework.Application;
|
||||
import ghidra.framework.preferences.Preferences;
|
||||
import ghidra.program.model.lang.Language;
|
||||
import ghidra.util.Msg;
|
||||
import ghidra.util.datastruct.WeakDataStructureFactory;
|
||||
import ghidra.util.datastruct.WeakSet;
|
||||
import ghidra.util.exception.CancelledException;
|
||||
import ghidra.util.exception.VersionException;
|
||||
import ghidra.util.task.TaskLauncher;
|
||||
import ghidra.util.task.TaskMonitor;
|
||||
|
||||
/**
|
||||
* Manages the set of FidFiles for the application. This uses the singleton pattern and
|
||||
* all users of Fid databases must use this to get open Fid databases. This ensures that
|
||||
* there is only one updateable Fid database open for any given FidFile.
|
||||
* there is only one updatable Fid database open for any given FidFile.
|
||||
*/
|
||||
public class FidFileManager {
|
||||
|
||||
@@ -48,7 +52,7 @@ public class FidFileManager {
|
||||
private WeakSet<ChangeListener> listeners;
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of the FidFileManager.
|
||||
* {@return the singleton instance of the FidFileManager.}
|
||||
*/
|
||||
public static FidFileManager getInstance() {
|
||||
if (THE_FID_FILE_MANAGER == null) {
|
||||
@@ -59,14 +63,23 @@ public class FidFileManager {
|
||||
|
||||
private FidFileManager() {
|
||||
listeners = WeakDataStructureFactory.createCopyOnWriteWeakSet();
|
||||
// findDeliveredFidFiles(); - too slow
|
||||
// restoreFromPreferences();
|
||||
}
|
||||
|
||||
private Set<FidFile> loadFidFiles() {
|
||||
if (fidFiles == null) {
|
||||
findDeliveredFidFiles();
|
||||
restoreFromPreferences();
|
||||
|
||||
TaskLauncher.launchModal("Loading Fid Files", monitor -> {
|
||||
|
||||
fidFiles = new CopyOnWriteArraySet<>();
|
||||
try {
|
||||
findDeliveredFidFiles(monitor);
|
||||
restoreFromPreferences(monitor);
|
||||
}
|
||||
catch (CancelledException ce) {
|
||||
Msg.showWarn(this, null, "Fid Loading Cancelled", "User cancelled Fid Db " +
|
||||
"loading. To load all Fid Db files, the tool must be restarted.");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return fidFiles;
|
||||
@@ -74,7 +87,7 @@ public class FidFileManager {
|
||||
|
||||
/**
|
||||
* Add user FidDb file
|
||||
* @param file
|
||||
* @param file the file
|
||||
* @return FidFile or null if invalid
|
||||
*/
|
||||
public FidFile addUserFidFile(File file) {
|
||||
@@ -105,7 +118,7 @@ public class FidFileManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all the FidFiles know to the application.
|
||||
* {@return a list of all the FidFiles know to the application.}
|
||||
*/
|
||||
public List<FidFile> getFidFiles() {
|
||||
loadFidFiles();
|
||||
@@ -114,13 +127,30 @@ public class FidFileManager {
|
||||
return files;
|
||||
}
|
||||
|
||||
public boolean hasFidFiles() {
|
||||
loadFidFiles();
|
||||
return !fidFiles.isEmpty();
|
||||
/**
|
||||
* Triggers a load of the Fid db files, if not already loaded.
|
||||
*/
|
||||
public void load() {
|
||||
if (fidFiles == null) {
|
||||
loadFidFiles();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return true if Fid db files have been loaded and files have been found.}
|
||||
*/
|
||||
public boolean hasFidFiles() {
|
||||
return fidFiles != null && !fidFiles.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return true if Fid db files have been loaded and user Fid files have been found.}
|
||||
*/
|
||||
public boolean hasUserFidFiles() {
|
||||
loadFidFiles();
|
||||
if (fidFiles == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (FidFile fidFile : fidFiles) {
|
||||
if (!fidFile.isInstalled()) {
|
||||
return true;
|
||||
@@ -130,8 +160,15 @@ public class FidFileManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all the user added (non installation) Fid files. This will
|
||||
* be files containing packed databases.
|
||||
* {@return true if the Fid db files have been loaded.}
|
||||
*/
|
||||
public boolean hasLoadedFidFiles() {
|
||||
return fidFiles != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return a list of all the user added (non installation) Fid files. This will
|
||||
* be files containing packed databases.}
|
||||
*/
|
||||
public List<FidFile> getUserAddedFiles() {
|
||||
loadFidFiles();
|
||||
@@ -251,17 +288,20 @@ public class FidFileManager {
|
||||
return list;
|
||||
}
|
||||
|
||||
private void restoreFromPreferences() {
|
||||
private void restoreFromPreferences(TaskMonitor monitor) throws CancelledException {
|
||||
Set<File> userAddedFiles = getFilesFromPreference(USER_ADDED_FILES);
|
||||
addUserFidFiles(userAddedFiles);
|
||||
monitor.initialize(userAddedFiles.size(), "Adding user Fid files...");
|
||||
doAddUserFidFiles(userAddedFiles, monitor);
|
||||
|
||||
Set<File> excludedFiles = getFilesFromPreference(INACTIVE_FID_FILES);
|
||||
excludeFidFiles(excludedFiles);
|
||||
monitor.initialize(excludedFiles.size(), "Removing inactive user Fid files...");
|
||||
doExcludeFidFiles(excludedFiles, monitor);
|
||||
}
|
||||
|
||||
private void addUserFidFiles(Set<File> userAddedFiles) {
|
||||
loadFidFiles();
|
||||
private void doAddUserFidFiles(Set<File> userAddedFiles, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
for (File file : userAddedFiles) {
|
||||
monitor.increment();
|
||||
FidFile fidFile = new FidFile(this, file, false);
|
||||
if (fidFile.isValidFile()) {
|
||||
fidFiles.add(fidFile);
|
||||
@@ -269,9 +309,10 @@ public class FidFileManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void excludeFidFiles(Set<File> excludedFiles) {
|
||||
loadFidFiles();
|
||||
private void doExcludeFidFiles(Set<File> excludedFiles, TaskMonitor monitor)
|
||||
throws CancelledException {
|
||||
for (FidFile fidFile : fidFiles) {
|
||||
monitor.increment();
|
||||
if (excludedFiles.contains(fidFile.getFile())) {
|
||||
fidFile.setActive(false);
|
||||
}
|
||||
@@ -296,11 +337,14 @@ public class FidFileManager {
|
||||
return set;
|
||||
}
|
||||
|
||||
private void findDeliveredFidFiles() {
|
||||
fidFiles = new CopyOnWriteArraySet<>();
|
||||
private void findDeliveredFidFiles(TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
List<ResourceFile> foundFiles =
|
||||
Application.findFilesByExtensionInApplication(FidFile.FID_RAW_DATABASE_FILE_EXTENSION);
|
||||
|
||||
monitor.initialize(foundFiles.size(), "Processing included Fid files...");
|
||||
for (ResourceFile resourceFile : foundFiles) {
|
||||
monitor.increment();
|
||||
File file = resourceFile.getFile(true);
|
||||
FidFile fidFile = new FidFile(this, file, true);
|
||||
if (fidFile.isValidFile()) {
|
||||
|
||||
@@ -94,7 +94,7 @@ public class FidPlugin extends ProgramPlugin implements ChangeListener {
|
||||
*/
|
||||
private void createStandardActions() {
|
||||
new ActionBuilder("Choose Active FidDbs", getName())
|
||||
.enabledWhen(ac -> fidFileManager.hasFidFiles())
|
||||
.enabledWhen(ac -> enabledForAnyFidFiles())
|
||||
.onAction(ac -> chooseActiveFidDbs())
|
||||
.menuPath(ToolConstants.MENU_TOOLS, FUNCTION_ID_NAME, "Choose active FidDbs...")
|
||||
.menuGroup(MENU_GROUP_1, "1")
|
||||
@@ -121,7 +121,7 @@ public class FidPlugin extends ProgramPlugin implements ChangeListener {
|
||||
.buildAndInstall(tool);
|
||||
|
||||
new ActionBuilder("Detach attached FidDb", getName())
|
||||
.enabledWhen(ac -> fidFileManager.hasUserFidFiles())
|
||||
.enabledWhen(ac -> enabledForUserFidFiles())
|
||||
.onAction(ac -> removeFidFile())
|
||||
.menuPath(ToolConstants.MENU_TOOLS, FUNCTION_ID_NAME, "Detach attached FidDb...")
|
||||
.menuGroup(MENU_GROUP_1, "4")
|
||||
@@ -130,8 +130,9 @@ public class FidPlugin extends ProgramPlugin implements ChangeListener {
|
||||
.buildAndInstall(tool);
|
||||
|
||||
new ActionBuilder("Populate FidDb from programs", getName())
|
||||
.enabledWhen(ac -> fidFileManager.hasUserFidFiles())
|
||||
.enabledWhen(ac -> enabledForUserFidFiles())
|
||||
.onAction(ac -> {
|
||||
fidFileManager.load();
|
||||
PopulateFidDialog populateFidDialog = new PopulateFidDialog(tool, service);
|
||||
tool.showDialog(populateFidDialog);
|
||||
})
|
||||
@@ -143,11 +144,30 @@ public class FidPlugin extends ProgramPlugin implements ChangeListener {
|
||||
.buildAndInstall(tool);
|
||||
}
|
||||
|
||||
private boolean enabledForAnyFidFiles() {
|
||||
if (!fidFileManager.hasLoadedFidFiles()) {
|
||||
// We haven't loaded Fid files yet. Since we don't know if we can enable, return true
|
||||
// so users can at least try to perform the action.
|
||||
return true;
|
||||
}
|
||||
return fidFileManager.hasFidFiles();
|
||||
}
|
||||
|
||||
private boolean enabledForUserFidFiles() {
|
||||
if (!fidFileManager.hasLoadedFidFiles()) {
|
||||
// We haven't loaded Fid files yet. Since we don't know if we can enable, return true
|
||||
// so users can at least try to perform the action.
|
||||
return true;
|
||||
}
|
||||
return fidFileManager.hasUserFidFiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to select which known FID databases are currently active
|
||||
* during search.
|
||||
*/
|
||||
private synchronized void chooseActiveFidDbs() {
|
||||
fidFileManager.load();
|
||||
ActiveFidConfigureDialog dialog =
|
||||
new ActiveFidConfigureDialog(fidFileManager.getFidFiles());
|
||||
tool.showDialog(dialog);
|
||||
@@ -159,6 +179,7 @@ public class FidPlugin extends ProgramPlugin implements ChangeListener {
|
||||
* extension (.fidb). If they don't, we will add it for them.
|
||||
*/
|
||||
private void createFidDb() {
|
||||
fidFileManager.load();
|
||||
File dbFile = askFile("Create new FidDb file", "Create");
|
||||
if (dbFile == null) {
|
||||
return;
|
||||
@@ -186,6 +207,7 @@ public class FidPlugin extends ProgramPlugin implements ChangeListener {
|
||||
* Method to attach an already-created (but heretofore unknown) database.
|
||||
*/
|
||||
private void attachFidDb() {
|
||||
fidFileManager.load();
|
||||
File dbFile = askFile("Attach existing FidDb file", "Attach");
|
||||
if (dbFile != null) {
|
||||
fidFileManager.addUserFidFile(dbFile);
|
||||
@@ -196,6 +218,8 @@ public class FidPlugin extends ProgramPlugin implements ChangeListener {
|
||||
* Method to "forget" about (close and stop trying to re-open next session) a FID database.
|
||||
*/
|
||||
private void removeFidFile() {
|
||||
fidFileManager.load();
|
||||
|
||||
FidFile fidFile = askChoice("Choose FidDb to detach", "Please choose the FidDb to detach",
|
||||
fidFileManager.getUserAddedFiles(), null);
|
||||
if (fidFile != null) {
|
||||
|
||||
Reference in New Issue
Block a user