You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by da...@apache.org on 2016/10/07 14:36:29 UTC

[01/37] tinkerpop git commit: Corrected a number of problems in close() operations for the driver. [Forced Update!]

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1458 9ceb85361 -> a80b7cde7 (forced update)


Corrected a number of problems in close() operations for the driver.

This was more of a commit than I wanted for tp31, but close() was really messed up. Fixed a number of race conditions and other logic that would allow the driver to hang on close. Also made it so that the Cluster makes an attempt to clean up any Client instances that it spawns.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/6d14adb0
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/6d14adb0
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/6d14adb0

Branch: refs/heads/TINKERPOP-1458
Commit: 6d14adb0819e2ede0b1e7794f384af2910fdbc84
Parents: 0070d3d
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Thu Sep 29 08:40:07 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Sep 30 06:53:53 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../upgrade/release-3.1.x-incubating.asciidoc   | 17 +++++
 .../tinkerpop/gremlin/driver/Channelizer.java   |  6 +-
 .../apache/tinkerpop/gremlin/driver/Client.java | 42 +++++++++--
 .../tinkerpop/gremlin/driver/Cluster.java       | 22 +++++-
 .../tinkerpop/gremlin/driver/Connection.java    | 68 +++++++++++++++--
 .../gremlin/driver/ConnectionPool.java          | 21 +++---
 .../tinkerpop/gremlin/driver/Handler.java       | 27 +++++--
 .../tinkerpop/gremlin/driver/ResultQueue.java   |  4 +
 .../driver/handler/WebSocketClientHandler.java  |  4 +-
 .../server/GremlinDriverIntegrateTest.java      | 79 +++++++++++++++++++-
 .../server/GremlinServerAuthIntegrateTest.java  |  5 +-
 .../GremlinServerAuthOldIntegrateTest.java      |  4 +-
 .../GremlinServerSessionIntegrateTest.java      |  6 +-
 14 files changed, 255 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index d0aa8e8..9f45477 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.1.5 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Improved handling of `Cluster.close()` and `Client.close()` to prevent the methods from hanging.
 * Fixed output redirection and potential memory leak in `GremlinGroovyScriptEngine`.
 * Corrected naming of `g_withPath_V_asXaX_out_out_mapXa_name_it_nameX` and `g_withPath_V_asXaX_out_mapXa_nameX` in `MapTest`.
 * Improved session cleanup when a close is triggered by the client.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/docs/src/upgrade/release-3.1.x-incubating.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.1.x-incubating.asciidoc b/docs/src/upgrade/release-3.1.x-incubating.asciidoc
index 400ea10..6cf9fb2 100644
--- a/docs/src/upgrade/release-3.1.x-incubating.asciidoc
+++ b/docs/src/upgrade/release-3.1.x-incubating.asciidoc
@@ -27,6 +27,23 @@ TinkerPop 3.1.5
 
 *Release Date: NOT OFFICIALLY RELEASED YET*
 
+Please see the link:https://github.com/apache/tinkerpop/blob/3.1.4/CHANGELOG.asciidoc#tinkerpop-315-release-date-XXXXXXXXXXXX[changelog] for a complete list of all the modifications that are part of this release.
+
+Upgrading for Users
+~~~~~~~~~~~~~~~~~~~
+
+Java Driver and close()
+^^^^^^^^^^^^^^^^^^^^^^^
+
+There were a few problems noted around the `close()` of `Cluster` and `Client` instances, including issues that
+presented as system hangs. These issues have been resolved, however, it is worth noting that an unchecked exception
+that was thrown under a certain situation has changed as part of the bug fixes. When submitting an in-session request
+on a `Client` that was closed (or closing) an `IllegalStateException` is thrown. This replaces older functionality
+that threw a `ConnectionException` and relied logic far deeper in the driver to produce that error and had the
+potential to open additional resources despite the intention of the user to "close".
+
+See: https://issues.apache.org/jira/browse/TINKERPOP-1467[TINKERPOP-1467]
+
 TinkerPop 3.1.4
 ---------------
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
index 40be11c..b3761b7 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
@@ -20,9 +20,6 @@ package org.apache.tinkerpop.gremlin.driver;
 
 import io.netty.channel.Channel;
 import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
-import io.netty.handler.ssl.SslContextBuilder;
-import io.netty.handler.ssl.SslProvider;
-import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
 import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinRequestEncoder;
 import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinResponseDecoder;
@@ -42,7 +39,6 @@ import io.netty.handler.ssl.SslContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentMap;
@@ -156,7 +152,7 @@ public interface Channelizer extends ChannelHandler {
          */
         @Override
         public void close(final Channel channel) {
-            channel.writeAndFlush(new CloseWebSocketFrame());
+            if (channel.isOpen()) channel.writeAndFlush(new CloseWebSocketFrame());
         }
 
         @Override

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
index 4aca9ca..3a03141 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
@@ -36,6 +36,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Collectors;
 
 /**
@@ -245,6 +246,8 @@ public abstract class Client {
      * A low-level method that allows the submission of a manually constructed {@link RequestMessage}.
      */
     public CompletableFuture<ResultSet> submitAsync(final RequestMessage msg) {
+        if (isClosing()) throw new IllegalStateException("Client has been closed");
+
         if (!initialized)
             init();
 
@@ -269,6 +272,8 @@ public abstract class Client {
         }
     }
 
+    public abstract boolean isClosing();
+
     /**
      * Closes the client by making a synchronous call to {@link #closeAsync()}.
      */
@@ -290,11 +295,17 @@ public abstract class Client {
     public final static class ClusteredClient extends Client {
 
         private ConcurrentMap<Host, ConnectionPool> hostConnectionPools = new ConcurrentHashMap<>();
+        private final AtomicReference<CompletableFuture<Void>> closing = new AtomicReference<>(null);
 
         ClusteredClient(final Cluster cluster) {
             super(cluster);
         }
 
+        @Override
+        public boolean isClosing() {
+            return closing.get() != null;
+        }
+
         /**
          * Submits a Gremlin script to the server and returns a {@link ResultSet} once the write of the request is
          * complete.
@@ -364,10 +375,14 @@ public abstract class Client {
          * Closes all the connection pools on all hosts.
          */
         @Override
-        public CompletableFuture<Void> closeAsync() {
+        public synchronized CompletableFuture<Void> closeAsync() {
+            if (closing.get() != null)
+                return closing.get();
+
             final CompletableFuture[] poolCloseFutures = new CompletableFuture[hostConnectionPools.size()];
             hostConnectionPools.values().stream().map(ConnectionPool::closeAsync).collect(Collectors.toList()).toArray(poolCloseFutures);
-            return CompletableFuture.allOf(poolCloseFutures);
+            closing.set(CompletableFuture.allOf(poolCloseFutures));
+            return closing.get();
         }
     }
 
@@ -448,11 +463,16 @@ public abstract class Client {
          * close on the {@code Client} that created it.
          */
         @Override
-        public CompletableFuture<Void> closeAsync() {
+        public synchronized CompletableFuture<Void> closeAsync() {
             close.complete(null);
             return close;
         }
 
+        @Override
+        public boolean isClosing() {
+            return close.isDone();
+        }
+
         /**
          * {@inheritDoc}
          */
@@ -483,6 +503,8 @@ public abstract class Client {
 
         private ConnectionPool connectionPool;
 
+        private final AtomicReference<CompletableFuture<Void>> closing = new AtomicReference<>(null);
+
         SessionedClient(final Cluster cluster, final String sessionId, final boolean manageTransactions) {
             super(cluster);
             this.sessionId = sessionId;
@@ -526,12 +548,22 @@ public abstract class Client {
             connectionPool = new ConnectionPool(host, this, Optional.of(1), Optional.of(1));
         }
 
+        @Override
+        public boolean isClosing() {
+            return closing.get() != null;
+        }
+
         /**
          * Close the bound {@link ConnectionPool}.
          */
         @Override
-        public CompletableFuture<Void> closeAsync() {
-            return connectionPool.closeAsync();
+        public synchronized CompletableFuture<Void> closeAsync() {
+            if (closing.get() != null)
+                return closing.get();
+
+            final CompletableFuture<Void> connectionPoolClose = connectionPool.closeAsync();
+            closing.set(connectionPoolClose);
+            return connectionPoolClose;
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
index 6a6a2e3..473991a 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
@@ -36,6 +36,7 @@ import javax.net.ssl.TrustManager;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.lang.ref.WeakReference;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.URI;
@@ -83,7 +84,9 @@ public final class Cluster {
      * submitted or can be directly initialized via {@link Client#init()}.
      */
     public <T extends Client> T connect() {
-        return (T) new Client.ClusteredClient(this);
+        final Client client = new Client.ClusteredClient(this);
+        manager.trackClient(client);
+        return (T) client;
     }
 
     /**
@@ -122,7 +125,9 @@ public final class Cluster {
     public <T extends Client> T connect(final String sessionId, final boolean manageTransactions) {
         if (null == sessionId || sessionId.isEmpty())
             throw new IllegalArgumentException("sessionId cannot be null or empty");
-        return (T) new Client.SessionedClient(this, sessionId, manageTransactions);
+        final Client client = new Client.SessionedClient(this, sessionId, manageTransactions);
+        manager.trackClient(client);
+        return (T) client;
     }
 
     @Override
@@ -684,6 +689,8 @@ public final class Cluster {
 
         private final AtomicReference<CompletableFuture<Void>> closeFuture = new AtomicReference<>();
 
+        private final List<WeakReference<Client>> openedClients = new ArrayList<>();
+
         private Manager(final Builder builder) {
             this.loadBalancingStrategy = builder.loadBalancingStrategy;
             this.authProps = builder.authProps;
@@ -730,6 +737,10 @@ public final class Cluster {
             });
         }
 
+        void trackClient(final Client client) {
+            openedClients.add(new WeakReference<>(client));
+        }
+
         public Host add(final InetSocketAddress address) {
             final Host newHost = new Host(address, Cluster.this);
             final Host previous = hosts.putIfAbsent(address, newHost);
@@ -745,6 +756,13 @@ public final class Cluster {
             if (closeFuture.get() != null)
                 return closeFuture.get();
 
+            for (WeakReference<Client> openedClient : openedClients) {
+                final Client client = openedClient.get();
+                if (client != null && !client.isClosing()) {
+                    client.close();
+                }
+            }
+
             final CompletableFuture<Void> closeIt = new CompletableFuture<>();
             closeFuture.set(closeIt);
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
index 220ad42..660ad0d 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
@@ -35,6 +35,8 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -128,7 +130,7 @@ final class Connection {
         return isDead;
     }
 
-    public boolean isClosed() {
+    boolean isClosing() {
         return closeFuture.get() != null;
     }
 
@@ -148,22 +150,26 @@ final class Connection {
         return pending;
     }
 
-    public CompletableFuture<Void> closeAsync() {
+    public synchronized CompletableFuture<Void> closeAsync() {
+        if (isClosing()) return closeFuture.get();
+
         final CompletableFuture<Void> future = new CompletableFuture<>();
-        if (!closeFuture.compareAndSet(null, future))
-            return closeFuture.get();
+        closeFuture.set(future);
 
         // make sure all requests in the queue are fully processed before killing.  if they are then shutdown
         // can be immediate.  if not this method will signal the readCompleted future defined in the write()
         // operation to check if it can close.  in this way the connection no longer receives writes, but
         // can continue to read. If a request never comes back the future won't get fulfilled and the connection
         // will maintain a "pending" request, that won't quite ever go away.  The build up of such a dead requests
-        // on a connection in the connection pool will force the pool to replace the connection for a fresh one
-        if (pending.isEmpty()) {
+        // on a connection in the connection pool will force the pool to replace the connection for a fresh one.
+        if (isOkToClose()) {
             if (null == channel)
                 future.complete(null);
             else
                 shutdown(future);
+        } else {
+            // there may be some pending requests. schedule a job to wait for those to complete and then shutdown
+            new CheckForPending(future).runUntilDone(cluster.executor(), 1000, TimeUnit.MILLISECONDS);
         }
 
         return future;
@@ -247,16 +253,20 @@ final class Connection {
         }
     }
 
+    private boolean isOkToClose() {
+        return pending.isEmpty() || (channel !=null && !channel.isOpen()) || !pool.host.isAvailable();
+    }
+
     /**
      * Close was signaled in closeAsync() but there were pending messages at that time. This method attempts the
      * shutdown if the returned result cleared up the last pending message.
      */
     private void tryShutdown() {
-        if (isClosed() && pending.isEmpty())
+        if (isClosing() && isOkToClose())
             shutdown(closeFuture.get());
     }
 
-    private void shutdown(final CompletableFuture<Void> future) {
+    private synchronized void shutdown(final CompletableFuture<Void> future) {
         // shutdown can be called directly from closeAsync() or after write() and therefore this method should only
         // be called once. once shutdown is initiated, it shouldn't be executed a second time or else it sends more
         // messages at the server and leads to ugly log messages over there.
@@ -286,6 +296,7 @@ final class Connection {
             }
 
             channelizer.close(channel);
+
             final ChannelPromise promise = channel.newPromise();
             promise.addListener(f -> {
                 if (f.cause() != null)
@@ -307,4 +318,45 @@ final class Connection {
     public String toString() {
         return connectionLabel;
     }
+
+    /**
+     * Self-cancelling tasks that periodically checks for the pending queue to clear before shutting down the
+     * {@code Connection}. Once it does that, it self cancels the scheduled job in the executor.
+     */
+    private final class CheckForPending implements Runnable {
+        private volatile ScheduledFuture<?> self;
+        private final CompletableFuture<Void> future;
+
+        CheckForPending(final CompletableFuture<Void> future) {
+            this.future = future;
+        }
+
+        @Override
+        public void run() {
+            logger.info("Checking for pending messages to complete before close on {}", this);
+
+            if (isOkToClose()) {
+                shutdown(future);
+                boolean interrupted = false;
+                try {
+                    while(null == self) {
+                        try {
+                            Thread.sleep(1);
+                        } catch (InterruptedException e) {
+                            interrupted = true;
+                        }
+                    }
+                    self.cancel(false);
+                } finally {
+                    if(interrupted) {
+                        Thread.currentThread().interrupt();
+                    }
+                }
+            }
+        }
+
+        void runUntilDone(final ScheduledExecutorService executor, final long period, final TimeUnit unit) {
+            self = executor.scheduleAtFixedRate(this, period, period, unit);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java
index 9955e82..4691b1b 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java
@@ -219,27 +219,26 @@ final class ConnectionPool {
     /**
      * Permanently kills the pool.
      */
-    public CompletableFuture<Void> closeAsync() {
-        logger.info("Signalled closing of connection pool on {} with core size of {}", host, minPoolSize);
+    public synchronized CompletableFuture<Void> closeAsync() {
+        if (closeFuture.get() != null) return closeFuture.get();
 
-        CompletableFuture<Void> future = closeFuture.get();
-        if (future != null)
-            return future;
+        logger.info("Signalled closing of connection pool on {} with core size of {}", host, minPoolSize);
 
         announceAllAvailableConnection();
-        future = CompletableFuture.allOf(killAvailableConnections());
-
-        return closeFuture.compareAndSet(null, future) ? future : closeFuture.get();
+        final CompletableFuture<Void> future = killAvailableConnections();
+        closeFuture.set(future);
+        return future;
     }
 
-    private CompletableFuture[] killAvailableConnections() {
+    private CompletableFuture<Void> killAvailableConnections() {
         final List<CompletableFuture<Void>> futures = new ArrayList<>(connections.size());
         for (Connection connection : connections) {
             final CompletableFuture<Void> future = connection.closeAsync();
-            future.thenRunAsync(open::decrementAndGet, cluster.executor());
+            future.thenRun(open::decrementAndGet);
             futures.add(future);
         }
-        return futures.toArray(new CompletableFuture[futures.size()]);
+
+        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]));
     }
 
     void replaceConnection(final Connection connection) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
index 773322a..65eb662 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
@@ -29,11 +29,11 @@ import io.netty.util.Attribute;
 import io.netty.util.AttributeKey;
 import io.netty.util.ReferenceCountUtil;
 import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.net.InetSocketAddress;
-import java.nio.charset.StandardCharsets;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
 import java.util.HashMap;
@@ -83,11 +83,24 @@ final class Handler {
             if (response.getStatus().getCode() == ResponseStatusCode.AUTHENTICATE) {
                 final Attribute<SaslClient> saslClient = channelHandlerContext.attr(saslClientKey);
                 final Attribute<Subject> subject = channelHandlerContext.attr(subjectKey);
-                RequestMessage.Builder messageBuilder = RequestMessage.build(Tokens.OPS_AUTHENTICATION);
+                final RequestMessage.Builder messageBuilder = RequestMessage.build(Tokens.OPS_AUTHENTICATION);
                 // First time through we don't have a sasl client
                 if (saslClient.get() == null) {
                     subject.set(login());
-                    saslClient.set(saslClient(getHostName(channelHandlerContext)));
+                    try {
+                        saslClient.set(saslClient(getHostName(channelHandlerContext)));
+                    } catch (SaslException saslException) {
+                        // push the sasl error into a failure response from the server. this ensures that standard
+                        // processing for the ResultQueue is kept. without this SaslException trap and subsequent
+                        // conversion to an authentication failure, the close() of the connection might not
+                        // succeed as it will appear as though pending messages remain present in the queue on the
+                        // connection and the shutdown won't proceed
+                        final ResponseMessage clientSideError = ResponseMessage.build(response.getRequestId())
+                                .code(ResponseStatusCode.FORBIDDEN).statusMessage(saslException.getMessage()).create();
+                        channelHandlerContext.fireChannelRead(clientSideError);
+                        return;
+                    }
+
                     messageBuilder.addArg(Tokens.ARGS_SASL_MECHANISM, getMechanism());
                     messageBuilder.addArg(Tokens.ARGS_SASL, saslClient.get().hasInitialResponse() ?
                                                                 evaluateChallenge(subject, saslClient, NULL_CHALLENGE) : null);
@@ -214,12 +227,12 @@ final class Handler {
             // there are that many failures someone would take notice and hopefully stop the client.
             logger.error("Could not process the response", cause);
 
-            // the channel took an error because of something pretty bad so release all the completeable
-            // futures out there
-            pending.entrySet().stream().forEach(kv -> kv.getValue().markError(cause));
+            // the channel took an error because of something pretty bad so release all the futures out there
+            pending.values().forEach(val -> val.markError(cause));
+            pending.clear();
 
             // serialization exceptions should not close the channel - that's worth a retry
-            if (!ExceptionUtils.getThrowableList(cause).stream().anyMatch(t -> t instanceof SerializationException))
+            if (!IteratorUtils.anyMatch(ExceptionUtils.getThrowableList(cause).iterator(), t -> t instanceof SerializationException))
                 ctx.close();
         }
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java
index 89a0225..e55456e 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java
@@ -76,6 +76,10 @@ final class ResultQueue {
         return this.size() == 0;
     }
 
+    public boolean isComplete() {
+        return readComplete.isDone();
+    }
+
     void drainTo(final Collection<Result> collection) {
         if (error.get() != null) throw new RuntimeException(error.get());
         resultLinkedBlockingQueue.drainTo(collection);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java
index 922775e..e2a5668 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java
@@ -95,9 +95,9 @@ public final class WebSocketClientHandler extends SimpleChannelInboundHandler<Ob
 
     @Override
     public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
-        logger.warn("Exception caught during WebSocket processing - closing connection", cause);
         if (!handshakeFuture.isDone()) handshakeFuture.setFailure(cause);
-        ctx.close();
+
+        // let the GremlinResponseHandler take care of exception logging, channel closing, and cleanup
         ctx.fireExceptionCaught(cause);
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
index 1a04b6b..bf66b0d 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
@@ -25,7 +25,6 @@ import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 import org.apache.tinkerpop.gremlin.driver.Result;
 import org.apache.tinkerpop.gremlin.driver.ResultSet;
-import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer;
@@ -746,11 +745,13 @@ public class GremlinDriverIntegrateTest extends AbstractGremlinServerIntegration
         client.close();
 
         try {
-            client.submit("x[0]+1");
+            client.submit("x[0]+1").all().get();
             fail("Should have thrown an exception because the connection is closed");
         } catch (Exception ex) {
             final Throwable root = ExceptionUtils.getRootCause(ex);
-            assertThat(root, instanceOf(ConnectionException.class));
+            assertThat(root, instanceOf(IllegalStateException.class));
+        } finally {
+            cluster.close();
         }
     }
 
@@ -1248,6 +1249,78 @@ public class GremlinDriverIntegrateTest extends AbstractGremlinServerIntegration
         }
     }
 
+    @Test
+    public void shouldCloseAllClientsOnCloseOfCluster() throws Exception {
+        final Cluster cluster = Cluster.open();
+        final Client sessionlessOne = cluster.connect();
+        final Client session = cluster.connect("session");
+        final Client sessionlessTwo = cluster.connect();
+        final Client sessionlessThree = cluster.connect();
+        final Client sessionlessFour = cluster.connect();
+
+        assertEquals(2, sessionlessOne.submit("1+1").all().get().get(0).getInt());
+        assertEquals(2, session.submit("1+1").all().get().get(0).getInt());
+        assertEquals(2, sessionlessTwo.submit("1+1").all().get().get(0).getInt());
+        assertEquals(2, sessionlessThree.submit("1+1").all().get().get(0).getInt());
+        // dont' send anything on the 4th client
+
+        // close one of these Clients before the Cluster
+        sessionlessThree.close();
+        cluster.close();
+
+        try {
+            sessionlessOne.submit("1+1").all().get();
+            fail("Should have tossed an exception because cluster was closed");
+        } catch (Exception ex) {
+            final Throwable root = ExceptionUtils.getRootCause(ex);
+            assertThat(root, instanceOf(IllegalStateException.class));
+            assertEquals("Client has been closed", root.getMessage());
+        }
+
+        try {
+            session.submit("1+1").all().get();
+            fail("Should have tossed an exception because cluster was closed");
+        } catch (Exception ex) {
+            final Throwable root = ExceptionUtils.getRootCause(ex);
+            assertThat(root, instanceOf(IllegalStateException.class));
+            assertEquals("Client has been closed", root.getMessage());
+        }
+
+        try {
+            sessionlessTwo.submit("1+1").all().get();
+            fail("Should have tossed an exception because cluster was closed");
+        } catch (Exception ex) {
+            final Throwable root = ExceptionUtils.getRootCause(ex);
+            assertThat(root, instanceOf(IllegalStateException.class));
+            assertEquals("Client has been closed", root.getMessage());
+        }
+
+        try {
+            sessionlessThree.submit("1+1").all().get();
+            fail("Should have tossed an exception because cluster was closed");
+        } catch (Exception ex) {
+            final Throwable root = ExceptionUtils.getRootCause(ex);
+            assertThat(root, instanceOf(IllegalStateException.class));
+            assertEquals("Client has been closed", root.getMessage());
+        }
+
+        try {
+            sessionlessFour.submit("1+1").all().get();
+            fail("Should have tossed an exception because cluster was closed");
+        } catch (Exception ex) {
+            final Throwable root = ExceptionUtils.getRootCause(ex);
+            assertThat(root, instanceOf(IllegalStateException.class));
+            assertEquals("Client has been closed", root.getMessage());
+        }
+
+        // allow call to close() even though closed through cluster
+        sessionlessOne.close();
+        session.close();
+        sessionlessTwo.close();
+
+        cluster.close();
+    }
+
     private void assertFutureTimeout(final CompletableFuture<List<Result>> futureFirst) {
         try
         {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthIntegrateTest.java
index 3e1b7e9..887d408 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthIntegrateTest.java
@@ -23,7 +23,6 @@ import org.apache.tinkerpop.gremlin.driver.Client;
 import org.apache.tinkerpop.gremlin.driver.Cluster;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
 import org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator;
-import org.ietf.jgss.GSSException;
 import org.junit.Test;
 
 import java.util.HashMap;
@@ -128,7 +127,7 @@ public class GremlinServerAuthIntegrateTest extends AbstractGremlinServerIntegra
             fail("This should not succeed as the client did not provide credentials");
         } catch(Exception ex) {
             final Throwable root = ExceptionUtils.getRootCause(ex);
-            assertEquals(GSSException.class, root.getClass());
+            assertEquals(ResponseException.class, root.getClass());
         } finally {
             cluster.close();
         }
@@ -157,7 +156,7 @@ public class GremlinServerAuthIntegrateTest extends AbstractGremlinServerIntegra
         final Client client = cluster.connect();
 
         try {
-            client.submit("1+1").all();
+            client.submit("1+1").all().get();
         } catch(Exception ex) {
             final Throwable root = ExceptionUtils.getRootCause(ex);
             assertEquals(ResponseException.class, root.getClass());

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthOldIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthOldIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthOldIntegrateTest.java
index f2e5622..2f332be 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthOldIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerAuthOldIntegrateTest.java
@@ -131,7 +131,7 @@ public class GremlinServerAuthOldIntegrateTest extends AbstractGremlinServerInte
             fail("This should not succeed as the client did not provide credentials");
         } catch(Exception ex) {
             final Throwable root = ExceptionUtils.getRootCause(ex);
-            assertEquals(GSSException.class, root.getClass());
+            assertEquals(ResponseException.class, root.getClass());
 
             // removed this assert as the text of the message changes based on kerberos config - stupid kerberos
             // assertThat(root.getMessage(), startsWith("Invalid name provided"));
@@ -163,7 +163,7 @@ public class GremlinServerAuthOldIntegrateTest extends AbstractGremlinServerInte
         final Client client = cluster.connect();
 
         try {
-            client.submit("1+1").all();
+            client.submit("1+1").all().get();
         } catch(Exception ex) {
             final Throwable root = ExceptionUtils.getRootCause(ex);
             assertEquals(ResponseException.class, root.getClass());

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6d14adb0/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
index 99b3a1b..3c1fef9 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
@@ -26,7 +26,6 @@ import org.apache.tinkerpop.gremlin.driver.Cluster;
 import org.apache.tinkerpop.gremlin.driver.Result;
 import org.apache.tinkerpop.gremlin.driver.ResultSet;
 import org.apache.tinkerpop.gremlin.driver.Tokens;
-import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
 import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
@@ -189,7 +188,7 @@ public class GremlinServerSessionIntegrateTest  extends AbstractGremlinServerInt
             fail("Session should be dead");
         } catch (Exception ex) {
             final Throwable root = ExceptionUtils.getRootCause(ex);
-            assertThat(root, instanceOf(ConnectionException.class));
+            assertThat(root, instanceOf(IllegalStateException.class));
         } finally {
             cluster.close();
         }
@@ -229,7 +228,8 @@ public class GremlinServerSessionIntegrateTest  extends AbstractGremlinServerInt
             cluster.close();
         }
 
-        assertEquals(1, recordingAppender.getMessages().stream()
+        // there will be on for the timeout and a second for closing the cluster
+        assertEquals(2, recordingAppender.getMessages().stream()
                 .filter(msg -> msg.equals("INFO - Session shouldHaveTheSessionTimeout closed\n")).count());
     }
 


[30/37] tinkerpop git commit: added integration tests for DriverRemoteTraversalSideEffects methods

Posted by da...@apache.org.
added integration tests for DriverRemoteTraversalSideEffects methods


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/4eeb6fba
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/4eeb6fba
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/4eeb6fba

Branch: refs/heads/TINKERPOP-1458
Commit: 4eeb6fba2867bfd73d9d58a39d29528fe31e921b
Parents: 77a3209
Author: davebshow <da...@gmail.com>
Authored: Wed Oct 5 15:01:59 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../server/GremlinServerIntegrateTest.java      | 79 ++++++++++++++++++--
 1 file changed, 73 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/4eeb6fba/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index e6e0021..61bf994 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -38,6 +38,7 @@ import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
+import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversalSideEffects;
 import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
 import org.apache.tinkerpop.gremlin.driver.simple.NioClient;
 import org.apache.tinkerpop.gremlin.driver.simple.SimpleClient;
@@ -55,6 +56,7 @@ import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.server.channel.NioChannelizer;
 import org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor;
+import org.apache.tinkerpop.gremlin.structure.util.Host;
 import org.apache.tinkerpop.gremlin.structure.util.detached.DetachedVertex;
 import org.apache.tinkerpop.gremlin.structure.util.empty.EmptyGraph;
 import org.apache.tinkerpop.gremlin.util.Log4jRecordingAppender;
@@ -64,6 +66,7 @@ import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.lang.reflect.Field;
 import java.nio.channels.ClosedChannelException;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -71,6 +74,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -104,7 +108,6 @@ import static org.junit.Assert.assertEquals;
 public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegrationTest {
 
     private Log4jRecordingAppender recordingAppender = null;
-
     private final Supplier<Graph> graphGetter = () -> server.getServerGremlinExecutor().getGraphManager().getGraphs().get("graph");
     private final Configuration conf = new BaseConfiguration() {{
         setProperty(Graph.GRAPH, RemoteGraph.class.getName());
@@ -833,16 +836,80 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
     }
 
     @Test
-    public void shouldCloseLocalSideEffects() throws Exception {
+    public void shouldGetSideEffectKeysUsingWithRemote() throws Exception {
         final Graph graph = EmptyGraph.instance();
         final GraphTraversalSource g = graph.traversal().withRemote(conf);
         g.addV("person").property("age", 20).iterate();
         g.addV("person").property("age", 10).iterate();
         final GraphTraversal traversal = g.V().aggregate("a").aggregate("b");
         traversal.iterate();
-        final List sideEffects = traversal.asAdmin().getSideEffects().get("a");
-        assertFalse(sideEffects.isEmpty());
-        traversal.asAdmin().getSideEffects().close();
-        assertNull(traversal.asAdmin().getSideEffects().get("b"));
+        final DriverRemoteTraversalSideEffects se = (DriverRemoteTraversalSideEffects) traversal.asAdmin().getSideEffects();
+
+        // Get keys
+        final Set<String> sideEffectKeys = se.keys();
+        assertEquals(2, sideEffectKeys.size());
+
+        // Get side effects
+        final List aSideEffects = se.get("a");
+        assertThat(aSideEffects.isEmpty(), is(false));
+        final List bSideEffects = se.get("b");
+        assertThat(bSideEffects.isEmpty(), is(false));
+
+        // Should get local keys/side effects after close
+        se.close();
+
+        final Set<String> localSideEffectKeys = se.keys();
+        assertEquals(2, localSideEffectKeys.size());
+
+        final List localASideEffects = se.get("a");
+        assertThat(localASideEffects.isEmpty(), is(false));
+
+        final List localBSideEffects = se.get("b");
+        assertThat(localBSideEffects.isEmpty(), is(false));
+    }
+
+    @Test
+    public void shouldCloseSideEffectsUsingWithRemote() throws Exception {
+        final Graph graph = EmptyGraph.instance();
+        final GraphTraversalSource g = graph.traversal().withRemote(conf);
+        g.addV("person").property("age", 20).iterate();
+        g.addV("person").property("age", 10).iterate();
+        final GraphTraversal traversal = g.V().aggregate("a").aggregate("b");
+        traversal.iterate();
+        final DriverRemoteTraversalSideEffects se = (DriverRemoteTraversalSideEffects) traversal.asAdmin().getSideEffects();
+        final List sideEffects = se.get("a");
+        assertThat(sideEffects.isEmpty(), is(false));
+        se.close();
+
+        // Can't get new side effects after close
+        assertNull(se.get("b"));
+
+        // Earlier keys should be cached locally
+        final Set<String> localSideEffectKeys = se.keys();
+        assertEquals(1, localSideEffectKeys.size());
+        final List localSideEffects = se.get("a");
+        assertThat(localSideEffects.isEmpty(), is(false));
+
+        // Try to get side effect from server
+        final Cluster cluster = Cluster.build("localhost").create();
+        final Client client = cluster.connect();
+        Field field = DriverRemoteTraversalSideEffects.class.getDeclaredField("serverSideEffect");
+        field.setAccessible(true);
+        UUID serverSideEffectId = (UUID) field.get(se);
+        final RequestMessage msg = RequestMessage.build(Tokens.OPS_GATHER)
+                .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffectId)
+                .addArg(Tokens.ARGS_SIDE_EFFECT_KEY, "b")
+                .processor("traversal").create();
+        boolean error;
+        try {
+            client.submitAsync(msg).get();
+            error = false;
+        } catch (Exception ex) {
+            error = true;
+        }
+        assertThat(error, is(true));
     }
 }
+
+
+


[11/37] tinkerpop git commit: Added support for or(has(x), has(y)) to be has(x.or(y)) in InlineFilterStrategy. While doing this, I found a bug in ConnectiveP steps where nested equivalents were not being inlined. That bug has been fixed. Added test cases

Posted by da...@apache.org.
Added support for or(has(x),has(y)) to be has(x.or(y)) in InlineFilterStrategy. While doing this, I found a bug in ConnectiveP steps where nested equivalents were not being inlined. That bug has been fixed. Added test cases to PTest to demonstrate proper inlining and nesting of ConnectivePs. I left two TODOs. One regarding match()-pulls that are labeled (interfering with FilterRankStrategy) and one regarding, has(x).has(y) being turned into has(x.and(y)). The reason why the latter isn't done now as it may greatly mess up providers who just rely on eq() for index lookups and are not smart enough to look into and()/or() predicates.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/8eb0fdde
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/8eb0fdde
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/8eb0fdde

Branch: refs/heads/TINKERPOP-1458
Commit: 8eb0fdded4fd8943a1541fda33e0785ea10751ee
Parents: 233a6ba
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Sep 29 10:39:20 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 08:24:17 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   3 +-
 .../upgrade/release-3.2.x-incubating.asciidoc   |  18 ++
 .../optimization/InlineFilterStrategy.java      |  45 +++-
 .../gremlin/process/traversal/util/AndP.java    |   8 +-
 .../process/traversal/util/ConnectiveP.java     |   3 +-
 .../gremlin/process/traversal/util/OrP.java     |   9 +-
 .../gremlin/process/traversal/PTest.java        | 245 ++++++++++---------
 .../optimization/InlineFilterStrategyTest.java  |  18 ++
 .../TinkerGraphStepStrategyTest.java            |   3 +-
 9 files changed, 233 insertions(+), 119 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8eb0fdde/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index ade43cd..d204b44 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Fixed a bug in `ConnectiveP` where nested equivalent connectives should be inlined.
 * Fixed a bug in `IncidentToAdjacentStrategy` where `TreeStep` traversals were allowed.
 * Fixed a end-step label bug in `MatchPredicateStrategy`.
 * Fixed a bug in `MatchPredicateStrategy` where inlined traversals did not have strategies applied to it.
@@ -33,7 +34,7 @@ TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 * Added `TraversalHelper.copyLabels()` for copying (or moving) labels form one step to another.
 * Added `TraversalHelper.applySingleLevelStrategies()` which will apply a subset of strategies but not walk the child tree.
 * Added the concept that hidden labels using during traversal compilation are removed at the end during `StandardVerificationStrategy`. (*breaking*)
-* Added `InlineFilterStrategy` which will determine if a `TraversalFilterStep`, `AndStep`, `MatchStep` children are filters and if so, inline them.
+* Added `InlineFilterStrategy` which will determine if a `TraversalFilterStep`, `AndStep`, `OrStep`, `MatchStep` children are filters and if so, inline them.
 * Removed `IdentityRemovalStrategy` from the default listing as its not worth the clock cycles.
 * Removed the "!" symbol in `NotStep.toString()` as it is confusing and the `NotStep`-name is sufficient.
 * Fixed a bug in `TraversalVertexProgram` (OLAP) around ordering and connectives (i.e. `and()` and `or()`).

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8eb0fdde/docs/src/upgrade/release-3.2.x-incubating.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.2.x-incubating.asciidoc b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
index 0ba09bd..49790af 100644
--- a/docs/src/upgrade/release-3.2.x-incubating.asciidoc
+++ b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
@@ -171,6 +171,15 @@ uses of these exception builders as they will be removed in the future.
 
 See: link:https://issues.apache.org/jira/browse/TINKERPOP-944[TINKERPOP-944]
 
+Hidden Step Labels for Compilation Only
++++++++++++++++++++++++++++++++++++++++
+
+In order for `SubgraphStrategy` to work, it was necessary to have multi-level children communicate with one another
+via hidden step labels. It was decided that hidden step labels are for compilation purposes only and will be removed
+prior to traversal evaluation. This is a valid decision given that hidden labels for graph system providers are
+not allowed to be used by users. Likewise, hidden labels for steps should not be allowed be used by
+users as well.
+
 PropertyMapStep with Selection Traversal
 ++++++++++++++++++++++++++++++++++++++++
 
@@ -181,6 +190,15 @@ and if so, use that in their introspection for respective strategies. This model
 See: link:https://issues.apache.org/jira/browse/TINKERPOP-1456[TINKERPOP-1456],
 link:https://issues.apache.org/jira/browse/TINKERPOP-844[TINKERPOP-844]
 
+ConnectiveP Nesting Inlined
++++++++++++++++++++++++++++
+
+There was a bug in `ConnectiveP` (`AndP`/`OrP`), where `eq(1).and(eq(2).and(eq(3)))` was `OrP(eq(1),AndP(eq(2),eq(3)))`
+instead of unnested/inlined as `OrP(eq(1),eq(2),eq(3))`. Likewise, for `AndP`. If a provider was leveraging `ConnectiveP`
+predicates for their custom steps (e.g. graph- or vertex-centric index lookups), then they should be aware of the inlining
+and can simplify any and/or-tree walking code in their respective `ProviderOptimizationStrategy`.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1470[TINKERPOP-1470]
 
 TinkerPop 3.2.2
 ---------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8eb0fdde/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
index 7452b3b..0b7a5cc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
@@ -20,6 +20,7 @@
 package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
 
 import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
@@ -29,10 +30,12 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DedupGlobalSte
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.DropStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.OrStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.TraversalFilterStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 
@@ -89,6 +92,46 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
                     traversal.removeStep(step);
                 }
             }
+            // or(has(x,y),has(x,z)) --> has(x,y.or(z))
+            for (final OrStep<?> step : TraversalHelper.getStepsOfClass(OrStep.class, traversal)) {
+                boolean process = true;
+                String key = null;
+                P predicate = null;
+                final List<String> labels = new ArrayList<>();
+                for (final Traversal.Admin<?, ?> childTraversal : step.getLocalChildren()) {
+                    this.apply(childTraversal); // todo: this may be a bad idea, but I can't seem to find a test case to break it
+                    for (final Step<?, ?> childStep : childTraversal.getSteps()) {
+                        if (childStep instanceof HasStep) {
+                            for (final HasContainer hasContainer : ((HasStep<?>) childStep).getHasContainers()) {
+                                if (null == key)
+                                    key = hasContainer.getKey();
+                                else if (!hasContainer.getKey().equals(key)) {
+                                    process = false;
+                                    break;
+                                }
+                                predicate = null == predicate ?
+                                        hasContainer.getPredicate() :
+                                        predicate.or(hasContainer.getPredicate());
+                            }
+                            labels.addAll(childStep.getLabels());
+                        } else {
+                            process = false;
+                            break;
+                        }
+                    }
+                    if (!process)
+                        break;
+                }
+                if (process) {
+                    changed = true;
+                    final HasStep hasStep = new HasStep<>(traversal, new HasContainer(key, predicate));
+                    TraversalHelper.replaceStep(step, hasStep, traversal);
+                    TraversalHelper.copyLabels(step, hasStep, false);
+                    for (final String label : labels) {
+                        hasStep.addLabel(label);
+                    }
+                }
+            }
             // and(x,y) --> x.y
             for (final AndStep<?> step : TraversalHelper.getStepsOfClass(AndStep.class, traversal)) {
                 boolean process = true;
@@ -139,6 +182,7 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
                                 TraversalHelper.applySingleLevelStrategies(traversal, matchTraversal, InlineFilterStrategy.class);
                                 step.removeGlobalChild(matchTraversal);
                                 step.getPreviousStep().addLabel(startLabel);
+                                // TODO: matchTraversal.getEndStep().addLabel(startLabel); (perhaps insert an identity so filter rank can push has()-left)
                                 if (null != endLabel) matchTraversal.getEndStep().addLabel(endLabel);
                                 TraversalHelper.insertTraversal((Step) step.getPreviousStep(), matchTraversal, traversal);
                             }
@@ -149,7 +193,6 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
                 }
             }
         }
-
     }
 
     private static final String determineStartLabelForHasPullOut(final MatchStep<?, ?> matchStep) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8eb0fdde/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/AndP.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/AndP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/AndP.java
index 8a7784f..cb001ff 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/AndP.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/AndP.java
@@ -34,6 +34,9 @@ public final class AndP<V> extends ConnectiveP<V> {
 
     public AndP(final List<P<V>> predicates) {
         super(predicates);
+        for (final P<V> p : predicates) {
+            this.and(p);
+        }
         this.biPredicate = new AndBiPredicate(this);
     }
 
@@ -49,7 +52,10 @@ public final class AndP<V> extends ConnectiveP<V> {
     public P<V> and(final Predicate<? super V> predicate) {
         if (!(predicate instanceof P))
             throw new IllegalArgumentException("Only P predicates can be and'd together");
-        this.predicates.add((P<V>) predicate);   // TODO: clone and add?
+        else if (predicate instanceof AndP)
+            this.predicates.addAll(((AndP) predicate).getPredicates());
+        else
+            this.predicates.add((P<V>) predicate);
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8eb0fdde/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ConnectiveP.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ConnectiveP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ConnectiveP.java
index 70f008a..855fc06 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ConnectiveP.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/ConnectiveP.java
@@ -31,13 +31,12 @@ import java.util.function.Predicate;
  */
 public abstract class ConnectiveP<V> extends P<V> {
 
-    protected List<P<V>> predicates;
+    protected List<P<V>> predicates = new ArrayList<>();
 
     public ConnectiveP(final List<P<V>> predicates) {
         super(null, null);
         if (predicates.size() < 2)
             throw new IllegalArgumentException("The provided " + this.getClass().getSimpleName() + " array must have at least two arguments: " + predicates.size());
-        this.predicates = new ArrayList<>(predicates); // to avoid Arrays.asList() and unmodifiable exceptions
     }
 
     @Deprecated

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8eb0fdde/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/OrP.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/OrP.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/OrP.java
index 8bc4387..f7363b4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/OrP.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/OrP.java
@@ -22,7 +22,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.function.BiPredicate;
@@ -35,6 +34,9 @@ public final class OrP<V> extends ConnectiveP<V> {
 
     public OrP(final List<P<V>> predicates) {
         super(predicates);
+        for (final P<V> p : predicates) {
+            this.or(p);
+        }
         this.biPredicate = new OrBiPredicate(this);
     }
 
@@ -50,7 +52,10 @@ public final class OrP<V> extends ConnectiveP<V> {
     public P<V> or(final Predicate<? super V> predicate) {
         if (!(predicate instanceof P))
             throw new IllegalArgumentException("Only P predicates can be or'd together");
-        this.predicates.add((P<V>) predicate);   // TODO: clone and add?
+        else if (predicate instanceof OrP)
+            this.predicates.addAll(((OrP) predicate).getPredicates());
+        else
+            this.predicates.add((P<V>) predicate);
         return this;
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8eb0fdde/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
index 3810c96..6ec33cc 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PTest.java
@@ -19,8 +19,11 @@
 package org.apache.tinkerpop.gremlin.process.traversal;
 
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.util.AndP;
+import org.apache.tinkerpop.gremlin.process.traversal.util.OrP;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 
@@ -29,135 +32,157 @@ import java.util.Arrays;
 import java.util.Random;
 import java.util.function.Predicate;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 /**
  * @author Daniel Kuppitz (http://gremlin.guru)
  */
-@RunWith(Parameterized.class)
+@RunWith(Enclosed.class)
 public class PTest {
 
-    @Parameterized.Parameters(name = "{0}.test({1}) = {2}")
-    public static Iterable<Object[]> data() {
-        return new ArrayList<>(Arrays.asList(new Object[][]{
-                {P.eq(0), 0, true},
-                {P.eq(0), 1, false},
-                {P.neq(0), 0, false},
-                {P.neq(0), 1, true},
-                {P.gt(0), -1, false},
-                {P.gt(0), 0, false},
-                {P.gt(0), 1, true},
-                {P.lt(0), -1, true},
-                {P.lt(0), 0, false},
-                {P.lt(0), 1, false},
-                {P.gte(0), -1, false},
-                {P.gte(0), 0, true},
-                {P.gte(0), 1, true},
-                {P.lte(0), -1, true},
-                {P.lte(0), 0, true},
-                {P.lte(0), 1, false},
-                {P.between(1, 10), 0, false},
-                {P.between(1, 10), 1, true},
-                {P.between(1, 10), 9, true},
-                {P.between(1, 10), 10, false},
-                {P.inside(1, 10), 0, false},
-                {P.inside(1, 10), 1, false},
-                {P.inside(1, 10), 9, true},
-                {P.inside(1, 10), 10, false},
-                {P.outside(1, 10), 0, true},
-                {P.outside(1, 10), 1, false},
-                {P.outside(1, 10), 9, false},
-                {P.outside(1, 10), 10, false},
-                {P.within(1, 2, 3), 0, false},
-                {P.within(1, 2, 3), 1, true},
-                {P.within(1, 2, 3), 10, false},
-                {P.within(Arrays.asList(1, 2, 3)), 0, false},
-                {P.within(Arrays.asList(1, 2, 3)), 1, true},
-                {P.within(Arrays.asList(1, 2, 3)), 10, false},
-                {P.without(1, 2, 3), 0, true},
-                {P.without(1, 2, 3), 1, false},
-                {P.without(1, 2, 3), 10, true},
-                {P.without(Arrays.asList(1, 2, 3)), 0, true},
-                {P.without(Arrays.asList(1, 2, 3)), 1, false},
-                {P.without(Arrays.asList(1, 2, 3)), 10, true},
-                {P.between("m", "n").and(P.neq("marko")), "marko", false},
-                {P.between("m", "n").and(P.neq("marko")), "matthias", true},
-                {P.between("m", "n").or(P.eq("daniel")), "marko", true},
-                {P.between("m", "n").or(P.eq("daniel")), "daniel", true},
-                {P.between("m", "n").or(P.eq("daniel")), "stephen", false},
-        }));
-    }
+    @RunWith(Parameterized.class)
+    public static class ParameterizedTest {
+
+        @Parameterized.Parameters(name = "{0}.test({1}) = {2}")
+        public static Iterable<Object[]> data() {
+            return new ArrayList<>(Arrays.asList(new Object[][]{
+                    {P.eq(0), 0, true},
+                    {P.eq(0), 1, false},
+                    {P.neq(0), 0, false},
+                    {P.neq(0), 1, true},
+                    {P.gt(0), -1, false},
+                    {P.gt(0), 0, false},
+                    {P.gt(0), 1, true},
+                    {P.lt(0), -1, true},
+                    {P.lt(0), 0, false},
+                    {P.lt(0), 1, false},
+                    {P.gte(0), -1, false},
+                    {P.gte(0), 0, true},
+                    {P.gte(0), 1, true},
+                    {P.lte(0), -1, true},
+                    {P.lte(0), 0, true},
+                    {P.lte(0), 1, false},
+                    {P.between(1, 10), 0, false},
+                    {P.between(1, 10), 1, true},
+                    {P.between(1, 10), 9, true},
+                    {P.between(1, 10), 10, false},
+                    {P.inside(1, 10), 0, false},
+                    {P.inside(1, 10), 1, false},
+                    {P.inside(1, 10), 9, true},
+                    {P.inside(1, 10), 10, false},
+                    {P.outside(1, 10), 0, true},
+                    {P.outside(1, 10), 1, false},
+                    {P.outside(1, 10), 9, false},
+                    {P.outside(1, 10), 10, false},
+                    {P.within(1, 2, 3), 0, false},
+                    {P.within(1, 2, 3), 1, true},
+                    {P.within(1, 2, 3), 10, false},
+                    {P.within(Arrays.asList(1, 2, 3)), 0, false},
+                    {P.within(Arrays.asList(1, 2, 3)), 1, true},
+                    {P.within(Arrays.asList(1, 2, 3)), 10, false},
+                    {P.without(1, 2, 3), 0, true},
+                    {P.without(1, 2, 3), 1, false},
+                    {P.without(1, 2, 3), 10, true},
+                    {P.without(Arrays.asList(1, 2, 3)), 0, true},
+                    {P.without(Arrays.asList(1, 2, 3)), 1, false},
+                    {P.without(Arrays.asList(1, 2, 3)), 10, true},
+                    {P.between("m", "n").and(P.neq("marko")), "marko", false},
+                    {P.between("m", "n").and(P.neq("marko")), "matthias", true},
+                    {P.between("m", "n").or(P.eq("daniel")), "marko", true},
+                    {P.between("m", "n").or(P.eq("daniel")), "daniel", true},
+                    {P.between("m", "n").or(P.eq("daniel")), "stephen", false},
+            }));
+        }
 
-    @Parameterized.Parameter(value = 0)
-    public P predicate;
+        @Parameterized.Parameter(value = 0)
+        public P predicate;
 
-    @Parameterized.Parameter(value = 1)
-    public Object value;
+        @Parameterized.Parameter(value = 1)
+        public Object value;
 
-    @Parameterized.Parameter(value = 2)
-    public boolean expected;
+        @Parameterized.Parameter(value = 2)
+        public boolean expected;
 
-    @Test
-    public void shouldTest() {
-        assertEquals(expected, predicate.test(value));
-        assertEquals(!expected, predicate.clone().negate().test(value));
-        assertEquals(!expected, P.not(predicate).test(value));
-    }
-
-    @Before
-    public void init() {
-        final Object pv = predicate.getValue();
-        final Random r = new Random();
-        assertNotNull(predicate.getBiPredicate());
-        predicate.setValue(r.nextDouble());
-        assertNotNull(predicate.getValue());
-        predicate.setValue(pv);
-        assertEquals(pv, predicate.getValue());
-        assertNotNull(predicate.hashCode());
-        assertEquals(predicate, predicate.clone());
-        assertNotEquals(__.identity(), predicate);
-
-        boolean thrown = true;
-        try {
-            predicate.and(new CustomPredicate());
-            thrown = false;
-        } catch (IllegalArgumentException ex) {
-            assertEquals("Only P predicates can be and'd together", ex.getMessage());
-        } finally {
-            assertTrue(thrown);
+        @Test
+        public void shouldTest() {
+            assertEquals(expected, predicate.test(value));
+            assertEquals(!expected, predicate.clone().negate().test(value));
+            assertEquals(!expected, P.not(predicate).test(value));
         }
 
-        thrown = true;
-        try {
-            predicate.or(new CustomPredicate());
-            thrown = false;
-        } catch (IllegalArgumentException ex) {
-            assertEquals("Only P predicates can be or'd together", ex.getMessage());
-        } finally {
-            assertTrue(thrown);
+        @Before
+        public void init() {
+            final Object pv = predicate.getValue();
+            final Random r = new Random();
+            assertNotNull(predicate.getBiPredicate());
+            predicate.setValue(r.nextDouble());
+            assertNotNull(predicate.getValue());
+            predicate.setValue(pv);
+            assertEquals(pv, predicate.getValue());
+            assertNotNull(predicate.hashCode());
+            assertEquals(predicate, predicate.clone());
+            assertNotEquals(__.identity(), predicate);
+
+            boolean thrown = true;
+            try {
+                predicate.and(new CustomPredicate());
+                thrown = false;
+            } catch (IllegalArgumentException ex) {
+                assertEquals("Only P predicates can be and'd together", ex.getMessage());
+            } finally {
+                assertTrue(thrown);
+            }
+
+            thrown = true;
+            try {
+                predicate.or(new CustomPredicate());
+                thrown = false;
+            } catch (IllegalArgumentException ex) {
+                assertEquals("Only P predicates can be or'd together", ex.getMessage());
+            } finally {
+                assertTrue(thrown);
+            }
         }
-    }
 
-    private class CustomPredicate implements Predicate {
+        private class CustomPredicate implements Predicate {
 
-        @Override
-        public boolean test(Object o) {
-            return false;
-        }
+            @Override
+            public boolean test(Object o) {
+                return false;
+            }
 
-        @Override
-        public Predicate and(Predicate other) {
-            return null;
-        }
+            @Override
+            public Predicate and(Predicate other) {
+                return null;
+            }
 
-        @Override
-        public Predicate negate() {
-            return null;
+            @Override
+            public Predicate negate() {
+                return null;
+            }
+
+            @Override
+            public Predicate or(Predicate other) {
+                return null;
+            }
         }
+    }
 
-        @Override
-        public Predicate or(Predicate other) {
-            return null;
+    public static class ConnectiveTest {
+
+        @Test
+        public void shouldComposeCorrectly() {
+            assertEquals(P.eq(1), P.eq(1));
+            assertEquals(P.eq(1).and(P.eq(2)), new AndP<>(Arrays.asList(P.eq(1), P.eq(2))));
+            assertEquals(P.eq(1).and(P.eq(2).and(P.eq(3))), new AndP<>(Arrays.asList(P.eq(1), P.eq(2), P.eq(3))));
+            assertEquals(P.eq(1).and(P.eq(2).and(P.eq(3).and(P.eq(4)))), new AndP<>(Arrays.asList(P.eq(1), P.eq(2), P.eq(3), P.eq(4))));
+            assertEquals(P.eq(1).or(P.eq(2).or(P.eq(3).or(P.eq(4)))), new OrP<>(Arrays.asList(P.eq(1), P.eq(2), P.eq(3), P.eq(4))));
+            assertEquals(P.eq(1).or(P.eq(2).and(P.eq(3).or(P.eq(4)))), new OrP<>(Arrays.asList(P.eq(1), new AndP<>(Arrays.asList(P.eq(2), new OrP<>(Arrays.asList(P.eq(3), P.eq(4))))))));
+            assertEquals(P.eq(1).and(P.eq(2).or(P.eq(3).and(P.eq(4)))), new AndP<>(Arrays.asList(P.eq(1), new OrP<>(Arrays.asList(P.eq(2), new AndP<>(Arrays.asList(P.eq(3), P.eq(4))))))));
+            assertEquals(P.eq(1).and(P.eq(2).and(P.eq(3).or(P.eq(4)))), new AndP<>(Arrays.asList(P.eq(1), P.eq(2), new OrP<>(Arrays.asList(P.eq(3), P.eq(4))))));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8eb0fdde/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
index aeae593..9530c82 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
@@ -29,6 +29,9 @@ import org.junit.runners.Parameterized;
 
 import java.util.Arrays;
 
+import static org.apache.tinkerpop.gremlin.process.traversal.P.eq;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.V;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.and;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
@@ -39,6 +42,7 @@ import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.limit;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.map;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.match;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.or;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.tail;
 import static org.junit.Assert.assertEquals;
@@ -46,6 +50,8 @@ import static org.junit.Assert.assertEquals;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
+
+
 @RunWith(Parameterized.class)
 public class InlineFilterStrategyTest {
 
@@ -74,9 +80,21 @@ public class InlineFilterStrategyTest {
                 {filter(has("age", P.gt(10)).as("a")), has("age", P.gt(10)).as("a")},
                 {filter(and(has("age", P.gt(10)).as("a"), has("name", "marko"))), has("age", P.gt(10)).as("a").has("name", "marko")},
                 //
+                {or(has("name", "marko"), has("age", 32)), or(has("name", "marko"), has("age", 32))},
+                {or(has("name", "marko"), has("name", "bob")), has("name", eq("marko").or(eq("bob")))},
+                {or(has("name", "marko"), has("name")), or(has("name", "marko"), has("name"))},
+                {or(has("age", 10), and(has("age", gt(20)), has("age", lt(100)))), has("age", eq(10).or(gt(20).and(lt(100))))},
+                {or(has("name", "marko"), filter(has("name", "bob"))), has("name", eq("marko").or(eq("bob")))},
+                {or(has("name", "marko"), filter(or(filter(has("name", "bob")), has("name", "stephen")))), has("name", eq("marko").or(eq("bob").or(eq("stephen"))))},
+                {or(has("name", "marko").as("a"), filter(or(filter(has("name", "bob")).as("b"), has("name", "stephen").as("c")))), has("name", eq("marko").or(eq("bob").or(eq("stephen")))).as("a", "b", "c")},
+                //
                 {and(has("age", P.gt(10)), filter(has("age", 22))), has("age", P.gt(10)).has("age", 22)},
+                {and(has("age", P.gt(10)).as("a"), filter(has("age", 22).as("b")).as("c")).as("d"), has("age", P.gt(10)).as("a").has("age", 22).as("b", "c", "d")},
                 {and(has("age", P.gt(10)).as("a"), and(filter(has("age", 22).as("b")).as("c"), has("name", "marko").as("d"))), has("age", P.gt(10)).as("a").has("age", 22).as("b", "c").has("name", "marko").as("d")},
+                {and(has("age", P.gt(10)).as("a"), and(has("name","stephen").as("b"), has("name", "marko").as("c")).as("d")).as("e"), has("age", P.gt(10)).as("a").has("name","stephen").as("b").has("name","marko").as("c","d","e")},
                 {and(has("age", P.gt(10)), and(out("knows"), has("name", "marko"))), has("age", P.gt(10)).and(out("knows"), has("name", "marko"))},
+                {and(has("age", P.gt(20)), or(has("age", lt(10)), has("age", gt(100)))), has("age", gt(20)).has("age", lt(10).or(gt(100)))},
+                {and(has("age", P.gt(20)).as("a"), or(has("age", lt(10)), has("age", gt(100)).as("b"))), has("age", gt(20)).as("a").has("age", lt(10).or(gt(100))).as("b")},
                 //
                 {V().match(as("a").has("age", 10), as("a").filter(has("name")).as("b")), V().as("a").has("age", 10).match(as("a").has("name").as("b"))},
                 {match(as("a").has("age", 10), as("a").filter(has("name")).as("b")), match(as("a").has("age", 10), as("a").has("name").as("b"))},

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8eb0fdde/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java
index d2bc0ea..9f97466 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java
@@ -48,7 +48,6 @@ import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.filter
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.not;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.properties;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.values;
 import static org.junit.Assert.assertEquals;
 
 /**
@@ -111,7 +110,7 @@ public class TinkerGraphStepStrategyTest {
                 {__.V().as("a").dedup().has("name", "marko").or(has("age"), has("age", gt(32))).filter(has("name", "bob")).has("lang", "java"),
                         g_V("name", eq("marko"), "name", eq("bob"), "lang", eq("java")).as("a").or(has("age"), has("age", gt(32))).dedup(), Arrays.asList(InlineFilterStrategy.instance(), FilterRankingStrategy.instance())},
                 {__.V().as("a").dedup().has("name", "marko").or(has("age", 10), has("age", gt(32))).filter(has("name", "bob")).has("lang", "java"),
-                        g_V("name", eq("marko"), "name", eq("bob"), "lang", eq("java")).as("a").or(has("age", 10), has("age", gt(32))).dedup(), TraversalStrategies.GlobalCache.getStrategies(TinkerGraph.class).toList()},
+                        g_V("name", eq("marko"), "age", eq(10).or(gt(32)), "name", eq("bob"), "lang", eq("java")).as("a").dedup(), TraversalStrategies.GlobalCache.getStrategies(TinkerGraph.class).toList()},
                 {__.V().has("name", "marko").or(not(has("age")), has("age", gt(32))).has("name", "bob").has("lang", "java"),
                         g_V("name", eq("marko"), "name", eq("bob"), "lang", eq("java")).or(not(filter(properties("age"))), has("age", gt(32))), TraversalStrategies.GlobalCache.getStrategies(TinkerGraph.class).toList()}
         });


[34/37] tinkerpop git commit: updated changelog

Posted by da...@apache.org.
updated changelog


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/86d373e6
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/86d373e6
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/86d373e6

Branch: refs/heads/TINKERPOP-1458
Commit: 86d373e6c7c758a32236d9f5ed49b92ee226055c
Parents: a67cc28
Author: davebshow <da...@gmail.com>
Authored: Wed Oct 5 18:10:15 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/86d373e6/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 1122a31..dc2d9d3 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -67,6 +67,7 @@ TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 * New build options for `gremlin-python` where `-DglvPython` is no longer required.
 * Added missing `InetAddress` to GraphSON extension module.
 * Gremlin Server `TraversalOpProcessor` now returns confirmation upon `Op` `close`.
+* Added `close` method Java driver and Python driver `DriverRemoteTraversalSideEffects`.
 
 [[release-3-2-2]]
 TinkerPop 3.2.2 (Release Date: September 6, 2016)


[12/37] tinkerpop git commit: cleaned up InlineFilterStrategy. Processing methods for step-types introduced. This is not only cleaner, but will allow users/providers to turn on/off InlineFiltering for different step types.

Posted by da...@apache.org.
cleaned up InlineFilterStrategy. Processing methods for step-types introduced. This is not only cleaner, but will allow users/providers to turn on/off InlineFiltering for different step types.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/9ef8a9a6
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/9ef8a9a6
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/9ef8a9a6

Branch: refs/heads/TINKERPOP-1458
Commit: 9ef8a9a6ce7fded4a98480de792d62ab0e62abab
Parents: 8eb0fdd
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Sep 29 13:36:20 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 08:24:17 2016 -0600

----------------------------------------------------------------------
 .../optimization/InlineFilterStrategy.java      | 240 ++++++++++---------
 1 file changed, 125 insertions(+), 115 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9ef8a9a6/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
index 0b7a5cc..a3ed9a1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
@@ -75,137 +75,147 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
         boolean changed = true; // recursively walk child traversals trying to inline them into the current traversal line.
         while (changed) {
             changed = false;
-            // filter(x.y) --> x.y
-            for (final TraversalFilterStep<?> step : TraversalHelper.getStepsOfClass(TraversalFilterStep.class, traversal)) {
-                final Traversal.Admin<?, ?> childTraversal = step.getLocalChildren().get(0);
-                if (TraversalHelper.hasAllStepsOfClass(childTraversal, FilterStep.class) &&
-                        !TraversalHelper.hasStepOfClass(childTraversal,
-                                DropStep.class,
-                                RangeGlobalStep.class,
-                                DedupGlobalStep.class,
-                                LambdaHolder.class)) {
+            for (final FilterStep<?> step : TraversalHelper.getStepsOfAssignableClass(FilterStep.class, traversal)) {
+                if (step instanceof TraversalFilterStep && InlineFilterStrategy.processTraversalFilterStep((TraversalFilterStep) step, traversal))
+                    // filter(x.y) --> x.y
                     changed = true;
-                    TraversalHelper.applySingleLevelStrategies(traversal, childTraversal, InlineFilterStrategy.class);
-                    final Step<?, ?> finalStep = childTraversal.getEndStep();
-                    TraversalHelper.insertTraversal((Step) step, childTraversal, traversal);
-                    TraversalHelper.copyLabels(step, finalStep, false);
-                    traversal.removeStep(step);
+                else if (step instanceof OrStep && InlineFilterStrategy.processOrStep((OrStep) step, traversal))
+                    // or(has(x,y),has(x,z)) --> has(x,y.or(z))
+                    changed = true;
+                else if (step instanceof AndStep && InlineFilterStrategy.processAndStep((AndStep) step, traversal))
+                    // and(x,y) --> x.y
+                    changed = true;
+            }
+            // match(as('a').has(key,value),...) --> as('a').has(key,value).match(...)
+            if (traversal.getParent() instanceof EmptyStep) {
+                for (final MatchStep<?, ?> step : TraversalHelper.getStepsOfClass(MatchStep.class, traversal)) {
+                    if (InlineFilterStrategy.processMatchStep(step, traversal))
+                        changed = true;
                 }
             }
-            // or(has(x,y),has(x,z)) --> has(x,y.or(z))
-            for (final OrStep<?> step : TraversalHelper.getStepsOfClass(OrStep.class, traversal)) {
-                boolean process = true;
-                String key = null;
-                P predicate = null;
-                final List<String> labels = new ArrayList<>();
-                for (final Traversal.Admin<?, ?> childTraversal : step.getLocalChildren()) {
-                    this.apply(childTraversal); // todo: this may be a bad idea, but I can't seem to find a test case to break it
-                    for (final Step<?, ?> childStep : childTraversal.getSteps()) {
-                        if (childStep instanceof HasStep) {
-                            for (final HasContainer hasContainer : ((HasStep<?>) childStep).getHasContainers()) {
-                                if (null == key)
-                                    key = hasContainer.getKey();
-                                else if (!hasContainer.getKey().equals(key)) {
-                                    process = false;
-                                    break;
-                                }
-                                predicate = null == predicate ?
-                                        hasContainer.getPredicate() :
-                                        predicate.or(hasContainer.getPredicate());
-                            }
-                            labels.addAll(childStep.getLabels());
-                        } else {
+        }
+    }
+
+    ////////////////////////////
+    ///////////////////////////
+
+    private static final boolean processTraversalFilterStep(final TraversalFilterStep<?> step, final Traversal.Admin<?, ?> traversal) {
+        final Traversal.Admin<?, ?> childTraversal = step.getLocalChildren().get(0);
+        if (TraversalHelper.hasAllStepsOfClass(childTraversal, FilterStep.class) &&
+                !TraversalHelper.hasStepOfClass(childTraversal,
+                        DropStep.class,
+                        RangeGlobalStep.class,
+                        DedupGlobalStep.class,
+                        LambdaHolder.class)) {
+            TraversalHelper.applySingleLevelStrategies(traversal, childTraversal, InlineFilterStrategy.class);
+            final Step<?, ?> finalStep = childTraversal.getEndStep();
+            TraversalHelper.insertTraversal((Step) step, childTraversal, traversal);
+            TraversalHelper.copyLabels(step, finalStep, false);
+            traversal.removeStep(step);
+            return true;
+        }
+        return false;
+    }
+
+    private static final boolean processOrStep(final OrStep<?> step, final Traversal.Admin<?, ?> traversal) {
+        boolean process = true;
+        String key = null;
+        P predicate = null;
+        final List<String> labels = new ArrayList<>();
+        for (final Traversal.Admin<?, ?> childTraversal : step.getLocalChildren()) {
+            InlineFilterStrategy.instance().apply(childTraversal); // todo: this may be a bad idea, but I can't seem to find a test case to break it
+            for (final Step<?, ?> childStep : childTraversal.getSteps()) {
+                if (childStep instanceof HasStep) {
+                    for (final HasContainer hasContainer : ((HasStep<?>) childStep).getHasContainers()) {
+                        if (null == key)
+                            key = hasContainer.getKey();
+                        else if (!hasContainer.getKey().equals(key)) {
                             process = false;
                             break;
                         }
+                        predicate = null == predicate ?
+                                hasContainer.getPredicate() :
+                                predicate.or(hasContainer.getPredicate());
                     }
-                    if (!process)
-                        break;
-                }
-                if (process) {
-                    changed = true;
-                    final HasStep hasStep = new HasStep<>(traversal, new HasContainer(key, predicate));
-                    TraversalHelper.replaceStep(step, hasStep, traversal);
-                    TraversalHelper.copyLabels(step, hasStep, false);
-                    for (final String label : labels) {
-                        hasStep.addLabel(label);
-                    }
+                    labels.addAll(childStep.getLabels());
+                } else {
+                    process = false;
+                    break;
                 }
             }
-            // and(x,y) --> x.y
-            for (final AndStep<?> step : TraversalHelper.getStepsOfClass(AndStep.class, traversal)) {
-                boolean process = true;
-                for (final Traversal.Admin<?, ?> childTraversal : step.getLocalChildren()) {
-                    if (!TraversalHelper.hasAllStepsOfClass(childTraversal, FilterStep.class) ||
-                            TraversalHelper.hasStepOfClass(childTraversal,
-                                    DropStep.class,
-                                    RangeGlobalStep.class,
-                                    DedupGlobalStep.class,
-                                    LambdaHolder.class)) {
-                        process = false;
-                        break;
-                    }
-                }
-                if (process) {
-                    changed = true;
-                    final List<Traversal.Admin<?, ?>> childTraversals = (List) step.getLocalChildren();
-                    Step<?, ?> finalStep = null;
-                    for (int i = childTraversals.size() - 1; i >= 0; i--) {
-                        final Traversal.Admin<?, ?> childTraversal = childTraversals.get(i);
-                        TraversalHelper.applySingleLevelStrategies(traversal, childTraversal, InlineFilterStrategy.class);
-                        if (null == finalStep)
-                            finalStep = childTraversal.getEndStep();
-                        TraversalHelper.insertTraversal((Step) step, childTraversals.get(i), traversal);
+            if (!process)
+                break;
+        }
+        if (process) {
+            final HasStep hasStep = new HasStep<>(traversal, new HasContainer(key, predicate));
+            TraversalHelper.replaceStep(step, hasStep, traversal);
+            TraversalHelper.copyLabels(step, hasStep, false);
+            for (final String label : labels) {
+                hasStep.addLabel(label);
+            }
+            return true;
+        }
+        return false;
+    }
 
-                    }
-                    if (null != finalStep) TraversalHelper.copyLabels(step, finalStep, false);
-                    traversal.removeStep(step);
-                }
+    private static final boolean processAndStep(final AndStep<?> step, final Traversal.Admin<?, ?> traversal) {
+        boolean process = true;
+        for (final Traversal.Admin<?, ?> childTraversal : step.getLocalChildren()) {
+            if (!TraversalHelper.hasAllStepsOfClass(childTraversal, FilterStep.class) ||
+                    TraversalHelper.hasStepOfClass(childTraversal,
+                            DropStep.class,
+                            RangeGlobalStep.class,
+                            DedupGlobalStep.class,
+                            LambdaHolder.class)) {
+                process = false;
+                break;
             }
-            // match(as('a').has(key,value),...) --> as('a').has(key,value).match(...)
-            if (traversal.getParent() instanceof EmptyStep) {
-                for (final MatchStep<?, ?> step : TraversalHelper.getStepsOfClass(MatchStep.class, traversal)) {
-                    final String startLabel = determineStartLabelForHasPullOut(step);
-                    if (null != startLabel) {
-                        for (final Traversal.Admin<?, ?> matchTraversal : new ArrayList<>(step.getGlobalChildren())) {
-                            if (!(step.getPreviousStep() instanceof EmptyStep) &&
-                                    TraversalHelper.hasAllStepsOfClass(matchTraversal,
-                                            HasStep.class,
-                                            MatchStep.MatchStartStep.class,
-                                            MatchStep.MatchEndStep.class) &&
-                                    matchTraversal.getStartStep() instanceof MatchStep.MatchStartStep &&
-                                    startLabel.equals(((MatchStep.MatchStartStep) matchTraversal.getStartStep()).getSelectKey().orElse(null))) {
-                                changed = true;
-                                final String endLabel = ((MatchStep.MatchEndStep) matchTraversal.getEndStep()).getMatchKey().orElse(null); // why would this exist? but just in case
-                                matchTraversal.removeStep(0);                                       // remove MatchStartStep
-                                matchTraversal.removeStep(matchTraversal.getSteps().size() - 1);    // remove MatchEndStep
-                                TraversalHelper.applySingleLevelStrategies(traversal, matchTraversal, InlineFilterStrategy.class);
-                                step.removeGlobalChild(matchTraversal);
-                                step.getPreviousStep().addLabel(startLabel);
-                                // TODO: matchTraversal.getEndStep().addLabel(startLabel); (perhaps insert an identity so filter rank can push has()-left)
-                                if (null != endLabel) matchTraversal.getEndStep().addLabel(endLabel);
-                                TraversalHelper.insertTraversal((Step) step.getPreviousStep(), matchTraversal, traversal);
-                            }
-                        }
-                        if (step.getGlobalChildren().isEmpty())
-                            traversal.removeStep(step);
-                    }
-                }
+        }
+        if (process) {
+            final List<Traversal.Admin<?, ?>> childTraversals = (List) step.getLocalChildren();
+            Step<?, ?> finalStep = null;
+            for (int i = childTraversals.size() - 1; i >= 0; i--) {
+                final Traversal.Admin<?, ?> childTraversal = childTraversals.get(i);
+                TraversalHelper.applySingleLevelStrategies(traversal, childTraversal, InlineFilterStrategy.class);
+                if (null == finalStep)
+                    finalStep = childTraversal.getEndStep();
+                TraversalHelper.insertTraversal((Step) step, childTraversals.get(i), traversal);
+
             }
+            if (null != finalStep) TraversalHelper.copyLabels(step, finalStep, false);
+            traversal.removeStep(step);
+            return true;
         }
+        return false;
     }
 
-    private static final String determineStartLabelForHasPullOut(final MatchStep<?, ?> matchStep) {
-        final String startLabel = MatchStep.Helper.computeStartLabel(matchStep.getGlobalChildren());
-        Step<?, ?> previousStep = matchStep.getPreviousStep();
-        if (previousStep.getLabels().contains(startLabel))
-            return startLabel;
-        while (!(previousStep instanceof EmptyStep)) {
-            if (!previousStep.getLabels().isEmpty())
-                return null;
-            previousStep = previousStep.getPreviousStep();
+    private static final boolean processMatchStep(final MatchStep<?, ?> step, final Traversal.Admin<?, ?> traversal) {
+        if (step.getPreviousStep() instanceof EmptyStep)
+            return false;
+        boolean changed = false;
+        final String startLabel = MatchStep.Helper.computeStartLabel(step.getGlobalChildren());
+        for (final Traversal.Admin<?, ?> matchTraversal : new ArrayList<>(step.getGlobalChildren())) {
+            if (TraversalHelper.hasAllStepsOfClass(matchTraversal,
+                    HasStep.class,
+                    MatchStep.MatchStartStep.class,
+                    MatchStep.MatchEndStep.class) &&
+                    matchTraversal.getStartStep() instanceof MatchStep.MatchStartStep &&
+                    startLabel.equals(((MatchStep.MatchStartStep) matchTraversal.getStartStep()).getSelectKey().orElse(null))) {
+                changed = true;
+                final String endLabel = ((MatchStep.MatchEndStep) matchTraversal.getEndStep()).getMatchKey().orElse(null); // why would this exist? but just in case
+                matchTraversal.removeStep(0);                                       // remove MatchStartStep
+                matchTraversal.removeStep(matchTraversal.getSteps().size() - 1);    // remove MatchEndStep
+                TraversalHelper.applySingleLevelStrategies(traversal, matchTraversal, InlineFilterStrategy.class);
+                step.removeGlobalChild(matchTraversal);
+                step.getPreviousStep().addLabel(startLabel);
+                // TODO: matchTraversal.getEndStep().addLabel(startLabel); (perhaps insert an identity so filter rank can push has()-left)
+                if (null != endLabel) matchTraversal.getEndStep().addLabel(endLabel);
+                TraversalHelper.insertTraversal((Step) step.getPreviousStep(), matchTraversal, traversal);
+            }
         }
-        return startLabel;
+        if (step.getGlobalChildren().isEmpty())
+            traversal.removeStep(step);
+        return changed;
     }
 
     @Override


[14/37] tinkerpop git commit: FilterRankStrategy now is smart about Scoping steps and thus, can rank labeled steps. order().as('a').dedup() is dedup().order().as('a'), but order().as('a').dedup('a') is order().as('a').dedup('a'). Lots of test cases in Fi

Posted by da...@apache.org.
FilterRankStrategy now is smart about Scoping steps and thus, can rank labeled steps. order().as('a').dedup() is dedup().order().as('a'), but order().as('a').dedup('a') is order().as('a').dedup('a'). Lots of test cases in FilterRankStrategyTest updated with more efficient reordering.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/56de6529
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/56de6529
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/56de6529

Branch: refs/heads/TINKERPOP-1458
Commit: 56de6529f2c5c59b83ff34d0190788a0ccfaf17c
Parents: 68bbae1
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Fri Sep 30 10:36:23 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 08:24:17 2016 -0600

----------------------------------------------------------------------
 .../optimization/FilterRankingStrategy.java     | 86 ++++++++------------
 .../process/traversal/util/TraversalHelper.java | 20 +++++
 .../optimization/FilterRankingStrategyTest.java | 15 ++--
 .../TinkerGraphStepStrategyTest.java            | 10 +--
 4 files changed, 68 insertions(+), 63 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/56de6529/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
index 06726b1..2065ea1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
@@ -22,6 +22,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Step;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.step.LambdaHolder;
+import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.AndStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.filter.ClassFilterStep;
@@ -39,17 +40,16 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.filter.WhereTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.OrderGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-import org.apache.tinkerpop.gremlin.structure.Graph;
-import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.Collections;
-import java.util.Iterator;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
 /**
- * FilterRankingStrategy reorders filter- and order-steps according to their rank. Labeled steps or lambda holders or
- * steps that contain child traversals, that have labeled steps or lambda holders, will not be reordered.
+ * FilterRankingStrategy reorders filter- and order-steps according to their rank. It will also do its best to push
+ * step labels as far "right" as possible in order to keep traversers as small and bulkable as possible prior to the
+ * absolute need for path-labeling.
  * <p/>
  * <table>
  * <thead>
@@ -89,12 +89,14 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
         boolean modified = true;
-        while(modified) {
+        while (modified) {
             modified = false;
+            final Set<String> currentLabels = new HashSet<>();
             for (final Step<?, ?> step : traversal.getSteps()) {
-                if (step instanceof FilterStep && !step.getLabels().isEmpty()) {
+                if (!step.getLabels().isEmpty()) {
+                    currentLabels.addAll(step.getLabels());
                     final Step<?, ?> nextStep = step.getNextStep();
-                    if (nextStep instanceof FilterStep && !(nextStep instanceof TraversalParent)) {
+                    if (validFilterStep(nextStep) && !usesLabels(nextStep, currentLabels)) {
                         TraversalHelper.copyLabels(step, nextStep, true);
                         modified = true;
                     }
@@ -104,7 +106,7 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave
             int prevRank = 0;
             for (int i = steps.size() - 1; i >= 0; i--) {
                 final Step curr = steps.get(i);
-                final int rank = rank(curr);
+                final int rank = usesLabels(curr, TraversalHelper.getLabelsUpTo(curr)) ? 0 : getStepRank(curr);
                 if (prevRank > 0 && rank > prevRank) {
                     final Step next = curr.getNextStep();
                     traversal.removeStep(next);
@@ -116,15 +118,6 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave
         }
     }
 
-    @Override
-    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
-        return PRIORS;
-    }
-
-    public static FilterRankingStrategy instance() {
-        return INSTANCE;
-    }
-
     /**
      * Ranks the given step. Steps with lower ranks can be moved in front of steps with higher ranks. 0 means that
      * the step has no rank and thus is not exchangeable with its neighbors.
@@ -159,47 +152,34 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave
             return 0;
     }
 
-    /**
-     * If the given step has no child traversal that holds a lambda, then the actual rank determined by
-     * {@link #getStepRank(Step)} is returned, otherwise 0.
-     *
-     * @param step the step to get a ranking for
-     * @return The rank of the given step.
-     */
-    private static int rank(final Step step) {
-        if (isNotOptimizableStep(step)) {
-            return 0;
-        }
-        final int rank = getStepRank(step);
-        if (rank > 0 && step instanceof TraversalParent) {
-            final TraversalParent tp = (TraversalParent) step;
-            final Iterator<Traversal.Admin<Object, Object>> childTraversalIterator = IteratorUtils.concat(
-                    tp.getLocalChildren().iterator(), tp.getGlobalChildren().iterator());
-            while (childTraversalIterator.hasNext()) {
-                if (TraversalHelper.anyStepRecursively(FilterRankingStrategy::isNotOptimizableStep, childTraversalIterator.next())) {
-                    return 0;
-                }
-            }
-        }
-        return rank;
+
+    private static boolean validFilterStep(final Step<?, ?> step) {
+        return ((step instanceof FilterStep && !(step instanceof LambdaHolder)) || step instanceof OrderGlobalStep);
     }
 
-    /**
-     * Returns true if the step is not optimizable, otherwise false. A step is not optimizable if it (or any of its
-     * child traversals) is a lambda holder or has a label.
-     *
-     * @param step the step to check for optimizability
-     * @return true if the given step is optimizable, otherwise false.
-     */
-    private static boolean isNotOptimizableStep(final Step<?, ?> step) {
+    private static boolean usesLabels(final Step<?, ?> step, final Set<String> labels) {
         if (step instanceof LambdaHolder)
             return true;
-        else {
-            for (final String label : step.getLabels()) {
-                if (!Graph.Hidden.isHidden(label))
+        if (step instanceof Scoping) {
+            final Set<String> scopes = ((Scoping) step).getScopeKeys();
+            for (final String label : labels) {
+                if (scopes.contains(label))
                     return true;
             }
-            return false;
         }
+        if (step instanceof TraversalParent) {
+            if (TraversalHelper.anyStepRecursively(s -> usesLabels(s, labels), (TraversalParent) step))
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Set<Class<? extends OptimizationStrategy>> applyPrior() {
+        return PRIORS;
+    }
+
+    public static FilterRankingStrategy instance() {
+        return INSTANCE;
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/56de6529/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
index be1406d..1fb9fab 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
@@ -425,6 +425,16 @@ public final class TraversalHelper {
         return false;
     }
 
+    public static boolean anyStepRecursively(final Predicate<Step> predicate, final TraversalParent step) {
+        for (final Traversal.Admin<?, ?> localChild : step.getLocalChildren()) {
+            if (anyStepRecursively(predicate, localChild)) return true;
+        }
+        for (final Traversal.Admin<?, ?> globalChild : step.getGlobalChildren()) {
+            if (anyStepRecursively(predicate, globalChild)) return true;
+        }
+        return false;
+    }
+
     public static <S> void addToCollection(final Collection<S> collection, final S s, final long bulk) {
         if (collection instanceof BulkSet) {
             ((BulkSet<S>) collection).add(s, bulk);
@@ -582,6 +592,16 @@ public final class TraversalHelper {
         }
     }
 
+    public static Set<String> getLabelsUpTo(final Step<?, ?> stopStep) {
+        final Set<String> labels = new HashSet<>();
+        Step<?, ?> step = stopStep.getPreviousStep();
+        while (!(step instanceof EmptyStep)) {
+            labels.addAll(step.getLabels());
+            step = step.getPreviousStep();
+        }
+        return labels;
+    }
+
     public static boolean hasAllStepsOfClass(final Traversal.Admin<?, ?> traversal, final Class<?>... classesToCheck) {
         for (final Step step : traversal.getSteps()) {
             boolean foundInstance = false;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/56de6529/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
index bd12e34..99e0cab 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -31,6 +32,7 @@ import org.junit.runners.Parameterized;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.function.Predicate;
 
 import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.filter;
@@ -77,15 +79,18 @@ public class FilterRankingStrategyTest {
 
     @Parameterized.Parameters(name = "{0}")
     public static Iterable<Object[]> generateTestParameters() {
-
+        final Predicate testP = t -> true;
         return Arrays.asList(new Object[][]{
                 {__.dedup().order(), __.dedup().order(), Collections.emptyList()},
-                {__.has("name", "marko").as("a").out().as("b").has("age", 32).where("a", neq("b")), __.has("name", "marko").as("a").out().as("b").has("age", 32).where("a", neq("b")), Collections.emptyList()},
+                {__.has("name", "marko").as("a").out().as("b").has("age", 32).where("a", neq("b")).as("c").out(), __.has("name", "marko").as("a").out().has("age", 32).as("b").where("a", neq("b")).as("c").out(), Collections.emptyList()},
                 {__.has("name", "marko").as("a").out().has("age", 32).as("b").where("a", neq("b")), __.has("name", "marko").as("a").out().has("age", 32).as("b").where("a", neq("b")), Collections.emptyList()},
-                {__.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a"), __.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a"), Collections.emptyList()},
-                {__.has("name", "marko").dedup().as("a").has("age", 32).has("name", "bob").as("b"), __.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a", "b"), Collections.emptyList()},
+                {__.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a"), __.has("name", "marko").has("age", 32).has("name", "bob").dedup().as("a"), Collections.emptyList()},
+                {__.has("name", "marko").dedup().as("a").has("age", 32).has("name", "bob").as("b"), __.has("name", "marko").has("age", 32).has("name", "bob").dedup().as("b", "a"), Collections.emptyList()},
                 {__.order().dedup(), __.dedup().order(), Collections.emptyList()},
-                {__.order().as("a").dedup(), __.order().as("a").dedup(), Collections.emptyList()},
+                {__.order().filter(testP).dedup(), __.order().filter(testP).dedup(), Collections.emptyList()},
+                {__.order().as("a").dedup(), __.dedup().order().as("a"), Collections.emptyList()},
+                {__.order().as("a").dedup("a"), __.order().as("a").dedup("a"), Collections.emptyList()},
+                // {__.order().as("a").dedup("a").has("name","marko"), __.has("name","marko").order().as("a").dedup("a"), Collections.emptyList()},
                 {__.identity().order().dedup(), __.dedup().order(), Collections.singletonList(IdentityRemovalStrategy.instance())},
                 {__.order().identity().dedup(), __.dedup().order(), Collections.singletonList(IdentityRemovalStrategy.instance())},
                 {__.order().out().dedup(), __.order().out().dedup(), Collections.emptyList()},

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/56de6529/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java
index 9f97466..35f936c 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/traversal/strategy/optimization/TinkerGraphStepStrategyTest.java
@@ -100,17 +100,17 @@ public class TinkerGraphStepStrategyTest {
                 {__.V().has("name", "marko").as("a").or(has("age"), has("age", gt(32))).has("lang", "java"),
                         g_V("name", eq("marko")).as("a").or(has("age"), has("age", gt(32))).has("lang", "java"), Collections.emptyList()},
                 {__.V().has("name", "marko").as("a").or(has("age"), has("age", gt(32))).has("lang", "java"),
-                        g_V("name", eq("marko"), "lang", eq("java")).as("a").or(has("age"), has("age", gt(32))), Collections.singletonList(FilterRankingStrategy.instance())},
+                        g_V("name", eq("marko"), "lang", eq("java")).or(has("age"), has("age", gt(32))).as("a"), Collections.singletonList(FilterRankingStrategy.instance())},
                 {__.V().dedup().has("name", "marko").or(has("age"), has("age", gt(32))).has("lang", "java"),
                         g_V("name", eq("marko"), "lang", eq("java")).or(has("age"), has("age", gt(32))).dedup(), Collections.singletonList(FilterRankingStrategy.instance())},
                 {__.V().as("a").dedup().has("name", "marko").or(has("age"), has("age", gt(32))).has("lang", "java"),
-                        g_V("name", eq("marko"), "lang", eq("java")).as("a").or(has("age"), has("age", gt(32))).dedup(), Collections.singletonList(FilterRankingStrategy.instance())},
+                        g_V("name", eq("marko"), "lang", eq("java")).or(has("age"), has("age", gt(32))).dedup().as("a"), Collections.singletonList(FilterRankingStrategy.instance())},
                 {__.V().as("a").has("name", "marko").as("b").or(has("age"), has("age", gt(32))).has("lang", "java"),
-                        g_V("name", eq("marko"), "lang", eq("java")).as("a", "b").or(has("age"), has("age", gt(32))), Collections.singletonList(FilterRankingStrategy.instance())},
+                        g_V("name", eq("marko"), "lang", eq("java")).or(has("age"), has("age", gt(32))).as("b", "a"), Collections.singletonList(FilterRankingStrategy.instance())},
                 {__.V().as("a").dedup().has("name", "marko").or(has("age"), has("age", gt(32))).filter(has("name", "bob")).has("lang", "java"),
-                        g_V("name", eq("marko"), "name", eq("bob"), "lang", eq("java")).as("a").or(has("age"), has("age", gt(32))).dedup(), Arrays.asList(InlineFilterStrategy.instance(), FilterRankingStrategy.instance())},
+                        g_V("name", eq("marko"), "name", eq("bob"), "lang", eq("java")).or(has("age"), has("age", gt(32))).dedup().as("a"), Arrays.asList(InlineFilterStrategy.instance(), FilterRankingStrategy.instance())},
                 {__.V().as("a").dedup().has("name", "marko").or(has("age", 10), has("age", gt(32))).filter(has("name", "bob")).has("lang", "java"),
-                        g_V("name", eq("marko"), "age", eq(10).or(gt(32)), "name", eq("bob"), "lang", eq("java")).as("a").dedup(), TraversalStrategies.GlobalCache.getStrategies(TinkerGraph.class).toList()},
+                        g_V("name", eq("marko"), "age", eq(10).or(gt(32)), "name", eq("bob"), "lang", eq("java")).dedup().as("a"), TraversalStrategies.GlobalCache.getStrategies(TinkerGraph.class).toList()},
                 {__.V().has("name", "marko").or(not(has("age")), has("age", gt(32))).has("name", "bob").has("lang", "java"),
                         g_V("name", eq("marko"), "name", eq("bob"), "lang", eq("java")).or(not(filter(properties("age"))), has("age", gt(32))), TraversalStrategies.GlobalCache.getStrategies(TinkerGraph.class).toList()}
         });


[08/37] tinkerpop git commit: CHANGELOG tweak.

Posted by da...@apache.org.
CHANGELOG tweak.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/bc00bb3c
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/bc00bb3c
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/bc00bb3c

Branch: refs/heads/TINKERPOP-1458
Commit: bc00bb3c4535aec8229b7770f9e8ab60326117ef
Parents: 62197e2
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Oct 3 08:23:38 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 08:24:17 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/bc00bb3c/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 60e895b..4dc4dc3 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,7 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* `FilterRankStrategy` now propagates labels "right" non-`Scoping` filters.
+* `FilterRankStrategy` now propagates labels "right" over non-`Scoping` filters.
 * Fixed a bug in `ConnectiveP` where nested equivalent connectives should be inlined.
 * Fixed a bug in `IncidentToAdjacentStrategy` where `TreeStep` traversals were allowed.
 * Fixed a end-step label bug in `MatchPredicateStrategy`.


[24/37] tinkerpop git commit: TraversalOpProcessor returns a success message upon receiveing a close command

Posted by da...@apache.org.
TraversalOpProcessor returns a success message upon receiveing a close command


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/e319ff65
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/e319ff65
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/e319ff65

Branch: refs/heads/TINKERPOP-1458
Commit: e319ff65102ae4a3be850821669f9cb7c1e38908
Parents: d43d4e0
Author: davebshow <da...@apache.org>
Authored: Thu Sep 22 14:51:21 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:30 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                                                | 1 +
 .../gremlin/server/op/traversal/TraversalOpProcessor.java         | 3 +++
 2 files changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e319ff65/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 93308b6..1122a31 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -66,6 +66,7 @@ TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 * VertexPrograms can now declare traverser requirements, e.g. to have access to the path when used with `.program()`.
 * New build options for `gremlin-python` where `-DglvPython` is no longer required.
 * Added missing `InetAddress` to GraphSON extension module.
+* Gremlin Server `TraversalOpProcessor` now returns confirmation upon `Op` `close`.
 
 [[release-3-2-2]]
 TinkerPop 3.2.2 (Release Date: September 6, 2016)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e319ff65/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
index 80cacd2..88d8d90 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
@@ -198,6 +198,9 @@ public class TraversalOpProcessor extends AbstractOpProcessor {
 
                     final Optional<UUID> sideEffect = msg.optionalArgs(Tokens.ARGS_SIDE_EFFECT);
                     cache.invalidate(sideEffect.get());
+
+                    final String successMessage = String.format("Successfully cleared side effect cache for [%s].", Tokens.ARGS_SIDE_EFFECT);
+                    ctx.getChannelHandlerContext().writeAndFlush(ResponseMessage.build(message).code(ResponseStatusCode.NO_CONTENT).statusMessage(successMessage).create());
                 };
 
                 break;


[10/37] tinkerpop git commit: FilterRankStategy is now smart about pushing labels 'right'. Why is this good -- it ensures that filter-chains are as concatenated as possible without changing path semantics. This is about increasing the number of potential

Posted by da...@apache.org.
FilterRankStategy is now smart about pushing labels 'right'. Why is this good -- it ensures that filter-chains are as concatenated as possible without changing path semantics. This is about increasing the number of potential has()-steps that providers can grab for index lookups. Also, InlineFilterStep is is able to compress has().has() chains into a single has() and propagate labels accordingly. Added various test cases to validate behavior. The only thing left is HasContainer being able to compress AndP predicates and we will have a really tight compression on filters.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/ff1c3844
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/ff1c3844
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/ff1c3844

Branch: refs/heads/TINKERPOP-1458
Commit: ff1c3844a487cf4db437edfdf7f2251c38da50ab
Parents: 9ef8a9a
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Sep 29 14:42:51 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 08:24:17 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../optimization/FilterRankingStrategy.java     | 16 ++++++--
 .../optimization/InlineFilterStrategy.java      | 18 ++++++++-
 .../process/traversal/util/TraversalHelper.java | 11 ++++--
 .../decoration/SubgraphStrategyTest.java        | 28 +++++++-------
 .../optimization/FilterRankingStrategyTest.java |  3 ++
 .../optimization/InlineFilterStrategyTest.java  | 39 +++++++++++++-------
 7 files changed, 79 insertions(+), 37 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff1c3844/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index d204b44..638a80c 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* `FilterRankStrategy` now propagates labels "right" across non-`TraversalParent` filters.
 * Fixed a bug in `ConnectiveP` where nested equivalent connectives should be inlined.
 * Fixed a bug in `IncidentToAdjacentStrategy` where `TreeStep` traversals were allowed.
 * Fixed a end-step label bug in `MatchPredicateStrategy`.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff1c3844/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
index 2a0a025..dead668 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
@@ -43,7 +43,6 @@ import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
 
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
@@ -89,9 +88,18 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave
 
     @Override
     public void apply(final Traversal.Admin<?, ?> traversal) {
-        boolean modified;
-        do {
+        boolean modified = true;
+        while(modified) {
             modified = false;
+            for (final Step<?, ?> step : traversal.getSteps()) {
+                if (!step.getLabels().isEmpty()) {
+                    final Step<?, ?> nextStep = step.getNextStep();
+                    if (nextStep instanceof FilterStep && !(nextStep instanceof TraversalParent)) {
+                        TraversalHelper.copyLabels(step, nextStep, true);
+                        modified = true;
+                    }
+                }
+            }
             final List<Step> steps = traversal.getSteps();
             int prevRank = 0;
             for (int i = steps.size() - 1; i >= 0; i--) {
@@ -105,7 +113,7 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave
                 }
                 prevRank = rank;
             }
-        } while (modified);
+        }
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff1c3844/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
index a3ed9a1..820143a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
@@ -76,7 +76,10 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
         while (changed) {
             changed = false;
             for (final FilterStep<?> step : TraversalHelper.getStepsOfAssignableClass(FilterStep.class, traversal)) {
-                if (step instanceof TraversalFilterStep && InlineFilterStrategy.processTraversalFilterStep((TraversalFilterStep) step, traversal))
+                if (step instanceof HasStep && InlineFilterStrategy.processHasStep((HasStep) step, traversal))
+                    // has(a,b).has(c) --> has(a,b,c)
+                    changed = true;
+                else if (step instanceof TraversalFilterStep && InlineFilterStrategy.processTraversalFilterStep((TraversalFilterStep) step, traversal))
                     // filter(x.y) --> x.y
                     changed = true;
                 else if (step instanceof OrStep && InlineFilterStrategy.processOrStep((OrStep) step, traversal))
@@ -99,6 +102,19 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
     ////////////////////////////
     ///////////////////////////
 
+    private static final boolean processHasStep(final HasStep<?> step, final Traversal.Admin<?, ?> traversal) {
+        if (step.getPreviousStep() instanceof HasStep) {
+            final HasStep<?> previousStep = (HasStep<?>) step.getPreviousStep();
+            for (final HasContainer hasContainer : step.getHasContainers()) {
+                previousStep.addHasContainer(hasContainer);
+            }
+            TraversalHelper.copyLabels(step, previousStep, false);
+            traversal.removeStep(step);
+            return true;
+        }
+        return false;
+    }
+
     private static final boolean processTraversalFilterStep(final TraversalFilterStep<?> step, final Traversal.Admin<?, ?> traversal) {
         final Traversal.Admin<?, ?> childTraversal = step.getLocalChildren().get(0);
         if (TraversalHelper.hasAllStepsOfClass(childTraversal, FilterStep.class) &&

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff1c3844/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
index 2192666..be1406d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
@@ -50,6 +50,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
@@ -572,10 +573,12 @@ public final class TraversalHelper {
     }
 
     public static void copyLabels(final Step<?, ?> fromStep, final Step<?, ?> toStep, final boolean moveLabels) {
-        for (final String label : fromStep.getLabels()) {
-            toStep.addLabel(label);
-            if (moveLabels)
-                fromStep.removeLabel(label);
+        if (!fromStep.getLabels().isEmpty()) {
+            for (final String label : moveLabels ? new LinkedHashSet<>(fromStep.getLabels()) : fromStep.getLabels()) {
+                toStep.addLabel(label);
+                if (moveLabels)
+                    fromStep.removeLabel(label);
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff1c3844/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java
index 7082838..901d3a5 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/decoration/SubgraphStrategyTest.java
@@ -69,28 +69,26 @@ public class SubgraphStrategyTest {
         @Parameterized.Parameter(value = 1)
         public Traversal optimized;
 
-
-        void applySubgraphStrategyTest(final Traversal traversal) {
-            final TraversalStrategies strategies = new DefaultTraversalStrategies();
-            strategies.addStrategies(SubgraphStrategy.build().
+        @Test
+        public void doTest() {
+            final TraversalStrategies originalStrategies = new DefaultTraversalStrategies();
+            originalStrategies.addStrategies(SubgraphStrategy.build().
                     vertices(__.and(has("name", "marko"), has("age", 29))).
                     edges(hasLabel("knows")).
                     vertexProperties(__.<VertexProperty, Long>values().count().and(is(P.lt(10)), is(0))).create());
-            strategies.addStrategies(InlineFilterStrategy.instance());
-            strategies.addStrategies(StandardVerificationStrategy.instance());
-            traversal.asAdmin().setStrategies(strategies);
-            traversal.asAdmin().applyStrategies();
-        }
-
-        @Test
-        public void doTest() {
-            applySubgraphStrategyTest(original);
-            assertEquals(optimized, original);
+            originalStrategies.addStrategies(InlineFilterStrategy.instance());
+            originalStrategies.addStrategies(StandardVerificationStrategy.instance());
+            this.original.asAdmin().setStrategies(originalStrategies);
+            this.original.asAdmin().applyStrategies();
+            final TraversalStrategies optimizedStrategies = new DefaultTraversalStrategies();
+            optimizedStrategies.addStrategies(InlineFilterStrategy.instance());
+            this.optimized.asAdmin().setStrategies(optimizedStrategies);
+            this.optimized.asAdmin().applyStrategies();
+            assertEquals(this.optimized, this.original);
         }
 
         @Parameterized.Parameters(name = "{0}")
         public static Iterable<Object[]> generateTestParameters() {
-
             return Arrays.asList(new Traversal[][]{
                     {__.outE(), __.outE().hasLabel("knows").and(
                             inV().has("name", "marko").has("age", 29),

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff1c3844/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
index dc0d17a..52379fd 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
@@ -32,6 +32,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 
+import static org.apache.tinkerpop.gremlin.process.traversal.P.eq;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.filter;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
@@ -79,6 +80,8 @@ public class FilterRankingStrategyTest {
 
         return Arrays.asList(new Object[][]{
                 {__.dedup().order(), __.dedup().order(), Collections.emptyList()},
+                {__.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a"), __.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a"), Collections.emptyList()},
+                {__.has("name", "marko").dedup().as("a").has("age", 32).has("name", "bob").as("b"), __.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a","b"), Collections.emptyList()},
                 {__.order().dedup(), __.dedup().order(), Collections.emptyList()},
                 {__.order().as("a").dedup(), __.order().as("a").dedup(), Collections.emptyList()},
                 {__.identity().order().dedup(), __.dedup().order(), Collections.singletonList(IdentityRemovalStrategy.instance())},

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ff1c3844/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
index 9530c82..abf1f00 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategyTest.java
@@ -22,6 +22,10 @@ package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
 import org.apache.tinkerpop.gremlin.process.traversal.P;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.HasContainer;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -40,7 +44,6 @@ import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.drop;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.filter;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.limit;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.map;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.match;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.or;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
@@ -74,11 +77,13 @@ public class InlineFilterStrategyTest {
     public static Iterable<Object[]> generateTestParameters() {
 
         return Arrays.asList(new Traversal[][]{
+                {has("age", 10).as("a").has("name", "marko").as("b").coin(0.5).as("c"), addHas(__.start(), "age", eq(10), "name", eq("marko")).as("a","b").coin(0.5).as("c")},
+                //
                 {filter(out("knows")), filter(out("knows"))},
-                {filter(has("age", P.gt(10))).as("a"), has("age", P.gt(10)).as("a")},
-                {filter(has("age", P.gt(10)).as("b")).as("a"), has("age", P.gt(10)).as("b", "a")},
-                {filter(has("age", P.gt(10)).as("a")), has("age", P.gt(10)).as("a")},
-                {filter(and(has("age", P.gt(10)).as("a"), has("name", "marko"))), has("age", P.gt(10)).as("a").has("name", "marko")},
+                {filter(has("age", gt(10))).as("a"), has("age", gt(10)).as("a")},
+                {filter(has("age", gt(10)).as("b")).as("a"), has("age", gt(10)).as("b", "a")},
+                {filter(has("age", gt(10)).as("a")), has("age", gt(10)).as("a")},
+                {filter(and(has("age", gt(10)).as("a"), has("name", "marko"))), addHas(__.start(), "age", gt(10), "name", eq("marko")).as("a")},
                 //
                 {or(has("name", "marko"), has("age", 32)), or(has("name", "marko"), has("age", 32))},
                 {or(has("name", "marko"), has("name", "bob")), has("name", eq("marko").or(eq("bob")))},
@@ -88,17 +93,17 @@ public class InlineFilterStrategyTest {
                 {or(has("name", "marko"), filter(or(filter(has("name", "bob")), has("name", "stephen")))), has("name", eq("marko").or(eq("bob").or(eq("stephen"))))},
                 {or(has("name", "marko").as("a"), filter(or(filter(has("name", "bob")).as("b"), has("name", "stephen").as("c")))), has("name", eq("marko").or(eq("bob").or(eq("stephen")))).as("a", "b", "c")},
                 //
-                {and(has("age", P.gt(10)), filter(has("age", 22))), has("age", P.gt(10)).has("age", 22)},
-                {and(has("age", P.gt(10)).as("a"), filter(has("age", 22).as("b")).as("c")).as("d"), has("age", P.gt(10)).as("a").has("age", 22).as("b", "c", "d")},
-                {and(has("age", P.gt(10)).as("a"), and(filter(has("age", 22).as("b")).as("c"), has("name", "marko").as("d"))), has("age", P.gt(10)).as("a").has("age", 22).as("b", "c").has("name", "marko").as("d")},
-                {and(has("age", P.gt(10)).as("a"), and(has("name","stephen").as("b"), has("name", "marko").as("c")).as("d")).as("e"), has("age", P.gt(10)).as("a").has("name","stephen").as("b").has("name","marko").as("c","d","e")},
-                {and(has("age", P.gt(10)), and(out("knows"), has("name", "marko"))), has("age", P.gt(10)).and(out("knows"), has("name", "marko"))},
-                {and(has("age", P.gt(20)), or(has("age", lt(10)), has("age", gt(100)))), has("age", gt(20)).has("age", lt(10).or(gt(100)))},
-                {and(has("age", P.gt(20)).as("a"), or(has("age", lt(10)), has("age", gt(100)).as("b"))), has("age", gt(20)).as("a").has("age", lt(10).or(gt(100))).as("b")},
+                {and(has("age", gt(10)), filter(has("age", 22))), addHas(__.start(), "age", gt(10), "age", eq(22))},
+                {and(has("age", gt(10)).as("a"), filter(has("age", 22).as("b")).as("c")).as("d"), addHas(__.start(), "age", gt(10), "age", eq(22)).as("a", "b", "c", "d")},
+                {and(has("age", gt(10)).as("a"), and(filter(has("age", 22).as("b")).as("c"), has("name", "marko").as("d"))), addHas(__.start(), "age", gt(10), "age", eq(22), "name", eq("marko")).as("a", "b", "c", "d")},
+                {and(has("age", gt(10)).as("a"), and(has("name", "stephen").as("b"), has("name", "marko").as("c")).as("d")).as("e"), addHas(__.start(), "age", gt(10), "name", eq("stephen"), "name", eq("marko")).as("a", "b", "c", "d", "e")},
+                {and(has("age", gt(10)), and(out("knows"), has("name", "marko"))), has("age", gt(10)).and(out("knows"), has("name", "marko"))},
+                {and(has("age", gt(20)), or(has("age", lt(10)), has("age", gt(100)))), addHas(__.start(), "age", gt(20), "age", lt(10).or(gt(100)))},
+                {and(has("age", gt(20)).as("a"), or(has("age", lt(10)), has("age", gt(100)).as("b"))), addHas(__.start(), "age", gt(20), "age", lt(10).or(gt(100))).as("a", "b")},
                 //
                 {V().match(as("a").has("age", 10), as("a").filter(has("name")).as("b")), V().as("a").has("age", 10).match(as("a").has("name").as("b"))},
                 {match(as("a").has("age", 10), as("a").filter(has("name")).as("b")), match(as("a").has("age", 10), as("a").has("name").as("b"))},
-                {map(match(as("a").has("age", 10), as("a").filter(has("name")).as("b"))), map(match(as("a").has("age", 10), as("a").has("name").as("b")))},
+                {__.map(match(as("a").has("age", 10), as("a").filter(has("name")).as("b"))), __.map(match(as("a").has("age", 10), as("a").has("name").as("b")))},
                 {V().match(as("a").has("age", 10)), V().as("a").has("age", 10)},
                 {V().match(as("a").has("age", 10).as("b"), as("a").filter(has("name")).as("b")), V().as("a").has("age", 10).as("b").match(as("a").has("name").as("b"))},
                 //
@@ -108,4 +113,12 @@ public class InlineFilterStrategyTest {
                 {filter(tail(10).as("a")), filter(tail(10).as("a"))},
         });
     }
+
+    private static GraphTraversal.Admin<?, ?> addHas(final GraphTraversal<?, ?> traversal, final Object... hasKeyValues) {
+        final HasStep<?> hasStep = new HasStep<>((Traversal.Admin) traversal);
+        for (int i = 0; i < hasKeyValues.length; i = i + 2) {
+            hasStep.addHasContainer(new HasContainer((String) hasKeyValues[i], (P) hasKeyValues[i + 1]));
+        }
+        return traversal.asAdmin().addStep(hasStep);
+    }
 }


[36/37] tinkerpop git commit: got rid of wildcard set by intellij

Posted by da...@apache.org.
got rid of wildcard set by intellij


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/36141820
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/36141820
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/36141820

Branch: refs/heads/TINKERPOP-1458
Commit: 36141820b6907b7242fc5c619e05df30185f5e92
Parents: 0457fb1
Author: davebshow <da...@gmail.com>
Authored: Thu Sep 29 12:04:03 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../tinkerpop/gremlin/server/GremlinServerIntegrateTest.java   | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/36141820/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index 7d6c0c9..a1d019b 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -65,7 +65,11 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.nio.channels.ClosedChannelException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;


[29/37] tinkerpop git commit: added close method to DriverRemoteTraversalSideEffects, implement AutoCloseable on TraversalSideEffects, add test for close method

Posted by da...@apache.org.
added close method to DriverRemoteTraversalSideEffects, implement AutoCloseable on TraversalSideEffects, add test for close method


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/0457fb1d
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/0457fb1d
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/0457fb1d

Branch: refs/heads/TINKERPOP-1458
Commit: 0457fb1dfc18044e5222362c8fe37e8a52314dbe
Parents: df9ff69
Author: davebshow <da...@gmail.com>
Authored: Thu Sep 29 11:55:09 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../process/traversal/TraversalSideEffects.java |  9 ++++-
 .../DriverRemoteTraversalSideEffects.java       | 21 +++++++++--
 .../server/GremlinServerIntegrateTest.java      | 38 +++++++++++++-------
 3 files changed, 51 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0457fb1d/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java
index 95b9fb1..ae6ef54 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalSideEffects.java
@@ -32,7 +32,7 @@ import java.util.function.UnaryOperator;
  *
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public interface TraversalSideEffects extends Cloneable, Serializable {
+public interface TraversalSideEffects extends Cloneable, Serializable, AutoCloseable {
 
     /**
      * Return true if the key is a registered side-effect.
@@ -83,6 +83,13 @@ public interface TraversalSideEffects extends Cloneable, Serializable {
     public Set<String> keys();
 
     /**
+     * Invalidate the side effect cache for traversal.
+     */
+    public default void close() throws Exception {
+        // do nothing
+    }
+
+    /**
      * Determines if there are any side-effects to be retrieved.
      */
     public default boolean isEmpty() {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0457fb1d/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
index 85d7abc..c565dfa 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
@@ -45,6 +45,8 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
 
     private final Map<String, Object> sideEffects = new HashMap<>();
 
+    private boolean closed = false;
+
     public DriverRemoteTraversalSideEffects(final Client client, final UUID serverSideEffect, final Host host) {
         this.client = client;
         this.serverSideEffect = serverSideEffect;
@@ -99,10 +101,23 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
         return keys;
     }
 
+
     @Override
     public void close() throws Exception {
-        // todo: need to add a call to "close" the side effects on the server - probably should ensure request only sends once
-
-        // leave the client open as it is owned by the DriverRemoteConnection not the traversal or side-effects
+        if (!closed) {
+            final RequestMessage msg = RequestMessage.build(Tokens.OPS_CLOSE)
+                    .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffect)
+                    .addArg(Tokens.ARGS_HOST, host)
+                    .processor("traversal").create();
+            try {
+                client.submitAsync(msg).get();
+                sideEffects.clear();
+                keys = null;
+                closed = true;
+            } catch (Exception ex) {
+                final Throwable root = ExceptionUtils.getRootCause(ex);
+                throw new RuntimeException("Error on closing side effects", root);
+            }
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/0457fb1d/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index 5a36acf..7d6c0c9 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -49,6 +49,7 @@ import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.InterpreterModeCust
 import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.SimpleSandboxExtension;
 import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.TimedInterruptCustomizerProvider;
 import org.apache.tinkerpop.gremlin.process.remote.RemoteGraph;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
@@ -64,11 +65,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.nio.channels.ClosedChannelException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -102,6 +99,14 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
 
     private Log4jRecordingAppender recordingAppender = null;
 
+    private final Supplier<Graph> graphGetter = () -> server.getServerGremlinExecutor().getGraphManager().getGraphs().get("graph");
+    private final Configuration conf = new BaseConfiguration() {{
+        setProperty(Graph.GRAPH, RemoteGraph.class.getName());
+        setProperty(GREMLIN_REMOTE_CONNECTION_CLASS, DriverRemoteConnection.class.getName());
+        setProperty(DriverRemoteConnection.GREMLIN_REMOTE_DRIVER_SOURCENAME, "g");
+        setProperty("hidden.for.testing.only", graphGetter);
+    }};
+
     @Before
     public void setupForEachTest() {
         recordingAppender = new Log4jRecordingAppender();
@@ -814,18 +819,25 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
 
     @Test
     public void shouldSupportLambdasUsingWithRemote() throws Exception {
-        final Supplier<Graph> graphGetter = () -> server.getServerGremlinExecutor().getGraphManager().getGraphs().get("graph");
-        final Configuration conf = new BaseConfiguration() {{
-            setProperty(Graph.GRAPH, RemoteGraph.class.getName());
-            setProperty(GREMLIN_REMOTE_CONNECTION_CLASS, DriverRemoteConnection.class.getName());
-            setProperty(DriverRemoteConnection.GREMLIN_REMOTE_DRIVER_SOURCENAME, "g");
-            setProperty("hidden.for.testing.only", graphGetter);
-        }};
-
         final Graph graph = EmptyGraph.instance();
         final GraphTraversalSource g = graph.traversal().withRemote(conf);
         g.addV("person").property("age", 20).iterate();
         g.addV("person").property("age", 10).iterate();
         assertEquals(50L, g.V().hasLabel("person").map(Lambda.function("it.get().value('age') + 10")).sum().next());
     }
+
+    @Test
+    public void shouldCloseSideEffects() throws Exception {
+        final Graph graph = EmptyGraph.instance();
+        final GraphTraversalSource g = graph.traversal().withRemote(conf);
+        g.addV("person").property("age", 20).iterate();
+        g.addV("person").property("age", 10).iterate();
+        final GraphTraversal traversal = g.V().aggregate("a");
+        traversal.iterate();
+        final Set sideEffects = traversal.asAdmin().getSideEffects().keys();
+        assertTrue(sideEffects.contains("a"));
+        traversal.asAdmin().getSideEffects().close();
+        final Set emptySideEffects = traversal.asAdmin().getSideEffects().keys();
+        assertTrue(emptySideEffects.isEmpty());
+    }
 }


[32/37] tinkerpop git commit: closed conn in tests, this should be done with pytest fixtures, but until then, manually

Posted by da...@apache.org.
closed conn in tests, this should be done with pytest fixtures, but until then, manually


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/44742f5b
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/44742f5b
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/44742f5b

Branch: refs/heads/TINKERPOP-1458
Commit: 44742f5bb1e30e079e55b7461db3ab82602c7c03
Parents: 359005a
Author: davebshow <da...@gmail.com>
Authored: Thu Oct 6 09:31:18 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../src/main/jython/tests/driver/test_driver_remote_connection.py | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/44742f5b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
index d8d2ed4..fa17808 100644
--- a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
@@ -117,6 +117,8 @@ class TestDriverRemoteConnection(TestCase):
             raise Exception("Accessing a non-existent key should throw an error")
         except KeyError:
             pass
+        connection.close()
+
 
     def test_side_effect_close(self):
         connection = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g')
@@ -150,6 +152,7 @@ class TestDriverRemoteConnection(TestCase):
         # Try to get 'b' directly from server, should throw error
         with pytest.raises(Exception):
             t.side_effects.value_lambda('b')
+        connection.close()
 
 
 if __name__ == '__main__':


[27/37] tinkerpop git commit: fixed side effect methods and updated tests

Posted by da...@apache.org.
fixed side effect methods and updated tests


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/be655e62
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/be655e62
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/be655e62

Branch: refs/heads/TINKERPOP-1458
Commit: be655e6226bd12cd8ceb84e7a21950548dfbc08b
Parents: 4eeb6fb
Author: davebshow <da...@gmail.com>
Authored: Wed Oct 5 17:59:15 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../DriverRemoteTraversalSideEffects.java       |  6 ++++-
 .../DriverRemoteTraversalSideEffectsTest.java   | 24 ++++++++++++++++++--
 .../server/GremlinServerIntegrateTest.java      | 18 +++++++++------
 3 files changed, 38 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/be655e62/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
index d2fced5..2dece11 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.remote.traversal.AbstractRemoteTrave
 
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
@@ -67,10 +68,13 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
                 try {
                     final Result result = client.submitAsync(msg).get().one();
                     sideEffects.put(key, null == result ? null : result.getObject());
+                    if (keys.isEmpty())
+                        keys = new HashSet<>();
                     keys.add(key);
                 } catch (Exception ex) {
                     final Throwable root = ExceptionUtils.getRootCause(ex);
-                    if (root.getMessage().equals("Could not find side-effects for " + serverSideEffect + "."))
+                    final String exMsg = null == root ? "" : root.getMessage();
+                    if (exMsg.equals("Could not find side-effects for " + serverSideEffect + "."))
                         sideEffects.put(key, null);
                     else
                         throw new RuntimeException("Could not get keys", root);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/be655e62/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java
index d4c5618..368ca92 100644
--- a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java
@@ -29,6 +29,7 @@ import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -63,10 +64,29 @@ public class DriverRemoteTraversalSideEffectsTest extends AbstractResultQueueTes
     }
 
     @Test
-    public void shouldNotContactRemoteMoreThanOnceForClose() throws Exception {
+    public void shoudlNotContactRemoteForGetAfterCloseIsCalled() throws Exception {
         final Client client = mock(Client.class);
         mockClientForCall(client);
         mockClientForCall(client);
+        final UUID sideEffectKey = UUID.fromString("31dec2c6-b214-4a6f-a68b-996608dce0d9");
+        final TraversalSideEffects sideEffects = new DriverRemoteTraversalSideEffects(client, sideEffectKey, null);
+
+        assertNotNull(sideEffects.get("a"));
+        sideEffects.close();
+
+        // Side effect 'a' should be cached locally
+        assertNotNull(sideEffects.get("a"));
+        assertNotNull(sideEffects.get("a"));
+        assertNotNull(sideEffects.get("a"));
+
+        // Once for get and once for close
+        verify(client, times(2)).submitAsync(any(RequestMessage.class));
+    }
+
+    @Test
+    public void shouldNotContactRemoteMoreThanOnceForClose() throws Exception {
+        final Client client = mock(Client.class);
+        mockClientForCall(client);
 
         final UUID sideEffectKey = UUID.fromString("31dec2c6-b214-4a6f-a68b-996608dce0d9");
         final TraversalSideEffects sideEffects = new DriverRemoteTraversalSideEffects(client, sideEffectKey, null);
@@ -79,7 +99,7 @@ public class DriverRemoteTraversalSideEffectsTest extends AbstractResultQueueTes
 
         assertEquals(0, sideEffects.keys().size());
 
-        // once for the keys and once for the close message
+        // once for the close message
         verify(client, times(1)).submitAsync(any(RequestMessage.class));
     }
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/be655e62/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index 61bf994..1c4d19e 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -52,6 +52,7 @@ import org.apache.tinkerpop.gremlin.groovy.jsr223.customizer.TimedInterruptCusto
 import org.apache.tinkerpop.gremlin.process.remote.RemoteGraph;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.T;
 import org.apache.tinkerpop.gremlin.server.channel.NioChannelizer;
@@ -850,9 +851,9 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
         assertEquals(2, sideEffectKeys.size());
 
         // Get side effects
-        final List aSideEffects = se.get("a");
+        final BulkSet aSideEffects = se.get("a");
         assertThat(aSideEffects.isEmpty(), is(false));
-        final List bSideEffects = se.get("b");
+        final BulkSet bSideEffects = se.get("b");
         assertThat(bSideEffects.isEmpty(), is(false));
 
         // Should get local keys/side effects after close
@@ -861,10 +862,10 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
         final Set<String> localSideEffectKeys = se.keys();
         assertEquals(2, localSideEffectKeys.size());
 
-        final List localASideEffects = se.get("a");
+        final BulkSet localASideEffects = se.get("a");
         assertThat(localASideEffects.isEmpty(), is(false));
 
-        final List localBSideEffects = se.get("b");
+        final BulkSet localBSideEffects = se.get("b");
         assertThat(localBSideEffects.isEmpty(), is(false));
     }
 
@@ -877,7 +878,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
         final GraphTraversal traversal = g.V().aggregate("a").aggregate("b");
         traversal.iterate();
         final DriverRemoteTraversalSideEffects se = (DriverRemoteTraversalSideEffects) traversal.asAdmin().getSideEffects();
-        final List sideEffects = se.get("a");
+        final BulkSet sideEffects = se.get("a");
         assertThat(sideEffects.isEmpty(), is(false));
         se.close();
 
@@ -887,7 +888,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
         // Earlier keys should be cached locally
         final Set<String> localSideEffectKeys = se.keys();
         assertEquals(1, localSideEffectKeys.size());
-        final List localSideEffects = se.get("a");
+        final BulkSet localSideEffects = se.get("a");
         assertThat(localSideEffects.isEmpty(), is(false));
 
         // Try to get side effect from server
@@ -896,13 +897,16 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
         Field field = DriverRemoteTraversalSideEffects.class.getDeclaredField("serverSideEffect");
         field.setAccessible(true);
         UUID serverSideEffectId = (UUID) field.get(se);
+        final Map<String, String> aliases = new HashMap<>();
+        aliases.put("g", "g");
         final RequestMessage msg = RequestMessage.build(Tokens.OPS_GATHER)
                 .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffectId)
                 .addArg(Tokens.ARGS_SIDE_EFFECT_KEY, "b")
+                .addArg(Tokens.ARGS_ALIASES, aliases)
                 .processor("traversal").create();
         boolean error;
         try {
-            client.submitAsync(msg).get();
+            client.submitAsync(msg).get().one();
             error = false;
         } catch (Exception ex) {
             error = true;


[13/37] tinkerpop git commit: FilterRankStrategy is getting nasty solid at optimizing filters and itself, as a strategy, is now super efficient -- gutting code here and there as I realize that this is just a that.

Posted by da...@apache.org.
FilterRankStrategy is getting nasty solid at optimizing filters and itself, as a strategy, is now super efficient -- gutting code here and there as I realize that this is just a that.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/b8a92a30
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/b8a92a30
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/b8a92a30

Branch: refs/heads/TINKERPOP-1458
Commit: b8a92a30df8ce67a437c8484d950437d3a34cbca
Parents: 56de652
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Fri Sep 30 13:42:33 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 08:24:17 2016 -0600

----------------------------------------------------------------------
 .../optimization/FilterRankingStrategy.java     | 43 ++++++++------------
 .../process/traversal/util/TraversalHelper.java | 10 -----
 .../optimization/FilterRankingStrategyTest.java | 11 ++++-
 .../PathRetractionStrategyTest.java             |  3 +-
 4 files changed, 26 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b8a92a30/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
index 2065ea1..2f8061b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
@@ -42,7 +42,6 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversal
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 
 import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -91,29 +90,24 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave
         boolean modified = true;
         while (modified) {
             modified = false;
-            final Set<String> currentLabels = new HashSet<>();
-            for (final Step<?, ?> step : traversal.getSteps()) {
-                if (!step.getLabels().isEmpty()) {
-                    currentLabels.addAll(step.getLabels());
-                    final Step<?, ?> nextStep = step.getNextStep();
-                    if (validFilterStep(nextStep) && !usesLabels(nextStep, currentLabels)) {
-                        TraversalHelper.copyLabels(step, nextStep, true);
-                        modified = true;
-                    }
-                }
-            }
             final List<Step> steps = traversal.getSteps();
-            int prevRank = 0;
-            for (int i = steps.size() - 1; i >= 0; i--) {
-                final Step curr = steps.get(i);
-                final int rank = usesLabels(curr, TraversalHelper.getLabelsUpTo(curr)) ? 0 : getStepRank(curr);
-                if (prevRank > 0 && rank > prevRank) {
-                    final Step next = curr.getNextStep();
-                    traversal.removeStep(next);
-                    traversal.addStep(i, next);
-                    modified = true;
+            for (int i = 0; i < steps.size() - 1; i++) {
+                final Step<?, ?> step = steps.get(i);
+                final Step<?, ?> nextStep = step.getNextStep();
+                if (!usesLabels(nextStep, step.getLabels())) {
+                    final int nextRank = getStepRank(nextStep);
+                    if (nextRank != 0) {
+                        if (!step.getLabels().isEmpty()) {
+                            TraversalHelper.copyLabels(step, nextStep, true);
+                            modified = true;
+                        }
+                        if (getStepRank(step) > nextRank) {
+                            traversal.removeStep(nextStep);
+                            traversal.addStep(i, nextStep);
+                            modified = true;
+                        }
+                    }
                 }
-                prevRank = rank;
             }
         }
     }
@@ -152,11 +146,6 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave
             return 0;
     }
 
-
-    private static boolean validFilterStep(final Step<?, ?> step) {
-        return ((step instanceof FilterStep && !(step instanceof LambdaHolder)) || step instanceof OrderGlobalStep);
-    }
-
     private static boolean usesLabels(final Step<?, ?> step, final Set<String> labels) {
         if (step instanceof LambdaHolder)
             return true;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b8a92a30/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
index 1fb9fab..87d3479 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
@@ -592,16 +592,6 @@ public final class TraversalHelper {
         }
     }
 
-    public static Set<String> getLabelsUpTo(final Step<?, ?> stopStep) {
-        final Set<String> labels = new HashSet<>();
-        Step<?, ?> step = stopStep.getPreviousStep();
-        while (!(step instanceof EmptyStep)) {
-            labels.addAll(step.getLabels());
-            step = step.getPreviousStep();
-        }
-        return labels;
-    }
-
     public static boolean hasAllStepsOfClass(final Traversal.Admin<?, ?> traversal, final Class<?>... classesToCheck) {
         for (final Step step : traversal.getSteps()) {
             boolean foundInstance = false;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b8a92a30/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
index 99e0cab..ff72f8c 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
@@ -21,7 +21,6 @@ package org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -34,6 +33,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.function.Predicate;
 
+import static org.apache.tinkerpop.gremlin.process.traversal.P.eq;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.filter;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
@@ -86,11 +86,18 @@ public class FilterRankingStrategyTest {
                 {__.has("name", "marko").as("a").out().has("age", 32).as("b").where("a", neq("b")), __.has("name", "marko").as("a").out().has("age", 32).as("b").where("a", neq("b")), Collections.emptyList()},
                 {__.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a"), __.has("name", "marko").has("age", 32).has("name", "bob").dedup().as("a"), Collections.emptyList()},
                 {__.has("name", "marko").dedup().as("a").has("age", 32).has("name", "bob").as("b"), __.has("name", "marko").has("age", 32).has("name", "bob").dedup().as("b", "a"), Collections.emptyList()},
+                {__.where("b", eq("c")).as("a").dedup("a").has("name", "marko"), __.has("name", "marko").where("b", eq("c")).as("a").dedup("a"), Collections.emptyList()},
+                {__.where("b", eq("c")).has("name", "bob").as("a").dedup("a").has("name", "marko"), __.has("name", "bob").has("name", "marko").where("b", eq("c")).as("a").dedup("a"), Collections.emptyList()},
+                {__.has("name","marko").as("a").out().has("name","bob").dedup().as("b").where(__.as("a").out().as("b")),__.has("name","marko").as("a").out().has("name","bob").dedup().as("b").where(__.as("a").out().as("b")),Collections.emptyList()},
+                {__.has("name","marko").as("a").out().has("name","bob").as("b").dedup().where(__.as("a").out().as("b")),__.has("name","marko").as("a").out().has("name","bob").dedup().as("b").where(__.as("a").out().as("b")),Collections.emptyList()},
+                {__.has("name","marko").as("a").out().has("name","bob").dedup().as("c").where(__.as("a").out().as("b")),__.has("name","marko").as("a").out().has("name","bob").where(__.as("a").out().as("b")).dedup().as("c"),Collections.emptyList()},
                 {__.order().dedup(), __.dedup().order(), Collections.emptyList()},
                 {__.order().filter(testP).dedup(), __.order().filter(testP).dedup(), Collections.emptyList()},
                 {__.order().as("a").dedup(), __.dedup().order().as("a"), Collections.emptyList()},
                 {__.order().as("a").dedup("a"), __.order().as("a").dedup("a"), Collections.emptyList()},
-                // {__.order().as("a").dedup("a").has("name","marko"), __.has("name","marko").order().as("a").dedup("a"), Collections.emptyList()},
+                {__.order().as("a").dedup("a").has("name", "marko"), __.has("name", "marko").as("a").dedup("a").order(), Collections.emptyList()},
+                {__.order().as("a").dedup("a").has("name", "marko").out(), __.has("name", "marko").as("a").dedup("a").order().out(), Collections.emptyList()},
+                {__.order().as("a").dedup("a").has("name", "marko").where("a", eq("b")).out(), __.has("name", "marko").as("a").where("a", eq("b")).dedup("a").order().out(), Collections.emptyList()},
                 {__.identity().order().dedup(), __.dedup().order(), Collections.singletonList(IdentityRemovalStrategy.instance())},
                 {__.order().identity().dedup(), __.dedup().order(), Collections.singletonList(IdentityRemovalStrategy.instance())},
                 {__.order().out().dedup(), __.order().out().dedup(), Collections.emptyList()},

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/b8a92a30/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
index 0063289..e95c729 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathRetractionStrategyTest.java
@@ -60,8 +60,7 @@ public class PathRetractionStrategyTest {
             new DefaultTraversalStrategies().addStrategies(PathRetractionStrategy.instance()),
             new DefaultTraversalStrategies().addStrategies(PathRetractionStrategy.instance(), PathProcessorStrategy.instance()),
             new DefaultTraversalStrategies().addStrategies(PathRetractionStrategy.instance(), PathProcessorStrategy.instance(), MatchPredicateStrategy.instance()),
-            new DefaultTraversalStrategies().addStrategies(PathRetractionStrategy.instance(), PathProcessorStrategy.instance(), MatchPredicateStrategy.instance(), RepeatUnrollStrategy.instance()),
-            TraversalStrategies.GlobalCache.getStrategies(Graph.class));
+            new DefaultTraversalStrategies().addStrategies(PathRetractionStrategy.instance(), PathProcessorStrategy.instance(), MatchPredicateStrategy.instance(), RepeatUnrollStrategy.instance()));
 
     @Parameterized.Parameter(value = 0)
     public Traversal.Admin traversal;


[18/37] tinkerpop git commit: merged NotStep fix and tests from tp31. CTR.

Posted by da...@apache.org.
merged NotStep fix and tests from tp31. CTR.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/8ab682fe
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/8ab682fe
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/8ab682fe

Branch: refs/heads/TINKERPOP-1458
Commit: 8ab682fef3e3da12904cb0d825abf4cc1ba8235a
Parents: bc00bb3 c7f42d8
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Oct 3 10:55:41 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 10:55:41 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                                 |  1 +
 .../process/traversal/step/filter/NotStep.java     |  7 +++++++
 .../traversal/step/map/GroovyMatchTest.groovy      | 10 ++++++++++
 .../process/traversal/step/map/MatchTest.java      | 17 +++++++++++++++++
 4 files changed, 35 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8ab682fe/CHANGELOG.asciidoc
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8ab682fe/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NotStep.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8ab682fe/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
----------------------------------------------------------------------
diff --cc gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
index b35b763,b3d8ea9..f953e91
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
@@@ -336,27 -336,17 +336,37 @@@ public abstract class GroovyMatchTest 
               g.V.match(
                      __.as('a').both.as('b'),
                      __.as('b').both.as('c')).dedup('a','b').by(label)
 -            """, g)
 +            """)
 +        }
 +
 +        @Override
 +        public Traversal<Vertex, Long> get_g_V_hasLabelXsongsX_matchXa_name_b__a_performances_cX_selectXb_cX_count() {
 +            new ScriptTraversal<>(g, "gremlin-groovy", """
 +             g.V.hasLabel('song').match(
 +                    __.as('a').values('name').as('b'),
 +                    __.as('a').values('performances').as('c')
 +            ).select('b', 'c').count();
 +            """)
 +        }
 +
 +        @Override
 +        public Traversal<Vertex, Long> get_g_V_matchXa_knows_count_bX_selectXbX() {
 +            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.match(__.as('a').out('knows').count.as('b')).select('b')")
 +        }
 +
 +        @Override
 +        public Traversal<Vertex, String> get_g_V_matchXa_knows_b__b_created_c__a_created_cX_dedupXa_b_cX_selectXaX_byXnameX() {
 +            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.match(__.as('a').out('knows').as('b'), __.as('b').out('created').as('c'), __.as('a').out('created').as('c')).dedup('a', 'b', 'c').select('a').by('name')")
          }
+ 
+         @Override
+         public Traversal<Vertex, String> get_g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name() {
 -            TraversalScriptHelper.compute("""
++            new ScriptTraversal<>(g, "gremlin-groovy", """
+                 g.V.not(match(
+                             __.as('a').age.as('b'),
+                             __.as('a').name.as('c')).
+                         where('b', eq('c')).select('a')).name
+             """, g)
+         }
      }
  }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8ab682fe/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
----------------------------------------------------------------------
diff --cc gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
index 508968a,46b8e59..ce60734
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
@@@ -146,16 -143,11 +147,20 @@@ public abstract class MatchTest extend
      // distinct values with by()-modulation
      public abstract Traversal<Vertex, Map<String, Vertex>> get_g_V_matchXa_both_b__b_both_cX_dedupXa_bX_byXlabelX();
  
 +    public abstract Traversal<Vertex, Long> get_g_V_hasLabelXsongsX_matchXa_name_b__a_performances_cX_selectXb_cX_count();
 +
 +    // reducing barrier on lazy standard shouldn't yield an empty barrier
 +    public abstract Traversal<Vertex, Long> get_g_V_matchXa_knows_count_bX_selectXbX();
 +
 +    // verifying keep labels and dedup labels interactions
 +    public abstract Traversal<Vertex, String> get_g_V_matchXa_knows_b__b_created_c__a_created_cX_dedupXa_b_cX_selectXaX_byXnameX();
 +
+     // test not(match)
+     public abstract Traversal<Vertex, String> get_g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name();
+ 
      @Test
      @LoadGraphWith(MODERN)
++
      public void g_V_valueMap_matchXa_selectXnameX_bX() {
          final Traversal<Vertex, Map<String, Object>> traversal = get_g_V_valueMap_matchXa_selectXnameX_bX();
          printTraversalForm(traversal);
@@@ -519,33 -496,13 +524,40 @@@
      }
  
      @Test
 +    @LoadGraphWith(GRATEFUL)
 +    public void g_V_hasLabelXsongsX_matchXa_name_b__a_performances_cX_selectXb_cX_count() {
 +        final Traversal<Vertex, Long> traversal = get_g_V_hasLabelXsongsX_matchXa_name_b__a_performances_cX_selectXb_cX_count();
 +        printTraversalForm(traversal);
 +        assertEquals(584, traversal.next().longValue());
 +        assertFalse(traversal.hasNext());
 +    }
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void g_V_matchXa_knows_count_bX_selectXbX() {
 +        final Traversal<Vertex, Long> traversal = get_g_V_matchXa_knows_count_bX_selectXbX();
 +        printTraversalForm(traversal);
 +        checkResults(Arrays.asList(0L, 0L, 0L, 0L, 0L, 2L), traversal);
 +        assertFalse(traversal.hasNext());
 +    }
 +
 +    @Test
 +    @LoadGraphWith(MODERN)
 +    public void g_V_matchXa_knows_b__b_created_c__a_created_cX_dedupXa_b_cX_selectXaX_byXnameX() {
 +        final Traversal<Vertex, String> traversal = get_g_V_matchXa_knows_b__b_created_c__a_created_cX_dedupXa_b_cX_selectXaX_byXnameX();
 +        printTraversalForm(traversal);
 +        assertEquals("marko", traversal.next());
 +        assertFalse(traversal.hasNext());
 +    }
 +
 +
+     @LoadGraphWith(MODERN)
+     public void g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name() {
+         final Traversal<Vertex, String> traversal = get_g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name();
+         printTraversalForm(traversal);
+         checkResults(Arrays.asList("marko", "peter", "josh", "vadas", "lop", "ripple"), traversal);
+     }
+ 
      public static class GreedyMatchTraversals extends Traversals {
          @Before
          public void setupTest() {
@@@ -804,24 -761,8 +816,29 @@@
          }
  
          @Override
 +        public Traversal<Vertex, Long> get_g_V_hasLabelXsongsX_matchXa_name_b__a_performances_cX_selectXb_cX_count() {
 +            return g.V().hasLabel("song").match(
 +                    __.as("a").values("name").as("b"),
 +                    __.as("a").values("performances").as("c")
 +            ).select("b", "c").count();
 +        }
 +
 +        @Override
 +        public Traversal<Vertex, Long> get_g_V_matchXa_knows_count_bX_selectXbX() {
 +            return g.V().match(as("a").out("knows").count().as("b")).select("b");
 +        }
 +
 +        @Override
 +        public Traversal<Vertex, String> get_g_V_matchXa_knows_b__b_created_c__a_created_cX_dedupXa_b_cX_selectXaX_byXnameX() {
 +            return g.V().match(
 +                    as("a").out("knows").as("b"),
 +                    as("b").out("created").as("c"),
 +                    as("a").out("created").as("c")).dedup("a", "b", "c").<String>select("a").by("name");
 +        }
++
++        @Override
+         public Traversal<Vertex, String> get_g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name() {
+             return g.V().not(match(__.as("a").values("age").as("b"), __.as("a").values("name").as("c")).where("b", eq("c")).select("a")).values("name");
+         }
      }
  }


[23/37] tinkerpop git commit: Added more javadoc and made nextTraverser() explicit.

Posted by da...@apache.org.
Added more javadoc and made nextTraverser() explicit.

nextTraverser() on AbstractRemoteTraversal is now an abstract method which will make it more clear that it should be implemented. This method is instrumental to getting "remoting" to work as RemoteStep only calls that method and not next()/hasNext(). TINKERPOP-1486 CTR


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/d43d4e01
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/d43d4e01
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/d43d4e01

Branch: refs/heads/TINKERPOP-1458
Commit: d43d4e01a3299f9031a2b1ac38790e67f1fe01cb
Parents: d23b971
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Oct 5 15:15:08 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Oct 5 15:15:08 2016 -0400

----------------------------------------------------------------------
 .../remote/traversal/AbstractRemoteTraversal.java | 17 +++++++++++++++++
 .../process/remote/traversal/RemoteTraversal.java | 18 ++++++++++++++++++
 .../traversal/RemoteTraversalSideEffects.java     | 13 +++++++++++++
 .../remote/traversal/step/map/RemoteStep.java     |  2 --
 .../driver/remote/DriverRemoteTraversal.java      |  9 ++++++++-
 5 files changed, 56 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d43d4e01/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversal.java
index 28eeae8..0c6a7aa 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/AbstractRemoteTraversal.java
@@ -18,12 +18,16 @@
  */
 package org.apache.tinkerpop.gremlin.process.remote.traversal;
 
+import org.apache.tinkerpop.gremlin.process.remote.traversal.step.map.RemoteStep;
 import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.TraverserGenerator;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 
@@ -32,9 +36,22 @@ import java.util.Optional;
 import java.util.Set;
 
 /**
+ * This is a stub implementation for {@link RemoteTraversal} and requires that the {@link #nextTraverser()} method
+ * is implemented from {@link Traversal.Admin}. It is this method that gets called from {@link RemoteStep} when
+ * the {@link Traversal} is iterated.
+ *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public abstract class AbstractRemoteTraversal<S,E> implements RemoteTraversal<S,E> {
+
+    /**
+     * Note that internally {@link #nextTraverser()} is called from within a loop (specifically in
+     * {@link AbstractStep#next()} that breaks properly when a {@link java.util.NoSuchElementException} is thrown. In
+     * other words the "results" should be iterated to force that failure.
+     */
+    @Override
+    public abstract Traverser.Admin<E> nextTraverser();
+
     @Override
     public Bytecode getBytecode() {
         throw new UnsupportedOperationException("Remote traversals do not support this method");

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d43d4e01/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversal.java
index 1f2ac74..9c893c2 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversal.java
@@ -18,12 +18,30 @@
  */
 package org.apache.tinkerpop.gremlin.process.remote.traversal;
 
+import org.apache.tinkerpop.gremlin.process.remote.RemoteConnection;
+import org.apache.tinkerpop.gremlin.process.remote.traversal.step.map.RemoteStep;
+import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 
 /**
+ * A {@link RemoteTraversal} is returned from {@link RemoteConnection#submit(Bytecode)}. It is iterated from within
+ * {@link RemoteStep} using {@link #nextTraverser()}. Implementations should typically be given a "result" from a
+ * remote source where the traversal was executed. The "result" should be an iterator which preferably has its data
+ * bulked.
+ * <p/>
+ * Note that internally {@link #nextTraverser()} is called from within a loop (specifically in
+ * {@link AbstractStep#next()} that breaks properly when a {@link java.util.NoSuchElementException} is thrown. In other
+ * words the "results" should be iterated to force that failure.
+ *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public interface RemoteTraversal<S,E> extends Traversal.Admin<S,E> {
+
+    /**
+     * Returns remote side-effects generated by the traversal so that they can accessible to the client. Note that
+     * "side-effect" refers to the value in "a" in the traversal {@code g.V().aggregate('a').values('name')}.
+     */
     @Override
     public RemoteTraversalSideEffects getSideEffects();
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d43d4e01/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversalSideEffects.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversalSideEffects.java
index 97fb36d..ff16bf9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversalSideEffects.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/RemoteTraversalSideEffects.java
@@ -19,11 +19,24 @@
 package org.apache.tinkerpop.gremlin.process.remote.traversal;
 
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalSideEffects;
 
 /**
+ * When a traversal is executed remotely, the ability to retrieve those side-effects (i.e. the value in "a" in the
+ * traversal {@code g.V().aggregate('a').values('name')}) can be exposed through this interface. As an example,
+ * with TinkerPop's {@code DriverRemoteConnection} that connects to Gremlin Server as a "remote", the side-effects
+ * are left on the server. The {@code RemoteTraversalSideEffects} implementation, in that case, lazily loads those
+ * side-effects when requested. Implementations should attempt to match the features of the locally processed
+ * {@link DefaultTraversalSideEffects} to keep consistency.
+ *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public interface RemoteTraversalSideEffects extends TraversalSideEffects, AutoCloseable {
+
+    /**
+     * If the "remote" that actually executed the traversal maintained resources that can be released, when the user
+     * is done with the side-effects, then this method can be used to trigger that release.
+     */
     @Override
     public default void close() throws Exception {
         //  do nothing

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d43d4e01/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/step/map/RemoteStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/step/map/RemoteStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/step/map/RemoteStep.java
index 99ca81e..c21f8c8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/step/map/RemoteStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/remote/traversal/step/map/RemoteStep.java
@@ -63,7 +63,5 @@ public final class RemoteStep<S, E> extends AbstractStep<S, E> {
             }
         }
         return this.remoteTraversal.nextTraverser();
-        //final Traverser.Admin<E> remoteTraverser = this.remoteTraversal.nextTraverser();
-        //return this.getTraversal().getTraverserGenerator().generate(remoteTraverser.get(), (Step) this, remoteTraverser.bulk());
     }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d43d4e01/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversal.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversal.java
index 14d89cc..e6e1c9b 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversal.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversal.java
@@ -25,6 +25,8 @@ import org.apache.tinkerpop.gremlin.driver.ResultSet;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.AbstractRemoteTraversal;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.DefaultRemoteTraverser;
 import org.apache.tinkerpop.gremlin.process.remote.traversal.RemoteTraversalSideEffects;
+import org.apache.tinkerpop.gremlin.process.remote.traversal.step.map.RemoteStep;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
 import org.apache.tinkerpop.gremlin.structure.Element;
@@ -37,7 +39,10 @@ import java.util.Optional;
 import java.util.function.Supplier;
 
 /**
- * A {@link AbstractRemoteTraversal} implementation for the Gremlin Driver.
+ * A {@link AbstractRemoteTraversal} implementation for the Gremlin Driver. This {@link Traversal} implementation is
+ * typically iterated from with {@link RemoteStep} where it the {@link #nextTraverser()} method is called. While
+ * this class provides implementations for both {@link #next()} and {@link #hasNext()} that unroll "bulked" results,
+ * those methods are not called directly from with TinkerPop remoting.
  *
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
@@ -93,6 +98,8 @@ public class DriverRemoteTraversal<S, E> extends AbstractRemoteTraversal<S, E> {
 
     @Override
     public Traverser.Admin<E> nextTraverser() {
+        // the lastTraverser is initialized as "empty" at start of iteration so the initial pass through will
+        // call next() to begin the iteration
         if (0L == this.lastTraverser.bulk())
             return this.traversers.next();
         else {


[35/37] tinkerpop git commit: removed extra lines

Posted by da...@apache.org.
removed extra lines


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/a67cc286
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/a67cc286
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/a67cc286

Branch: refs/heads/TINKERPOP-1458
Commit: a67cc286c6ad865c9c054ad1f125c83588cd83e8
Parents: 20bcc83
Author: davebshow <da...@gmail.com>
Authored: Wed Oct 5 18:06:02 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../src/main/jython/tests/driver/test_driver_remote_connection.py | 1 -
 .../tinkerpop/gremlin/server/GremlinServerIntegrateTest.java      | 3 ---
 2 files changed, 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a67cc286/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
index d3163d3..d8d2ed4 100644
--- a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
@@ -106,7 +106,6 @@ class TestDriverRemoteConnection(TestCase):
         assert 3 == n["lop"]
         assert 1 == n["ripple"]
 
-
         t = g.withSideEffect('m',32).V().map(lambda: "x: x.sideEffects('m')")
         results = t.toSet()
         assert 1 == len(results)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a67cc286/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index 1c4d19e..f810ebc 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -914,6 +914,3 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
         assertThat(error, is(true));
     }
 }
-
-
-


[17/37] tinkerpop git commit: fixed a bug in NotStep where child requirements were not being analyzed. Added a test to MatchTest to verify proper functioning. CTR.

Posted by da...@apache.org.
fixed a bug in NotStep where child requirements were not being analyzed. Added a test to MatchTest to verify proper functioning. CTR.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/c7f42d82
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/c7f42d82
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/c7f42d82

Branch: refs/heads/TINKERPOP-1458
Commit: c7f42d827414ea7dced0549c02bbc37f40666849
Parents: 85ec40b
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Oct 3 10:46:04 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 10:46:04 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../process/traversal/step/filter/NotStep.java  |  7 +++
 .../traversal/step/map/GroovyMatchTest.groovy   | 10 ++++
 .../process/traversal/step/map/MatchTest.java   | 63 ++++++++++++++------
 4 files changed, 62 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c7f42d82/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index d0aa8e8..cf89a5c 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.1.5 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Fixed a bug in `NotStep` where child requirements were not being analyzed.
 * Fixed output redirection and potential memory leak in `GremlinGroovyScriptEngine`.
 * Corrected naming of `g_withPath_V_asXaX_out_out_mapXa_name_it_nameX` and `g_withPath_V_asXaX_out_mapXa_nameX` in `MapTest`.
 * Improved session cleanup when a close is triggered by the client.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c7f42d82/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NotStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NotStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NotStep.java
index 56ad497..e0f7038 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NotStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/NotStep.java
@@ -21,11 +21,13 @@ package org.apache.tinkerpop.gremlin.process.traversal.step.filter;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -65,4 +67,9 @@ public final class NotStep<S> extends FilterStep<S> implements TraversalParent {
     public int hashCode() {
         return super.hashCode() ^ this.notTraversal.hashCode();
     }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements();
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c7f42d82/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
index c2f9d43..b3d8ea9 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyMatchTest.groovy
@@ -338,5 +338,15 @@ public abstract class GroovyMatchTest {
                     __.as('b').both.as('c')).dedup('a','b').by(label)
             """, g)
         }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name() {
+            TraversalScriptHelper.compute("""
+                g.V.not(match(
+                            __.as('a').age.as('b'),
+                            __.as('a').name.as('c')).
+                        where('b', eq('c')).select('a')).name
+            """, g)
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/c7f42d82/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
index 5d2ed95..46b8e59 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MatchTest.java
@@ -43,8 +43,17 @@ import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.GRATEFUL;
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.eq;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
-import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;
-import static org.junit.Assert.*;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.and;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.match;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.not;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.or;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.repeat;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.where;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 /**
  * @author Joshua Shinavier (http://fortytwo.net)
@@ -134,6 +143,9 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
     // distinct values with by()-modulation
     public abstract Traversal<Vertex, Map<String, Vertex>> get_g_V_matchXa_both_b__b_both_cX_dedupXa_bX_byXlabelX();
 
+    // test not(match)
+    public abstract Traversal<Vertex, String> get_g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_valueMap_matchXa_selectXnameX_bX() {
@@ -144,7 +156,7 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
             counter++;
             final Map<String, Object> map = traversal.next();
             assertTrue(Map.class.isAssignableFrom(map.get("a").getClass()));
-            final String name = ((Map<String,List<String>>) map.get("a")).get("name").get(0);
+            final String name = ((Map<String, List<String>>) map.get("a")).get("name").get(0);
             assertEquals(name, ((List<String>) map.get("b")).get(0));
         }
         assertEquals(6, counter);
@@ -156,12 +168,12 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
         final Traversal<Vertex, Map<String, Vertex>> traversal = get_g_V_matchXa_out_bX();
         printTraversalForm(traversal);
         checkResults(makeMapList(2,
-                        "a", convertToVertex(graph, "marko"), "b", convertToVertex(graph, "lop"),
-                        "a", convertToVertex(graph, "marko"), "b", convertToVertex(graph, "josh"),
-                        "a", convertToVertex(graph, "marko"), "b", convertToVertex(graph, "vadas"),
-                        "a", convertToVertex(graph, "josh"), "b", convertToVertex(graph, "ripple"),
-                        "a", convertToVertex(graph, "josh"), "b", convertToVertex(graph, "lop"),
-                        "a", convertToVertex(graph, "peter"), "b", convertToVertex(graph, "lop")),
+                "a", convertToVertex(graph, "marko"), "b", convertToVertex(graph, "lop"),
+                "a", convertToVertex(graph, "marko"), "b", convertToVertex(graph, "josh"),
+                "a", convertToVertex(graph, "marko"), "b", convertToVertex(graph, "vadas"),
+                "a", convertToVertex(graph, "josh"), "b", convertToVertex(graph, "ripple"),
+                "a", convertToVertex(graph, "josh"), "b", convertToVertex(graph, "lop"),
+                "a", convertToVertex(graph, "peter"), "b", convertToVertex(graph, "lop")),
                 traversal);
     }
 
@@ -266,10 +278,10 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
         final Traversal<Vertex, Map<String, Vertex>> traversal = get_g_V_matchXa_created_b__b_0created_aX();
         printTraversalForm(traversal);
         checkResults(makeMapList(2,
-                        "a", convertToVertex(graph, "marko"), "b", convertToVertex(graph, "lop"),
-                        "a", convertToVertex(graph, "josh"), "b", convertToVertex(graph, "lop"),
-                        "a", convertToVertex(graph, "peter"), "b", convertToVertex(graph, "lop"),
-                        "a", convertToVertex(graph, "josh"), "b", convertToVertex(graph, "ripple")),
+                "a", convertToVertex(graph, "marko"), "b", convertToVertex(graph, "lop"),
+                "a", convertToVertex(graph, "josh"), "b", convertToVertex(graph, "lop"),
+                "a", convertToVertex(graph, "peter"), "b", convertToVertex(graph, "lop"),
+                "a", convertToVertex(graph, "josh"), "b", convertToVertex(graph, "ripple")),
                 traversal);
 
     }
@@ -368,12 +380,12 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
 
     private void assertCommon(Traversal<Vertex, Map<String, Vertex>> traversal) {
         checkResults(makeMapList(4,
-                    "a", convertToVertex(graph, "Garcia"), "b", convertToVertex(graph, "CREAM PUFF WAR"), "c", convertToVertex(graph, "CREAM PUFF WAR"), "d", convertToVertex(graph, "Garcia"),
-                    "a", convertToVertex(graph, "Garcia"), "b", convertToVertex(graph, "CREAM PUFF WAR"), "c", convertToVertex(graph, "CRYPTICAL ENVELOPMENT"), "d", convertToVertex(graph, "Garcia"),
-                    "a", convertToVertex(graph, "Garcia"), "b", convertToVertex(graph, "CRYPTICAL ENVELOPMENT"), "c", convertToVertex(graph, "CREAM PUFF WAR"), "d", convertToVertex(graph, "Garcia"),
-                    "a", convertToVertex(graph, "Garcia"), "b", convertToVertex(graph, "CRYPTICAL ENVELOPMENT"), "c", convertToVertex(graph, "CRYPTICAL ENVELOPMENT"), "d", convertToVertex(graph, "Garcia"),
-                    "a", convertToVertex(graph, "Grateful_Dead"), "b", convertToVertex(graph, "CANT COME DOWN"), "c", convertToVertex(graph, "DOWN SO LONG"), "d", convertToVertex(graph, "Garcia"),
-                    "a", convertToVertex(graph, "Grateful_Dead"), "b", convertToVertex(graph, "THE ONLY TIME IS NOW"), "c", convertToVertex(graph, "DOWN SO LONG"), "d", convertToVertex(graph, "Garcia")), traversal);
+                "a", convertToVertex(graph, "Garcia"), "b", convertToVertex(graph, "CREAM PUFF WAR"), "c", convertToVertex(graph, "CREAM PUFF WAR"), "d", convertToVertex(graph, "Garcia"),
+                "a", convertToVertex(graph, "Garcia"), "b", convertToVertex(graph, "CREAM PUFF WAR"), "c", convertToVertex(graph, "CRYPTICAL ENVELOPMENT"), "d", convertToVertex(graph, "Garcia"),
+                "a", convertToVertex(graph, "Garcia"), "b", convertToVertex(graph, "CRYPTICAL ENVELOPMENT"), "c", convertToVertex(graph, "CREAM PUFF WAR"), "d", convertToVertex(graph, "Garcia"),
+                "a", convertToVertex(graph, "Garcia"), "b", convertToVertex(graph, "CRYPTICAL ENVELOPMENT"), "c", convertToVertex(graph, "CRYPTICAL ENVELOPMENT"), "d", convertToVertex(graph, "Garcia"),
+                "a", convertToVertex(graph, "Grateful_Dead"), "b", convertToVertex(graph, "CANT COME DOWN"), "c", convertToVertex(graph, "DOWN SO LONG"), "d", convertToVertex(graph, "Garcia"),
+                "a", convertToVertex(graph, "Grateful_Dead"), "b", convertToVertex(graph, "THE ONLY TIME IS NOW"), "c", convertToVertex(graph, "DOWN SO LONG"), "d", convertToVertex(graph, "Garcia")), traversal);
     }
 
     @Test
@@ -483,6 +495,14 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
         assertEquals(results.size(), counter);
     }
 
+    @Test
+    @LoadGraphWith(MODERN)
+    public void g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name() {
+        final Traversal<Vertex, String> traversal = get_g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name();
+        printTraversalForm(traversal);
+        checkResults(Arrays.asList("marko", "peter", "josh", "vadas", "lop", "ripple"), traversal);
+    }
+
     public static class GreedyMatchTraversals extends Traversals {
         @Before
         public void setupTest() {
@@ -739,5 +759,10 @@ public abstract class MatchTest extends AbstractGremlinProcessTest {
                     as("a").both().as("b"),
                     as("b").both().as("c")).dedup("a", "b").by(T.label);
         }
+
+        @Override
+        public Traversal<Vertex, String> get_g_V_notXmatchXa_age_b__a_name_cX_whereXb_eqXcXX_selectXaXX_name() {
+            return g.V().not(match(__.as("a").values("age").as("b"), __.as("a").values("name").as("c")).where("b", eq("c")).select("a")).values("name");
+        }
     }
 }


[15/37] tinkerpop git commit: added more FilterRankStrategy tests.

Posted by da...@apache.org.
added more FilterRankStrategy tests.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/68bbae10
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/68bbae10
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/68bbae10

Branch: refs/heads/TINKERPOP-1458
Commit: 68bbae10521350085b60f4dbf8819f06494ff6be
Parents: ff1c384
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Sep 29 15:56:06 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 08:24:17 2016 -0600

----------------------------------------------------------------------
 .../traversal/strategy/optimization/FilterRankingStrategy.java | 2 +-
 .../strategy/optimization/FilterRankingStrategyTest.java       | 6 ++++--
 2 files changed, 5 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68bbae10/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
index dead668..06726b1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategy.java
@@ -92,7 +92,7 @@ public final class FilterRankingStrategy extends AbstractTraversalStrategy<Trave
         while(modified) {
             modified = false;
             for (final Step<?, ?> step : traversal.getSteps()) {
-                if (!step.getLabels().isEmpty()) {
+                if (step instanceof FilterStep && !step.getLabels().isEmpty()) {
                     final Step<?, ?> nextStep = step.getNextStep();
                     if (nextStep instanceof FilterStep && !(nextStep instanceof TraversalParent)) {
                         TraversalHelper.copyLabels(step, nextStep, true);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/68bbae10/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
index 52379fd..bd12e34 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/FilterRankingStrategyTest.java
@@ -32,7 +32,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 
-import static org.apache.tinkerpop.gremlin.process.traversal.P.eq;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.filter;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
@@ -80,8 +80,10 @@ public class FilterRankingStrategyTest {
 
         return Arrays.asList(new Object[][]{
                 {__.dedup().order(), __.dedup().order(), Collections.emptyList()},
+                {__.has("name", "marko").as("a").out().as("b").has("age", 32).where("a", neq("b")), __.has("name", "marko").as("a").out().as("b").has("age", 32).where("a", neq("b")), Collections.emptyList()},
+                {__.has("name", "marko").as("a").out().has("age", 32).as("b").where("a", neq("b")), __.has("name", "marko").as("a").out().has("age", 32).as("b").where("a", neq("b")), Collections.emptyList()},
                 {__.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a"), __.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a"), Collections.emptyList()},
-                {__.has("name", "marko").dedup().as("a").has("age", 32).has("name", "bob").as("b"), __.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a","b"), Collections.emptyList()},
+                {__.has("name", "marko").dedup().as("a").has("age", 32).has("name", "bob").as("b"), __.has("name", "marko").has("age", 32).dedup().has("name", "bob").as("a", "b"), Collections.emptyList()},
                 {__.order().dedup(), __.dedup().order(), Collections.emptyList()},
                 {__.order().as("a").dedup(), __.order().as("a").dedup(), Collections.emptyList()},
                 {__.identity().order().dedup(), __.dedup().order(), Collections.singletonList(IdentityRemovalStrategy.instance())},


[07/37] tinkerpop git commit: Merge remote-tracking branch 'origin/TINKERPOP-1467' into TINKERPOP-1467-master

Posted by da...@apache.org.
Merge remote-tracking branch 'origin/TINKERPOP-1467' into TINKERPOP-1467-master

Conflicts:
	gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
	gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
	gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
	gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/9d860ca0
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/9d860ca0
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/9d860ca0

Branch: refs/heads/TINKERPOP-1458
Commit: 9d860ca0c880bf7d8c974df4d021266d1868dcf0
Parents: 233a6ba 6d14adb
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Sat Oct 1 05:48:21 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Sat Oct 1 05:48:21 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../upgrade/release-3.1.x-incubating.asciidoc   | 17 +++++
 .../tinkerpop/gremlin/driver/Channelizer.java   |  2 +-
 .../apache/tinkerpop/gremlin/driver/Client.java | 42 +++++++++--
 .../tinkerpop/gremlin/driver/Cluster.java       | 24 +++++-
 .../tinkerpop/gremlin/driver/Connection.java    | 67 +++++++++++++++--
 .../gremlin/driver/ConnectionPool.java          | 21 +++---
 .../tinkerpop/gremlin/driver/Handler.java       | 26 +++++--
 .../tinkerpop/gremlin/driver/ResultQueue.java   |  4 +
 .../driver/handler/WebSocketClientHandler.java  |  4 +-
 .../server/GremlinDriverIntegrateTest.java      | 79 +++++++++++++++++++-
 .../server/GremlinServerAuthIntegrateTest.java  |  5 +-
 .../GremlinServerAuthOldIntegrateTest.java      |  4 +-
 .../GremlinServerSessionIntegrateTest.java      |  6 +-
 14 files changed, 255 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/CHANGELOG.asciidoc
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
----------------------------------------------------------------------
diff --cc gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
index 7b9262e,3a03141..bd397a1
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Client.java
@@@ -350,11 -295,17 +355,17 @@@ public abstract class Client 
      public final static class ClusteredClient extends Client {
  
          private ConcurrentMap<Host, ConnectionPool> hostConnectionPools = new ConcurrentHashMap<>();
+         private final AtomicReference<CompletableFuture<Void>> closing = new AtomicReference<>(null);
  
 -        ClusteredClient(final Cluster cluster) {
 -            super(cluster);
 +        ClusteredClient(final Cluster cluster, final Client.Settings settings) {
 +            super(cluster, settings);
          }
  
+         @Override
+         public boolean isClosing() {
+             return closing.get() != null;
+         }
+ 
          /**
           * Submits a Gremlin script to the server and returns a {@link ResultSet} once the write of the request is
           * complete.
@@@ -650,10 -503,12 +670,12 @@@
  
          private ConnectionPool connectionPool;
  
+         private final AtomicReference<CompletableFuture<Void>> closing = new AtomicReference<>(null);
+ 
 -        SessionedClient(final Cluster cluster, final String sessionId, final boolean manageTransactions) {
 -            super(cluster);
 -            this.sessionId = sessionId;
 -            this.manageTransactions = manageTransactions;
 +        SessionedClient(final Cluster cluster, final Client.Settings settings) {
 +            super(cluster, settings);
 +            this.sessionId = settings.getSession().get().sessionId;
 +            this.manageTransactions = settings.getSession().get().manageTransactions;
          }
  
          String getSessionId() {
@@@ -697,134 -557,13 +724,139 @@@
           * Close the bound {@link ConnectionPool}.
           */
          @Override
-         public CompletableFuture<Void> closeAsync() {
-             return connectionPool.closeAsync();
+         public synchronized CompletableFuture<Void> closeAsync() {
+             if (closing.get() != null)
+                 return closing.get();
+ 
+             final CompletableFuture<Void> connectionPoolClose = connectionPool.closeAsync();
+             closing.set(connectionPoolClose);
+             return connectionPoolClose;
          }
      }
 +
 +    /**
 +     * Settings given to {@link Cluster#connect(Settings)} that configures how a {@link Client} will behave.
 +     */
 +    public static class Settings {
 +        private final Optional<SessionSettings> session;
 +
 +        private Settings(final Builder builder) {
 +            this.session = builder.session;
 +        }
 +
 +        public static Builder build() {
 +            return new Builder();
 +        }
 +
 +        /**
 +         * Determines if the {@link Client} is to be constructed with a session. If the value is present, then a
 +         * session is expected.
 +         */
 +        public Optional<SessionSettings> getSession() {
 +            return session;
 +        }
 +
 +        public static class Builder {
 +            private Optional<SessionSettings> session = Optional.empty();
 +
 +            private Builder() {}
 +
 +            /**
 +             * Enables a session. By default this will create a random session name and configure transactions to be
 +             * unmanaged. This method will override settings provided by calls to the other overloads of
 +             * {@code useSession}.
 +             */
 +            public Builder useSession(final boolean enabled) {
 +                session = enabled ? Optional.of(SessionSettings.build().create()) : Optional.empty();
 +                return this;
 +            }
 +
 +            /**
 +             * Enables a session. By default this will create a session with the provided name and configure
 +             * transactions to be unmanaged. This method will override settings provided by calls to the other
 +             * overloads of {@code useSession}.
 +             */
 +            public Builder useSession(final String sessionId) {
 +                session = sessionId != null && !sessionId.isEmpty() ?
 +                        Optional.of(SessionSettings.build().sessionId(sessionId).create()) : Optional.empty();
 +                return this;
 +            }
 +
 +            /**
 +             * Enables a session. This method will override settings provided by calls to the other overloads of
 +             * {@code useSession}.
 +             */
 +            public Builder useSession(final SessionSettings settings) {
 +                session = Optional.ofNullable(settings);
 +                return this;
 +            }
 +
 +            public Settings create() {
 +                return new Settings(this);
 +            }
 +
 +        }
 +    }
 +
 +    /**
 +     * Settings for a {@link Client} that involve a session.
 +     */
 +    public static class SessionSettings {
 +        private final boolean manageTransactions;
 +        private final String sessionId;
 +
 +        private SessionSettings(final Builder builder) {
 +            manageTransactions = builder.manageTransactions;
 +            sessionId = builder.sessionId;
 +        }
 +
 +        /**
 +         * If enabled, transactions will be "managed" such that each request will represent a complete transaction.
 +         */
 +        public boolean manageTransactions() {
 +            return manageTransactions;
 +        }
 +
 +        /**
 +         * Provides the identifier of the session.
 +         */
 +        public String getSessionId() {
 +            return sessionId;
 +        }
 +
 +        public static SessionSettings.Builder build() {
 +            return new SessionSettings.Builder();
 +        }
 +
 +        public static class Builder {
 +            private boolean manageTransactions = false;
 +            private String sessionId = UUID.randomUUID().toString();
 +
 +            private Builder() {}
 +
 +            /**
 +             * If enabled, transactions will be "managed" such that each request will represent a complete transaction.
 +             * By default this value is {@code false}.
 +             */
 +            public Builder manageTransactions(final boolean manage) {
 +                manageTransactions = manage;
 +                return this;
 +            }
 +
 +            /**
 +             * Provides the identifier of the session. This value cannot be null or empty. By default it is set to
 +             * a random {@code UUID}.
 +             */
 +            public Builder sessionId(final String sessionId) {
 +                if (null == sessionId || sessionId.isEmpty())
 +                    throw new IllegalArgumentException("sessionId cannot be null or empty");
 +                this.sessionId = sessionId;
 +                return this;
 +            }
 +
 +            public SessionSettings create() {
 +                return new SessionSettings(this);
 +            }
 +        }
 +    }
  }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
----------------------------------------------------------------------
diff --cc gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
index b9a3cee,473991a..567bfb4
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
@@@ -84,7 -84,9 +85,9 @@@ public final class Cluster 
       * submitted or can be directly initialized via {@link Client#init()}.
       */
      public <T extends Client> T connect() {
-         return (T) new Client.ClusteredClient(this, Client.Settings.build().create());
 -        final Client client = new Client.ClusteredClient(this);
++        final Client client = new Client.ClusteredClient(this, Client.Settings.build().create());
+         manager.trackClient(client);
+         return (T) client;
      }
  
      /**
@@@ -121,19 -123,11 +124,21 @@@
       * @param manageTransactions enables auto-transactions when set to true
       */
      public <T extends Client> T connect(final String sessionId, final boolean manageTransactions) {
 -        if (null == sessionId || sessionId.isEmpty())
 -            throw new IllegalArgumentException("sessionId cannot be null or empty");
 -        final Client client = new Client.SessionedClient(this, sessionId, manageTransactions);
 +        final Client.SessionSettings sessionSettings = Client.SessionSettings.build()
 +                .manageTransactions(manageTransactions)
 +                .sessionId(sessionId).create();
 +        final Client.Settings settings = Client.Settings.build().useSession(sessionSettings).create();
 +        return connect(settings);
 +    }
 +
 +    /**
 +     * Creates a new {@link Client} based on the settings provided.
 +     */
 +    public <T extends Client> T connect(final Client.Settings settings) {
-         return settings.getSession().isPresent() ? (T) new Client.SessionedClient(this, settings) :
-                 (T) new Client.ClusteredClient(this, settings);
++        final Client client = settings.getSession().isPresent() ? new Client.SessionedClient(this, settings) :
++                new Client.ClusteredClient(this, settings);
+         manager.trackClient(client);
+         return (T) client;
      }
  
      @Override
@@@ -863,15 -687,11 +868,17 @@@
  
          private final ScheduledExecutorService executor;
  
 +        private final int nioPoolSize;
 +        private final int workerPoolSize;
 +        private final int port;
 +
          private final AtomicReference<CompletableFuture<Void>> closeFuture = new AtomicReference<>();
  
+         private final List<WeakReference<Client>> openedClients = new ArrayList<>();
+ 
          private Manager(final Builder builder) {
 +            validateBuilder(builder);
 +
              this.loadBalancingStrategy = builder.loadBalancingStrategy;
              this.authProps = builder.authProps;
              this.contactPoints = builder.getContactPoints();

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
----------------------------------------------------------------------
diff --cc gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
index 02ec0b3,660ad0d..2a68032
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Connection.java
@@@ -158,15 -150,12 +159,16 @@@ final class Connection 
          return pending;
      }
  
-     public CompletableFuture<Void> closeAsync() {
+     public synchronized CompletableFuture<Void> closeAsync() {
+         if (isClosing()) return closeFuture.get();
+ 
          final CompletableFuture<Void> future = new CompletableFuture<>();
-         if (!closeFuture.compareAndSet(null, future))
-             return closeFuture.get();
+         closeFuture.set(future);
  
 +        // stop any pings being sent at the server for keep-alive
 +        final ScheduledFuture keepAlive = keepAliveFuture.get();
 +        if (keepAlive != null) keepAlive.cancel(true);
 +
          // make sure all requests in the queue are fully processed before killing.  if they are then shutdown
          // can be immediate.  if not this method will signal the readCompleted future defined in the write()
          // operation to check if it can close.  in this way the connection no longer receives writes, but

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ConnectionPool.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Handler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/ResultQueue.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9d860ca0/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
----------------------------------------------------------------------
diff --cc gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
index 96cde54,bf66b0d..d8aff4a
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinDriverIntegrateTest.java
@@@ -26,9 -25,7 +26,8 @@@ import org.apache.tinkerpop.gremlin.dri
  import org.apache.tinkerpop.gremlin.driver.Cluster;
  import org.apache.tinkerpop.gremlin.driver.Result;
  import org.apache.tinkerpop.gremlin.driver.ResultSet;
- import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
  import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
 +import org.apache.tinkerpop.gremlin.driver.handler.WebSocketClientHandler;
  import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
  import org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer;
  import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0;


[04/37] tinkerpop git commit: Added note to release docs about updating links on download page. CTR

Posted by da...@apache.org.
Added note to release docs about updating links on download page. CTR


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/85ec40be
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/85ec40be
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/85ec40be

Branch: refs/heads/TINKERPOP-1458
Commit: 85ec40beb48fbec720d4bcaeac377eb411a2baba
Parents: 0070d3d
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Sep 30 13:05:06 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Sep 30 13:05:06 2016 -0400

----------------------------------------------------------------------
 docs/src/dev/developer/release.asciidoc | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/85ec40be/docs/src/dev/developer/release.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/dev/developer/release.asciidoc b/docs/src/dev/developer/release.asciidoc
index f9baa94..086a2d4 100644
--- a/docs/src/dev/developer/release.asciidoc
+++ b/docs/src/dev/developer/release.asciidoc
@@ -152,6 +152,8 @@ Release & Promote
 . Copy release files from `dev/xx.yy.zz` to `release/xx.yy.zz`.
 . `cd release; svn add xx.yy.zz/; svn ci -m "TinkerPop xx.yy.zz release"`
 . Update homepage with references to latest distribution and to other internal links elsewhere on the page.
+.. On the link:http://tinkerpop.apache.org/downloads.html[Downloads] page, when moving "Current Releases" to "Archived
+Releases" recall that the hyperlink must change to point to version in the link:https://archive.apache.org/dist/tinkerpop/[Apache Archives].
 . Wait for Apache Sonatype to sync the artifacts to Maven Central at (link:http://repo1.maven.org/maven2/org/apache/tinkerpop/tinkerpop/[http://repo1.maven.org/maven2/org/apache/tinkerpop/tinkerpop/]).
 . Wait for zip distributions to to sync to the Apache mirrors (i.e ensure the download links work from a mirror).
 . If there are releases present in SVN that represents lines of code that are no longer under development, then remove those releases. In other words, if `3.2.0` is present and `3.2.1` is released then remove `3.2.0`.  However, if `3.1.3` is present and that line of code is still under potential development, it may stay.


[05/37] tinkerpop git commit: Merge branch 'tp31'

Posted by da...@apache.org.
Merge branch 'tp31'


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/ee813e90
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/ee813e90
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/ee813e90

Branch: refs/heads/TINKERPOP-1458
Commit: ee813e90230145297aa6b5c30cbbb4a4fe7857cd
Parents: f2b027b 85ec40b
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Sep 30 13:05:48 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Sep 30 13:05:48 2016 -0400

----------------------------------------------------------------------
 docs/src/dev/developer/release.asciidoc | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ee813e90/docs/src/dev/developer/release.asciidoc
----------------------------------------------------------------------


[37/37] tinkerpop git commit: Add some tests for DriverRemoteTraversalSideEffects.

Posted by da...@apache.org.
Add some tests for DriverRemoteTraversalSideEffects.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/77a32090
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/77a32090
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/77a32090

Branch: refs/heads/TINKERPOP-1458
Commit: 77a3209091b897e97fc6d75f4cad32e8a3284d57
Parents: e3d417c
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Sep 30 09:23:29 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 gremlin-driver/pom.xml                          |  5 +
 .../DriverRemoteTraversalSideEffectsTest.java   | 96 ++++++++++++++++++++
 2 files changed, 101 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77a32090/gremlin-driver/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-driver/pom.xml b/gremlin-driver/pom.xml
index 41e775c..65beb52 100644
--- a/gremlin-driver/pom.xml
+++ b/gremlin-driver/pom.xml
@@ -79,6 +79,11 @@ limitations under the License.
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.hamcrest</groupId>
             <artifactId>hamcrest-all</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/77a32090/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java
new file mode 100644
index 0000000..d4c5618
--- /dev/null
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffectsTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.tinkerpop.gremlin.driver.remote;
+
+import org.apache.tinkerpop.gremlin.driver.AbstractResultQueueTest;
+import org.apache.tinkerpop.gremlin.driver.Client;
+import org.apache.tinkerpop.gremlin.driver.ResultSet;
+import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
+import org.junit.Test;
+
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class DriverRemoteTraversalSideEffectsTest extends AbstractResultQueueTest {
+
+    @Test
+    public void shouldNotContactRemoteForKeysAfterCloseIsCalled() throws Exception {
+        final Client client = mock(Client.class);
+        mockClientForCall(client);
+        mockClientForCall(client);
+
+        final UUID sideEffectKey = UUID.fromString("31dec2c6-b214-4a6f-a68b-996608dce0d9");
+        final TraversalSideEffects sideEffects = new DriverRemoteTraversalSideEffects(client, sideEffectKey, null);
+
+        assertEquals(1, sideEffects.keys().size());
+        sideEffects.close();
+
+        // call this again and again and it will only hit the cached keys - no more server calls
+        assertEquals(1, sideEffects.keys().size());
+        assertEquals(1, sideEffects.keys().size());
+        assertEquals(1, sideEffects.keys().size());
+        assertEquals(1, sideEffects.keys().size());
+
+        // once for the keys and once for the close message
+        verify(client, times(2)).submitAsync(any(RequestMessage.class));
+    }
+
+    @Test
+    public void shouldNotContactRemoteMoreThanOnceForClose() throws Exception {
+        final Client client = mock(Client.class);
+        mockClientForCall(client);
+        mockClientForCall(client);
+
+        final UUID sideEffectKey = UUID.fromString("31dec2c6-b214-4a6f-a68b-996608dce0d9");
+        final TraversalSideEffects sideEffects = new DriverRemoteTraversalSideEffects(client, sideEffectKey, null);
+
+        sideEffects.close();
+        sideEffects.close();
+        sideEffects.close();
+        sideEffects.close();
+        sideEffects.close();
+
+        assertEquals(0, sideEffects.keys().size());
+
+        // once for the keys and once for the close message
+        verify(client, times(1)).submitAsync(any(RequestMessage.class));
+    }
+
+    private void mockClientForCall(final Client client) throws Exception {
+        final ResultSet returnedResultSet = new ResultSet(resultQueue, pool, readCompleted, RequestMessage.build("traversal").create(), null);
+        addToQueue(1, 0, true, true, 1);
+        final CompletableFuture<ResultSet> returnedFuture = new CompletableFuture<>();
+        returnedFuture.complete(returnedResultSet);
+
+        // the return is just generic garbage from addToQueue for any call to submitAsync() - but given the logic
+        // of DriverRemoteTraversalSideEffects, that's ok
+        when(client.submitAsync(any(RequestMessage.class))).thenReturn(returnedFuture);
+    }
+}


[22/37] tinkerpop git commit: Merge branch 'tp31'

Posted by da...@apache.org.
Merge branch 'tp31'


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/d23b971d
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/d23b971d
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/d23b971d

Branch: refs/heads/TINKERPOP-1458
Commit: d23b971d02b00a4aad64882fb772e993e261c348
Parents: 5e55379 ffe0b1f
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Tue Oct 4 19:50:45 2016 +0200
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Tue Oct 4 19:50:45 2016 +0200

----------------------------------------------------------------------
 bin/publish-docs.sh | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d23b971d/bin/publish-docs.sh
----------------------------------------------------------------------


[02/37] tinkerpop git commit: Improved errors produced by GraphSON/GryoReader.readGraph()

Posted by da...@apache.org.
Improved errors produced by GraphSON/GryoReader.readGraph()

in cases where the edge is being loaded and the vertex cannot be found in the cache. No such change was needed for GraphML as it has a slightly different loading model. CTR


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/8d0d2f16
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/8d0d2f16
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/8d0d2f16

Branch: refs/heads/TINKERPOP-1458
Commit: 8d0d2f161dea16a569c27d48f7cc34c0d94a4ab9
Parents: 4fc05e8
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Sep 30 12:16:44 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Sep 30 12:16:44 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                                               | 1 +
 .../tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java  | 4 ++++
 .../apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java   | 4 ++++
 3 files changed, 9 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8d0d2f16/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index cfa5a07..9b3be83 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -59,6 +59,7 @@ TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 * Renamed the `empty.result.indicator` preference to `result.indicator.null` in Gremlin Console
 * If `result.indicator.null` is set to an empty string, then no "result line" is printed in Gremlin Console.
 * Deprecated `reconnectInitialDelay` on the Java driver.
+* Produced better errors in `readGraph` of `GryoReader` and `GraphSONReader` if a `Vertex` cannot be found in the cache on edge loading.
 * VertexPrograms can now declare traverser requirements, e.g. to have access to the path when used with `.program()`.
 * New build options for `gremlin-python` where `-DglvPython` is no longer required.
 * Added missing `InetAddress` to GraphSON extension module.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8d0d2f16/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java
index 667aa86..a1ccc5e 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONReader.java
@@ -114,6 +114,10 @@ public final class GraphSONReader implements GraphReader {
             // StarAdjacentVertex whose equality should match StarVertex.
             final Vertex cachedOutV = cache.get(e.outVertex());
             final Vertex cachedInV = cache.get(e.inVertex());
+
+            if (null == cachedOutV) throw new IllegalStateException(String.format("Could not find outV with id [%s] to create edge with id [%s]", e.outVertex().id(), e.id()));
+            if (null == cachedInV) throw new IllegalStateException(String.format("Could not find inV with id [%s] to create edge with id [%s]", e.inVertex().id(), e.id()));
+
             final Edge newEdge = edgeFeatures.willAllowId(e.id()) ? cachedOutV.addEdge(e.label(), cachedInV, T.id, e.id()) : cachedOutV.addEdge(e.label(), cachedInV);
             e.properties().forEachRemaining(p -> newEdge.property(p.key(), p.value()));
             if (supportsTx && counter.incrementAndGet() % batchSize == 0)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/8d0d2f16/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java
index c34101b..d9e9d7b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoReader.java
@@ -103,6 +103,10 @@ public final class GryoReader implements GraphReader {
             // StarAdjacentVertex whose equality should match StarVertex.
             final Vertex cachedOutV = cache.get(e.outVertex());
             final Vertex cachedInV = cache.get(e.inVertex());
+
+            if (null == cachedOutV) throw new IllegalStateException(String.format("Could not find outV with id [%s] to create edge with id [%s]", e.outVertex().id(), e.id()));
+            if (null == cachedInV) throw new IllegalStateException(String.format("Could not find inV with id [%s] to create edge with id [%s]", e.inVertex().id(), e.id()));
+
             final Edge newEdge = edgeFeatures.willAllowId(e.id()) ? cachedOutV.addEdge(e.label(), cachedInV, T.id, e.id()) : cachedOutV.addEdge(e.label(), cachedInV);
             e.properties().forEachRemaining(p -> newEdge.property(p.key(), p.value()));
             if (supportsTx && counter.incrementAndGet() % batchSize == 0)


[19/37] tinkerpop git commit: Merge remote-tracking branch 'origin/TINKERPOP-1467' into tp31

Posted by da...@apache.org.
Merge remote-tracking branch 'origin/TINKERPOP-1467' into tp31

Conflicts:
	CHANGELOG.asciidoc


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/9ba68068
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/9ba68068
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/9ba68068

Branch: refs/heads/TINKERPOP-1458
Commit: 9ba68068f711913df221477256c7c62e7a1df835
Parents: c7f42d8 6d14adb
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Oct 4 13:39:36 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Oct 4 13:39:36 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../upgrade/release-3.1.x-incubating.asciidoc   | 17 +++++
 .../tinkerpop/gremlin/driver/Channelizer.java   |  6 +-
 .../apache/tinkerpop/gremlin/driver/Client.java | 42 +++++++++--
 .../tinkerpop/gremlin/driver/Cluster.java       | 22 +++++-
 .../tinkerpop/gremlin/driver/Connection.java    | 68 +++++++++++++++--
 .../gremlin/driver/ConnectionPool.java          | 21 +++---
 .../tinkerpop/gremlin/driver/Handler.java       | 27 +++++--
 .../tinkerpop/gremlin/driver/ResultQueue.java   |  4 +
 .../driver/handler/WebSocketClientHandler.java  |  4 +-
 .../server/GremlinDriverIntegrateTest.java      | 79 +++++++++++++++++++-
 .../server/GremlinServerAuthIntegrateTest.java  |  5 +-
 .../GremlinServerAuthOldIntegrateTest.java      |  4 +-
 .../GremlinServerSessionIntegrateTest.java      |  6 +-
 14 files changed, 255 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/9ba68068/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --cc CHANGELOG.asciidoc
index cf89a5c,9f45477..1917aae
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@@ -26,7 -26,7 +26,8 @@@ image::https://raw.githubusercontent.co
  TinkerPop 3.1.5 (Release Date: NOT OFFICIALLY RELEASED YET)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
+ * Improved handling of `Cluster.close()` and `Client.close()` to prevent the methods from hanging.
 +* Fixed a bug in `NotStep` where child requirements were not being analyzed.
  * Fixed output redirection and potential memory leak in `GremlinGroovyScriptEngine`.
  * Corrected naming of `g_withPath_V_asXaX_out_out_mapXa_name_it_nameX` and `g_withPath_V_asXaX_out_mapXa_nameX` in `MapTest`.
  * Improved session cleanup when a close is triggered by the client.


[31/37] tinkerpop git commit: fixed logic in DriverRemoteSideEffects, don't clear local side effect cache

Posted by da...@apache.org.
fixed logic in DriverRemoteSideEffects, don't clear local side effect cache


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/e3d417ca
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/e3d417ca
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/e3d417ca

Branch: refs/heads/TINKERPOP-1458
Commit: e3d417ca3cd19aea600bb1dbca3e67aa2174535f
Parents: 3614182
Author: davebshow <da...@gmail.com>
Authored: Thu Sep 29 13:04:57 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../DriverRemoteTraversalSideEffects.java       | 48 ++++++++++----------
 .../server/GremlinServerIntegrateTest.java      | 13 +++---
 2 files changed, 31 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e3d417ca/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
index c565dfa..d2fced5 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
@@ -39,7 +39,7 @@ import java.util.stream.Collectors;
 public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSideEffects {
 
     private final Client client;
-    private Set<String> keys = null;
+    private Set<String> keys = Collections.emptySet();
     private final UUID serverSideEffect;
     private final Host host;
 
@@ -56,22 +56,27 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
     @Override
     public <V> V get(final String key) throws IllegalArgumentException {
         if (!sideEffects.containsKey(key)) {
-            // specify the ARGS_HOST so that the LoadBalancingStrategy is subverted and the connection is forced
-            // from the specified host (i.e. the host from the previous request as that host will hold the side-effects)
-            final RequestMessage msg = RequestMessage.build(Tokens.OPS_GATHER)
-                    .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffect)
-                    .addArg(Tokens.ARGS_SIDE_EFFECT_KEY, key)
-                    .addArg(Tokens.ARGS_HOST, host)
-                    .processor("traversal").create();
-            try {
-                final Result result = client.submitAsync(msg).get().one();
-                sideEffects.put(key, null == result ? null : result.getObject());
-            } catch (Exception ex) {
-                final Throwable root = ExceptionUtils.getRootCause(ex);
-                if (root.getMessage().equals("Could not find side-effects for " + serverSideEffect + "."))
-                    sideEffects.put(key, null);
-                else
-                    throw new RuntimeException("Could not get keys", root);
+            if (!closed) {
+                // specify the ARGS_HOST so that the LoadBalancingStrategy is subverted and the connection is forced
+                // from the specified host (i.e. the host from the previous request as that host will hold the side-effects)
+                final RequestMessage msg = RequestMessage.build(Tokens.OPS_GATHER)
+                        .addArg(Tokens.ARGS_SIDE_EFFECT, serverSideEffect)
+                        .addArg(Tokens.ARGS_SIDE_EFFECT_KEY, key)
+                        .addArg(Tokens.ARGS_HOST, host)
+                        .processor("traversal").create();
+                try {
+                    final Result result = client.submitAsync(msg).get().one();
+                    sideEffects.put(key, null == result ? null : result.getObject());
+                    keys.add(key);
+                } catch (Exception ex) {
+                    final Throwable root = ExceptionUtils.getRootCause(ex);
+                    if (root.getMessage().equals("Could not find side-effects for " + serverSideEffect + "."))
+                        sideEffects.put(key, null);
+                    else
+                        throw new RuntimeException("Could not get keys", root);
+                }
+            } else {
+                sideEffects.put(key, null);
             }
         }
 
@@ -80,7 +85,7 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
 
     @Override
     public Set<String> keys() {
-        if (null == keys) {
+        if (!closed) {
             // specify the ARGS_HOST so that the LoadBalancingStrategy is subverted and the connection is forced
             // from the specified host (i.e. the host from the previous request as that host will hold the side-effects)
             final RequestMessage msg = RequestMessage.build(Tokens.OPS_KEYS)
@@ -91,9 +96,7 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
                 keys = client.submitAsync(msg).get().all().get().stream().map(r -> r.getString()).collect(Collectors.toSet());
             } catch (Exception ex) {
                 final Throwable root = ExceptionUtils.getRootCause(ex);
-                if (root.getMessage().equals("Could not find side-effects for " + serverSideEffect + "."))
-                    keys = Collections.emptySet();
-                else
+                if (!root.getMessage().equals("Could not find side-effects for " + serverSideEffect + "."))
                     throw new RuntimeException("Could not get keys", root);
             }
         }
@@ -101,7 +104,6 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
         return keys;
     }
 
-
     @Override
     public void close() throws Exception {
         if (!closed) {
@@ -111,8 +113,6 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
                     .processor("traversal").create();
             try {
                 client.submitAsync(msg).get();
-                sideEffects.clear();
-                keys = null;
                 closed = true;
             } catch (Exception ex) {
                 final Throwable root = ExceptionUtils.getRootCause(ex);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e3d417ca/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index a1d019b..e6e0021 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -70,6 +70,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -90,6 +91,7 @@ import static org.hamcrest.core.StringEndsWith.endsWith;
 import static org.hamcrest.core.StringStartsWith.startsWith;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeThat;
 import static org.junit.Assert.assertEquals;
@@ -831,17 +833,16 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
     }
 
     @Test
-    public void shouldCloseSideEffects() throws Exception {
+    public void shouldCloseLocalSideEffects() throws Exception {
         final Graph graph = EmptyGraph.instance();
         final GraphTraversalSource g = graph.traversal().withRemote(conf);
         g.addV("person").property("age", 20).iterate();
         g.addV("person").property("age", 10).iterate();
-        final GraphTraversal traversal = g.V().aggregate("a");
+        final GraphTraversal traversal = g.V().aggregate("a").aggregate("b");
         traversal.iterate();
-        final Set sideEffects = traversal.asAdmin().getSideEffects().keys();
-        assertTrue(sideEffects.contains("a"));
+        final List sideEffects = traversal.asAdmin().getSideEffects().get("a");
+        assertFalse(sideEffects.isEmpty());
         traversal.asAdmin().getSideEffects().close();
-        final Set emptySideEffects = traversal.asAdmin().getSideEffects().keys();
-        assertTrue(emptySideEffects.isEmpty());
+        assertNull(traversal.asAdmin().getSideEffects().get("b"));
     }
 }


[25/37] tinkerpop git commit: added close method to gremlin python sideeffects

Posted by da...@apache.org.
added close method to gremlin python sideeffects


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/df9ff696
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/df9ff696
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/df9ff696

Branch: refs/heads/TINKERPOP-1458
Commit: df9ff696a16ff8495b3845e1f1888faf2e539624
Parents: e319ff6
Author: davebshow <da...@apache.org>
Authored: Mon Sep 26 13:25:17 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:30 2016 -0400

----------------------------------------------------------------------
 .../driver/driver_remote_connection.py          | 22 +++++++++++++++++++-
 .../gremlin_python/driver/remote_connection.py  |  6 +++++-
 .../driver/test_driver_remote_connection.py     |  8 ++++++-
 3 files changed, 33 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df9ff696/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
index cac5e73..e47c8e6 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/driver_remote_connection.py
@@ -52,7 +52,8 @@ class DriverRemoteConnection(RemoteConnection):
         traversers = self._loop.run_sync(lambda: self.submit_traversal_bytecode(request_id, bytecode))
         side_effect_keys = lambda: self._loop.run_sync(lambda: self.submit_sideEffect_keys(request_id))
         side_effect_value = lambda key: self._loop.run_sync(lambda: self.submit_sideEffect_value(request_id, key))
-        return RemoteTraversal(iter(traversers), RemoteTraversalSideEffects(side_effect_keys, side_effect_value))
+        side_effect_close = lambda: self._loop.run_sync(lambda: self.submit_sideEffect_close(request_id))
+        return RemoteTraversal(iter(traversers), RemoteTraversalSideEffects(side_effect_keys, side_effect_value, side_effect_close))
 
     @gen.coroutine
     def submit_traversal_bytecode(self, request_id, bytecode):
@@ -115,6 +116,25 @@ class DriverRemoteConnection(RemoteConnection):
         raise gen.Return(value)
 
     @gen.coroutine
+    def submit_sideEffect_close(self, request_id):
+        message = {
+            "requestId": {
+                "@type": "g:UUID",
+                "@value": str(uuid.uuid4())
+            },
+            "op": "close",
+            "processor": "traversal",
+            "args": {
+                "sideEffect": {
+                    "@type": "g:UUID",
+                    "@value": request_id
+                }
+            }
+        }
+        result = yield self._execute_message(message)
+        raise gen.Return(result)
+
+    @gen.coroutine
     def _execute_message(self, send_message):
         send_message = b"".join([b"\x21",
                                  b"application/vnd.gremlin-v2.0+json",

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df9ff696/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
index 0b84a26..3e7293f 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
@@ -57,9 +57,10 @@ class RemoteTraversal(Traversal):
 
 
 class RemoteTraversalSideEffects(TraversalSideEffects):
-    def __init__(self, keys_lambda, value_lambda):
+    def __init__(self, keys_lambda, value_lambda, close_lambda):
         self.keys_lambda = keys_lambda
         self.value_lambda = value_lambda
+        self.close_lambda = close_lambda
 
     def keys(self):
         return self.keys_lambda()
@@ -67,6 +68,9 @@ class RemoteTraversalSideEffects(TraversalSideEffects):
     def get(self, key):
         return self.value_lambda(key)
 
+    def close(self):
+        return self.close_lambda()
+
 
 class RemoteStrategy(TraversalStrategy):
     def __init__(self, remote_connection):

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/df9ff696/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
index b0efcf1..d96d35d 100644
--- a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
@@ -22,6 +22,8 @@ __author__ = 'Marko A. Rodriguez (http://markorodriguez.com)'
 import unittest
 from unittest import TestCase
 
+import pytest
+
 from gremlin_python import statics
 from gremlin_python.statics import long
 from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
@@ -103,7 +105,7 @@ class TestDriverRemoteConnection(TestCase):
         assert "ripple" in n.keys()
         assert 3 == n["lop"]
         assert 1 == n["ripple"]
-        #
+
         t = g.withSideEffect('m',32).V().map(lambda: "x: x.sideEffects('m')")
         results = t.toSet()
         assert 1 == len(results)
@@ -115,6 +117,10 @@ class TestDriverRemoteConnection(TestCase):
             raise Exception("Accessing a non-existent key should throw an error")
         except KeyError:
             pass
+        result = t.side_effects.close()
+        assert not result
+        with pytest.raises(KeyError):
+            x = t.side_effects['m']
         connection.close()
 
 


[28/37] tinkerpop git commit: added 'safe' error parsing code to keys method

Posted by da...@apache.org.
added 'safe' error parsing code to keys method


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/359005af
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/359005af
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/359005af

Branch: refs/heads/TINKERPOP-1458
Commit: 359005afcc703a1639c5ea093d167a193918a830
Parents: 86d373e
Author: davebshow <da...@gmail.com>
Authored: Wed Oct 5 18:46:37 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../gremlin/driver/remote/DriverRemoteTraversalSideEffects.java   | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/359005af/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
index 2dece11..642db13 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
@@ -100,7 +100,8 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
                 keys = client.submitAsync(msg).get().all().get().stream().map(r -> r.getString()).collect(Collectors.toSet());
             } catch (Exception ex) {
                 final Throwable root = ExceptionUtils.getRootCause(ex);
-                if (!root.getMessage().equals("Could not find side-effects for " + serverSideEffect + "."))
+                final String exMsg = null == root ? "" : root.getMessage();
+                if (!exMsg.equals("Could not find side-effects for " + serverSideEffect + "."))
                     throw new RuntimeException("Could not get keys", root);
             }
         }


[33/37] tinkerpop git commit: updated driver to cache side effects locally

Posted by da...@apache.org.
updated driver to cache side effects locally


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/20bcc832
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/20bcc832
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/20bcc832

Branch: refs/heads/TINKERPOP-1458
Commit: 20bcc83268c7439db9e3efaf78cae66f17f8ecf0
Parents: be655e6
Author: davebshow <da...@gmail.com>
Authored: Wed Oct 5 18:00:27 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../gremlin_python/driver/remote_connection.py  | 26 ++++++++++---
 .../driver/test_driver_remote_connection.py     | 39 +++++++++++++++++---
 2 files changed, 54 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/20bcc832/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py b/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
index 3e7293f..46fb760 100644
--- a/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
+++ b/gremlin-python/src/main/jython/gremlin_python/driver/remote_connection.py
@@ -58,18 +58,32 @@ class RemoteTraversal(Traversal):
 
 class RemoteTraversalSideEffects(TraversalSideEffects):
     def __init__(self, keys_lambda, value_lambda, close_lambda):
-        self.keys_lambda = keys_lambda
-        self.value_lambda = value_lambda
-        self.close_lambda = close_lambda
+        self._keys_lambda = keys_lambda
+        self._value_lambda = value_lambda
+        self._close_lambda = close_lambda
+        self._keys = set()
+        self._side_effects = {}
+        self._closed = False
 
     def keys(self):
-        return self.keys_lambda()
+        if not self._closed:
+            self._keys = self._keys_lambda()
+        return self._keys
 
     def get(self, key):
-        return self.value_lambda(key)
+        if not self._side_effects.get(key):
+            if not self._closed:
+                results = self._value_lambda(key)
+                self._side_effects[key] = results
+                self._keys.add(key)
+            else:
+                return None
+        return self._side_effects[key]
 
     def close(self):
-        return self.close_lambda()
+        results = self._close_lambda()
+        self._closed = True
+        return results
 
 
 class RemoteStrategy(TraversalStrategy):

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/20bcc832/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
index d96d35d..d3163d3 100644
--- a/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
+++ b/gremlin-python/src/main/jython/tests/driver/test_driver_remote_connection.py
@@ -106,6 +106,7 @@ class TestDriverRemoteConnection(TestCase):
         assert 3 == n["lop"]
         assert 1 == n["ripple"]
 
+
         t = g.withSideEffect('m',32).V().map(lambda: "x: x.sideEffects('m')")
         results = t.toSet()
         assert 1 == len(results)
@@ -117,11 +118,39 @@ class TestDriverRemoteConnection(TestCase):
             raise Exception("Accessing a non-existent key should throw an error")
         except KeyError:
             pass
-        result = t.side_effects.close()
-        assert not result
-        with pytest.raises(KeyError):
-            x = t.side_effects['m']
-        connection.close()
+
+    def test_side_effect_close(self):
+        connection = DriverRemoteConnection('ws://localhost:8182/gremlin', 'g')
+        g = Graph().traversal().withRemote(connection)
+        t = g.V().aggregate('a').aggregate('b')
+        t.toList()
+
+        # The 'a' key should return some side effects
+        results = t.side_effects.get('a')
+        assert results
+
+        # Close result is None
+        results = t.side_effects.close()
+        assert not results
+
+        # Shouldn't get any new info from server
+        # 'b' isn't in local cache
+        results = t.side_effects.get('b')
+        assert not results
+
+        # But 'a' should still be cached locally
+        results = t.side_effects.get('a')
+        assert results
+
+        # 'a' should have been added to local keys cache, but not 'b'
+        results = t.side_effects.keys()
+        assert len(results) == 1
+        a, = results
+        assert a == 'a'
+
+        # Try to get 'b' directly from server, should throw error
+        with pytest.raises(Exception):
+            t.side_effects.value_lambda('b')
 
 
 if __name__ == '__main__':


[26/37] tinkerpop git commit: fixed java code as per @spmallette review

Posted by da...@apache.org.
fixed java code as per @spmallette review


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/a80b7cde
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/a80b7cde
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/a80b7cde

Branch: refs/heads/TINKERPOP-1458
Commit: a80b7cde7d537e236de0d3c95001c49ef350a4be
Parents: 44742f5
Author: davebshow <da...@gmail.com>
Authored: Thu Oct 6 20:21:37 2016 -0400
Committer: davebshow <da...@gmail.com>
Committed: Fri Oct 7 10:34:31 2016 -0400

----------------------------------------------------------------------
 .../driver/remote/DriverRemoteTraversalSideEffects.java       | 7 +++++--
 .../tinkerpop/gremlin/server/GremlinServerIntegrateTest.java  | 4 ++--
 2 files changed, 7 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80b7cde/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
index 642db13..1de1766 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/remote/DriverRemoteTraversalSideEffects.java
@@ -68,7 +68,7 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
                 try {
                     final Result result = client.submitAsync(msg).get().one();
                     sideEffects.put(key, null == result ? null : result.getObject());
-                    if (keys.isEmpty())
+                    if (keys.equals(Collections.emptySet()))
                         keys = new HashSet<>();
                     keys.add(key);
                 } catch (Exception ex) {
@@ -97,7 +97,10 @@ public class DriverRemoteTraversalSideEffects extends AbstractRemoteTraversalSid
                     .addArg(Tokens.ARGS_HOST, host)
                     .processor("traversal").create();
             try {
-                keys = client.submitAsync(msg).get().all().get().stream().map(r -> r.getString()).collect(Collectors.toSet());
+                if (keys.equals(Collections.emptySet()))
+                    keys = new HashSet<>();
+
+                client.submitAsync(msg).get().all().get().forEach(r -> keys.add(r.getString()));
             } catch (Exception ex) {
                 final Throwable root = ExceptionUtils.getRootCause(ex);
                 final String exMsg = null == root ? "" : root.getMessage();

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a80b7cde/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index f810ebc..9bc6cd9 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -894,9 +894,9 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
         // Try to get side effect from server
         final Cluster cluster = Cluster.build("localhost").create();
         final Client client = cluster.connect();
-        Field field = DriverRemoteTraversalSideEffects.class.getDeclaredField("serverSideEffect");
+        final Field field = DriverRemoteTraversalSideEffects.class.getDeclaredField("serverSideEffect");
         field.setAccessible(true);
-        UUID serverSideEffectId = (UUID) field.get(se);
+        final UUID serverSideEffectId = (UUID) field.get(se);
         final Map<String, String> aliases = new HashMap<>();
         aliases.put("g", "g");
         final RequestMessage msg = RequestMessage.build(Tokens.OPS_GATHER)


[09/37] tinkerpop git commit: made the recommended changes from @dkuppitz.

Posted by da...@apache.org.
made the recommended changes from @dkuppitz.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/e3991eae
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/e3991eae
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/e3991eae

Branch: refs/heads/TINKERPOP-1458
Commit: e3991eae76e1a3eca64c9b20582c025a92447daf
Parents: b8a92a3
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Oct 3 08:09:19 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 08:24:17 2016 -0600

----------------------------------------------------------------------
 .../optimization/InlineFilterStrategy.java      | 29 ++++++++------------
 1 file changed, 12 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/e3991eae/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
index 820143a..8072ca0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/InlineFilterStrategy.java
@@ -42,6 +42,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -75,24 +76,18 @@ public final class InlineFilterStrategy extends AbstractTraversalStrategy<Traver
         boolean changed = true; // recursively walk child traversals trying to inline them into the current traversal line.
         while (changed) {
             changed = false;
-            for (final FilterStep<?> step : TraversalHelper.getStepsOfAssignableClass(FilterStep.class, traversal)) {
-                if (step instanceof HasStep && InlineFilterStrategy.processHasStep((HasStep) step, traversal))
-                    // has(a,b).has(c) --> has(a,b,c)
-                    changed = true;
-                else if (step instanceof TraversalFilterStep && InlineFilterStrategy.processTraversalFilterStep((TraversalFilterStep) step, traversal))
-                    // filter(x.y) --> x.y
-                    changed = true;
-                else if (step instanceof OrStep && InlineFilterStrategy.processOrStep((OrStep) step, traversal))
-                    // or(has(x,y),has(x,z)) --> has(x,y.or(z))
-                    changed = true;
-                else if (step instanceof AndStep && InlineFilterStrategy.processAndStep((AndStep) step, traversal))
-                    // and(x,y) --> x.y
-                    changed = true;
+            final Iterator<FilterStep> filterStepIterator = TraversalHelper.getStepsOfAssignableClass(FilterStep.class, traversal).iterator();
+            while (!changed && filterStepIterator.hasNext()) {
+                final FilterStep<?> step = filterStepIterator.next();
+                changed = step instanceof HasStep && InlineFilterStrategy.processHasStep((HasStep) step, traversal) ||
+                        step instanceof TraversalFilterStep && InlineFilterStrategy.processTraversalFilterStep((TraversalFilterStep) step, traversal) ||
+                        step instanceof OrStep && InlineFilterStrategy.processOrStep((OrStep) step, traversal) ||
+                        step instanceof AndStep && InlineFilterStrategy.processAndStep((AndStep) step, traversal);
             }
-            // match(as('a').has(key,value),...) --> as('a').has(key,value).match(...)
-            if (traversal.getParent() instanceof EmptyStep) {
-                for (final MatchStep<?, ?> step : TraversalHelper.getStepsOfClass(MatchStep.class, traversal)) {
-                    if (InlineFilterStrategy.processMatchStep(step, traversal))
+            if (!changed && traversal.getParent() instanceof EmptyStep) {
+                final Iterator<MatchStep> matchStepIterator = TraversalHelper.getStepsOfClass(MatchStep.class, traversal).iterator();
+                while (!changed && matchStepIterator.hasNext()) {
+                    if (InlineFilterStrategy.processMatchStep(matchStepIterator.next(), traversal))
                         changed = true;
                 }
             }


[16/37] tinkerpop git commit: minor change to CHANGELOG.

Posted by da...@apache.org.
minor change to CHANGELOG.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/62197e25
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/62197e25
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/62197e25

Branch: refs/heads/TINKERPOP-1458
Commit: 62197e25369bfcfd9b7036c6cc379182e5a6b073
Parents: e3991ea
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Mon Oct 3 08:14:58 2016 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Mon Oct 3 08:24:17 2016 -0600

----------------------------------------------------------------------
 CHANGELOG.asciidoc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/62197e25/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 638a80c..60e895b 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,7 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* `FilterRankStrategy` now propagates labels "right" across non-`TraversalParent` filters.
+* `FilterRankStrategy` now propagates labels "right" non-`Scoping` filters.
 * Fixed a bug in `ConnectiveP` where nested equivalent connectives should be inlined.
 * Fixed a bug in `IncidentToAdjacentStrategy` where `TreeStep` traversals were allowed.
 * Fixed a end-step label bug in `MatchPredicateStrategy`.


[03/37] tinkerpop git commit: Finalize variable. CTR

Posted by da...@apache.org.
Finalize variable. CTR


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/f2b027be
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/f2b027be
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/f2b027be

Branch: refs/heads/TINKERPOP-1458
Commit: f2b027beef8ec5a0dcd379dc2c68e4688bf73b03
Parents: 8d0d2f1
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Sep 30 13:01:11 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Sep 30 13:01:24 2016 -0400

----------------------------------------------------------------------
 .../gremlin/server/op/traversal/TraversalOpProcessor.java          | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f2b027be/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
index e1534e2..80cacd2 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/traversal/TraversalOpProcessor.java
@@ -231,7 +231,7 @@ public class TraversalOpProcessor extends AbstractOpProcessor {
         return aliases.get();
     }
 
-    private static Optional<Map<String, String>> validatedAliases(RequestMessage message) throws OpProcessorException {
+    private static Optional<Map<String, String>> validatedAliases(final RequestMessage message) throws OpProcessorException {
         final Optional<Map<String, String>> aliases = message.optionalArgs(Tokens.ARGS_ALIASES);
         if (!aliases.isPresent()) {
             final String msg = String.format("A message with [%s] op code requires a [%s] argument.", Tokens.OPS_BYTECODE, Tokens.ARGS_ALIASES);


[20/37] tinkerpop git commit: Merge remote-tracking branch 'origin/TINKERPOP-1467-master'

Posted by da...@apache.org.
Merge remote-tracking branch 'origin/TINKERPOP-1467-master'

Conflicts:
	CHANGELOG.asciidoc


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/5e55379a
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/5e55379a
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/5e55379a

Branch: refs/heads/TINKERPOP-1458
Commit: 5e55379a8d25a5964bb9554206651cebd7a591ce
Parents: 8ab682f 9d860ca
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Oct 4 13:40:52 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Oct 4 13:40:52 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../upgrade/release-3.1.x-incubating.asciidoc   | 17 +++++
 .../tinkerpop/gremlin/driver/Channelizer.java   |  2 +-
 .../apache/tinkerpop/gremlin/driver/Client.java | 42 +++++++++--
 .../tinkerpop/gremlin/driver/Cluster.java       | 24 +++++-
 .../tinkerpop/gremlin/driver/Connection.java    | 67 +++++++++++++++--
 .../gremlin/driver/ConnectionPool.java          | 21 +++---
 .../tinkerpop/gremlin/driver/Handler.java       | 26 +++++--
 .../tinkerpop/gremlin/driver/ResultQueue.java   |  4 +
 .../driver/handler/WebSocketClientHandler.java  |  4 +-
 .../server/GremlinDriverIntegrateTest.java      | 79 +++++++++++++++++++-
 .../server/GremlinServerAuthIntegrateTest.java  |  5 +-
 .../GremlinServerAuthOldIntegrateTest.java      |  4 +-
 .../GremlinServerSessionIntegrateTest.java      |  6 +-
 14 files changed, 255 insertions(+), 47 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/5e55379a/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --cc CHANGELOG.asciidoc
index dc2b03b,86ed392..93308b6
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@@ -429,7 -427,7 +429,8 @@@ image::https://raw.githubusercontent.co
  TinkerPop 3.1.5 (Release Date: NOT OFFICIALLY RELEASED YET)
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
+ * Improved handling of `Cluster.close()` and `Client.close()` to prevent the methods from hanging.
 +* Fixed a bug in `NotStep` where child requirements were not being analyzed.
  * Fixed output redirection and potential memory leak in `GremlinGroovyScriptEngine`.
  * Corrected naming of `g_withPath_V_asXaX_out_out_mapXa_name_it_nameX` and `g_withPath_V_asXaX_out_mapXa_nameX` in `MapTest`.
  * Improved session cleanup when a close is triggered by the client.


[06/37] tinkerpop git commit: Added simple validations to Cluster instance creations CTR

Posted by da...@apache.org.
Added simple validations to Cluster instance creations CTR


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/233a6ba4
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/233a6ba4
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/233a6ba4

Branch: refs/heads/TINKERPOP-1458
Commit: 233a6ba460f618a5c684f0bc2533175f90948d0e
Parents: ee813e9
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Sep 30 14:52:43 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Sep 30 14:52:43 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../tinkerpop/gremlin/driver/Cluster.java       | 55 +++++++++++-
 .../gremlin/driver/ClusterBuilderTest.java      | 88 ++++++++++++++++++++
 3 files changed, 142 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/233a6ba4/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 9b3be83..ade43cd 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -59,6 +59,7 @@ TinkerPop 3.2.3 (Release Date: NOT OFFICIALLY RELEASED YET)
 * Renamed the `empty.result.indicator` preference to `result.indicator.null` in Gremlin Console
 * If `result.indicator.null` is set to an empty string, then no "result line" is printed in Gremlin Console.
 * Deprecated `reconnectInitialDelay` on the Java driver.
+* Added some validations to `Cluster` instance building.
 * Produced better errors in `readGraph` of `GryoReader` and `GraphSONReader` if a `Vertex` cannot be found in the cache on edge loading.
 * VertexPrograms can now declare traverser requirements, e.g. to have access to the path when used with `.program()`.
 * New build options for `gremlin-python` where `-DglvPython` is no longer required.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/233a6ba4/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
index f420de0..b9a3cee 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
@@ -510,7 +510,6 @@ public final class Cluster {
          * Size of the pool for handling request/response operations.  Defaults to the number of available processors.
          */
         public Builder nioPoolSize(final int nioPoolSize) {
-            if (nioPoolSize < 1) throw new IllegalArgumentException("The workerPoolSize must be greater than zero");
             this.nioPoolSize = nioPoolSize;
             return this;
         }
@@ -520,7 +519,6 @@ public final class Cluster {
          * by 2
          */
         public Builder workerPoolSize(final int workerPoolSize) {
-            if (workerPoolSize < 1) throw new IllegalArgumentException("The workerPoolSize must be greater than zero");
             this.workerPoolSize = workerPoolSize;
             return this;
         }
@@ -872,6 +870,8 @@ public final class Cluster {
         private final AtomicReference<CompletableFuture<Void>> closeFuture = new AtomicReference<>();
 
         private Manager(final Builder builder) {
+            validateBuilder(builder);
+
             this.loadBalancingStrategy = builder.loadBalancingStrategy;
             this.authProps = builder.authProps;
             this.contactPoints = builder.getContactPoints();
@@ -909,6 +909,57 @@ public final class Cluster {
                     new BasicThreadFactory.Builder().namingPattern("gremlin-driver-worker-%d").build());
         }
 
+        private void validateBuilder(final Builder builder) {
+            if (builder.minInProcessPerConnection < 0)
+                throw new IllegalArgumentException("minInProcessPerConnection must be greater than or equal to zero");
+
+            if (builder.maxInProcessPerConnection < 1)
+                throw new IllegalArgumentException("maxInProcessPerConnection must be greater than zero");
+
+            if (builder.minInProcessPerConnection > builder.maxInProcessPerConnection)
+                throw new IllegalArgumentException("maxInProcessPerConnection cannot be less than minInProcessPerConnection");
+
+            if (builder.minSimultaneousUsagePerConnection < 0)
+                throw new IllegalArgumentException("minSimultaneousUsagePerConnection must be greater than or equal to zero");
+
+            if (builder.maxSimultaneousUsagePerConnection < 1)
+                throw new IllegalArgumentException("maxSimultaneousUsagePerConnection must be greater than zero");
+
+            if (builder.minSimultaneousUsagePerConnection > builder.maxSimultaneousUsagePerConnection)
+                throw new IllegalArgumentException("maxSimultaneousUsagePerConnection cannot be less than minSimultaneousUsagePerConnection");
+
+            if (builder.minConnectionPoolSize < 0)
+                throw new IllegalArgumentException("minConnectionPoolSize must be greater than or equal to zero");
+
+            if (builder.maxConnectionPoolSize < 1)
+                throw new IllegalArgumentException("maxConnectionPoolSize must be greater than zero");
+
+            if (builder.minConnectionPoolSize > builder.maxConnectionPoolSize)
+                throw new IllegalArgumentException("maxConnectionPoolSize cannot be less than minConnectionPoolSize");
+
+            if (builder.maxWaitForConnection < 1)
+                throw new IllegalArgumentException("maxWaitForConnection must be greater than zero");
+
+            if (builder.maxWaitForSessionClose < 1)
+                throw new IllegalArgumentException("maxWaitForSessionClose must be greater than zero");
+
+            if (builder.maxContentLength < 1)
+                throw new IllegalArgumentException("maxContentLength must be greater than zero");
+
+            if (builder.reconnectInterval < 1)
+                throw new IllegalArgumentException("reconnectInterval must be greater than zero");
+
+            if (builder.resultIterationBatchSize < 1)
+                throw new IllegalArgumentException("resultIterationBatchSize must be greater than zero");
+
+            if (builder.nioPoolSize < 1)
+                throw new IllegalArgumentException("nioPoolSize must be greater than zero");
+
+            if (builder.workerPoolSize < 1)
+                throw new IllegalArgumentException("workerPoolSize must be greater than zero");
+
+        }
+
         synchronized void init() {
             if (initialized)
                 return;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/233a6ba4/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClusterBuilderTest.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClusterBuilderTest.java b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClusterBuilderTest.java
new file mode 100644
index 0000000..cb5c469
--- /dev/null
+++ b/gremlin-driver/src/test/java/org/apache/tinkerpop/gremlin/driver/ClusterBuilderTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF 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.apache.tinkerpop.gremlin.driver;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@RunWith(Parameterized.class)
+public class ClusterBuilderTest {
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Iterable<Object[]> data() {
+        return Arrays.asList(new Object[][]{
+                {"maxInProcessPerConnection0", Cluster.build().maxInProcessPerConnection(0), "maxInProcessPerConnection must be greater than zero"},
+                {"maxInProcessPerConnectionNeg1", Cluster.build().maxInProcessPerConnection(-1), "maxInProcessPerConnection must be greater than zero"},
+                {"minInProcessPerConnectionNeg1", Cluster.build().minInProcessPerConnection(-1), "minInProcessPerConnection must be greater than or equal to zero"},
+                {"minInProcessPerConnectionLtMax", Cluster.build().minInProcessPerConnection(100).maxInProcessPerConnection(99), "maxInProcessPerConnection cannot be less than minInProcessPerConnection"},
+                {"maxSimultaneousUsagePerConnection0", Cluster.build().maxSimultaneousUsagePerConnection(0), "maxSimultaneousUsagePerConnection must be greater than zero"},
+                {"maxSimultaneousUsagePerConnectionNeg1", Cluster.build().maxSimultaneousUsagePerConnection(-1), "maxSimultaneousUsagePerConnection must be greater than zero"},
+                {"minSimultaneousUsagePerConnectionNeg1", Cluster.build().minSimultaneousUsagePerConnection(-1), "minSimultaneousUsagePerConnection must be greater than or equal to zero"},
+                {"minSimultaneousUsagePerConnectionLtMax", Cluster.build().minSimultaneousUsagePerConnection(100).maxSimultaneousUsagePerConnection(99), "maxSimultaneousUsagePerConnection cannot be less than minSimultaneousUsagePerConnection"},
+                {"maxConnectionPoolSize0", Cluster.build().maxConnectionPoolSize(0), "maxConnectionPoolSize must be greater than zero"},
+                {"maxConnectionPoolSizeNeg1", Cluster.build().maxConnectionPoolSize(-1), "maxConnectionPoolSize must be greater than zero"},
+                {"minConnectionPoolSizeNeg1", Cluster.build().minConnectionPoolSize(-1), "minConnectionPoolSize must be greater than or equal to zero"},
+                {"minConnectionPoolSizeLteMax", Cluster.build().minConnectionPoolSize(100).maxConnectionPoolSize(99), "maxConnectionPoolSize cannot be less than minConnectionPoolSize"},
+                {"minConnectionPoolSizeLteMax", Cluster.build().minConnectionPoolSize(100).maxConnectionPoolSize(99), "maxConnectionPoolSize cannot be less than minConnectionPoolSize"},
+                {"maxConnectionPoolSize0", Cluster.build().maxWaitForConnection(0), "maxWaitForConnection must be greater than zero"},
+                {"maxWaitForSessionClose0", Cluster.build().maxWaitForSessionClose(0), "maxWaitForSessionClose must be greater than zero"},
+                {"maxWaitForSessionCloseNeg1", Cluster.build().maxWaitForSessionClose(-1), "maxWaitForSessionClose must be greater than zero"},
+                {"maxContentLength0", Cluster.build().maxContentLength(0), "maxContentLength must be greater than zero"},
+                {"maxContentLengthNeg1", Cluster.build().maxContentLength(-1), "maxContentLength must be greater than zero"},
+                {"reconnectInterval0", Cluster.build().reconnectInterval(0), "reconnectInterval must be greater than zero"},
+                {"reconnectIntervalNeg1", Cluster.build().reconnectInterval(-1), "reconnectInterval must be greater than zero"},
+                {"resultIterationBatchSize0", Cluster.build().resultIterationBatchSize(0), "resultIterationBatchSize must be greater than zero"},
+                {"resultIterationBatchSizeNeg1", Cluster.build().resultIterationBatchSize(-1), "resultIterationBatchSize must be greater than zero"},
+                {"nioPoolSize0", Cluster.build().nioPoolSize(0), "nioPoolSize must be greater than zero"},
+                {"nioPoolSizeNeg1", Cluster.build().nioPoolSize(-1), "nioPoolSize must be greater than zero"},
+                {"workerPoolSize0", Cluster.build().workerPoolSize(0), "workerPoolSize must be greater than zero"},
+                {"workerPoolSizeNeg1", Cluster.build().workerPoolSize(-1), "workerPoolSize must be greater than zero"}});
+    }
+
+    @Parameterized.Parameter(value = 0)
+    public String name;
+
+    @Parameterized.Parameter(value = 1)
+    public Cluster.Builder builder;
+
+    @Parameterized.Parameter(value = 2)
+    public String expectedErrorMessage;
+
+    @Test
+    public void shouldNotConstructAnInvalidConnection() {
+        try {
+            builder.create();
+            fail("Should not have created cluster instance");
+        } catch (Exception ex) {
+            assertThat(ex, instanceOf(IllegalArgumentException.class));
+            assertEquals(expectedErrorMessage, ex.getMessage());
+        }
+    }
+}


[21/37] tinkerpop git commit: CTR: Handle new directories properly in `publish-docs.sh`.

Posted by da...@apache.org.
CTR: Handle new directories properly in `publish-docs.sh`.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/ffe0b1f5
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/ffe0b1f5
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/ffe0b1f5

Branch: refs/heads/TINKERPOP-1458
Commit: ffe0b1f55af41e649961374e14b251d795286bed
Parents: 9ba6806
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Tue Oct 4 19:49:41 2016 +0200
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Tue Oct 4 19:49:41 2016 +0200

----------------------------------------------------------------------
 bin/publish-docs.sh | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/ffe0b1f5/bin/publish-docs.sh
----------------------------------------------------------------------
diff --git a/bin/publish-docs.sh b/bin/publish-docs.sh
index 49ed9bd..739deb5 100755
--- a/bin/publish-docs.sh
+++ b/bin/publish-docs.sh
@@ -53,15 +53,23 @@ diff -rq -I 'Generated by javadoc' -I '^<meta name="date"' javadocs/${VERSION}/
 # copy new / modified files
 for file in $(cat ../publish-docs.docs | awk '/^[AU]/ {print $2}' | grep -v '.graffle$')
 do
-  cp "../docs/htmlsingle/${file}" "docs/${VERSION}/${file}"
+  if [ -d "../docs/htmlsingle/${file}" ]; then
+    mkdir -p "docs/${VERSION}/${file}" && cp -r "../docs/htmlsingle/${file}"/* "$_"
+  else
+    mkdir -p "docs/${VERSION}/`dirname ${file}`" && cp "../docs/htmlsingle/${file}" "$_"
+  fi
 done
 for file in $(cat ../publish-docs.javadocs | awk '/^[AU]/ {print $2}')
 do
-  cp "../site/apidocs/${file}" "javadocs/${VERSION}/${file}"
+  if [ -d "../site/apidocs/${file}" ]; then
+    mkdir -p "javadocs/${VERSION}/${file}" && cp -r "../site/apidocs/${file}"/* "$_"
+  else
+    mkdir -p "javadocs/${VERSION}/`dirname ${file}`" && cp "../site/apidocs/${file}" "$_"
+  fi
 done
 
-pushd "docs/${VERSION}/"; cat ../../../publish-docs.docs | awk '/^A/ {print $2}' | grep -v '.graffle$' | xargs --no-run-if-empty svn add; popd
-pushd "javadocs/${VERSION}/"; cat ../../../publish-docs.javadocs | awk '/^A/ {print $2}' | xargs --no-run-if-empty svn add; popd
+pushd "docs/${VERSION}/"; cat ../../../publish-docs.docs | awk '/^A/ {print $2}' | grep -v '.graffle$' | xargs --no-run-if-empty svn add --parents; popd
+pushd "javadocs/${VERSION}/"; cat ../../../publish-docs.javadocs | awk '/^A/ {print $2}' | xargs --no-run-if-empty svn add --parents; popd
 
 # delete old files
 pushd "docs/${VERSION}/"; cat ../../../publish-docs.docs | awk '/^D/ {print $2}' | xargs --no-run-if-empty svn delete; popd