[ 
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.

Reply via email to