mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-05 19:42:36 +02:00
GP-4615 Corrected source archive transaction error for various archive
operations (Closes #6503)
This commit is contained in:
parent
5beb81f8c9
commit
72d9d0eeb2
4 changed files with 76 additions and 68 deletions
|
@ -84,7 +84,7 @@ import ghidra.util.task.TaskMonitor;
|
|||
)
|
||||
//@formatter:on
|
||||
public class DataTypeManagerPlugin extends ProgramPlugin implements DomainObjectListener,
|
||||
DataTypeManagerService, DataTypeArchiveService, PopupActionProvider {
|
||||
DataTypeManagerService, PopupActionProvider {
|
||||
|
||||
private static final String EXTENSIONS_PATH_PREFIX = Path.GHIDRA_HOME + "/Extensions";
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ package ghidra.app.plugin.core.datamgr;
|
|||
|
||||
import java.awt.FontMetrics;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
@ -31,8 +32,8 @@ import ghidra.app.util.html.MissingArchiveDataTypeHTMLRepresentation;
|
|||
import ghidra.program.database.data.*;
|
||||
import ghidra.program.model.data.*;
|
||||
import ghidra.util.*;
|
||||
import ghidra.util.exception.AssertException;
|
||||
import ghidra.util.exception.DuplicateNameException;
|
||||
import ghidra.util.exception.*;
|
||||
import utility.function.ExceptionalConsumer;
|
||||
|
||||
/**
|
||||
* Class for performing basic functions related to synchronizing data types between a program and
|
||||
|
@ -43,8 +44,6 @@ public class DataTypeSynchronizer {
|
|||
private final DataTypeManager dataTypeManager;
|
||||
private final SourceArchive sourceArchive;
|
||||
private final DataTypeManager sourceDTM;
|
||||
private int sourceTransactionID;
|
||||
private int localTransactionID;
|
||||
|
||||
/**
|
||||
* Creates a DataTypeSynchronizer to be used for synchronizing data types between a program
|
||||
|
@ -63,12 +62,7 @@ public class DataTypeSynchronizer {
|
|||
}
|
||||
|
||||
public List<DataTypeSyncInfo> findOutOfSynchDataTypes() {
|
||||
// long lastChangeTimeForSource = sourceDTM.getLastChangeTimeForMyManager();
|
||||
// long lastSyncTimeForSource = sourceArchive.getLastSyncTime();
|
||||
//
|
||||
// if (lastChangeTimeForSource == lastSyncTimeForSource && !sourceArchive.isDirty()) {
|
||||
// return new ArrayList<DataTypeSyncInfo>();
|
||||
// }
|
||||
|
||||
List<DataType> dataTypes = dataTypeManager.getDataTypes(sourceArchive);
|
||||
|
||||
List<DataTypeSyncInfo> dataTypeSyncInfo = new ArrayList<>();
|
||||
|
@ -91,7 +85,7 @@ public class DataTypeSynchronizer {
|
|||
return dataTypeSyncInfo;
|
||||
}
|
||||
|
||||
public static void commit(DataTypeManager sourceDTM, DataType refDT) {
|
||||
private static void commit(DataTypeManager sourceDTM, DataType refDT) {
|
||||
DataTypeManager refDTM = refDT.getDataTypeManager();
|
||||
int sourceTransactionID = sourceDTM.startTransaction("Commit Datatype Changes");
|
||||
int refTransactionID = refDTM.startTransaction("Update DataType Sync Time");
|
||||
|
@ -104,7 +98,7 @@ public class DataTypeSynchronizer {
|
|||
}
|
||||
}
|
||||
|
||||
public static void update(DataTypeManager refDTM, DataType sourceDT) {
|
||||
private static void update(DataTypeManager refDTM, DataType sourceDT) {
|
||||
int transactionID = refDTM.startTransaction("Update Datatype");
|
||||
try {
|
||||
updateAssumingTransactionsOpen(refDTM, sourceDT);
|
||||
|
@ -114,7 +108,7 @@ public class DataTypeSynchronizer {
|
|||
}
|
||||
}
|
||||
|
||||
public static void commitAssumingTransactionsOpen(DataTypeManager sourceDTM, DataType refDT) {
|
||||
static void commitAssumingTransactionsOpen(DataTypeManager sourceDTM, DataType refDT) {
|
||||
|
||||
// Must refresh associations of refDt and its dependencies to ensure that any
|
||||
// non-sourced datatype is properly associated to the sourceDTM
|
||||
|
@ -138,7 +132,7 @@ public class DataTypeSynchronizer {
|
|||
refDT.setLastChangeTimeInSourceArchive(lastChangeTime);
|
||||
}
|
||||
|
||||
public static void updateAssumingTransactionsOpen(DataTypeManager refDTM, DataType sourceDT) {
|
||||
static void updateAssumingTransactionsOpen(DataTypeManager refDTM, DataType sourceDT) {
|
||||
long lastChangeTime = sourceDT.getLastChangeTime();
|
||||
DataType refDT = refDTM.resolve(sourceDT, DataTypeConflictHandler.REPLACE_HANDLER);
|
||||
if (!isPointerOrArray(sourceDT)) {
|
||||
|
@ -215,20 +209,20 @@ public class DataTypeSynchronizer {
|
|||
return sourceArchive.getName();
|
||||
}
|
||||
|
||||
public void openTransactions() {
|
||||
if (sourceDTM != null) {
|
||||
sourceTransactionID = sourceDTM.startTransaction("Data Type Synchronization");
|
||||
}
|
||||
localTransactionID = dataTypeManager.startTransaction("Data Type Synchronization");
|
||||
}
|
||||
|
||||
public void closeTransactions() {
|
||||
dataTypeManager.endTransaction(localTransactionID, true);
|
||||
if (sourceDTM != null) {
|
||||
sourceDTM.endTransaction(sourceTransactionID, true);
|
||||
}
|
||||
|
||||
}
|
||||
// public void openTransactions() {
|
||||
//// if (sourceDTM != null) {
|
||||
//// sourceTransactionID = sourceDTM.startTransaction("Data Type Synchronization");
|
||||
//// }
|
||||
// localTransactionID = dataTypeManager.startTransaction("Data Type Synchronization");
|
||||
// }
|
||||
//
|
||||
// public void closeTransactions() {
|
||||
// dataTypeManager.endTransaction(localTransactionID, true);
|
||||
//// if (sourceDTM != null) {
|
||||
//// sourceDTM.endTransaction(sourceTransactionID, true);
|
||||
//// }
|
||||
//
|
||||
// }
|
||||
|
||||
/**
|
||||
* If the indicated data type is associated with a source archive, this will remove the
|
||||
|
@ -544,4 +538,33 @@ public class DataTypeSynchronizer {
|
|||
dataTypeManager.endTransaction(transactionID, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void performBulkOperation(String actionName, List<DataTypeSyncInfo> selectedList,
|
||||
ExceptionalConsumer<DataTypeSyncInfo, CancelledException> infoApplier,
|
||||
Consumer<List<DataTypeSyncInfo>> handleOutOfSync,
|
||||
boolean sourceRequiresTransaction) throws CancelledException {
|
||||
if (sourceDTM == null) {
|
||||
throw new RuntimeException("Source archive required");
|
||||
}
|
||||
|
||||
int sourceTransactionId = sourceRequiresTransaction ?
|
||||
sourceDTM.startTransaction(actionName) : 0;
|
||||
int transactionID = dataTypeManager.startTransaction(actionName);
|
||||
try {
|
||||
for (DataTypeSyncInfo info : selectedList) {
|
||||
infoApplier.accept(info);
|
||||
}
|
||||
List<DataTypeSyncInfo> outOfSyncList = findOutOfSynchDataTypes();
|
||||
handleOutOfSync.accept(outOfSyncList);
|
||||
if (outOfSyncList.isEmpty()) {
|
||||
markSynchronized();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
dataTypeManager.endTransaction(transactionID, true);
|
||||
if (sourceRequiresTransaction) {
|
||||
sourceDTM.endTransaction(sourceTransactionId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -229,7 +229,7 @@ public class DisassociateDataTypeAction extends DockingAction {
|
|||
private void disassociate(DataTypeSynchronizer synchronizer, DataTypeManager dtm,
|
||||
List<DataType> types, TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
synchronizer.openTransactions();
|
||||
int txId = dtm.startTransaction(getName());
|
||||
try {
|
||||
for (DataType dt : types) {
|
||||
monitor.checkCancelled();
|
||||
|
@ -241,7 +241,7 @@ public class DisassociateDataTypeAction extends DockingAction {
|
|||
synchronizer.reSyncOutOfSyncInTimeOnlyDataTypes();
|
||||
}
|
||||
finally {
|
||||
synchronizer.closeTransactions();
|
||||
dtm.endTransaction(txId, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,10 +129,9 @@ public abstract class SyncAction extends DockingAction implements Comparable<Syn
|
|||
tree.collapseAll(archiveNode);
|
||||
|
||||
monitor.setMessage("Finding out-of-sync types");
|
||||
Set<DataTypeSyncInfo> outOfSynchDataTypes =
|
||||
new HashSet<>(synchronizer.findOutOfSynchDataTypes());
|
||||
List<DataTypeSyncInfo> outOfSynchDataTypes = synchronizer.findOutOfSynchDataTypes();
|
||||
|
||||
removeAndUpdateOutOfSyncInTimeOnlyDataTypes(synchronizer, outOfSynchDataTypes);
|
||||
removeAndUpdateOutOfSyncInTimeOnlyDataTypes(synchronizer, synchronizer.findOutOfSynchDataTypes());
|
||||
if (outOfSynchDataTypes.isEmpty()) {
|
||||
showNoDataTypesToSyncMessage();
|
||||
return;
|
||||
|
@ -159,11 +158,8 @@ public abstract class SyncAction extends DockingAction implements Comparable<Syn
|
|||
monitor.initialize(selectedList.size());
|
||||
processSelectedDataTypes(synchronizer, selectedList, outOfSynchDataTypes, monitor);
|
||||
|
||||
Set<DataTypeSyncInfo> outOfSynchDataTypesAfterProcessed =
|
||||
new HashSet<>(synchronizer.findOutOfSynchDataTypes());
|
||||
|
||||
reportAnyLeftOverOutOfSyncDataTypes(sourceArchive.getName(),
|
||||
outOfSynchDataTypesAfterProcessed);
|
||||
synchronizer.findOutOfSynchDataTypes());
|
||||
}
|
||||
catch (CancelledException e) {
|
||||
// nothing to report
|
||||
|
@ -184,7 +180,7 @@ public abstract class SyncAction extends DockingAction implements Comparable<Syn
|
|||
}
|
||||
|
||||
private void reportAnyLeftOverOutOfSyncDataTypes(String archiveName,
|
||||
Set<DataTypeSyncInfo> outOfSynchDataTypes) {
|
||||
List<DataTypeSyncInfo> outOfSynchDataTypes) {
|
||||
if (outOfSynchDataTypes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -195,35 +191,24 @@ public abstract class SyncAction extends DockingAction implements Comparable<Syn
|
|||
|
||||
}
|
||||
|
||||
private void processSelectedDataTypes(DataTypeSynchronizer synchronizer,
|
||||
List<DataTypeSyncInfo> selectedList, Set<DataTypeSyncInfo> outOfSynchDataTypes,
|
||||
protected void processSelectedDataTypes(DataTypeSynchronizer synchronizer,
|
||||
List<DataTypeSyncInfo> selectedList, List<DataTypeSyncInfo> outOfSynchDataTypes,
|
||||
TaskMonitor monitor) throws CancelledException {
|
||||
|
||||
synchronizer.openTransactions();
|
||||
try {
|
||||
for (DataTypeSyncInfo info : selectedList) {
|
||||
monitor.checkCancelled();
|
||||
monitor.setMessage("Syncing " + info.getName());
|
||||
applyOperation(info);
|
||||
outOfSynchDataTypes.remove(info);
|
||||
monitor.incrementProgress(1);
|
||||
}
|
||||
|
||||
|
||||
synchronizer.performBulkOperation(getName(), selectedList, info -> {
|
||||
monitor.checkCancelled();
|
||||
monitor.setMessage("Syncing " + info.getName());
|
||||
applyOperation(info);
|
||||
outOfSynchDataTypes.remove(info);
|
||||
monitor.incrementProgress(1);
|
||||
|
||||
}, outOfSyncList -> {
|
||||
// dataTypeChanged can cause other related data types to become updated
|
||||
// and their times will appear out of sync. So clean up any that actually
|
||||
// are the same.
|
||||
Set<DataTypeSyncInfo> outOfSynchDataTypesAfterProcessed =
|
||||
new HashSet<>(synchronizer.findOutOfSynchDataTypes());
|
||||
removeAndUpdateOutOfSyncInTimeOnlyDataTypes(synchronizer,
|
||||
outOfSynchDataTypesAfterProcessed);
|
||||
if (outOfSynchDataTypesAfterProcessed.isEmpty()) {
|
||||
synchronizer.markSynchronized();
|
||||
}
|
||||
|
||||
}
|
||||
finally {
|
||||
synchronizer.closeTransactions();
|
||||
}
|
||||
removeAndUpdateOutOfSyncInTimeOnlyDataTypes(synchronizer, outOfSyncList);
|
||||
|
||||
}, requiresArchiveOpenForEditing());
|
||||
}
|
||||
|
||||
private boolean confirmOperation(List<DataTypeSyncInfo> selectedList) {
|
||||
|
@ -246,7 +231,7 @@ public abstract class SyncAction extends DockingAction implements Comparable<Syn
|
|||
}
|
||||
|
||||
private void showNoDataTypesForThisOperationMessage(String archiveName,
|
||||
Set<DataTypeSyncInfo> outOfSyncInfos) {
|
||||
List<DataTypeSyncInfo> outOfSyncInfos) {
|
||||
String status = getStatusMessage(outOfSyncInfos);
|
||||
Msg.showInfo(getClass(), plugin.getTool().getToolFrame(), "No Data Type Changes",
|
||||
"No data types found to " + getOperationName() + " for archive \"" + archiveName +
|
||||
|
@ -258,7 +243,7 @@ public abstract class SyncAction extends DockingAction implements Comparable<Syn
|
|||
"Archive \"" + archiveName + "\" must be open for editing.");
|
||||
}
|
||||
|
||||
private String getStatusMessage(Set<DataTypeSyncInfo> outOfSyncInfos) {
|
||||
private String getStatusMessage(List<DataTypeSyncInfo> outOfSyncInfos) {
|
||||
int orphanCount = 0;
|
||||
int conflictCount = 0;
|
||||
int updateCount = 0;
|
||||
|
@ -307,7 +292,7 @@ public abstract class SyncAction extends DockingAction implements Comparable<Syn
|
|||
return getMenuOrder() - o.getMenuOrder();
|
||||
}
|
||||
|
||||
protected List<DataTypeSyncInfo> filterList(Set<DataTypeSyncInfo> allOutOfSyncDataTypes) {
|
||||
protected List<DataTypeSyncInfo> filterList(List<DataTypeSyncInfo> allOutOfSyncDataTypes) {
|
||||
List<DataTypeSyncInfo> filteredList = new ArrayList<>();
|
||||
for (DataTypeSyncInfo dataTypeSyncInfo : allOutOfSyncDataTypes) {
|
||||
if (isAppropriateForAction(dataTypeSyncInfo)) {
|
||||
|
@ -324,7 +309,7 @@ public abstract class SyncAction extends DockingAction implements Comparable<Syn
|
|||
* @param outOfSynchDataTypes list of all datatypes that are marked as "out of sync".
|
||||
*/
|
||||
private void removeAndUpdateOutOfSyncInTimeOnlyDataTypes(DataTypeSynchronizer synchronizer,
|
||||
Set<DataTypeSyncInfo> outOfSynchDataTypes) {
|
||||
List<DataTypeSyncInfo> outOfSynchDataTypes) {
|
||||
List<DataTypeSyncInfo> list = new ArrayList<>();
|
||||
|
||||
Iterator<DataTypeSyncInfo> iterator = outOfSynchDataTypes.iterator();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue