|
[
Permlink
| « Hide
]
Knut Anders Hatlen added a comment - 20/May/08 03:16 PM
I think this is also a problem for the statement event listeners (JDBC 4.0 feature).
I agree that copying the collection sounds like a reasonable approach. Strictly speaking, we only need a copy if there are at least two listeners in the list, but it is perhaps not worth the extra complexity to avoid copying 1-element lists. I'll try it and see how complex it gets.
Alternatively, we could have a copy-on-write scheme so that we only pay the extra price if we actually modify the list of listeners (this assumes that the listeners are triggered more frequently than they are modified). For the statement event listeners, we could get this more or less for free with java.util.concurrent.CopyOnWriteArrayList (new in Java 1.5) since that code is compiled with the 1.6 compiler. Here's a test and a fix for the statement event listeners. In the current trunk, adding or removing listeners from a listener causes ConcurrentModificationException (both client and embedded). Since this was JDBC 4.0 code, I went for the simple solution and just replaced Vector/ArrayList with CopyOnWriteArrayList and removed the synchronization.
All the regression tests passed. I had a look at ' d3401-statement_events.diff'. I think it looks good, but I have one question.
Any reason why you allow null objects into the list of listeners in ClientPooledConnection40 and ClientXAConnection40? Can't you get an NPE when you iterate through the list of listeners and invoke the callback method? I ran the new test(s) successfully, but modifying it to add a null listener causes failures. +1 to commit if you plan to address the NPE elsewhere or in a followup patch. Thanks for looking at the patch Kristian. Since the different handling of null in client versus embedded is an existing issue, I filed a new bug (
Committed d3401-statement_events.diff with revision 660959.
Attaching a patch which fixes the problem with the ConnectionEventListeners, enables the test case for removing a listener and adds a test case for adding a listener.
The fix makes the PC update a variable each time it starts iterating over the list of listeners and each time it has finished iterating. That way, (add/remove)ConnectionEventListener knows if the list is currently being iterated over. If it is being iterated over, the list is cloned and the add/remove operation is performed on the clone. That way, the iterator is not affected and continues to work just as if no listener has been added or removed. The logic is somewhat more complex than the code for the statement event listeners, as we don't have CopyOnWriteArrayList available in Java 1.4. However, it is less costly, as it only copies the list in the cases where modifying the list directly would have caused problems (CopyOnWriteArrayList always copies the list when it's modified). All the regression tests passed with this patch. I looked at the patch 'd3401-connection_events.diff' and it looks good to me.
suites.All (Sun JDK 1.5) and derbyall (Sun JDK 1.6) passed without failures. +1 to commit Thanks for reviewing the patch, Kristian.
Committed revision 663641. I'll probably merge it to 10.4 in a couple of days, so I'm leaving the issue open for now. Merged to 10.4 and committed revision 664655.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||