[
https://issues.apache.org/jira/browse/DERBY-3757?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12791555#action_12791555
]
Knut Anders Hatlen commented on DERBY-3757:
-------------------------------------------
I've looked more at the synchronization in the TransactionTable class (see
comment on DERBY-3092), and I believe that getTransactionInfo() should
synchronize on "trans" instead of "this". Synchronization on "this" is used to
prevent transaction table entries from changing status to update transactions,
which is not important for that method. Instead, we should synchronize on
"trans" to prevent entries from being removed between the calls to
hasMoreElements() and nextElement().
As to Mike's question about how nextElement() could end up returning null, I
think the key is that the Enumeration object returned by Hashtable.elements()
is not thread-safe. Although all of Hashtable's public methods are
synchronized, none of the methods of the returned Enumeration object are
synchronized. This means that there's nothing preventing Hashtable.remove()
from being called and executed in one thread while another thread is executing
nextElement().
I looked at OpenJDK's implementation of Hashtable, and it looks to me that
executing remove() while nextElement() is executing, depending on the exact
timing, may result in nextElement() returning null or throwing
NoSuchElementException. (The manifestation as a NoSuchElementException is
logged as DERBY-3916.) If we synchronize on the Hashtable object, we would
prevent both of these problems.
> 'ASSERT FAILED transaction table has null entry when running new
> StressMultiTest
> --------------------------------------------------------------------------------
>
> Key: DERBY-3757
> URL: https://issues.apache.org/jira/browse/DERBY-3757
> Project: Derby
> Issue Type: Bug
> Components: Store
> Affects Versions: 10.5.1.1
> Environment: Windows XP
> java version "1.5.0"
> Java(TM) 2 Runtime Environment, Standard Edition (build pwi32dev-20070201
> (SR4))
> IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 2.3 Windows XP x86-32
> j9vmwi3223-20070201 (JIT enabled)
> J9VM - 20070131_11312_lHdSMR
> JIT - 20070109_1805ifx1_r8
> GC - 200701_09)
> JCL - 20070131
> Reporter: Kathey Marsden
> Assignee: Knut Anders Hatlen
> Attachments: Derby-3757_1.diff, testStressMulti.tar.gz
>
>
> When trying the DERBY-1764-V2.diff patch of DERBY-1764, I got this assertion
> running the test. It appears to be a bug iin Derby.
> 1)
> testStressMulti(org.apache.derbyTesting.functionTests.tests.multi.StressMultiTest)java.sql.SQLException:
> Java exception: 'ASSERT FAILED transaction table has null entry:
> org.apache.derby.shared.common.sanity.AssertFailure'.
> at
> org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(SQLExceptionFactory.java:45)
> at org.apache.derby.impl.jdbc.Util.newEmbedSQLException(Util.java:87)
> at org.apache.derby.impl.jdbc.Util.javaException(Util.java:244)
> at
> org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(TransactionResourceImpl.java:403)
> at
> org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(TransactionResourceImpl.java:346)
> at
> org.apache.derby.impl.jdbc.EmbedConnection.handleException(EmbedConnection.java:2183)
> at
> org.apache.derby.impl.jdbc.ConnectionChild.handleException(ConnectionChild.java:81)
> at
> org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1325)
> at
> org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:625)
> at <unknown class>.<unknown method>(Unknown Source)
> at
> org.apache.derbyTesting.functionTests.tests.multi.StressMultiTest$StressMultiRunnable.run(StressMultiTest.jav
> a:317)
> at java.lang.Thread.run(Thread.java:803)
> Caused by: org.apache.derby.shared.common.sanity.AssertFailure: ASSERT FAILED
> transaction table has null entry
> at
> org.apache.derby.shared.common.sanity.SanityManager.ASSERT(SanityManager.java:120)
> at
> org.apache.derby.impl.store.raw.xact.TransactionTable.getTransactionInfo(TransactionTable.java:968)
> at
> org.apache.derby.impl.store.raw.xact.XactFactory.getTransactionInfo(XactFactory.java:991)
> at
> org.apache.derby.impl.store.raw.RawStore.getTransactionInfo(RawStore.java:1153)
> at
> org.apache.derby.impl.store.access.RAMAccessManager.getTransactionInfo(RAMAccessManager.java:912)
> at
> org.apache.derby.impl.services.locks.Deadlock.buildException(Deadlock.java:266)
> at
> org.apache.derby.impl.services.locks.ConcurrentLockSet.lockObject(ConcurrentLockSet.java:613)
> at
> org.apache.derby.impl.services.locks.AbstractPool.lockObject(AbstractPool.java:117)
> at
> org.apache.derby.impl.store.raw.xact.RowLocking3.lockRecordForWrite(RowLocking3.java:248)
> at
> org.apache.derby.impl.store.access.heap.HeapController.lockRow(HeapController.java:504)
> at
> org.apache.derby.impl.store.access.heap.HeapController.lockRow(HeapController.java:638)
> at
> org.apache.derby.impl.store.access.btree.index.B2IRowLocking3.lockRowOnPage(B2IRowLocking3.java:335)
> at
> org.apache.derby.impl.store.access.btree.index.B2IRowLocking3._lockScanRow(B2IRowLocking3.java:628)
> at
> org.apache.derby.impl.store.access.btree.index.B2IRowLockingRR.lockScanRow(B2IRowLockingRR.java:112)
> at
> org.apache.derby.impl.store.access.btree.BTreeForwardScan.fetchRows(BTreeForwardScan.java:304)
> at
> org.apache.derby.impl.store.access.btree.BTreeScan.fetchNext(BTreeScan.java:1809)
> at
> org.apache.derby.impl.sql.execute.TableScanResultSet.getNextRowCore(TableScanResultSet.java:680)
> at
> org.apache.derby.impl.sql.execute.IndexRowToBaseRowResultSet.getNextRowCore(IndexRowToBaseRowResultSet.java:3
> 73)
> at
> org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(ProjectRestrictResultSet.java:255)
> at
> org.apache.derby.impl.sql.execute.NormalizeResultSet.getNextRowCore(NormalizeResultSet.java:186)
> at
> org.apache.derby.impl.sql.execute.DMLWriteResultSet.getNextRowCore(DMLWriteResultSet.java:127)
> at
> org.apache.derby.impl.sql.execute.UpdateResultSet.collectAffectedRows(UpdateResultSet.java:424)
> at
> org.apache.derby.impl.sql.execute.UpdateResultSet.open(UpdateResultSet.java:246)
> at
> org.apache.derby.impl.sql.GenericPreparedStatement.execute(GenericPreparedStatement.java:384)
> at
> org.apache.derby.impl.jdbc.EmbedStatement.executeStatement(EmbedStatement.java:1235)
> at
> org.apache.derby.impl.jdbc.EmbedStatement.execute(EmbedStatement.java:625)
> at
> org.apache.derby.impl.jdbc.EmbedStatement.executeUpdate(EmbedStatement.java:175)
> at
> org.apache.derbyTesting.functionTests.tests.multi.StressMultiTest$StressMultiRunnable.update(StressMultiTest.
> java:471)
> ... 2 more
> FAILURES!!!
> Tests run: 3, Failures: 0, Errors: 1
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.