0
votes

This is a continuation of "Transaction was rolled back more times than it was started" Exception?

I managed to narrow down some of the problems I have experienced since I started to use OrientGraphFactory (meaning that before I used OrientGraph and did not see this NPE)

package oThread;

import java.io.File;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientGraph;
import com.tinkerpop.blueprints.impls.orient.OrientGraphFactory;

public class OThread {
    public static void main(String[] args){
        File f = new File(System.getProperty("user.home"), "oThread");
        f.mkdir();          
        OrientGraphFactory factory = new OrientGraphFactory("plocal:" + System.getProperty("user.home") + File.separatorChar + "oThread").setupPool(1, 10);
        factory.setAutoStartTx(false);
        final Vertex v1;
        final OrientGraph g = factory.getTx();
        g.begin();
        v1 = g.addVertex(null);
        g.commit();
        Thread t = new Thread(new Runnable(){
            public void run(){
                try{
                    v1.query().direction(Direction.OUT).labels("currentSuite").has("ID", 0).edges().iterator().hasNext();
                }
                catch(Exception x){
                    x.toString();
                }
            }
        });
        t.start();
        try {
             v1.query().direction(Direction.OUT).labels("currentSuite").has("ID", 0).edges().iterator().hasNext();
            t.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

The query inside the thread thows an NPE while the query outside the thread does not.

The stacktrace is

java.lang.NullPointerException
    at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.getEdgeClassNames(OrientBaseGraph.java:307)
    at com.tinkerpop.blueprints.impls.orient.OrientVertex.getEdges(OrientVertex.java:1005)
    at com.tinkerpop.blueprints.impls.orient.OrientVertex.getEdges(OrientVertex.java:988)
    at com.tinkerpop.blueprints.util.DefaultVertexQuery$DefaultVertexQueryIterable.<init>(DefaultVertexQuery.java:110)
    at com.tinkerpop.blueprints.util.DefaultVertexQuery.edges(DefaultVertexQuery.java:80)
    at oThread.OThread$1.run(OThread.java:28)
    at java.lang.Thread.run(Thread.java:745)

jvm 1.7.0_79 orientdb 2.0.12 CE. OS X 10.9

Any clues? Thanks a lot in advance!

UPDATE:

It seems that by asking the factory for another Graph instance and retrieving the vertex created before the query does not fail. I can work with that.

QUESTION:

"What happens when multiple clients add edges on the same vertex? OrientDB could throw the OConcurrentModificationException exception as well" is this statement true if one thread deletes an edge while another adds a second edge?

Just out of curiosity.

1

1 Answers

1
votes

The problem here is that you are using the same db instance in two different threads, you should avoid this because db is not thread safe.

OConcurrentModificationException can happen when you update the same vertex from two different processes. It's a technical detail: if a vertex has less than 40 edges (it's a configurable threshold), edge pointers are stored in the vertex documents, so adding an edge also leads to an increase in vertex version. Over this threshold edges are stored in an external structure (an SBTreeBonsai), so edge addition does not lead to increases in vertex version; in this case you do not have OConcurrentModificationException. Just make sure to fetch two distinct vertex instances and do not work in concurrency on the same object from two threads, it can lead to problems.