I'll try to generate a test case, but that is probably not going to be easy; I have noticed that a ConcurrentModificationException will only occur under somewhat bizarre circumstances that I do not yet fully understand, but this could to be related to the amount of time it takes the iterator to walk through scon.updateList. I'll try using the iterator and put in a delay.
Note the comments in the JDK API documentation about how this exception cannot be relied on. My guess is that next() does not check for modification every time next() is called on the iterator, and actually does not only check for structural but any kind of modification.
Hello Jan,
I've had a quick look at this and your change looks OK but I cannot see
why it would actually be needed given that ri.flush does not remove the
element, mearly nulls it.
I did find a related bug in SRecordMeta.flush.
I'll look at this some more later. If you can add a test case to
BasicTests (say) that would be great.
I'm hoping to get more feedback from people from the 2.15 candidate
before making it the production release.
Regards,
Anthony
Jan Tietze wrote:
>
> Anyone have any idea on whether this replacement for SConnection.flush()
>
> /** Flush all records of tables in this transaction to the database. */
> public static void flush(){
> SConnection scon = getBegunConnection();&
nbsp;
> // Iterator ci = scon.updateList.iterator();
>
> for (int i = 0; i < scon.updateList.size(); i++)
> {
> SRecordInstance ri = (SRecordInstance)scon.updateList.get(i);
> if (ri != null) ri.flush(); // Could have been manually flushed.
> }
> scon.updateList.clear();
> }
>
> will solve the problem and actually implement the intended behavior
> without side effects? I have implemented this and it seems to work
> fine. The previous code (as contained in 1.12 and 2.15) was
>
> /** Flush all records of tables in this transaction to the datab
ase. */
> public static void flush(){
> SConnection scon = getBegunConnection();
> Iterator ci = scon.updateList.iterator();
> while (ci.hasNext()) {
> SRecordInstance ri = (SRecordInstance)ci.next();
> if (ri != null) ri.flush(); // Could have been manually flushed.
> }
> scon.updateList.clear();
> }
> But - as shown below - this will lead to a
> ConcurrentModificationException sometimes.
>
> >>> jan.tietze <at> cuc.de 12.10.2004 15:57:26 >>>
> Interestingly, this problem now seems to hit me if I'm reading the
> source and exception correctly:
>
;
> java.util.ConcurrentModificationException
> at java.util.AbstractList$Itr.checkForComodification(Unknown Source)
> at java.util.AbstractList$Itr.next(Unknown Source)
> at simpleorm.core.SConnection.flush(SConnection.java:469)
> at simpleorm.core.SConnection.commit(SConnection.java:424)
> [...]
>
> in a single-thread process.
>
> I'm also in the process of upgrading from 1.12 to 2.15 and looked into
> the source, and it doesn't seem to correct this issue. I'll try this
> later today though.
>
> >>> sylvainhamel <at> hotmail.com 04.10.2004 14:48:35 >>>
>
> Will have a look.
>
> --- In SimpleORM <at> yahoogroups.com, Anthony & Melissa Berglas
> <berglas <at> S..> wrote:
> > Done, thanks.
> >
>
> Sylvain, is my use of java.util.Iterator.remove() break .Net? It
> is Java2.
> >
> > Regards,
> >
> > Anthony
> >
> > Weinhold Ingo wrote:
> >
> > > Howdy,
> > >
> > > I'm new to SimpleORM (more precisely have been evaluting it for a
> few weeks), so first thanks to Anthony for the nice tool.
> > >
> > > While reading a bit through the sources I've found a bug in
> SRecordMeta.flushAndPurge():
> > >
> > > public void flushAndPurge() {
> > > SConnection scon = SConnection.getBegunConnection();
> > > java.util.Iterator
ci = scon.transactionCache.values
> ().iterator();
> > > ! while (ci.hasNext()) {
> > > SRecordInstance ri = (SRecordInstance)ci.next();
> > > if (ri.getMeta() == this)
> > > ri.flushAndPurge();
> > > }
> > > }
> > >
> > > While iterating through transactionCache (a HashMap)
> ri.flushAndPurge() modifies it (remove()s the entry), which is not
> considered safe (expect a ConcurrentModificationException earlier or
> later).
> > >
> > > Simple solutions would be 1. to do the work in two passes --
> build
a separate list with the concerned records first and iterate
> over it afterwards -- or 2. have a package private
> SRecordInstance.flushAndPurge(boolean remove) that doesn't remove the
> record from the cache when being told so, and remove it in
> SRecordMeta using the iterator instead.
> >! >
> > > CU, Ingo
>
> Yahoo! Groups Sponsor
> ADVERTISEMENT
> <
http://us.ard.yahoo.com/SIG=1299q8rms/M=294855.5468653.6549235.3001176/D=groups/S=1705006905:HM/EXP=1097683510/A=2376776/R=0/SIG=11ldm1jvc/*http://promotions.yahoo.com/ydomains2004/index.html>
>
>
> Yahoo! Groups Links
>
;
> * To visit your group on the web, go to:
>
http://groups.yahoo.com/group/SimpleORM/>
> * To unsubscribe from this group, send an email to:
> SimpleORM-unsubscribe <at> yahoogroups.com
> <mailto:SimpleORM-unsubscribe <at> yahoogroups.com?subject=Unsubscribe>
>
> * Your use of Yahoo! Groups is subject to the Yahoo! Terms of
> Service <
http://docs.yahoo.com/info/terms/>.
>
>