GP-4692 Corrected post-checkin/merge update of open

database/domain-object
This commit is contained in:
ghidra1 2024-06-12 17:31:22 -04:00
parent 734ff7b669
commit bac18feabf
3 changed files with 85 additions and 20 deletions

View file

@ -78,8 +78,8 @@ public class BufferMgr {
*/ */
private BufferNode cacheHead; private BufferNode cacheHead;
private BufferNode cacheTail; private BufferNode cacheTail;
private int cacheSize = 0; private int cacheSize;
private int buffersOnHand = 0; private int buffersOnHand;
private int lockCount = 0; private int lockCount = 0;
/** /**
@ -235,6 +235,10 @@ public class BufferMgr {
private void initializeCache() throws IOException { private void initializeCache() throws IOException {
if (lockCount != 0) {
throw new IOException("Unable to re-initialize buffer cache while in-use");
}
if (cacheFile != null) { if (cacheFile != null) {
cacheFile.delete(); cacheFile.delete();
} }
@ -244,6 +248,9 @@ public class BufferMgr {
cacheTail = new BufferNode(TAIL, -1); cacheTail = new BufferNode(TAIL, -1);
cacheHead.nextCached = cacheTail; cacheHead.nextCached = cacheTail;
cacheTail.prevCached = cacheHead; cacheTail.prevCached = cacheHead;
cacheSize = 0;
buffersOnHand = 0;
// Create disk cache file // Create disk cache file
cacheFile = new LocalBufferFile(bufferSize, CACHE_FILE_PREFIX, CACHE_FILE_EXT); cacheFile = new LocalBufferFile(bufferSize, CACHE_FILE_PREFIX, CACHE_FILE_EXT);
@ -257,6 +264,8 @@ public class BufferMgr {
cacheFile.setParameter(name, sourceFile.getParameter(name)); cacheFile.setParameter(name, sourceFile.getParameter(name));
} }
} }
resetCacheStatistics();
if (alwaysPreCache) { if (alwaysPreCache) {
startPreCacheIfNeeded(); startPreCacheIfNeeded();
@ -2058,7 +2067,7 @@ public class BufferMgr {
public void resetCacheStatistics() { public void resetCacheStatistics() {
cacheHits = 0; cacheHits = 0;
cacheMisses = 0; cacheMisses = 0;
lowWaterMark = cacheSize; lowWaterMark = cacheSize - 1;
} }
public String getStatusInfo() { public String getStatusInfo() {

View file

@ -1149,7 +1149,7 @@ public class GhidraFileData {
if (keepCheckedOut) { if (keepCheckedOut) {
// Maintain exclusive chekout if private repository or file is open for update // Maintain exclusive checkout if private repository or file is open for update
boolean exclusive = !versionedFileSystem.isShared() || (inUseDomainObj != null); boolean exclusive = !versionedFileSystem.isShared() || (inUseDomainObj != null);
ProjectLocator projectLocator = parent.getProjectLocator(); ProjectLocator projectLocator = parent.getProjectLocator();
@ -1169,6 +1169,11 @@ public class GhidraFileData {
projectLocator.isTransient())); projectLocator.isTransient()));
folderItem.setCheckout(checkout.getCheckoutId(), exclusive, folderItem.setCheckout(checkout.getCheckoutId(), exclusive,
checkout.getCheckoutVersion(), folderItem.getCurrentVersion()); checkout.getCheckoutVersion(), folderItem.getCurrentVersion());
if (inUseDomainObj != null) {
// Reset source file and change-sets for open database
getContentHandler().resetDBSourceFile(folderItem, inUseDomainObj);
}
} }
else { else {
// NOTE: file open read-only may prevent removal and result in hijack // NOTE: file open read-only may prevent removal and result in hijack
@ -1180,10 +1185,7 @@ public class GhidraFileData {
// Ignore - should result in Hijacked file // Ignore - should result in Hijacked file
} }
} }
if (inUseDomainObj != null) {
getContentHandler().resetDBSourceFile(folderItem, inUseDomainObj);
}
} // end of synchronized block } // end of synchronized block
if (inUseDomainObj != null) { if (inUseDomainObj != null) {
@ -1535,15 +1537,16 @@ public class GhidraFileData {
} }
} }
} }
if (inUseDomainObj != null) {
// Reset source file and change-sets for open database
contentHandler.resetDBSourceFile(folderItem, inUseDomainObj);
}
} }
else { else {
undoCheckout(false, true); undoCheckout(false, true);
} }
if (inUseDomainObj != null) {
contentHandler.resetDBSourceFile(folderItem, inUseDomainObj);
}
} // end of synchronized block } // end of synchronized block
if (inUseDomainObj != null) { if (inUseDomainObj != null) {
@ -1915,6 +1918,8 @@ public class GhidraFileData {
try { try {
inUseDomainObj = getAndLockInUseDomainObjectForMergeUpdate("merge"); inUseDomainObj = getAndLockInUseDomainObjectForMergeUpdate("merge");
ContentHandler<?> contentHandler = getContentHandler();
if (!modifiedSinceCheckout()) { if (!modifiedSinceCheckout()) {
// Quick merge // Quick merge
folderItem.updateCheckout(versionedFolderItem, true, monitor); folderItem.updateCheckout(versionedFolderItem, true, monitor);
@ -1925,8 +1930,6 @@ public class GhidraFileData {
throw new IOException("Merge failed, merge is not supported in headless mode"); throw new IOException("Merge failed, merge is not supported in headless mode");
} }
ContentHandler<?> contentHandler = getContentHandler();
// Test versioned file for VersionException // Test versioned file for VersionException
int mergeVer = versionedFolderItem.getCurrentVersion(); int mergeVer = versionedFolderItem.getCurrentVersion();
if (!okToUpgrade) { if (!okToUpgrade) {
@ -1995,14 +1998,13 @@ public class GhidraFileData {
versionedFolderItem.updateCheckoutVersion(checkoutId, mergeVer, versionedFolderItem.updateCheckoutVersion(checkoutId, mergeVer,
ClientUtil.getUserName()); ClientUtil.getUserName());
tmpItem = null; tmpItem = null;
Msg.info(this, "Merge completed for " + name);
if (inUseDomainObj != null) {
contentHandler.resetDBSourceFile(folderItem, inUseDomainObj);
}
} }
Msg.info(this, "Updated checkout completed for " + name);
if (inUseDomainObj != null) { if (inUseDomainObj != null) {
// Reset source file and change-sets for open database
contentHandler.resetDBSourceFile(folderItem, inUseDomainObj);
inUseDomainObj.invalidate(); inUseDomainObj.invalidate();
} }
} }

View file

@ -36,6 +36,8 @@ import generic.theme.GIcon;
import ghidra.framework.main.projectdata.actions.VersionControlAction; import ghidra.framework.main.projectdata.actions.VersionControlAction;
import ghidra.framework.model.DomainFile; import ghidra.framework.model.DomainFile;
import ghidra.framework.model.DomainFolder; import ghidra.framework.model.DomainFolder;
import ghidra.program.database.ProgramDB;
import ghidra.program.model.address.AddressSpace;
import ghidra.program.model.listing.CodeUnit; import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Program; import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.SourceType; import ghidra.program.model.symbol.SourceType;
@ -219,7 +221,7 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
waitForSwing(); waitForSwing();
waitForTasks(); waitForTasks();
Program program = (Program) ((DomainFileNode) node).getDomainFile() ProgramDB program = (ProgramDB) ((DomainFileNode) node).getDomainFile()
.getDomainObject(this, .getDomainObject(this,
true, false, TaskMonitor.DUMMY); true, false, TaskMonitor.DUMMY);
int transactionID = program.startTransaction("test"); int transactionID = program.startTransaction("test");
@ -253,6 +255,58 @@ public class VersionControlAction2Test extends AbstractVersionControlActionTest
assertTrue(!df.isCheckedOut()); assertTrue(!df.isCheckedOut());
} }
@Test
public void testCheckInWhileOpen() throws Exception {
GTreeNode node = getNode(PROGRAM_A);
addToVersionControl(node, false);
selectNode(node);
DockingActionIf action = getAction("CheckOut");
runSwing(() -> action.actionPerformed(getDomainFileActionContext(node)), false);
waitForSwing();
waitForTasks();
ProgramDB program = (ProgramDB) ((DomainFileNode) node).getDomainFile()
.getDomainObject(this,
true, false, TaskMonitor.DUMMY);
int transactionID = program.startTransaction("test");
try {
// Ensure that buffer memory cache has been completely consumed
// Max BufferMgr cache size is 256*16KByte=4MByte
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
program.getMemory().createInitializedBlock("BigBlock", space.getAddress(0x80000000L),
4*1024*1024, (byte)0xff, TaskMonitor.DUMMY, false);
}
finally {
program.endTransaction(transactionID, true);
program.save(null, TaskMonitor.DUMMY);
}
try {
DockingActionIf checkInAction = getAction("CheckIn");
runSwing(() -> checkInAction.actionPerformed(getDomainFileActionContext(node)), false);
waitForSwing();
VersionControlDialog dialog = waitForDialogComponent(VersionControlDialog.class);
assertNotNull(dialog);
JTextArea textArea = findComponent(dialog, JTextArea.class);
assertNotNull(textArea);
JCheckBox cb = findComponent(dialog, JCheckBox.class);
assertNotNull(cb);
runSwing(() -> {
textArea.setText("This is a test");
cb.setSelected(false);
});
pressButtonByText(dialog, "OK");
waitForTasks();
DomainFile df = ((DomainFileNode) node).getDomainFile();
assertTrue(df.isCheckedOut());
}
finally {
program.release(this);
}
}
@Test @Test
public void testDeleteVersionCheckedOut() throws Exception { public void testDeleteVersionCheckedOut() throws Exception {