This is an automated email from the ASF dual-hosted git repository.

colegreer pushed a commit to branch 3.7-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/3.7-dev by this push:
     new db369864ab Transaction reads should not interfere with 
add/update/delete (#3163)
db369864ab is described below

commit db369864ab77ac7be743d38adb8994ee8b123ea0
Author: andreachild <[email protected]>
AuthorDate: Fri Jul 25 12:38:45 2025 -0700

    Transaction reads should not interfere with add/update/delete (#3163)
    
    https://issues.apache.org/jira/browse/TINKERPOP-3142
    
    Changed TinkerElementContainer to no longer consider element reads as being 
'used in a transaction' which should be reserved for element add/update/delete 
only. This is appropriate for TinkerTransactionGraph because the isolation 
level is 'read committed'. With this isolation level, we do not need to protect 
against 'unrepeatable reads' or 'phantom reads'.
    
    Prior to this change, a read-only thread could cause a 'Conflict: element 
modified in another transaction' error in a separate thread which was 
attempting add/drop/update.
---
 CHANGELOG.asciidoc                                 |   1 +
 .../reference/implementations-tinkergraph.asciidoc |   4 +-
 .../structure/TinkerElementContainer.java          |   7 +-
 .../structure/TinkerTransactionGraphTest.java      | 218 +++++++++++++++++----
 4 files changed, 190 insertions(+), 40 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 4cda658fbb..340ed51910 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -57,6 +57,7 @@ 
image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 * Increased default `max_content_length`/`max_msg_size` in `gremlin-python` 
from 4MB to 10MB.
 * Added the `PopContaining` interface designed to get label and `Pop` 
combinations held in a `PopInstruction` object.
 * Fixed bug preventing a vertex from being dropped and then re-added in the 
same `TinkerTransaction`
+* Fixed bug which could cause a 'Conflict: element modified in another 
transaction' when a transaction is attempting to add/drop/update a vertex or 
edge while another transaction is reading the same vertex or edge.
 
 [[release-3-7-3]]
 === TinkerPop 3.7.3 (October 23, 2024)
diff --git a/docs/src/reference/implementations-tinkergraph.asciidoc 
b/docs/src/reference/implementations-tinkergraph.asciidoc
index ecd43faede..1377448496 100644
--- a/docs/src/reference/implementations-tinkergraph.asciidoc
+++ b/docs/src/reference/implementations-tinkergraph.asciidoc
@@ -221,8 +221,8 @@ supported. You can think of the transaction as belonging to 
a thread, any traver
 will share the same transaction even if you attempt to start a new transaction.
 
 `TinkerTransactionGraph` provides the `read committed` transaction isolation 
level. This means that it will always try to
-guard against dirty reads. While you may notice stricter isolation semantics 
in some cases, you should not depend on
-this behavior as it may change in the future.
+guard against dirty reads but will not prevent non-repeatable reads or phantom 
reads. While you may notice stricter 
+isolation semantics in some cases, you should not depend on this behavior as 
it may change in the future.
 
 `TinkerTransactionGraph` employs optimistic locking as its locking strategy. 
This reduces complexity in the design as
 there are fewer timeouts that the user needs to manage. However, a consequence 
of this approach is that a transaction
diff --git 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerElementContainer.java
 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerElementContainer.java
index afd875aff1..e945a68c79 100644
--- 
a/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerElementContainer.java
+++ 
b/tinkergraph-gremlin/src/main/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerElementContainer.java
@@ -59,7 +59,7 @@ final class TinkerElementContainer<T extends TinkerElement> {
     private final ThreadLocal<Boolean> isReadInTx = ThreadLocal.withInitial(() 
-> false);
 
     /**
-     * Count of usages of container in different transactions.
+     * Count of modification/deletion/addition usages of container in 
different transactions (reads do not contribute to this count).
      * Needed to understand whether this element is used in other transactions 
or it can be deleted during rollback.
      */
     private final AtomicInteger usesInTransactions = new AtomicInteger(0);
@@ -97,7 +97,6 @@ final class TinkerElementContainer<T extends TinkerElement> {
 
         if (!isReadInTx.get()) {
             isReadInTx.set(true);
-            usesInTransactions.incrementAndGet();
             tx.markRead(this);
         }
 
@@ -205,7 +204,7 @@ final class TinkerElementContainer<T extends TinkerElement> 
{
     }
 
     /**
-     * Used to understand if element is in use by any transaction.
+     * Used to understand if element is in use (added, modified, or deleted) 
by any transaction.
      */
     public boolean inUse() {
         return usesInTransactions.get() > 0;
@@ -246,8 +245,6 @@ final class TinkerElementContainer<T extends TinkerElement> 
{
             usesInTransactions.decrementAndGet();
         if (isModifiedInTx.get())
             usesInTransactions.decrementAndGet();
-        if (isReadInTx.get())
-            usesInTransactions.decrementAndGet();
     }
 
     /**
diff --git 
a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerTransactionGraphTest.java
 
b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerTransactionGraphTest.java
index ce3f73f756..ef9a616987 100644
--- 
a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerTransactionGraphTest.java
+++ 
b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerTransactionGraphTest.java
@@ -18,21 +18,26 @@
  */
 package org.apache.tinkerpop.gremlin.tinkergraph.structure;
 
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 import 
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.structure.Edge;
+import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.apache.tinkerpop.gremlin.structure.VertexProperty;
 import org.apache.tinkerpop.gremlin.structure.util.TransactionException;
 import org.junit.Test;
 
-import java.util.ArrayList;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -44,6 +49,9 @@ import static org.junit.Assert.fail;
 public class TinkerTransactionGraphTest {
 
     private static final String PROPERTY_NAME = "name";
+    private static final String PROPERTY_WEIGHT = "weight";
+    private static final String EDGE_LABEL = "tests";
+    private static final int EDGE_ID = 200;
     final Object vid = 100;
 
     ///// vertex tests
@@ -255,13 +263,13 @@ public class TinkerTransactionGraphTest {
 
         final TinkerVertex v1 = (TinkerVertex) gtx.addV().next();
         final TinkerVertex v2 = (TinkerVertex) gtx.addV().next();
-        gtx.addE("tests").from(v1).to(v2).next();
+        gtx.addE(EDGE_LABEL).from(v1).to(v2).next();
         gtx.tx().commit();
 
         assertEquals(2, (long) gtx.V().count().next());
         assertEquals(1, (long) gtx.E().count().next());
 
-        gtx.E().hasLabel("tests").drop().iterate();
+        gtx.E().hasLabel(EDGE_LABEL).drop().iterate();
 
         assertEquals(2, (long) gtx.V().count().next());
         assertEquals(0, (long) gtx.E().count().next());
@@ -284,8 +292,8 @@ public class TinkerTransactionGraphTest {
         final TinkerVertex v1afterTx = g.getVertices().get(v1.id()).get();
         final TinkerVertex v2afterTx = g.getVertices().get(v2.id()).get();
         assertNull(v1afterTx.inEdgesId);
-        assertEquals(0, v1afterTx.outEdgesId.get("tests").size());
-        assertEquals(0, v2afterTx.inEdgesId.get("tests").size());
+        assertEquals(0, v1afterTx.outEdgesId.get(EDGE_LABEL).size());
+        assertEquals(0, v2afterTx.inEdgesId.get(EDGE_LABEL).size());
         assertNull(v2afterTx.outEdgesId);
 
         // should remove unused container
@@ -302,13 +310,13 @@ public class TinkerTransactionGraphTest {
 
         final TinkerVertex v1 = (TinkerVertex) gtx.addV().next();
         final TinkerVertex v2 = (TinkerVertex) gtx.addV().next();
-        gtx.addE("tests").from(v1).to(v2).next();
+        gtx.addE(EDGE_LABEL).from(v1).to(v2).next();
         gtx.tx().commit();
 
         assertEquals(2, (long) gtx.V().count().next());
         assertEquals(1, (long) gtx.E().count().next());
 
-        gtx.E().hasLabel("tests").drop().iterate();
+        gtx.E().hasLabel(EDGE_LABEL).drop().iterate();
 
         assertEquals(2, (long) gtx.V().count().next());
         assertEquals(0, (long) gtx.E().count().next());
@@ -320,7 +328,7 @@ public class TinkerTransactionGraphTest {
             assertEquals(1L, (long) gtx2.E().count().next());
 
             // try to remove edge
-            gtx2.E().hasLabel("tests").drop().iterate();
+            gtx2.E().hasLabel(EDGE_LABEL).drop().iterate();
 
             // should be ok
             assertEquals(2, (long) gtx2.V().count().next());
@@ -349,8 +357,8 @@ public class TinkerTransactionGraphTest {
         final TinkerVertex v1afterTx = g.getVertices().get(v1.id()).get();
         final TinkerVertex v2afterTx = g.getVertices().get(v2.id()).get();
         assertNull(v1afterTx.inEdgesId);
-        assertEquals(0, v1afterTx.outEdgesId.get("tests").size());
-        assertEquals(0, v2afterTx.inEdgesId.get("tests").size());
+        assertEquals(0, v1afterTx.outEdgesId.get(EDGE_LABEL).size());
+        assertEquals(0, v2afterTx.inEdgesId.get(EDGE_LABEL).size());
         assertNull(v2afterTx.outEdgesId);
 
         countElementsInNewThreadTx(g, 2, 0);
@@ -529,7 +537,7 @@ public class TinkerTransactionGraphTest {
 
         final TinkerVertex v1 = (TinkerVertex) gtx.addV().next();
         final TinkerVertex v2 = (TinkerVertex) gtx.addV().next();
-        final TinkerEdge edge = (TinkerEdge) 
gtx.addE("tests").property("test-property", 1).from(v1).to(v2).next();
+        final TinkerEdge edge = (TinkerEdge) 
gtx.addE(EDGE_LABEL).property("test-property", 1).from(v1).to(v2).next();
 
         assertEquals(1L, (long) gtx.E().has("test-property", 
1).count().next());
         assertEquals(1L, (long) gtx.E().count().next());
@@ -569,7 +577,7 @@ public class TinkerTransactionGraphTest {
 
         final TinkerVertex v1 = (TinkerVertex) gtx.addV().next();
         final TinkerVertex v2 = (TinkerVertex) gtx.addV().next();
-        final TinkerEdge edge = (TinkerEdge) 
gtx.addE("tests").property("test-property", 1).from(v1).to(v2).next();
+        final TinkerEdge edge = (TinkerEdge) 
gtx.addE(EDGE_LABEL).property("test-property", 1).from(v1).to(v2).next();
         gtx.tx().commit();
 
         gtx.E(edge.id()).property("test-property", 2).iterate();
@@ -616,7 +624,7 @@ public class TinkerTransactionGraphTest {
 
         final TinkerVertex v1 = (TinkerVertex) gtx.addV().next();
         final TinkerVertex v2 = (TinkerVertex) gtx.addV().next();
-        final TinkerEdge edge = (TinkerEdge) 
gtx.addE("tests").property("test-property", 1).from(v1).to(v2).next();
+        final TinkerEdge edge = (TinkerEdge) 
gtx.addE(EDGE_LABEL).property("test-property", 1).from(v1).to(v2).next();
         gtx.tx().commit();
 
         gtx.E(edge.id()).drop().iterate();
@@ -658,7 +666,7 @@ public class TinkerTransactionGraphTest {
 
         final TinkerVertex v1 = (TinkerVertex) gtx.addV().next();
         final TinkerVertex v2 = (TinkerVertex) gtx.addV().next();
-        final TinkerEdge edge = (TinkerEdge) 
gtx.addE("tests").property("test-property", nullValue).
+        final TinkerEdge edge = (TinkerEdge) 
gtx.addE(EDGE_LABEL).property("test-property", nullValue).
                 from(v1).to(v2).next();
 
         assertEquals(1L, (long) gtx.E().has("test-property", 
nullValue).count().next());
@@ -701,7 +709,7 @@ public class TinkerTransactionGraphTest {
         // create initial edge with indexed property
         final TinkerVertex v1 = (TinkerVertex) gtx.addV().next();
         final TinkerVertex v2 = (TinkerVertex) gtx.addV().next();
-        final TinkerEdge edge = (TinkerEdge) 
gtx.addE("tests").property("test-property", 1).
+        final TinkerEdge edge = (TinkerEdge) 
gtx.addE(EDGE_LABEL).property("test-property", 1).
                 from(v1).to(v2).next();
 
         gtx.tx().commit();
@@ -1030,7 +1038,7 @@ public class TinkerTransactionGraphTest {
 
         final Vertex v1 = gtx.addV().next();
         final Vertex v2 = gtx.addV().next();
-        final Edge edge = gtx.addE("tests").from(v1).to(v2).next();
+        final Edge edge = gtx.addE(EDGE_LABEL).from(v1).to(v2).next();
         gtx.tx().commit();
 
         // tx1 try to add property
@@ -1099,13 +1107,13 @@ public class TinkerTransactionGraphTest {
 
         final Vertex v1 = gtx.addV().next();
         final Vertex v2 = gtx.addV().next();
-        gtx.addE("tests").from(v1).to(v2).next();
+        gtx.addE(EDGE_LABEL).from(v1).to(v2).next();
         gtx.tx().commit();
 
         assertEquals(2, (long) gtx.V().count().next());
         assertEquals(1, (long) gtx.E().count().next());
 
-        gtx.E().hasLabel("tests").drop().iterate();
+        gtx.E().hasLabel(EDGE_LABEL).drop().iterate();
 
         assertEquals(2, (long) gtx.V().count().next());
         assertEquals(0, (long) gtx.E().count().next());
@@ -1134,7 +1142,7 @@ public class TinkerTransactionGraphTest {
 
         final Vertex v1 = gtx.addV().next();
         final Vertex v2 = gtx.addV().next();
-        final Edge edge = gtx.addE("tests").from(v1).to(v2).next();
+        final Edge edge = gtx.addE(EDGE_LABEL).from(v1).to(v2).next();
         gtx.tx().commit();
 
         // change test property
@@ -1235,13 +1243,13 @@ public class TinkerTransactionGraphTest {
 
         final Vertex v1 = gtx.addV().next();
         final Vertex v2 = gtx.addV().next();
-        gtx.addE("tests").from(v1).to(v2).next();
+        gtx.addE(EDGE_LABEL).from(v1).to(v2).next();
         gtx.tx().commit();
 
         assertEquals(2, (long) gtx.V().count().next());
         assertEquals(1, (long) gtx.E().count().next());
 
-        gtx.E().hasLabel("tests").drop().iterate();
+        gtx.E().hasLabel(EDGE_LABEL).drop().iterate();
 
         assertEquals(2, (long) gtx.V().count().next());
         assertEquals(0, (long) gtx.E().count().next());
@@ -1253,7 +1261,7 @@ public class TinkerTransactionGraphTest {
             assertEquals(1L, (long) gtx2.E().count().next());
 
             // try to remove edge
-            gtx2.E().hasLabel("tests").drop().iterate();
+            gtx2.E().hasLabel(EDGE_LABEL).drop().iterate();
 
             // should be ok
             assertEquals(2, (long) gtx2.V().count().next());
@@ -1517,7 +1525,7 @@ public class TinkerTransactionGraphTest {
         final GraphTraversalSource gtx = tx.begin();
         Vertex vertex = gtx.addV().property(T.id, vid).property(PROPERTY_NAME, 
"test").next();
         // add self-referencing edge
-        gtx.addE("tests").from(vertex).to(vertex).next();
+        gtx.addE(EDGE_LABEL).from(vertex).to(vertex).next();
         gtx.tx().commit();
 
         verifyCommittedSingleVertex(g, "test");
@@ -1546,7 +1554,7 @@ public class TinkerTransactionGraphTest {
         // create vertex with a property
         final Vertex vertex = gtx.addV().property(T.id, 
vid).property(PROPERTY_NAME, "test").next();
         // add self-referencing edge
-        gtx.addE("tests").from(vertex).to(vertex).next();
+        gtx.addE(EDGE_LABEL).from(vertex).to(vertex).next();
         // drop vertex
         gtx.V(vid).drop().iterate();
         // add vertex again with different properties but no edges
@@ -1566,7 +1574,7 @@ public class TinkerTransactionGraphTest {
         // create vertex with a property
         final Vertex vertex = gtx.addV().property(T.id, 
vid).property(PROPERTY_NAME, "test").next();
         // add self-referencing edge
-        gtx.addE("tests").from(vertex).to(vertex).next();
+        gtx.addE(EDGE_LABEL).from(vertex).to(vertex).next();
         // drop vertex
         gtx.V(vid).drop().iterate();
         // add vertex again with different properties but no edges
@@ -1589,7 +1597,7 @@ public class TinkerTransactionGraphTest {
         // create vertex with a property
         final Vertex vertex = gtx1.addV().property(T.id, 
vid).property(PROPERTY_NAME, "test").next();
         // add self-referencing edge
-        gtx1.addE("tests").from(vertex).to(vertex).next();
+        gtx1.addE(EDGE_LABEL).from(vertex).to(vertex).next();
         // drop vertex
         gtx1.V(vid).drop().iterate();
         gtx1.tx().commit();
@@ -1705,6 +1713,115 @@ public class TinkerTransactionGraphTest {
             verifyCommittedSingleVertex(g, "updated");
         }
     }
+
+    @Test
+    public void 
readVertexShouldNotConflictWithDropAddUpdateVertexInSeparateTransaction() 
throws InterruptedException {
+        final TinkerTransactionGraph graph = TinkerTransactionGraph.open();
+        final GraphTraversalSource g = graph.traversal();
+        final GraphTraversalSource gtx = g.tx().begin();
+        final AtomicReference<AssertionError> validationException = new 
AtomicReference<>();
+
+        // commit the initial vertex
+        gtx.addV().property(T.id, vid).next();
+        gtx.tx().commit();
+
+        // reader threads which are constantly reading the vertex ids in a 
separate transaction
+        CountDownLatch signal = new CountDownLatch(1);
+        List<Thread> readers = startInNewThreads(() -> {
+            while (signal.getCount() > 0) {
+                List<Object> vertexIds = g.V().id().toList();
+                // vertexIds should be empty or have a single id equal to the 
vertexId
+                if (validationException.get() == null && vertexIds.size() > 1 
|| (vertexIds.size() == 1 && !vertexIds.get(0).equals(vid))) {
+                    validationException.set(new AssertionError("Unexpected 
vertexIds: " + vertexIds));
+                }
+            }
+        }, 2);
+
+        // drop, add, update the same vertex a number of times to validate 
that the reader thread should not interfere with the updates
+        for (int i = 0; i < 50; i++) {
+            Thread.sleep(50);
+            g.V(vid).drop().iterate();
+            g.tx().commit();
+            Thread.sleep(50);
+            g.addV().property(T.id, vid).next();
+            g.tx().commit();
+            g.V(vid).property(VertexProperty.Cardinality.single, "name", 
"test").next();
+            g.tx().commit();
+            g.V(vid).property(VertexProperty.Cardinality.single, "name", 
"updated").next();
+            g.tx().commit();
+        }
+
+        // stop the reader thread
+        signal.countDown();
+        readers.forEach(t -> {
+            try {
+                t.join();
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+        verifyCommittedSingleVertex(graph, "updated");
+        if (validationException.get() != null) {
+            throw validationException.get();
+        }
+    }
+
+    @Test
+    public void 
readEdgeShouldNotConflictWithDropAddUpdateEdgeInSeparateTransaction() throws 
InterruptedException {
+        final TinkerTransactionGraph graph = TinkerTransactionGraph.open();
+        final GraphTraversalSource g = graph.traversal();
+        final GraphTraversalSource gtx = g.tx().begin();
+        final AtomicReference<AssertionError> validationException = new 
AtomicReference<>();
+
+        // commit the initial vertex with self-referencing edge
+        Vertex vertex = gtx.addV().property(T.id, vid).next();
+        gtx.addE(EDGE_LABEL).from(vertex).to(vertex).property(T.id, 
EDGE_ID).next();
+        gtx.tx().commit();
+
+        // reader threads which are constantly reading the edge ids in a 
separate transaction
+        CountDownLatch signal = new CountDownLatch(1);
+        List<Thread> readers = startInNewThreads(() -> {
+            while (signal.getCount() > 0) {
+                List<Object> edgIds = g.E().id().toList();
+                if (validationException.get() == null && (edgIds.size() > 1 || 
(edgIds.size() == 1 && !edgIds.get(0).equals(EDGE_ID)))) {
+                    validationException.set(new AssertionError("Unexpected 
edgeIds: " + edgIds));
+                }
+
+            }
+        }, 2);
+
+        // drop, add, update the same edge a number of times to validate that 
the reader thread should not interfere with the updates
+        for (int i = 0; i < 50; i++) {
+            Thread.sleep(50);
+            g.E().drop().iterate();
+            g.tx().commit();
+            Thread.sleep(50);
+            Vertex v = g.V(vid).next();
+            g.addE(EDGE_LABEL).property(T.id, EDGE_ID).from(v).to(v).next();
+            g.tx().commit();
+            g.E(EDGE_ID).property(PROPERTY_WEIGHT, 10.12).next();
+            g.tx().commit();
+            g.E(EDGE_ID).property(PROPERTY_WEIGHT, 8.6).next();
+            g.tx().commit();
+        }
+
+        // stop the reader threads
+        signal.countDown();
+        readers.forEach(t -> {
+            try {
+                t.join();
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+        });
+        
+        verifyCommittedSingleVertex(graph);
+        verifyCommittedSingleEdge(graph, 8.6);
+        if (validationException.get() != null) {
+            throw validationException.get();
+        }
+    }
     
     private void runInNewThread(final Runnable runnable) {
         final Thread thread = new Thread(runnable);
@@ -1716,6 +1833,41 @@ public class TinkerTransactionGraphTest {
         }
     }
 
+    private List<Thread> startInNewThreads(final Runnable runnable, int 
numThreads) {
+        return IntStream.range(0, numThreads).mapToObj(i -> {
+            final Thread thread = new Thread(runnable);
+            thread.start();
+            return thread;
+        }).collect(Collectors.toList());
+    }
+    
+    private void verifyCommittedSingleEdge(final TinkerTransactionGraph g, 
final Object weightValue) {
+        // graph should only have a single edge
+        assertEquals(1, g.getEdges().size());
+
+        // the single edge should have the expected id
+        final TinkerElementContainer<TinkerEdge> edgeContainer = 
g.getEdges().get(EDGE_ID);
+
+        // container should be committed and not have an update in progress
+        assertFalse(edgeContainer.isChanged());
+        assertFalse(edgeContainer.inUse());
+
+        // the element in the container should have the same id
+        // there are multiple ways to obtain the container element's id and 
they should be consistent
+        assertEquals(EDGE_ID, edgeContainer.getElementId());
+        assertEquals(EDGE_ID, edgeContainer.get().id());
+        final TinkerEdge unmodified = edgeContainer.getUnmodified();
+        assertEquals(EDGE_ID, unmodified.id());
+        assertEquals(EDGE_LABEL, unmodified.label());
+
+        if (weightValue != null) {
+            Iterator<Property<Object>> properties = 
unmodified.properties(PROPERTY_WEIGHT);
+            assertEquals(weightValue, properties.next().value());
+        } else {
+            assertNull(unmodified.properties);
+        }
+    }
+
     private void verifyCommittedSingleVertex(final TinkerTransactionGraph g) {
         verifyCommittedSingleVertex(g, null);
     }
@@ -1739,13 +1891,13 @@ public class TinkerTransactionGraphTest {
         assertEquals(vid, unmodified.id());
 
         if (namePropertyValue != null) {
-            final Map<String, List<VertexProperty>> properties = 
g.getVertices().get(vid).getUnmodified().properties;
+            final Map<String, List<VertexProperty>> properties = 
unmodified.properties;
             assertEquals(1, properties.size());
             final List<VertexProperty> nameProperties = 
properties.get(PROPERTY_NAME);
             assertEquals(1, nameProperties.size());
             assertEquals(namePropertyValue, nameProperties.get(0).value());
         } else {
-            assertNull(vertexContainer.getUnmodified().properties);
+            assertNull(unmodified.properties);
         }
     }
 }

Reply via email to