Merge remote-tracking branch 'origin/GP-7070_ghidra1_DBHandleIsChanged'

into patch (Closes #9346)
This commit is contained in:
Ryan Kurtz
2026-07-15 15:01:49 -04:00
2 changed files with 47 additions and 6 deletions

View File

@@ -46,6 +46,7 @@ public class DBHandle {
private long lastTransactionID; private long lastTransactionID;
private volatile boolean txStarted = false; private volatile boolean txStarted = false;
private volatile long txStartingModCount;
private boolean waitingForNewTransaction = false; private boolean waitingForNewTransaction = false;
private boolean reloadInProgress = false; private boolean reloadInProgress = false;
@@ -472,6 +473,7 @@ public class DBHandle {
} }
waitingForNewTransaction = false; waitingForNewTransaction = false;
txStarted = true; txStarted = true;
txStartingModCount = getModCount();
return ++lastTransactionID; return ++lastTransactionID;
} }
@@ -509,7 +511,7 @@ public class DBHandle {
*/ */
private synchronized boolean doEndTransaction(long id, boolean commit) private synchronized boolean doEndTransaction(long id, boolean commit)
throws DBRollbackException, IOException { throws DBRollbackException, IOException {
if (id != lastTransactionID) { if (!txStarted || id != lastTransactionID) {
throw new IllegalStateException("Transaction id is not active"); throw new IllegalStateException("Transaction id is not active");
} }
try { try {
@@ -530,8 +532,10 @@ public class DBHandle {
} }
} }
finally { finally {
if (commit) {
cachedChangedState = isChanged();
}
txStarted = false; txStarted = false;
cacheChangedState();
} }
return false; return false;
} }
@@ -762,11 +766,17 @@ public class DBHandle {
/** /**
* Determine if the underlying database has changed. * Determine if the underlying database has changed.
* NOTE: The returned value reflects a cached state assuming all underlaying database * <p>
* transactions, saving, etc. are facilitated by this handle object. * While a transaction is active this value will reflect changes made during the transaction
* which could ultimately never get committed. When a transaction is not active it is a
* reflection of the committed state.
*
* @return true if unsaved changes have been made. * @return true if unsaved changes have been made.
*/ */
public boolean isChanged() { public boolean isChanged() {
if (txStarted) {
return cachedChangedState || txStartingModCount != getModCount();
}
return cachedChangedState; return cachedChangedState;
} }

View File

@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -552,6 +552,37 @@ public class DBTest extends AbstractGenericTest {
} }
@Test
public void testIsChanged() throws IOException {
assertFalse(dbh.isChanged());
long txId = dbh.startTransaction();
try {
assertFalse(dbh.isChanged());
}
finally {
dbh.endTransaction(txId, true);
}
assertFalse(dbh.isChanged());
txId = dbh.startTransaction();
try {
assertFalse(dbh.isChanged());
DBTestUtils.createLongKeyTable(dbh, "TABLE", DBTestUtils.SINGLE_LONG, false, false);
assertEquals(1, dbh.getTableCount());
assertTrue(dbh.isChanged());
}
finally {
dbh.endTransaction(txId, true);
}
assertTrue(dbh.isChanged());
}
@Test @Test
public void testEvents() throws IOException { public void testEvents() throws IOException {