Hello.
Are nested transaction supported?
>From what I'm testing here, it looks like unless I specify .failure() on the
nested transaction, before it reaches .finish() the transaction is
considered to be successful (even if I didn't call .success() on it). Though
if I do call .failure() then the root transaction will be rolled back with
exception:
Exception in thread "main" org.neo4j.graphdb.TransactionFailureException:
Unable to commit transaction
    at
org.neo4j.kernel.TopLevelTransaction.finish(TopLevelTransaction.java:98)
    at
org.neo4j.examples.CalculateShortestPath.main(CalculateShortestPath.java:116)
Caused by: javax.transaction.RollbackException: Failed to commit,
transaction rolledback
    at
org.neo4j.kernel.impl.transaction.TxManager.rollbackCommit(TxManager.java:811)
    at
org.neo4j.kernel.impl.transaction.TxManager.commit(TxManager.java:645)
    at
org.neo4j.kernel.impl.transaction.TransactionImpl.commit(TransactionImpl.java:109)
    at
org.neo4j.kernel.TopLevelTransaction.finish(TopLevelTransaction.java:85)
    ... 1 more

In the root transaction however, if I don't explicitly call .success() it is
considered failure and rolled back on finish. This seem to be the main
difference between root transaction and the nested transaction; was this
intended?

here's a sample program to test: (points 1. and 2. are important to me)
1. run it as it is, to see that nested transaction doesn't default to
failure when none of .failure() or .success() are specified before reaching
.finish(); is this a feature? (I just remembered that possibly someone told
me about this yesterday? I cannot find the message)
2. uncomment // nestyTx.failure();  to see what happens when specifically
stating that the nested transaction failed ==> the root one will rollback
with exception, which might be fine, I guess... though maybe I would expect
that the root transaction not be affected by a rolled back child
transaction, I mean, I might retry the child transaction and succeed the
second time, but the root will fail because some child transaction failed
before...
to get the idea of this, use this code block (you'll know where to put it,
replacing the old part):
                Transaction nestyTx = graphDb.beginTx();
                try {
                    Relationship rel = one.createRelationshipTo(
graphDb.createNode(), moo );
                    if ( i % 2 == 0 ) {
                        nestyTx.success();// no need to uncomment this, for
nested this is the default, not intended?
                    } else {
                        nestyTx.failure();// XXX: uncomment this to cause
rootTx to fail
                    }
                } finally {
                    nestyTx.finish();
                }

3. comment out the rootTx (all of begin/success/finish at once) to see the
speed that nestyTx has when it isn't a nested transaction ==> way slower
than when it's nested - though I guess this might make sense, since nothing
is really committed unless the root transaction commits.

/**
 * Licensed to Neo Technology under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Neo Technology licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.neo4j.examples;

import java.io.*;
import java.text.*;

import org.neo4j.graphdb.*;
import org.neo4j.graphdb.index.*;
import org.neo4j.kernel.*;



public class CalculateShortestPath {

    private static final int
SHOWINFO_IF_COUNTING_REL_TOOK_MORE_THAN_ns    = 2 * 300;
    private static final int            SHOWINFO_IF_REL_TOOK_MORE_THAN_ns
        = 30000;
    private static final int            SHOWEVERY_xTH_REL
        = 10000;
    private static final int            HOWMANY_RELATIONSHIPS
        = 9000;
    private static final String            DB_PATH
                = "neo4j-shortest-path";
    private static final String            NAME_KEY
            = "name";
    private static RelationshipType        KNOWS
            = DynamicRelationshipType

            .withName( "KNOWS" );

    private static GraphDatabaseService    graphDb;
    private static Index<Node>            indexService;
    private static DecimalFormat        commaDelimitedFormatter
            = new DecimalFormat( "###,###" );


    public static String number( double val ) {
        return commaDelimitedFormatter.format( val );
    }


    public static void main( final String[] args ) {
        // deleteFileOrDirectory( new File( DB_PATH ) );// XXX:
        graphDb = new EmbeddedGraphDatabase( DB_PATH );
        indexService = graphDb.index().forNodes( "nodes" );
        registerShutdownHook();
        Transaction rootTx;
        rootTx = graphDb.beginTx();
        Node one = getOrCreateNode( "one" );
        DynamicRelationshipType moo = DynamicRelationshipType.withName(
"moo" );
        try {
            for ( int i = 1; i <= HOWMANY_RELATIONSHIPS; i++ ) {
                long start = System.nanoTime();
                Transaction nestyTx = graphDb.beginTx();
                try {
                    Relationship rel = one.createRelationshipTo(
graphDb.createNode(), moo );
                    // nestyTx.success();//no need to uncomment this, for
nested this is the default
                    // nestyTx.failure();//XXX: uncomment this to cause
rootTx to fail
                } finally {
                    nestyTx.finish();
                }
                // rel.setProperty( "relname", i );
                long end = System.nanoTime();
                if ( ( i % SHOWEVERY_xTH_REL == 0 ) || ( end - start >
SHOWINFO_IF_REL_TOOK_MORE_THAN_ns ) ) {
                    System.out.println( number( i ) + " timeDelta=" +
number( end - start ) );
                }
            }

            System.out.println( "counting..." );
            long start = System.nanoTime();
            Iterable<Relationship> rel = one.getRelationships(
Direction.OUTGOING, moo );
            long count = 0;
            long tstart = 0;
            for ( Relationship relationship : rel ) {
                // long tend = System.nanoTime();
                count++;
                // if ( ( tend - tstart >
SHOWINFO_IF_COUNTING_REL_TOOK_MORE_THAN_ns ) ) {
                // System.out.println( number( count ) + " timeDelta=" +
number( tend - tstart ) );
                // }
                // tstart = System.nanoTime();
            }
            long end = System.nanoTime();
            System.out.println( "Node `" + one.getProperty( NAME_KEY ) + "`
has " + number( count ) + " out rels, time="
                + number( end - start ) );

            // /*
            // * (Neo) --> (Trinity)
            // * \ ^
            // * v /
            // * (Morpheus) --> (Cypher)
            // * \ |
            // * v v
            // * (Agent Smith)
            // */
            // createChain( "Neo", "Trinity" );
            // createChain( "Neo", "Morpheus", "Trinity" );
            // createChain( "Morpheus", "Cypher", "Agent Smith" );
            // createChain( "Morpheus", "Agent Smith" );
            rootTx.success();
        } finally {
            long start = System.nanoTime();
            rootTx.finish();
            long end = System.nanoTime();
            System.out.println( "tx.finish() time=" + number( end - start )
);
        }


        rootTx = graphDb.beginTx();
        try {
            System.out.println( "counting outside of transaction..." );
            long start = System.nanoTime();
            Iterable<Relationship> rel = one.getRelationships(
Direction.OUTGOING, moo );
            long count = 0;
            for ( Relationship relationship : rel ) {
                count++;
            }
            long end = System.nanoTime();
            System.out.println( "Node `" + one.getProperty( NAME_KEY ) + "`
has " + number( count ) + " out rels, time="
                + number( end - start ) );
            // So let's find the shortest path between Neo and Agent Smith
            // Node neo = getOrCreateNode( "Neo" );
            // Node agentSmith = getOrCreateNode( "Agent Smith" );
            // // START SNIPPET: shortestPathUsage
            // PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
Traversal.expanderForTypes( KNOWS, Direction.BOTH ), 4
            // );
            // Path foundPath = finder.findSinglePath( neo, agentSmith );
            // System.out.println( "Path from Neo to Agent Smith: " +
Traversal.simplePathToString( foundPath, NAME_KEY ) );
            // END SNIPPET: shortestPathUsage
            rootTx.success();
        } finally {
            rootTx.finish();
        }

        // graphDb.shutdown();
    }


    private static void createChain( String... names ) {
        for ( int i = 0; i < names.length - 1; i++ ) {
            Node firstNode = getOrCreateNode( names[i] );
            Node secondNode = getOrCreateNode( names[i + 1] );
            firstNode.createRelationshipTo( secondNode, KNOWS );
        }
    }


    private static Node getOrCreateNode( String name ) {
        Node node = indexService.get( NAME_KEY, name ).getSingle();
        if ( node == null ) {
            System.out.println( "creating new node with name=" + name );
            node = graphDb.createNode();
            node.setProperty( NAME_KEY, name );
            indexService.add( node, NAME_KEY, name );
        }
        return node;
    }


    private static void registerShutdownHook() {
        // Registers a shutdown hook for the Neo4j instance so that it
        // shuts down nicely when the VM exits (even if you "Ctrl-C" the
        // running example before it's completed)
        Runtime.getRuntime().addShutdownHook( new Thread() {

            @SuppressWarnings( "synthetic-access" )
            @Override
            public void run() {
                System.out.println( "Shutting down database ..." );
                graphDb.shutdown();
            }
        } );
    }


    private static void deleteFileOrDirectory( File file ) {
        if ( file.exists() ) {
            if ( file.isDirectory() ) {
                for ( File child : file.listFiles() ) {
                    deleteFileOrDirectory( child );
                }
            }
            file.delete();
        }
    }
}
_______________________________________________
Neo4j mailing list
User@lists.neo4j.org
https://lists.neo4j.org/mailman/listinfo/user

Reply via email to