java.util.ConcurrentModificationException when using repeat step

158 views
Skip to first unread message

Max Benjamin

unread,
Dec 2, 2016, 11:21:51 AM12/2/16
to Gremlin-users
I'm using Titan 1.0 with Tinkerpop 3.0.1-incubating.

We have edges with properties on them and I have a traversal that looks like this:

g.V(start).emit().repeat(__.inE().has("isParent", true).outV());


I have attempted to exclude what appeared to be the issue (IncidentToAdjacentStrategy.java) by adding a lambda step to my traversal

g.V(start).filter(x -> true).emit().repeat(__.inE().has("isParent", true).outV());

That got me a bit further but the code still fails.

Here is the Java 8 stacktrace:

Caused by: java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
        at java.util.ArrayList$Itr.next(ArrayList.java:851)
        at java.util.Collections$UnmodifiableCollection$1.next(Collections.java:
1042)
        at org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper.h
asStepOfAssignableClassRecursively(TraversalHelper.java:228)
        at org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.
IncidentToAdjacentStrategy.apply(IncidentToAdjacentStrategy.java:75)
        at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalS
trategies.applyStrategies(DefaultTraversalStrategies.java:77)
        at org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaT
raversal.applyStrategies(AbstractLambdaTraversal.java:70)
        at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal.
applyStrategies(DefaultTraversal.java:91)
        at org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversal.
hasNext(DefaultTraversal.java:116)

I found a post that seems relevant to my issue, but there was no resolution.

https://groups.google.com/forum/#!msg/gremlin-users/Qy-eNtIMJkk/zMcU5PB6DAAJ;context-place=forum/gremlin-users

I am not sure what my options are at this point other than attempting to move to a newer version of Tinkerpop. Any help would be appreciated.

Daniel Kuppitz

unread,
Dec 2, 2016, 1:23:46 PM12/2/16
to gremli...@googlegroups.com
A version update is probably the best choice. I guess another option is to write an optimal traversal, so that strategies don't try to modify it.
However, if g.V(start).emit().repeat(__.inE().has("isParent", true).outV()) is in fact the original traversal that was throwing ConcurrentModificationExceptions, then I don't know how to rewrite it, since strategies have actually nothing to do here.

Cheers,
Daniel


--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/145420b2-645a-45ea-8b37-3c0ebb5df49e%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Max Benjamin

unread,
Dec 2, 2016, 11:13:53 PM12/2/16
to Gremlin-users
I plugged away at this today and found that emit() was the problem under heavy concurrency for whatever reason. In our application we want to see all vertices that can be reached exhaustively from a start point. emit() seemed like the best option but any use of emit() always resulted in a concurrent modification exception.

The query looks like this now (results is an ArrayList<Vertex>):

g.V(start).sideEffect(x -> results.add(x.get()).repeat(__.inE().has("isParent", true).outV().sideEffect(x -> results.add(x.get())).until(__.inE().has("isParent", true).count().is(0)).iterate()

I've heard that one should refrain from using lambda steps if possible, but I couldn't figure out how to use store() to accomplish this in tinkerpop3. In tinkerpop2 I remember store just took a Collection object which is what I've emulated here. 
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.

Daniel Kuppitz

unread,
Dec 3, 2016, 12:24:28 AM12/3/16
to gremli...@googlegroups.com
The new store() creates collections implicitly in the traverser's memory.

results = g.V(start).store("x").
            repeat(__.inE().has("isParent", true).outV().store("x")).
              until(__.not(__.inE().has("isParent", true))).
            cap("x").next()

It's also worth to read the docs. The code samples for Store Step show pretty clearly how it works.

Cheers,
Daniel


To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/cde99187-72d3-433c-ab78-6bfe82100960%40googlegroups.com.

Max Benjamin

unread,
Dec 3, 2016, 10:18:26 AM12/3/16
to Gremlin-users
Thanks for the example Daniel. I modified the code to use the store and cap steps.However in tinkerpop-3.0.1-incubating a BulkSet is output from cap("x").next(). I can then copy the contents to a List Collection and everything works just like the query with the lambda steps.

Is the performance of the store/cap query with an additional Collection copy faster or the same as using the lambda steps is this case? In other words, is there a large implicit cost to using a simple LambdaStep in gremlin?

Daniel Kuppitz

unread,
Dec 3, 2016, 10:48:42 AM12/3/16
to gremli...@googlegroups.com
The problem with lambda steps is that we can't inspect them, hence we have to assume that you're doing the craziest things in there, requiring all features you can think of. These assumptions prevent most strategies from doing their work and chances are high(er) that you end up with a traversal that doesn't have an optimal execution plan. If the default BulkSet is the only problem, you can also provide a custom side-effect (it can be any mutable collection):

results = [] // or result = [] as Set
g.withSideEffect("x", result).V(start).store("x").
  repeat(__.inE().has("isParent", true).outV().store("x")).
    until(__.not(__.inE().has("isParent", true))).
  iterate()

Cheers,
Daniel


To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/ce4529c2-b295-446c-a21c-b64cb46e58ba%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages